0

This is more of a design pattern question rather than realm , I am trying to add two different types of objects into realm.

complaint 
dealer

i have created a two separate function to add these two objects. My problem is i dont want to write separate code for inserting data in to realm for each object , i want to generalize like by defining a common class and then extending that class.

here is my current code

for dealers

public void insertDealersData(final Dealers dealers){

    final Realm realm = getExplicitRealm() ;
    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {

            int newDealersSize = dealers.getDealersLists().size();
            Dealers dbDealers=   realm.where(Dealers.class).findFirst();
            
            if(dbDealers!=null){
                for(int i =0;i<newDealersSize;i++){
                    DealersList temp=   realm.where(DealersList.class).equalTo("dealerid",
                            dealers.getDealersLists().get(i).getDealerid()).findFirst();
                    if(temp!=null){
                        dbDealers.getDealersLists().set(i,temp);
                    }else{
                        dbDealers.getDealersLists().add( dealers.getDealersLists().get(i));
                    }
                }
            }else{
                realm.copyToRealmOrUpdate(dealers);
                Log.i(TAG, "insertDealersData : dump");
            }
        }
    },new Realm.Transaction.Callback(){

        @Override
        public void onSuccess() {
            realm.close();
        }
        @Override
        public void onError(Exception e ) {
            realm.close();       
        }
    });
}

for complaint public void insertComplaintData(final Complaint complaint){

    final Realm realm = getExplicitRealm() ;

    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
        
            int newComplaintSize = complaint.getComplaintLists().size();
            Complaint dbComplaint=   realm.where(Complaint.class).findFirst();

            if(dbComplaint!=null){
                for(int i =0;i<newComplaintSize;i++){
                    ComplaintList temp=   realm.where(ComplaintList.class).equalTo("incidentid",
                            complaint.getComplaintLists().get(i).getIncidentid()).findFirst();
                    if(temp!=null){
                        dbComplaint.getComplaintLists().set(i,temp);
                        Log.i(TAG, "insertComplaintData : update existing");
                    }else{
                        dbComplaint.getComplaintLists().add(complaint.getComplaintLists().get(i));
                        Log.i(TAG, "insertComplaintData : add new ");
                    }
                }

            }else{
                realm.copyToRealmOrUpdate(complaint);
                Log.i(TAG, "insertComplaintData : dump");
            }
        }
    },new Realm.Transaction.Callback(){
        @Override
        public void onSuccess() {
            realm.close(); 
        }
        @Override
        public void onError(Exception e ) {
            realm.close();
        }
    });
}

as you can see there is no change in a code except the object type. so can any one suggest how can i generalize a code by reducing the redundancy.

Complaint model

public class Complaint extends RealmObject{

    private String status;    
    private String errorMessage;    
    private String count;
    @PrimaryKey    
    private String userId;    
    private String organizationId;
    @JsonField(name ="complaints" , typeConverter = ComplaintListConverter.class)
    private RealmList<ComplaintList> complaintLists;    
    
}
@JsonObject
public  class ComplaintList extends RealmObject implements ComplaintInterface {

    @PrimaryKey
    private String _id;    
    private String incidentid;    
    private String title;    
    private String casetypecode;
    private String customerid;
}

Dealer Model

public class Dealers extends RealmObject {
    private String status;
    private String errorMessage;
    private String count;
    @PrimaryKey
    private String userId;
    private String organizationId;
    @JsonField(name="dealers", typeConverter = DealersListConverter.class)
    private RealmList<DealersList> dealersLists;
}


public class DealersList extends RealmObject {


    @PrimaryKey
    private String _id;
    private String dealerid;
    private String accountnumber;
    private String name;
    private String alletec_type;
    private String telephone1;
    
}
Community
  • 1
  • 1
