Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
languagejava
firstline1
titleMergeBehaviour
linenumberstrue
package org.openmrs.module.fhir.api.merge;

/**
 * <h1>MergeBehaviour</h1>
 * Reflects merging behaviour for type T.
 * <p><b>Note:</b> use Object.class as a type T for more generic merging behaviour.</p>
 *
 * @see <a href="https://issues.openmrs.org/browse/SYNCT-243">SYNCT-243</a>
 * @since 1.15.0
 */
public interface MergeBehaviour<T> {
	/**
	 * <p>Resolves merge conflicts for entities' synchronization.</p>
	 *
	 * @param local represents local version of an entity
	 * @param foreign represents foreign version of an entity
	 * @param clazz represents specific class which extends T
	 * @return returns a result which depends on implemented merging behaviour
	 */
	MergeResult<T> resolveDiff(Class<? extends T> clazz, T local, T foreign);
}

MergeResult is an abstract object and it is extended by either MergeSuccess or MergeConflict. The MergeConflict represents a situation when MergeBehaviour couldn't merge objects automatically. The MergeSuccess represents situations when:
- local object overrides another,
- foreign object overrides another,
- local and foreign objects are merged,
- we do not have to change any objects.

An example implementation might look like this:

Code Block
languagejava
firstline1
titleAn example implementation
linenumberstrue
package org.openmrs.module.fhir.api.merge;

import org.openmrs.BaseOpenmrsData;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URI;

public class TestMergeBehaviour implements MergeBehaviour<BaseOpenmrsData> {

   @Override
   public MergeResult<BaseOpenmrsData> resolveDiff(Class<? extends BaseOpenmrsData> clazz,
                                       BaseOpenmrsData local, BaseOpenmrsData foreign) {
      MergeResult<BaseOpenmrsData> result;
      BaseOpenmrsData merged;

      if (local.getDateChanged().after(foreign.getDateChanged())) {
         merged = deepClone(foreign);
         result = new MergeSuccess<>(clazz, local, foreign, URI.create("www.example.com/api/object"), merged,
               true, false);
      } else {
         result = new MergeConflict<>(clazz, local, foreign);
      }

      return result;
   }

   private BaseOpenmrsData deepClone(BaseOpenmrsData org) {
      BaseOpenmrsData clone = null;
      try {
         ByteArrayOutputStream baOUT = new ByteArrayOutputStream();
         ObjectOutputStream oOUT = new ObjectOutputStream(baOUT);
         oOUT.writeObject(org);

         ByteArrayInputStream baIN = new ByteArrayInputStream(baOUT.toByteArray());
         ObjectInputStream oIN = new ObjectInputStream(baIN);
         clone = (BaseOpenmrsData) oIN.readObject();
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
      return clone;
   }
}

...