package org.openlca.app.cloud.ui.diff;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.graphics.Image;
import org.openlca.app.cloud.JsonLoader;
import org.openlca.app.cloud.ui.compare.ModelLabelProvider;
import org.openlca.app.cloud.ui.compare.ModelNodeBuilder;
import org.openlca.app.cloud.ui.compare.ModelUtil;
import org.openlca.app.cloud.ui.compare.json.DiffEditorDialog;
import org.openlca.app.cloud.ui.compare.json.JsonNode;
import org.openlca.app.cloud.ui.compare.json.JsonUtil;
import org.openlca.app.cloud.ui.compare.json.viewer.JsonTreeViewer.Direction;
import org.openlca.app.rcp.images.Images;
import org.openlca.cloud.model.data.Dataset;
import com.google.gson.JsonObject;
class CompareHelper {
private JsonLoader loader;
private Map<String, JsonNode> nodes = new HashMap<>();
CompareHelper(JsonLoader loader) {
this.loader = loader;
}
boolean openDiffEditor(DiffNode node, boolean viewMode) {
if (node == null || node.isModelTypeNode())
return false;
DiffData data = new DiffData();
data.result = (DiffResult) node.content;
DiffEditorDialog dialog = prepareDialog(data, viewMode);
dialog.setTitle(getTitle(node));
dialog.setLogo(getLogo(node));
int code = dialog.open();
if (code == IDialogConstants.CANCEL_ID)
return false;
if (!data.result.isConflict())
return false;
boolean localDiffersFromRemote = dialog.leftDiffersFromRight();
boolean keepLocalModel = code == DiffEditorDialog.KEEP_LOCAL_MODEL;
updateResult(data, localDiffersFromRemote, keepLocalModel);
return true;
}
void reset() {
nodes.clear();
}
private DiffEditorDialog prepareDialog(DiffData data, boolean viewMode) {
data.node = nodes.get(toKey(data.result.getDataset()));
if (data.node == null)
createNode(data);
else {
data.local = JsonUtil.toJsonObject(data.node.leftElement);
data.remote = JsonUtil.toJsonObject(data.node.rightElement);
}
if (viewMode || !data.result.isConflict())
return DiffEditorDialog.forViewing(data.node, new ModelLabelProvider(),
ModelUtil.getDependencyResolver(), data.result.getType().direction);
DiffEditorDialog dialog = DiffEditorDialog.forEditing(data.node, new ModelLabelProvider(),
ModelUtil.getDependencyResolver(), data.result.getType().direction);
return dialog;
}
private void createNode(DiffData data) {
if (data.result.local != null)
data.local = loader.getLocalJson(data.result.local.getDataset());
if (data.result.remote != null && !data.result.remote.isDeleted())
data.remote = loader.getRemoteJson(data.result.remote);
else if (data.result.getType().direction == Direction.LEFT_TO_RIGHT)
data.remote = loader.getRemoteJson(data.result.getDataset());
data.node = new ModelNodeBuilder().build(data.local, data.remote);
nodes.put(toKey(data.result.getDataset()), data.node);
}
private void updateResult(DiffData data, boolean localDiffersFromRemote,
boolean keepLocalModel) {
data.result.reset();
if (overwriteRemoteChanges(data, localDiffersFromRemote, keepLocalModel))
data.result.setOverwriteRemoteChanges(true);
else
data.result.setOverwriteLocalChanges(true);
data.result.setMergedData(getMergedData(data, keepLocalModel));
}
private boolean overwriteRemoteChanges(DiffData data,
boolean localDiffersFromRemote, boolean keepLocalModel) {
if (data.hasLocal() && data.hasRemote() && localDiffersFromRemote)
return true;
return keepLocalModel;
}
private JsonObject getMergedData(DiffData data, boolean keepLocalModel) {
if (data.hasLocal() && data.hasRemote())
return data.local;
if (data.hasLocal() && keepLocalModel)
return data.local;
if (data.hasRemote() && !keepLocalModel)
return data.remote;
return null;
}
private String getTitle(DiffNode node) {
if (node.isModelTypeNode())
return null;
DiffResult result = (DiffResult) node.content;
return result.getDataset().fullPath;
}
private Image getLogo(DiffNode node) {
if (node.isModelTypeNode())
return null;
if (node.isModelNode())
return Images.get(node.getModelType());
DiffResult result = (DiffResult) node.content;
return Images.getForCategory(result.getDataset().categoryType);
}
private String toKey(Dataset dataset) {
return dataset.type.name() + dataset.refId;
}
private class DiffData {
private JsonObject local;
private JsonObject remote;
private JsonNode node;
private DiffResult result;
private boolean hasLocal() {
return local != null;
}
private boolean hasRemote() {
return remote != null;
}
}
}