private void setChanges(
     Instance dest,
     Instance src,
     Function<Instance, Instance> oldFunction,
     long[] changes,
     boolean isInput) {
   AModelType type = InvocationContext.get().getTypeManager().getByPrefix(dest._type());
   List<AIField> fields = type.getAllFields();
   for (AIField f : fields) {
     if (f.getName().equals("id")) {
       dest._setId(src.getId());
       continue;
     }
     // If this field changed
     int index = dest._getPropertyIndex(f.getName());
     if (InstanceImpl._hasBit(changes, index)) {
       if (f.isChild()) {
         setChildValue(dest, src, f, oldFunction, isInput);
       } else {
         Property<?> property = src._get(f.getName());
         if (property == null) {
           continue;
         }
         dest._set(f.getName(), property.getValue());
       }
       dest._markChange(index, null, null);
     }
   }
 }
  private Instance cloneSingleChildValue(
      Instance value,
      Instance dest,
      AIField field,
      Function<Instance, Instance> oldFunction,
      boolean isInput) {
    Instance srcValue = (Instance) value;
    if (!srcValue.isEmbedded()) {
      return getChanges(srcValue, oldFunction, isInput);
    }

    Instance destValue = (Instance) dest._get(field.getName()).getValue();
    if (destValue == null) {
      value = srcValue.cloneInstance();
    } else {
      value = prepareChanges(srcValue, destValue, oldFunction, isInput);
    }
    return value;
  }
  private void setChildValue(
      Instance dest,
      Instance src,
      AIField field,
      Function<Instance, Instance> oldFunction,
      boolean isInput) {
    Object value = src._get(field.getName()).getValue();
    if (field.getType().isCollection()) {
      @SuppressWarnings("unchecked")
      List<Instance> coll = (List<Instance>) value;
      List<Instance> result = new ArrayList<Instance>();
      coll.forEach(i -> result.add(getChanges(i, oldFunction, isInput)));
      value = result;
    } else {
      // Simply clone value with changed properties
      if (value != null) {
        value = cloneSingleChildValue((Instance) value, dest, field, oldFunction, isInput);
      }
    }

    dest._set(field.getName(), value);
  }