save arrayList<Class> as a string inside Room - java

I am using Room library from jetpack and i want to save my arrayList inside Room database.
I am using typeConverter to convert arrayList into String, but still getting error.
Error Message : Cannot figure out how to save this field into database. You can consider adding a type converter for it.
this is my typeConverter.
public class TypeConverterUtils {
#TypeConverter
public static String fromArray(ArrayList<CropData> arrayList) {
return GsonUtils.toGson(arrayList);
}
}
this is my Database class.
#TypeConverters({TypeConverterUtils.class})
public abstract class CheruvuDatabase extends RoomDatabase {
private static final String DATABASE_NAME = "Cheruvu.db";
public abstract OtpDAO otpDAO();
public abstract FarmerInfoDAO farmerInfoDAO();
// For Singleton instantiation
private static final Object LOCK = new Object();
private static volatile CheruvuDatabase sInstance;
public static CheruvuDatabase getInstance(Context context) {
if (sInstance == null) {
synchronized (LOCK) {
if (sInstance == null) {
context.getApplicationContext().deleteDatabase(CheruvuDatabase.DATABASE_NAME);
sInstance = Room.databaseBuilder(context.getApplicationContext(), CheruvuDatabase.class, CheruvuDatabase.DATABASE_NAME)
.fallbackToDestructiveMigration()
.allowMainThreadQueries()
.build();
}
}
}
return sInstance;
}
}
I want to store this ArrayList.
private ArrayList cropData = new ArrayList<>();
this is my CropData class.
public class CropData {
private String cropName;
private Crop crop;
private Float cropAcres;
private Float cropYield;
private Float cropPrice;
public String getCropName() {
return cropName;
}
public void setCropName(String cropName) {
this.cropName = cropName;
}
public Crop getCrop() {
return crop;
}
public void setCrop(Crop crop) {
this.crop = crop;
}
public Float getCropAcres() {
return cropAcres;
}
public void setCropAcres(Float cropAcres) {
this.cropAcres = cropAcres;
}
public Float getCropYield() {
return cropYield;
}
public void setCropYield(Float cropYield) {
this.cropYield = cropYield;
}
public Float getCropPrice() {
return cropPrice;
}
public void setCropPrice(Float cropPrice) {
this.cropPrice = cropPrice;
}
}

Have you added #Embedded on the ArrayList variable? because you will be needed to Embed the Class, that you want to convert.
for example,
ArrayList<CropData> cropData;
and CropData.class is different. so just add
#Embedded
ArrayList<CropData> cropData;
and your problem will be solved.

Related

How can I avoid complie error "lambda expression should be final or effectively final", if I want to apply different actions under different state?

For example I have two simple as possible classes, A and B
I want to take some action on objects of B, if some specific field of A object is changed I should do one thing, If some other field is changed I should do second thing, how can I do that with Lambda?
A:
public class A {
private int someField;
private String nextField;
public A(int someField, String nextField) {
this.someField = someField;
this.nextField = nextField;
}
public int getSomeField() {
return someField;
}
public void setSomeField(int someField) {
this.someField = someField;
}
public String getNextField() {
return nextField;
}
public void setNextField(String nextField) {
this.nextField = nextField;
}
}
B:
public class B {
private String someField;
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
public B(String someField) {
this.someField = someField;
}
}
Demo:
public class Demo {
public static <T> boolean isFieldChanged(T oldValue, T newValue) {
return !Objects.equals(oldValue, newValue);
}
public static void someActionOne(B test){
return;
}
public static void someActionTwo(B test){
return;
}
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
Consumer<B> action = null;
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
action = Demo::someActionOne;
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
action = Demo::someActionTwo;
}
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
mockData.forEach(b -> action.accept(b));
}
}
How can I avoid compile error in that case?
To be effectively-final, a variable must not be changed after initialization.
If you want to use different actions, just initialize them twice:
public static void main(String[] args) {
A oldData = new A(35, "old");
A clientData = new A(25, "ClientData");
List<B> mockData = new ArrayList<>(Arrays.asList(new B("test1"), new B("test2")));
if (isFieldChanged(oldData.getNextField(), clientData.getNextField())) {
mockData.forEach(Demo::someActionOne);
} else if (isFieldChanged(oldData.getSomeField(), clientData.getSomeField())) {
mockData.forEach(Demo::someActionTwo);
}
}

How can I get a value of instance which is already set in another class?

