package org.openlca.app.cloud.ui.diff; import org.openlca.app.cloud.index.Diff; import org.openlca.app.cloud.index.DiffType; import org.openlca.app.cloud.ui.compare.json.viewer.JsonTreeViewer.Direction; import org.openlca.cloud.model.data.Dataset; import org.openlca.cloud.model.data.FetchRequestData; import org.openlca.core.model.Version; import com.google.gson.JsonObject; public class DiffResult { public final FetchRequestData remote; public final Diff local; private JsonObject mergedData; private boolean overwriteLocalChanges; private boolean overwriteRemoteChanges; public boolean ignoreRemote; public DiffResult(FetchRequestData remote) { this(remote, null); } public DiffResult(Diff local) { this(null, local); } public DiffResult(FetchRequestData remote, Diff local) { this.remote = remote; if (local != null) this.local = local.copy(); else this.local = null; } public Dataset getDataset() { if (remote != null) return toDataset(remote); return local.getDataset(); } private Dataset toDataset(FetchRequestData data) { Dataset dataset = new Dataset(); dataset.categoryType = data.categoryType; dataset.categoryRefId = data.categoryRefId; dataset.fullPath = data.fullPath; dataset.type = data.type; dataset.refId = data.refId; dataset.name = data.name; dataset.lastChange = data.lastChange; dataset.version = data.version; return dataset; } public DiffResponse getType() { // both null is not an option if (remote == null && local == null) return DiffResponse.NONE; if (remote == null) if (local.type == DiffType.NO_DIFF) return DiffResponse.NONE; // ignore remote means that remote was not even fetched, we have to // take this into account else if (local.type == DiffType.DELETED) if (ignoreRemote) return DiffResponse.DELETE_FROM_REMOTE; else return DiffResponse.NONE; else if (!ignoreRemote) return DiffResponse.ADD_TO_REMOTE; else if (local.type == DiffType.NEW) return DiffResponse.ADD_TO_REMOTE; else return DiffResponse.MODIFY_IN_REMOTE; if (local == null || local.type == null) if (remote.isDeleted()) return DiffResponse.NONE; else return DiffResponse.ADD_TO_LOCAL; // remote & local can not be null anymore return getTypeMixed(); } private DiffResponse getTypeMixed() { if (isEqual()) return DiffResponse.NONE; switch (local.type) { case NO_DIFF: if (remote.isDeleted()) return DiffResponse.DELETE_FROM_LOCAL; // TODO check if this always correct if (isNewer(local.getDataset().version, remote.version)) return DiffResponse.MODIFY_IN_REMOTE; return DiffResponse.MODIFY_IN_LOCAL; case DELETED: if (remote.isDeleted()) return DiffResponse.NONE; if (!remote.version.equals(local.dataset.version)) return DiffResponse.CONFLICT; return DiffResponse.DELETE_FROM_REMOTE; case CHANGED: if (!remote.version.equals(local.dataset.version)) return DiffResponse.CONFLICT; // TODO check if this always correct if (isNewer(local.getDataset().version, remote.version)) return DiffResponse.MODIFY_IN_REMOTE; return DiffResponse.MODIFY_IN_LOCAL; default: return DiffResponse.NONE; } } private boolean isNewer(String version1, String version2) { Version local = Version.fromString(version1); Version remote = Version.fromString(version2); if (local.getMajor() > remote.getMajor()) return true; if (local.getMajor() < remote.getMajor()) return false; if (local.getMinor() > remote.getMinor()) return true; if (local.getMinor() < remote.getMinor()) return false; if (local.getUpdate() > remote.getUpdate()) return true; return false; } private boolean isEqual() { boolean localDeleted = local.type == DiffType.DELETED; if (localDeleted && !remote.isDeleted()) return false; if (remote.isDeleted() && !localDeleted) return false; if (remote.type != local.getDataset().type) return false; if (!remote.refId.equals(local.getDataset().refId)) return false; if (!remote.version.equals(local.getDataset().version)) return false; if (remote.lastChange != local.getDataset().lastChange) return false; return true; } boolean isConflict() { return getType() == DiffResponse.CONFLICT; } public String getDisplayName() { if (local != null) return local.getDataset().name; if (remote != null) return remote.name; return null; } public JsonObject getMergedData() { return mergedData; } public boolean overwriteLocalChanges() { return overwriteLocalChanges; } public boolean overwriteRemoteChanges() { return overwriteRemoteChanges; } void setMergedData(JsonObject mergedData) { this.mergedData = mergedData; } void setOverwriteLocalChanges(boolean overwriteLocalChanges) { this.overwriteLocalChanges = overwriteLocalChanges; } void setOverwriteRemoteChanges(boolean overwriteRemoteChanges) { this.overwriteRemoteChanges = overwriteRemoteChanges; } void reset() { overwriteLocalChanges = false; overwriteRemoteChanges = false; mergedData = null; } @Override public String toString() { String l = "null"; if (local != null) { l = "modelType: " + local.getDataset().type; l += ", name: " + local.getDataset().name; l += ", type: " + local.type; } String r = "null"; if (remote != null) { l = "modelType: " + remote.type; l += ", name: " + remote.name; } String text = "local: {" + l + "}, remote: {" + r + "}, resultType: {" + getType() + "}"; return text; } public static enum DiffResponse { NONE(Direction.LEFT_TO_RIGHT), // avoid null pointer ADD_TO_LOCAL(Direction.RIGHT_TO_LEFT), DELETE_FROM_LOCAL(Direction.RIGHT_TO_LEFT), MODIFY_IN_REMOTE(Direction.LEFT_TO_RIGHT), MODIFY_IN_LOCAL(Direction.RIGHT_TO_LEFT), ADD_TO_REMOTE(Direction.LEFT_TO_RIGHT), DELETE_FROM_REMOTE(Direction.LEFT_TO_RIGHT), CONFLICT(Direction.RIGHT_TO_LEFT); // LEFT_TO_RIGHT means merging is not possible // RIGHT_TO_LEFT means merging is possible public Direction direction; private DiffResponse(Direction direction) { this.direction = direction; } public boolean isOneOf(DiffResponse... types) { if (types == null) return false; for (DiffResponse type : types) if (type == this) return true; return false; } } }