Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

214
LINES

< > BotCompany Repo | #1030885 // RealmCopy - successor of quickExport

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (16206L/105K).

sclass RealmCopy {
  O dest = mc(); // destination realm
  new IdentityHashMap seen;
  new HashMap<Class> classMap;
  new HashMap<Class, L<Field>> fieldsForClass;
  //IF1<S, Class> classFinder = toIF1(_defaultClassFinder());
  bool fullCopy; // descend into objects even when they have the same type
  bool nonTransientOnly; // skip transient fields?
  bool handleEnclosingInstancesProperly; // if false, set enclosing instance to null initially
  
  VStack.Computable copyComputation(O o) {
    ret new CopyObject(o);
  }
  
  O copy(O o) {
    ret evalInVStack(copyComputation(o));
  }
  
  noeq record CopyObject(O o) extends VStackComputableWithStep {
    void step(VStack stack) {
      // null and simple types
      
      if (o == null || o instanceof String || o instanceof Number) {
        ifdef RealmCopy_debug
          print("Simple object: " + o);
        endifdef
        ret with stack.ret(o);
      }
      
      // seen object

      O oo = seen.get(o);
      if (oo != null) stack.ret(oo);
      
      dispatchByType(stack, o);
    }
  }

  void dispatchByType(VStack stack, O o) {  
    if (o cast O[])
      ret with stack.replace(new CopyObjectArray(o));
      
    if (o cast Cl)
      if (!overrideCollectionOrMapCopy(o))
        ret with stack.replace(new CopyCollection(o));
      
    if (o cast Map)
      if (!overrideCollectionOrMapCopy(o))
        ret with stack.replace(new CopyMap(o));
      
    ret with stack.replace(new CopyObjectFieldByField(o));
  }
  
  noeq record CopyObjectArray(O[] o) extends VStackComputableWithStep {
    O[] out;
    int i;
    
    void step(VStack stack) {
      if (step == 0) {
        out = newObjectArrayOfSameType(o);
        seen.put(o, out);
        ++step;
      }
      
      if (stack.hasSubResult())
        out[i++] = stack.subResult();

      if (i >= o.length)
        ret with stack.ret(out);
        
      stack.call(new CopyObject(o[i]));
    }
  }

  noeq record CopyCollection(Cl o) extends VStackComputableWithStep {
    Cl out;
    Iterator it;
    
    void step(VStack stack) {
      if (step == 0) {
        out = similarEmptyCollection(o);
        seen.put(o, out);
        it = iterator(o);
        ++step;
      }
      
      if (stack.hasSubResult())
        out.add(stack.subResult());

      if (!it.hasNext())
        ret with stack.ret(out);
        
      stack.call(new CopyObject(it.next()));
    }
  }

  noeq record CopyMap(Map o) extends VStackComputableWithStep {
    Map out;
    Iterator<Map.Entry> it;
    Map.Entry entry;
    O copiedKey;
    
    void step(VStack stack) {
      if (step == 0) {
        out = similarEmptyMap(o);
        seen.put(o, out);
        it = iterator(o.entrySet());
        ++step;
      }
      
      if (stack.hasSubResult()) {
        if (step == 1) {
          // got the copied key
          copiedKey = stack.subResult();
          // now copy the value
          stack.call(new CopyObject(entry.getValue()));
          ret with ++step;
        } else {
          // got the copied value - can put into map
          out.put(copiedKey, stack.subResult());
          step = 1;
        }
      }

      if (!it.hasNext())
        ret with stack.ret(out);
        
      entry = it.next();
      stack.call(new CopyObject(entry.getKey()));
    }
  }

  noeq record CopyObjectFieldByField(O o) extends VStackComputableWithStep {
    S className;
    Class c, destClass;
    O out;
    O enclosing;
    L<Field> fields;
    Iterator<Field> itField;
    Field field;
    Field[] enclosingFields;
    
    void step(VStack stack) {
      if (step == 0) {
        c = o.getClass();
        
        destClass = classMap.get(c);
        if (destClass == null) {
          destClass = findDestClass(c);
          classMap.put(c, destClass);
        }

        if (destClass == c && !fullCopy)
          ret with stack.ret(o); // short cut unless deep copying
        
        // take care of enclosing instance
        
        enclosingFields = thisDollarOneFields(c);
        if (handleEnclosingInstancesProperly
          && nempty(enclosingFields))
          stack.push(new CopyObject(fieldGet(first(enclosingFields), o)));

        ret with step = 1;
      } else if (step == 1) {
        // create new object
        
        try {
          if (stack.hasSubResult())
            out = unlisted_gen(destClass, stack.subResult());
          else if (nempty(enclosingFields))
            out = unlisted_gen(destClass, (O) null);
          else
            out = unlisted_gen(destClass);
        } on fail {
          printVars_str(+c, +destClass, +enclosingFields);
        }
        seen.put(o, out);
          
        fields = getOrCreate(fieldsForClass, c, () -> 
          nonTransientOnly
            ? nonStaticNonTransientFieldObjects(o)
            : nonStaticFieldObjects(o));
        itField = iterator(fields);
        
        ret with ++step;
      }
      
      if (stack.hasSubResult()) {
        ifdef RealmCopy_debug
          printFunctionCall setOpt(out, field.getName(), stack.subResult());
        endifdef
        setOpt(out, field.getName(), stack.subResult());
      }
        
      if (!itField.hasNext())
        ret with stack.ret(out);
        
      field = itField.next();
      stack.push(new CopyObject(fieldGet(field, o));
    }
  }
  
  Class findDestClass(Class c) {
    Class destClass = null;
    S className = c.getName();
    className = loadableUtilsClassNameToMain(className);
    if (!isAnonymousClassName(className))
      destClass = getClass_vmName_withLoadableUtils(dest, className);
    ret or(destClass, c);
  }

  // set to true if you want to copy a map or collection field-by-field
  swappable bool overrideCollectionOrMapCopy(O o) { false; }
}

Author comment

Began life as a copy of #1002777

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, mqqgnosmbjvj, pyentgdyhuwx, vouqrxazstgt

No comments. add comment

Snippet ID: #1030885
Snippet name: RealmCopy - successor of quickExport
Eternal ID of this version: #1030885/32
Text MD5: 91fe90d3e2dfef86fbddfbfeb04ea547
Transpilation MD5: 61099b57bd3d8361b89b6913ca601a8c
Author: stefan
Category: eleu / nl
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-06-23 23:58:50
Source code size: 5955 bytes / 214 lines
Pitched / IR pitched: No / No
Views / Downloads: 258 / 561
Version history: 31 change(s)
Referenced in: [show references]