I have two classes :
UniteStratigraphique.java :
#DatabaseTable(tableName = "unitestratigraphique")
public class UniteStratigraphique {
public final static String ID_FIELD_NAME = "id";
#DatabaseField(generatedId = true, columnName = ID_FIELD_NAME)
private int id;
// CAMPAGNES
#DatabaseField(foreign = true, foreignAutoRefresh = true)
private Campagne campagne;
#ForeignCollectionField
private ForeignCollection<Campagne> listeCampagnes;
public UniteStratigraphique() {}
public Campagne getCampagne() {
return campagne;
}
public void setCampagne(Campagne campagne) {
this.campagne = campagne;
}
public ArrayList<Campagne> getListeCampagnes() {
ArrayList<Campagne> campagnesArray = new ArrayList<Campagne>();
for (Campagne campagne : listeCampagnes) {
campagnesArray.add(campagne);
}
return campagnesArray;
}
public ForeignCollection<Campagne> getListeCampagnesForeign() {
return listeCampagnes;
}
public void setListeCampagnes(ForeignCollection<Campagne> listeCampagnes) {
this.listeCampagnes = listeCampagnes;
}
}
Campagne.java :
#DatabaseTable(tableName = "campagne")
public class Campagne {
#DatabaseField(generatedId = true)
private int id;
// UNITE STRATIGRAPHIQUE
#ForeignCollectionField
private ForeignCollection<UniteStratigraphique> listeUniteStratigraphique;
#DatabaseField(foreign = true, foreignAutoRefresh = true)
private UniteStratigraphique uniteStratigraphique;
public Campagne() {}
public ArrayList<UniteStratigraphique> getListeUniteStratigraphique() {
ArrayList<UniteStratigraphique> usArray = new ArrayList<UniteStratigraphique>();
for (UniteStratigraphique us : listeUniteStratigraphique){
usArray.add(us);
}
return usArray;
}
public ForeignCollection<UniteStratigraphique> getListeUniteStratigraphiqueForeign() {
return listeUniteStratigraphique;
}
public void setListeUniteStratigraphique(
ForeignCollection<UniteStratigraphique> listeUniteStratigraphique) {
this.listeUniteStratigraphique = listeUniteStratigraphique;
}
public int getSizeListeUniteStratigraphique() {
return listeUniteStratigraphique.size();
}
public UniteStratigraphique getUniteStratigraphique() {
return uniteStratigraphique;
}
public void setUniteStratigraphique(UniteStratigraphique uniteStratigraphique) {
this.uniteStratigraphique = uniteStratigraphique;
}
}
As you can see, these are Many-To-Many linked (0...n---0...n, with ORMLite annotations).
Now, my workflow is :
I create multiple "UniteStratigraphique" classes and I store them into my database (this works fine).
=> So I have n * "UniteStratigraphique" stored.
After that what I want is to create a "Campagne" class wich will contain multiple "UniteStratigraphique" classes.
=> So I want to set this field from "Campagne.java" :
#ForeignCollectionField
private ForeignCollection<UniteStratigraphique> listeUniteStratigraphique;
with the n * "UniteStratigraphique" elements I just stored before.
I tried to do this with this DAO method but it only duplicate the "UniteStratigraphique" classes into my db and no link is made..
public void addUsToCampagne(Campagne campagne,
ArrayList<UniteStratigraphique> usArray) {
ForeignCollection<UniteStratigraphique> usForeign = campagne
.getListeUniteStratigraphiqueForeign();
if (usForeign == null) {
try {
usForeign = getHelper().getCampagneDao()
.getEmptyForeignCollection("listeUniteStratigraphique");
for (UniteStratigraphique us : usArray) {
usForeign.add(us);
}
} catch (SQLException e) {
e.printStackTrace();
}
}else{
for (UniteStratigraphique us : usArray) {
usForeign.add(us);
}
}
}
And in my Activity I'm doing this :
db.addCampagne(campagne);
if( myUniteStratigraphiqueArray.size() > 0){
db.addUsToCampagne(campagne, myUniteStratigraphiqueArray);
}
Many to Many relations are non automatic with ORMLite, the only way to achieve it is to make a 3rd Table only for link beetween these 2 classes..
This link refers to this problem : What is the best way to implement many-to-many relationships using ORMLite?
And the example here : https://github.com/j256/ormlite-jdbc/tree/master/src/test/java/com/j256/ormlite/examples/manytomany
Hope it helped.
Related
I am trying to set the property of an object I've created in Android Studio using Kotlin. I am using a for loop to make a new object each time and add it to an array. When I initialize my object and try to set the topId it says "Val cannot reassigned" even though I'm declaring it a var.
for (i in 1..5) {
var topRanNum = generateRandomNum(topSize)
var top = currentSeasonTops[topRanNum]
var topLoopCounter = 0
var topId = top.id
var newOutfit: Outfit = Outfit()
if(top.wornCount < 5 ) {
newOutfit.topId = top.id
}
}
Outfit Class
public Outfit() {}
public Outfit(Long topId, Long bottomId, String topPhotoPath, String bottomPhotoPath) {
this.topId = topId;
this.bottomId = bottomId;
this.topPhotoPath = topPhotoPath;
this.bottomPhotoPath = bottomPhotoPath;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTopPhotoPath() {
return topPhotoPath;
}
public String getBottomPhotoPath() {
return bottomPhotoPath;
}
public Long getTopId() {
return topId;
}
public Long getBottomId() {
return bottomId;
}
This happens because you need to declare an accessible setter from outside in Java for topId or make the variable accessible from outside.
E.g.
public void setTopId(Long topId) {
this.topId = topId;
}
I'm willing to try the new Room Library from Android and I met the below error:
Error:(19, 29) error: Cannot figure out how to save this field into
database. You can consider adding a type converter for it.
This error refers to the following class member:
private HashSet<String> fruits;
I have the following class:
#Entity(tableName = "SchoolLunches")
public class SchoolLunch {
#PrimaryKey(autoGenerate = true)
private int lunchId;
private boolean isFresh;
private boolean containsMeat;
private HashSet<String> fruits;
public int getLunchId() {
return lunchId;
}
public void setLunchId(int lunchId) {
this.lunchId = lunchId;
}
public boolean isFresh() {
return isFresh;
}
public void setFresh(boolean fresh) {
isFresh = fresh;
}
public boolean isContainsMeat() {
return containsMeat;
}
public void setContainsMeat(boolean containsMeat) {
this.containsMeat = containsMeat;
}
public HashSet<String> getFruits() {
return fruits;
}
public void setFruits(HashSet<String> fruits) {
this.fruits = fruits;
}
Also, there is a relative DAO class:
#Dao
public interface SchoolLunchDAO {
#Query("SELECT * FROM SchoolLunches")
List<SchoolLunch> getAll();
#Insert
void insertAll(SchoolLunch... schoolLunches);
#Query("DELETE FROM SchoolLunches")
void deleteAll();
}
Since I'm trying to be a very good developer, I wrote a unit test as follows:
#Test
public void singleEntityTest() {
HashSet<String> fruitSet = new HashSet<>();
fruitSet.add("Apple");
fruitSet.add("Orange");
SchoolLunch schoolLunch = new SchoolLunch();
schoolLunch.setContainsMeat(false);
schoolLunch.setFresh(true);
schoolLunch.setFruits(fruitSet);
schoolLunchDAO.insertAll(schoolLunch);
List<SchoolLunch> schoolLunches = schoolLunchDAO.getAll();
assertEquals(schoolLunches.size(), 1);
SchoolLunch extractedSchoolLunch = schoolLunches.get(0);
assertEquals(false, extractedSchoolLunch.isContainsMeat());
assertEquals(true, extractedSchoolLunch.isFresh());
assertEquals(2, extractedSchoolLunch.getFruits().size());
}
What should I do here?
What should I do here?
You could create a type converter, as suggested by the error message. Room does not know how to persist a HashSet<String>, or a Restaurant, or other arbitrary objects.
Step #1: Decide what basic type you want to convert your HashSet<String> into (e.g., a String)
Step #2: Write a class with public static type conversion methods, annotated with #TypeConverter, to do the conversion (e.g., HashSet<String> to String, String to HashSet<String>), in some safe fashion (e.g., use Gson, formatting your String as JSON)
Step #3: Add a #TypeConverters annotation to your RoomDatabase or other scope, to teach Room about your #TypeConverter methods
For example, here are a pair of type converter methods for converting a Set<String> to/from a regular String, using JSON as the format of the String.
#TypeConverter
public static String fromStringSet(Set<String> strings) {
if (strings==null) {
return(null);
}
StringWriter result=new StringWriter();
JsonWriter json=new JsonWriter(result);
try {
json.beginArray();
for (String s : strings) {
json.value(s);
}
json.endArray();
json.close();
}
catch (IOException e) {
Log.e(TAG, "Exception creating JSON", e);
}
return(result.toString());
}
#TypeConverter
public static Set<String> toStringSet(String strings) {
if (strings==null) {
return(null);
}
StringReader reader=new StringReader(strings);
JsonReader json=new JsonReader(reader);
HashSet<String> result=new HashSet<>();
try {
json.beginArray();
while (json.hasNext()) {
result.add(json.nextString());
}
json.endArray();
}
catch (IOException e) {
Log.e(TAG, "Exception parsing JSON", e);
}
return(result);
}
I created the following class and now it works. Thank you, CommonsWare!
public class Converters {
private static final String SEPARATOR = ",";
#TypeConverter
public static HashSet<String> fromString(String valueAsString) {
HashSet<String> hashSet = new HashSet<>();
if (valueAsString != null && !valueAsString.isEmpty()) {
String[] values = valueAsString.split(SEPARATOR);
hashSet.addAll(Arrays.asList(values));
}
return hashSet;
}
#TypeConverter
public static String hashSetToString(HashSet<String> hashSet) {
StringBuilder stringBuilder = new StringBuilder();
for (String currentElement : hashSet) {
stringBuilder.append(currentElement);
stringBuilder.append(SEPARATOR);
}
return stringBuilder.toString();
}
}
I did the search about "cascade delete" operation for the Realm. Sadly that feature has not been implemented yet. I made my own implementation of it and shared it here.
How to make generic code for the Realm "cascade delete" operation ?
1) Copy this code to your project
import android.util.Log;
import java.lang.reflect.Method;
import io.realm.RealmList;
import io.realm.RealmObject;
import com.company.project.models.IRealmCascade;
/**
*/
public class RealmUtils
{
public static void deleteCascade( RealmObject dataObject )
{
if (dataObject == null)
{
return;
}
if( IRealmCascade.class.isAssignableFrom( dataObject.getClass() ) )
{
for( Method method : dataObject.getClass().getSuperclass().getDeclaredMethods() )
{
try {
//Ignore generated methods
if( (method.getName().contains("realmGet$")) || (method.getName().contains("access$super")) )
{
continue;
}
Class<?> resultType = method.getReturnType();
//Ignore non object members
if (resultType.isPrimitive()) {
continue;
}
if (RealmObject.class.isAssignableFrom(resultType)) {
//Delete Realm object
try {
RealmObject childObject = (RealmObject) method.invoke(dataObject);
RealmUtils.deleteCascade(childObject);
} catch (Exception ex) {
Log.e("REALM", "CASCADE DELETE OBJECT: " + ex.toString());
}
} else if (RealmList.class.isAssignableFrom(resultType)) {
//Delete RealmList items
try {
RealmList childList = (RealmList) method.invoke(dataObject);
while( childList.iterator().hasNext() )
{
RealmObject listItem = (RealmObject)childList.iterator().next();
RealmUtils.deleteCascade(listItem);
}
} catch (Exception ex) {
Log.e("REALM", "CASCADE DELETE LIST: " + ex.toString());
}
}
}
catch (Exception ex)
{
Log.e("REALM", "CASCADE DELETE ITERATION: " + ex.toString());
}
}
}
dataObject.deleteFromRealm();
}
}
2) Add interface to your project. If your Realm object implement this interface all child objects will be deleted after call deleteCascade. If interface not implemented this function delete Realm object but don't delete child objects.
public interface IRealmCascade {
}
3) Declare your Realm object. Example below.
public class NodeModel extends RealmObject implements IRITSerializable, IRealmCascade {
#PrimaryKey
#SerializedName("id") private String objId;
#SerializedName("parentId") private String parentId;
#SerializedName("contentType") private String nodeType;
#Required
#SerializedName("name") private String name;
#SerializedName("settings") private RealmList<ValueTypeModel> columns;
public String getObjId() {
return objId;
}
public void setObjId(String objId) {
this.objId = objId;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getNodeType() {
return nodeType;
}
public void setNodeType(String nodeType) {
this.nodeType = nodeType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmList<ValueTypeModel> getColumns() {
return columns;
}
public void setColumns(RealmList<ValueTypeModel> columns) {
this.columns = columns;
}
}
4) You need to call RealmUtils.deleteCascade(realmObject); instead realmObject.removeFromRealm();
Example below
Update data in local database
for( NodeModel nodeItem: incomingData.getNodesList() )
{
RealmResults<NodeModel> results = bgRealm.where(NodeModel.class).equalTo("objId", nodeItem.getObjId()).findAll();
if (results.size() > 0)
{
RealmUtils.deleteCascade(results.first());
}
bgRealm.copyToRealm(nodeItem);
}
Enjoy your clean DB! :)
I have a variation on this implementation that others might find useful.
In the original implementation: RealmObject sub-classes that are to be traversable "implement IRealmCascade". Any RealmObjects that do not implement the interface will be treated as leaf nodes (the object will be deleted, but its children will not).
In my implementation: Any RealmObject/RealmList is traversable (they don't need to implement any interface). If the class has a member that is NOT to be traversed, the getter for that member is annotated with "#SkipDelete".
/**
* Traverse the tree of RealmObjects, deleting the RealmObject/RealmList children
* and the root RealmObject.
* <br><br>
* This method uses reflection to get the rootObject's "getter" methods. The
* getter methods are called to get the RealmObject/RealmList children, and
* those objects are deleted from the Realm.
* <br><br>
* If any of the getter methods return a RealmObject/RealmList that should NOT be
* deleted, those getter methods should be annotated with {#link SkipDelete}.
*
* #param rootObject The root of the RealmObject tree
*/
public static void delete(RealmObject rootObject) {
if (rootObject == null) {
return;
}
for (Method method : rootObject.getClass().getSuperclass().getDeclaredMethods()) {
try {
// Ignore non-getter methods
boolean noParams = method.getParameterTypes().length == 0;
if (!(method.getName().startsWith("get")) || !noParams) {
continue;
}
// Ignore primitive members
Class<?> resultType = method.getReturnType();
if (resultType.isPrimitive()) {
continue;
}
// Ignore methods annotated with SkipDelete
if (method.isAnnotationPresent(SkipDelete.class)) {
continue;
}
if (RealmObject.class.isAssignableFrom(resultType)) {
// getter method returns a RealmObject, delete it
try {
RealmObject childObject = (RealmObject) method.invoke(rootObject);
delete(childObject, true);
} catch (Exception ex) {
Log.e("delete: RealmObject " + resultType.getSimpleName(), ex);
}
} else if (RealmList.class.isAssignableFrom(resultType)) {
// getter method returns a RealmList, delete the objects in the list
try {
RealmList childList = (RealmList) method.invoke(rootObject);
while (childList.iterator().hasNext()) {
RealmObject listItem = (RealmObject)childList.iterator().next();
delete(listItem, true);
}
} catch (Exception ex) {
Log.e("delete: RealmList " + resultType.getSimpleName(), ex);
}
}
}
catch (Exception ex) {
Log.e("delete: ", ex);
}
}
rootObject.deleteFromRealm();
}
/**
* This annotation is used to mark a "getter" method that should be skipped
* over on the cascading delete traversal of the RealmObject/RealmList tree.
*/
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface SkipDelete {
}
In your RealmObject
public class Design extends RealmObject {
private MyRealmObject1 obj1; // do CascadeDelete on this member
private MyRealmObject2 obj2; // don't do CascadeDelete on this member
....
public MyRealmObject1 getObj1() {
return obj1;
}
#CascadeDelete.SkipDelete // don't do CascadeDelete of obj2
public MyRealmObject2 getObj2() {
return obj2;
}
}
I got tired using this library, this is my first time using it and made a lot of success ways, but i'm a bit confused in getting the following Json :
{
"Guides":
{
"English": {"ArabicSony":"Test1","ArabicNexus":"Test2","ArabicSamsung":"Test3","ArabicHTC":"Test4"}
,"Arabic": {"EnglishSony":"Test1","EnglishNexus":"Test2","EnglishSamsung":"Test3","EnglishHTC":"Test4"}
}
}
Googled and saw a lot of guides and answered, and made my List like this :
public class PostItem {
List<PostItemArabic> Arabic;
List<PostItemEnglish> English;
}
class PostItemArabic{
private String ArabicSony;
private String ArabicNexus;
private String ArabicSamsung;
private String ArabicHTC;
public String getArabicSony() {
return ArabicSony;
}
public void setArabicSony(String arabicSony) {
ArabicSony = arabicSony;
}
public String getArabicNexus() {
return ArabicNexus;
}
public void setArabicNexus(String arabicNexus) {
ArabicNexus = arabicNexus;
}
public String getArabicSamsung() {
return ArabicSamsung;
}
public void setArabicSamsung(String arabicSamsung) {
ArabicSamsung = arabicSamsung;
}
public String getArabicHTC() {
return ArabicHTC;
}
public void setArabicHTC(String arabicHTC) {
ArabicHTC = arabicHTC;
}
}
class PostItemEnglish{
private String EnglishSony;
private String EnglishNexus;
private String EnglishSamsung;
private String EnglishHTC;
public String getEnglishSony() {
return EnglishSony;
}
public void setEnglishSony(String englishSony) {
EnglishSony = englishSony;
}
public String getEnglishNexus() {
return EnglishNexus;
}
public void setEnglishNexus(String englishNexus) {
EnglishNexus = englishNexus;
}
public String getEnglishSamsung() {
return EnglishSamsung;
}
public void setEnglishSamsung(String englishSamsung) {
EnglishSamsung = englishSamsung;
}
public String getEnglishHTC() {
return EnglishHTC;
}
public void setEnglishHTC(String englishHTC) {
EnglishHTC = englishHTC;
}
}
My Model :
private class Model {
private List<PostItem> Guides;
public List<PostItem> getGuides() {
return Guides;
}
public void setGuides(List<PostItem> roms_center) {
this.Guides = roms_center;
}
}
And printing the result like this :
List<PostItem> Guides = response.body().getGuides();
for(int i = 0 ; i < Guides.size() ; i ++ ) {
for (int b = 0; b < Guides.get(i).English.size() ; b++){
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishHTC());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishNexus());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishSamsung());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishSony());
}
for (int b = 0; b < Guides.get(i).Arabic.size() ; b++){
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicHTC());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicNexus());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicSamsung());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicSony());
}
}
My work isn't correct, and getting a lot of errors,
Here's the last error i got :
`Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 3 column 18 path $.Guides
What's the way to make it correct ? `
Based on your models when you try to get the guides list your telling retrofit to populate an array. Retrofit is then getting the data and finding that it is a single object and not array. So you need to update your model to reflect the data returned. For example:
class PostItem {
List<Language> mLanguages;
}
class Language{
String mLanguageTitle; //for example english
List<String> mData; //for this is your list of data
}
Then in your activity instead of getting guides you would get just a post item for example:
response.body().getPostItem();
Hope it helps !
First of all, you can use the retrofit Gson library.
You can handle this in two ways:
Option 1: reformat your languages in your json to be an array like Doug says.
{
"Guides":
[
{"Lang":"English","ArabicSony":"Test1","ArabicNexus":"Test2","ArabicSamsung":"Test3","ArabicHTC":"Test4"}
, {"Lang":"Arabic","EnglishSony":"Test1","EnglishNexus":"Test2","EnglishSamsung":"Test3","EnglishHTC":"Test4"}
]
}
Then you will need to redesign your class to reflect this structure.
Like Doug sayd:
class PostItem {
List<Language> mLanguages;
}
Option 2: Create a custom json desirializer in your class. this will take the Json and break it down into whatever structure you want it to be.
public class PostItem implements JsonDeserializer
#Override
public MyDesirializer deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jarabic = (JsonObject) json.get("Arabic");
//whatever manipulations you want to do (fill with your own code)
PostItem item = new PostItem();
item.arabic = jarabic;
...
...
return item;
}
I am generating protobuf class using Squareup Wire protobuf libary
here is my proto file
syntax = "proto2";
package squareup.dinosaurs;
option java_package = "com.squareup.dinosaurs";
message Dinosaur {
// Common name of this dinosaur, like "Stegosaurus".
optional string name = 1;
// URLs with images of this dinosaur.
repeated string picture_urls = 2;
}
and here is my auto generated code
// Code generated by Wire protocol buffer compiler, do not edit.
// Source file: dinosaur/dinosaur.proto at 8:1
package com.squareup.dinosaurs;
import com.squareup.wire.FieldEncoding;
import com.squareup.wire.Message;
import com.squareup.wire.ProtoAdapter;
import com.squareup.wire.ProtoReader;
import com.squareup.wire.ProtoWriter;
import java.io.IOException;
import java.lang.Object;
import java.lang.Override;
import java.lang.String;
import java.lang.StringBuilder;
import java.util.List;
import okio.ByteString;
public final class Dinosaur extends Message<Dinosaur, Dinosaur.Builder> {
public static final ProtoAdapter<Dinosaur> ADAPTER = new ProtoAdapter<Dinosaur>(FieldEncoding.LENGTH_DELIMITED, Dinosaur.class) {
#Override
public int encodedSize(Dinosaur value) {
return (value.name != null ? ProtoAdapter.STRING.encodedSizeWithTag(1, value.name) : 0)
+ ProtoAdapter.STRING.asRepeated().encodedSizeWithTag(2, value.picture_urls)
+ value.unknownFields().size();
}
#Override
public void encode(ProtoWriter writer, Dinosaur value) throws IOException {
if (value.name != null) ProtoAdapter.STRING.encodeWithTag(writer, 1, value.name);
if (value.picture_urls != null) ProtoAdapter.STRING.asRepeated().encodeWithTag(writer, 2, value.picture_urls);
writer.writeBytes(value.unknownFields());
}
#Override
public Dinosaur decode(ProtoReader reader) throws IOException {
Builder builder = new Builder();
long token = reader.beginMessage();
for (int tag; (tag = reader.nextTag()) != -1;) {
switch (tag) {
case 1: builder.name(ProtoAdapter.STRING.decode(reader)); break;
case 2: builder.picture_urls.add(ProtoAdapter.STRING.decode(reader)); break;
default: {
FieldEncoding fieldEncoding = reader.peekFieldEncoding();
Object value = fieldEncoding.rawProtoAdapter().decode(reader);
builder.addUnknownField(tag, fieldEncoding, value);
}
}
}
reader.endMessage(token);
return builder.build();
}
#Override
public Dinosaur redact(Dinosaur value) {
Builder builder = value.newBuilder();
builder.clearUnknownFields();
return builder.build();
}
};
private static final long serialVersionUID = 0L;
public static final String DEFAULT_NAME = "";
/**
* Common name of this dinosaur, like "Stegosaurus".
*/
public final String name;
/**
* URLs with images of this dinosaur.
*/
public final List<String> picture_urls;
public Dinosaur(String name, List<String> picture_urls) {
this(name, picture_urls, ByteString.EMPTY);
}
public Dinosaur(String name, List<String> picture_urls, ByteString unknownFields) {
super(unknownFields);
this.name = name;
this.picture_urls = immutableCopyOf("picture_urls", picture_urls);
}
#Override
public Builder newBuilder() {
Builder builder = new Builder();
builder.name = name;
builder.picture_urls = copyOf("picture_urls", picture_urls);
builder.addUnknownFields(unknownFields());
return builder;
}
#Override
public boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof Dinosaur)) return false;
Dinosaur o = (Dinosaur) other;
return equals(unknownFields(), o.unknownFields())
&& equals(name, o.name)
&& equals(picture_urls, o.picture_urls);
}
#Override
public int hashCode() {
int result = super.hashCode;
if (result == 0) {
result = unknownFields().hashCode();
result = result * 37 + (name != null ? name.hashCode() : 0);
result = result * 37 + (picture_urls != null ? picture_urls.hashCode() : 1);
super.hashCode = result;
}
return result;
}
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (name != null) builder.append(", name=").append(name);
if (picture_urls != null) builder.append(", picture_urls=").append(picture_urls);
return builder.replace(0, 2, "Dinosaur{").append('}').toString();
}
public static final class Builder extends com.squareup.wire.Message.Builder<Dinosaur, Builder> {
public String name;
public List<String> picture_urls;
public Builder() {
picture_urls = newMutableList();
}
/**
* Common name of this dinosaur, like "Stegosaurus".
*/
public Builder name(String name) {
this.name = name;
return this;
}
/**
* URLs with images of this dinosaur.
*/
public Builder picture_urls(List<String> picture_urls) {
checkElementsNotNull(picture_urls);
this.picture_urls = picture_urls;
return this;
}
#Override
public Dinosaur build() {
return new Dinosaur(name, picture_urls, buildUnknownFields());
}
}
}
now the issue is i want to directly store the value of Dinosaur into the database using Realm in android. i want Dinosaur class to act as a model.
but the problem is Dinosaur class is declared as final so i cant even derive it.
So is there any design pattern or way that exists to reuse or convert Dinosaur class into model?
You cannot use the Wire Dinosaur with Realm as Wire also require you to extend the Message class, while Realm require you to extend RealmObject.
If you want to combine the two you can create a RealmDinosaur class that accept the wire Dinosaur. Something like this:
public class RealmDinosaur extends RealmObject {
private String name;
private RealmList<RealmString> pictureUrls;
public RealmDinosaur(Dinosaur dino) {
// Fill Realm fields. Note that Realm doesn't support Lists
// with primitive strings yet.
// See https://realm.io/docs/java/latest/#primitive-lists
}
// getter and setters
}
realm.beginTransaction();
realm.copyToRealm(new RealmDinosaur(wireDinosaur));
realm.commitTransaction();
Short answer: no.
For me, this is one of several show-stoppers for wide adoption of Realm.
The developers of Realm don't seem to have considered real-world use-cases such as yours, where your data objects already inherit from something.
They also seem don't seem to get Android's threading requirements.
If you really want to use Realm, I think that you'll have to create another set of objects, likely in another package, that you only use with Realm. Then, you'd have to copy your data from your 'real' objects into the Realm objects.
Personally, for anything non-trivial, I'd either use the built-in SQLite, or find another database that better meets your needs.