I'm a new to Java. I have 3 classes: 1-DataHolder 2-SetToDateHolder 3-GetFromDataHolder; In the "SetToDateHolder" class, I set the value to dataholder object, and I trying to access it in the "GetFromDataHolder" class, but it got null value, I know it happens because of new instance created. Can you help me to realize that I can get the value of instance which I have set in another class.
These are the classes:
public class DataHolder {
private String myName;
public String getMyName() {
return myName;
}
public void setMyName(String myName) {
this.myName = myName;
}
}
public class SetToDataHolder {
public static void main(String[] args) {
DataHolder dataHolder = new DataHolder();
dataHolder.setMyName("Wesley");
}
}
public class GetFromDataHolder{
public static void main(String[] args) {
DataHolder dataHolder = new DataHolder();
System.out.println(dataHolder.getMyName());
}
}
I don't really understand why you need 2 additional classes as you already have the getter / setter in your DataHolder class, but here's how you should be able to proceed your logic:
public class DataHolder {
private String myName;
public String getMyName() {
return myName;
}
public void setMyName(String myName) {
this.myName = myName;
}
}
public class SetToDataHolder {
private DataHolder dataHolder;
public SetToDataHolder(DataHolder dataHolder){
this.dataHolder = dataHolder;
}
public void setMyName(String myName) {
this.dataHolder.setMyName(myName);
}
}
public class GetFromDataHolder{
private DataHolder dataHolder;
public GetFromDataHolder(DataHolder dataHolder){
this.dataHolder = dataHolder;
}
public String getMyName() {
this.dataHolder.getMyName();
}
}
public class MainClass{
public static void main(String[] args){
DataHolder dataHolder = new DataHolder();
SetToDataHolder setToDataHolder = new SetToDataHolder(dataHolder);
setToDataHolder.setMyName("Wesley");
GetFromDataHolder getFromDataHolder = new GetFromDataHolder(dataHolder);
System.out.println(getFromDataHolder.getMyName());
}
}
The idea is that your SetToDataHolder and GetFromDataHolder, have access to the same instance of DataHolder.

How print the entire data structure created with Composite?

I have class-Composite:
public class CompositeText implements ComponentText {
private TypeComponent type;
private String value;
private final List<ComponentText> childComponents;
private CompositeText() {
childComponents = new ArrayList<>();
}
public CompositeText(String value, TypeComponent typeComponent) {
this.value = value;
this.type = typeComponent;
childComponents = new ArrayList<>();
}
#Override
public void add(ComponentText componentText) {
childComponents.add(componentText);
}
#Override
public void remove(ComponentText componentText) {
childComponents.remove(componentText);
}
#Override
public TypeComponent getComponentType() {
return this.type;
}
#Override
public ComponentText getChild(int index) {
return childComponents.get(index);
}
#Override
public int getCountChildElements() {
return childComponents.size();
}
#Override
public int getCountAllElements() {
return childComponents.stream()
.mapToInt(ComponentText::getCountAllElements)
.sum();
}
#Override
public String toString() {
return null;
}
}
I created classes that perform the same action - parsing, parsing text into paragraphs, into sentences, into tokens, into symbols.
public class IntoParagraphParser implements ActionParser {
// call IntoSentenceParser
}
public class IntoSentenceParser implements ActionParser {
// call IntoLexemeParser
}
public class IntoLexemeParser implements ActionParser {
// call IntoSymbolParser
}
public class IntoSymbolParser implements ActionParser {
}
All data is stored in List <ComponentText> childComponents in class-Composite - CompositeText.
How to properly create a method so that it prints all the data that is inside the composite?
I think this will be the method toString() in CompositeText.
Class IntoParagraphParser look:
public class IntoParagraphParser implements ActionParser {
private static final String PARAGRAPH_SPLIT_REGEX = "(?m)(?=^\\s{4})";
private static final IntoParagraphParser paragraphParser = new IntoParagraphParser();
private static final IntoSentenceParser sentenceParser = IntoSentenceParser.getInstance();
private IntoParagraphParser() {
}
public static IntoParagraphParser getInstance() {
return paragraphParser;
}
public ComponentText parse(String text) throws TextException {
ComponentText oneParagraph;
ComponentText componentParagraph = new CompositeText(text, TypeComponent.PARAGRAPH);
String[] arrayParagraph = text.split(PARAGRAPH_SPLIT_REGEX);
for(String element: arrayParagraph) {
oneParagraph = new CompositeText(element, TypeComponent.PARAGRAPH);
oneParagraph.add(sentenceParser.parse(element));
componentParagraph.add(oneParagraph);
}
return componentParagraph;
}
}
Need #Override the method toString() in CompositeText like this:
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (ComponentText component : childComponents) {
builder.append(component.toString());
}
return builder.toString();
}
But how to write this code correctly with Stream API?
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
childComponents.stream().map(...????
return builder.toString();
}