Hunt
  • 8,215
  • 28
  • 116
  • 256
  • The flow looks similar but you are calling different methods: `getDealersList()` vs. `getComplaintsList()`, so it is more than just the "Object type". If you only have two different types I would probably live with the code duplication as any attempt to generalize would make the code longer + more unreadable. – Christian Melchior Nov 17 '16 at 08:35
  • If you share the model class for `Complaint` and `Dealer`, then I will answer this question – EpicPandaForce Nov 17 '16 at 09:46
  • @EpicPandaForce i have updated my question with models – Hunt Nov 17 '16 at 12:26
  • @EpicPandaForce will you be able to suggest anything else i am planning to delete this question because i fond there is no relevance asking it – Hunt Nov 19 '16 at 06:12
  • ah, yeah, sorry I was too busy with work and then I forgot this one. Hold on – EpicPandaForce Nov 19 '16 at 07:16

1 Answers1

1
public interface Insertable<L extends RealmObject & InsertableList> {
    Class<L> getListClass();
    List<L> getList();
    String getListIdField();
}

public interface InsertableList {
    String getId();
}

public <T extends RealmObject & Insertable<L>, L extends RealmObject & InsertableList> void insertData(final T insertable) {
    final Realm realm = getExplicitRealm();
    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            int newListSize = insertable.getList().size();
            T dbInsertable = realm.where((Class<T>)insertable.getClass()).findFirst();

            if(dbInsertable != null) {
                for(int i = 0; i < newListSize; i++) {
                    L temp = realm.where(insertable.getListClass())
                            .equalTo(insertable.getListIdField(), insertable.getList().get(i).getId())
                            .findFirst();
                    if(temp != null) {
                        dbInsertable.getList().set(i, temp);
                    } else {
                        dbInsertable.getList().add(insertable.getList().get(i));
                    }
                }
            } else {
                realm.copyToRealmOrUpdate(insertable);
                Log.i(TAG, "insertDealersData : dump");
            }
        }
    }, new Realm.Transaction.Callback(){
        @Override
        public void onSuccess() {
            realm.close();
        }
        @Override
        public void onError(Exception e ) {
            realm.close();
        }
    });
}

public class Dealers extends RealmObject implements Insertable<DealersList> {
    private String status;
    private String errorMessage;
    private String count;
    @PrimaryKey
    private String userId;
    private String organizationId;
    @JsonField(name="dealers", typeConverter = DealersListConverter.class)
    private RealmList<DealersList> dealersLists;

    @Override
    public Class<DealersList> getListClass() {
        return DealersList.class;
    }

    @Override
    public List<DealersList> getList() {
        return dealersLists;
    }

    @Override
    public String getListIdField() {
        return "_id";
    }
}


public class DealersList extends RealmObject implements InsertableList {


    @PrimaryKey
    private String _id;
    private String dealerid;
    private String accountnumber;
    private String name;
    private String alletec_type;
    private String telephone1;

    @Override
    public String getId() {
        return _id;
    }
}
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • +1 Thanks for your time and input , i appreciate that. But m trying to learn how exactly you have derived this solution :) seems its a blend of java generics and design pattern. need a little time to grasp it :) I exactly want to learn all these if possible then can you share the road map to acquire this type of skills. I read many articles too on your blog and found pretty informative preciously design realm scheme effectively. – Hunt Nov 20 '16 at 19:05
  • @Hunt there isn't much design pattern to it, I just ripped out all things "too-specific" that I needed to share between the two classes into their own interface, and otherwise I just turned the whole thing into a template method `public void blah` based on that. I acquired these skills when I first put together **[this monster](https://github.com/Zhuinden/SpringBootDemoRestService/blob/master/DemoRestService/src/main/java/springpetserver/rest/methods/DefaultControllerMethods.java)** in backend code. – EpicPandaForce Nov 20 '16 at 19:26
  • Along with [this question / answer](http://stackoverflow.com/questions/28234960/java-generics-and-enum-loss-of-template-parameters). After that, it was quite easy to write answers like [this one](http://stackoverflow.com/questions/30616864/how-to-make-type-safety-with-generics) – EpicPandaForce Nov 20 '16 at 19:34
  • ThtsGrt ! thanks for all your help , i will try to create few examples based on your references. is that any direct medium to reach you via chat / email if you don't mind can you share it ? – Hunt Nov 20 '16 at 19:57
  • My name is `Zhuinden` on pretty much every other platform, I'm always around on **Skype** unless I'm in a meeting or something weird. – EpicPandaForce Nov 20 '16 at 20:02