Simplify multiple inheriting classes (with all same content) of abstract class

I like to count multiple things in my app and save the value to android sharedpreferences. Everything works, but I am not satisfied with the class design in general.
Very simple abstract class. Class parameter is used to name keys in sharedPreferences.
public abstract class Counter {
private Context mContext;
private Class mClass;
Counter(Class myClass, Context context) {
this.mClass = myClass;
this.mContext = context;
}
public Integer getValue() {
return PrefManager.with(mContext).getInt(mClass.getName(), 0);
//return UniversalPreferences.getInstance().get(counterName, 1);
}
public void increment() {
PrefManager.with(mContext).save(mClass.getName(), getValue() + 1);
//UniversalPreferences.getInstance().put(counterName, getCurrentValue(counterName) + 1);
}
}
So far I have already 5 classes inheriting from Counter with all the same content.
public class CounterAppLaunch extends Counter {
#SuppressLint("StaticFieldLeak")
private static CounterAppLaunch instance;
private CounterAppLaunch(Context context) {
super(CounterAppLaunch.class, context);
}
public static CounterAppLaunch getInstance(Context context) {
if(CounterAppLaunch.instance == null) {
CounterAppLaunch.instance = new CounterAppLaunch(context);
}
return CounterAppLaunch.instance;
}
}
I have counters I like to call from different classes and increment there (eg. CounterAPICall or CounterOnResumeCallExample). Which works with this code just fine.
This code might be useful to retrieve an appropriate counter:
public Counter{
private int count;
public Counter(){
count = 0;
}
public int getValue(){
return count;
}
public void increment(){
counter++;
}
}
public CounterStorage(){
private static HashMap<String, Counter> counterMap = new HashMap<>();
public static Counter getInstance(String str){
if (counterMap.containsKey(str)) return counterMap.get(str);
Counter newCounter = new Counter();
counterMap.add(str, newCounter);
return newCounter;
}
}
In this case, Counter isn't an abstract class. For any purpose, you can give a Counter a name, which is stored in the map.
With the help of Dependency injection and having HasA also, we can try,
public class CounterAppLaunch{
#Autowired
CounterAdapter counterAdapter;
#SuppressLint("StaticFieldLeak")
private static CounterAppLaunch instance;
private CounterAppLaunch(Context context) {
super(CounterAppLaunch.class, context);
}
public static CounterAppLaunch getInstance(Context context) {
if(CounterAppLaunch.instance == null) {
CounterAppLaunch.instance = new CounterAppLaunch(context);
}
return CounterAppLaunch.instance;
}
}
CounterAdapter extends Counter{
#Autowired
private Context mContext;
#Autowired
private Class mClass;
// getter and setter
}
public abstract class Counter {
private Context mContext;
private Class mClass;
Counter(Class myClass, Context context) {
this.mClass = myClass;
this.mContext = context;
}
public Integer getValue() {
return PrefManager.with(mContext).getInt(mClass.getName(), 0);
//return UniversalPreferences.getInstance().get(counterName, 1);
}
public void increment() {
PrefManager.with(mContext).save(mClass.getName(), getValue() + 1);
//UniversalPreferences.getInstance().put(counterName, getCurrentValue(counterName) + 1);
}
}

Java data structure for String and Class

I am looking to store information in a list or array, and then access the info through a method using a String parameter.
public void blah(String name){
DataStructure[apple].getInfo1; //a float
DataStucture[apple].getInfo2; //an int
Some pseudocode of how the info will be stored:
DataStructure.add(apple);
apple.setFloat(5f);
apple.setInt(1);
My main confusion is how to access this information using a String. Since I will be having a lot of objects in this structure, I figured the easiest way to access the info would be to look up the name directly.
Like this:
public class DataStructure {
private float info1;
private int info2;
public DataStructure(float info1, int info2) {
super();
this.info1 = info1;
this.info2 = info2;
}
public float getInfo1() {
return info1;
}
public void setInfo1(float info1) {
this.info1 = info1;
}
public int getInfo2() {
return info2;
}
public void setInfo2(int info2) {
this.info2 = info2;
}
}
import java.util.HashMap;
public class Test {
public static void main(String[] args) {
final HashMap<String, DataStructure> map = new HashMap<String, DataStructure>();
map.put("apple", new DataStructure(5f, 1));
}
}

Categories