package models.dataSynchronizationModel;
import designPatternExtensions.DependencyInversion;
import designPatternExtensions.MediatorInsertion;
import designPatternExtensions.PresenterInsertion;
import models.deltaAlgebra.*;
import parser.*;
import parser.exceptions.ExpectedJsonValue;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* The final data synchronization design containing delta algebra and dependency injection.
*
* @author Nitta
*
*/
public class DataSynchronizationDesign {
private List<DataSynchronizationContext> synchronizationContexts;
private DeltaComplex deltaComplex;
private List<DependencyInversion> dependencyInversions = new ArrayList<>();
private List<MediatorInsertion> mediatorInsertions = new ArrayList<>();
private List<PresenterInsertion> presenterInsertions = new ArrayList<>();
public static String toComponentName(String name) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
public static String toVariableName(String name) {
return name.substring(0, 1).toLowerCase() + name.substring(1);
}
public DataSynchronizationDesign(DataSynchronizationContext synchronizationContexts) throws IllegalRelationException {
this.synchronizationContexts = new ArrayList<>();
this.synchronizationContexts.add(synchronizationContexts);
this.deltaComplex = createDefaultDeltaComplex(synchronizationContexts);
}
public DataSynchronizationDesign(JsonValue jsonValue) throws IllegalRelationException {
this.synchronizationContexts = new ArrayList<>();
for (StringValue keyValue : jsonValue.getJson().keySet()) {
String key = keyValue.getStringValue();
if (key.equals("contexts")) {
ArrayValue arrayValue = (ArrayValue) jsonValue.getValue(keyValue);
setSynchronizationContexts(arrayValue);
}
}
}
public void addDependencyInversion(DependencyInversion dependencyInversion) {
dependencyInversions.add(dependencyInversion);
}
public List<DependencyInversion> getDependencyInversions() {
return dependencyInversions;
}
public void addMediatorInsertion(MediatorInsertion mediatorInsertion) {
mediatorInsertions.add(mediatorInsertion);
}
public List<MediatorInsertion> getMediatorInsertions() {
return mediatorInsertions;
}
public void addPresenterInsertion(PresenterInsertion presenterInsertion) {
presenterInsertions.add(presenterInsertion);
}
public List<PresenterInsertion> getPresenterInsertions() {
return presenterInsertions;
}
public DeltaComplex createDefaultDeltaComplex(DataSynchronizationContext transferContext) throws IllegalRelationException {
Stack<Delta> deltaStack = constructDefaultDeltas(transferContext);
// Add all deltas.
DeltaComplex deltaComplex = null;
while (!deltaStack.isEmpty()) {
if (deltaComplex == null) {
deltaComplex = new DeltaComplex(deltaStack.pop());
} else {
deltaComplex.attach(deltaStack.pop());
}
}
return deltaComplex;
}
/*
* construct default deltas that satisfy the law of demeter.
*
* @param synchronizationContext a synchronization context in data synchronization model
* @return generated deltas
*/
private Stack<Delta> constructDefaultDeltas(DataSynchronizationContext synchronizationContext) throws IllegalRelationException {
Stack<Delta> deltaStack = new Stack<>();
TransferStyle transferStyle = synchronizationContext.getTransferStyle();
ObjectNode srcObj = null;
ObjectNode dstObj = null;
boolean useShortcut = true;
if (transferStyle == TransferStyle.PUSH) {
// Transfer style is PUSH
srcObj = synchronizationContext.getSrcTopObject();
dstObj = synchronizationContext.getDstTopObject();
} else {
// Transfer style is PULL or PLAIN
srcObj = synchronizationContext.getDstTopObject();
dstObj = synchronizationContext.getSrcTopObject();
if (transferStyle == TransferStyle.PLAIN) {
useShortcut = false;
}
}
String refName = toVariableName(dstObj.getName());
ReferenceEdge prevReference = new ReferenceEdge(srcObj, dstObj, refName);
if (!synchronizationContext.isFlat()) {
boolean toOne = true; // identifiable multiplicity
List<Relation> allRelations = new ArrayList<>(synchronizationContext.getIntermediateRelations());
if (useShortcut) {
for (Relation relation : allRelations) {
if (synchronizationContext.getSrcObjectHierarchy().isPrefixOf(relation.getSrcObjectHierarchy())
|| synchronizationContext.getDstObjectHierarchy().isPrefixOf(relation.getDstObjectHierarchy())) {
useShortcut = false;
break;
}
}
}
if (useShortcut) {
allRelations.add(synchronizationContext.getSyncronizationRelation().getPrevRelation());
} else {
if (transferStyle == TransferStyle.PLAIN) {
allRelations.add(synchronizationContext.getSyncronizationRelation());
} else {
Relation lastRelation = allRelations.getLast();
Relation bottomRelation = null;
if (!synchronizationContext.getSrcObjectHierarchy().isPrefixOf(lastRelation.getSrcObjectHierarchy())) {
bottomRelation = new Relation(synchronizationContext.getSrcObjectHierarchy().getPrevObjectHierarchy(),
synchronizationContext.getSrcObjectHierarchy(),
synchronizationContext.getTransferMultiplicity());
allRelations.add(bottomRelation);
} else if (!synchronizationContext.getDstObjectHierarchy().isPrefixOf(lastRelation.getDstObjectHierarchy())) {
bottomRelation = new Relation(synchronizationContext.getSrcObjectHierarchy(),
synchronizationContext.getDstObjectHierarchy().getPrevObjectHierarchy(),
synchronizationContext.getTransferMultiplicity());
allRelations.add(bottomRelation);
}
}
}
ObjectHierarchy srcHierarchy = null;
ObjectHierarchy dstHierarchy = null;
for (Relation relation: allRelations) {
ObjectHierarchy newSrcHierarchy = null;
ObjectHierarchy newDstHierarchy = null;
if (transferStyle == TransferStyle.PUSH) {
newSrcHierarchy = relation.getSrcObjectHierarchy();
newDstHierarchy = relation.getDstObjectHierarchy();
} else {
newSrcHierarchy = relation.getDstObjectHierarchy();
newDstHierarchy = relation.getSrcObjectHierarchy();
}
if (srcHierarchy == null) {
srcHierarchy = new ObjectHierarchy(newSrcHierarchy.getTop());
}
if (dstHierarchy == null) {
dstHierarchy = new ObjectHierarchy(newDstHierarchy.getTop());
}
while (dstHierarchy.getDepth() < newDstHierarchy.getDepth() || srcHierarchy.getDepth() < newSrcHierarchy.getDepth()) {
List<ReferenceEdge> oneDestinations = new ArrayList<>();
List<ReferenceEdge> manyDestinations = new ArrayList<>();
boolean tmpToOne = toOne;
for (int i = 0; i < newDstHierarchy.getDepth(); i++) {
ReferenceEdge dstEdge = newDstHierarchy.getEdge(i);
if (dstHierarchy != null && i < dstHierarchy.getDepth()) {
if (!dstHierarchy.getEdge(i).equals(dstEdge)) {
throw new IllegalRelationException();
}
} else {
dstHierarchy.addEdge(dstEdge);
if (dstEdge.toMany()) {
tmpToOne = false;
toOne = false;
}
if (!tmpToOne &&
(transferStyle == TransferStyle.PUSH && relation.toOne()
|| transferStyle != TransferStyle.PUSH && (relation.oneTo()))) {
// If the specified multiplicity of destination objects does not match to their identifiable multiplicity,
// then the reference to select one destination object from identifiable multiple objects is needed.
manyDestinations.add(dstEdge);
toOne = true;
} else {
// If the specified multiplicity of destination objects and their identifiable are both many or both one,
// then the reference to select one destination object from identifiable multiple objects is not needed.
oneDestinations.add(dstEdge);
}
}
}
// 1) Create component obtaining deltas.
Delta delta = null;
ReferenceEdge prevDstEdge = null;
for (int i = oneDestinations.size() - 1; i >= 0; i--) {
ReferenceEdge dstEdge = oneDestinations.get(i);
if (prevDstEdge != null) {
srcObj = (ObjectNode) dstEdge.getSource();
dstObj = (ObjectNode) prevDstEdge.getDestination();
String dataName = toVariableName(prevDstEdge.getName());
if (!newSrcHierarchy.contains((ObjectNode) dstEdge.getDestination())) {
PrimitiveDelta primDelta = null;
if (!prevDstEdge.toMany()) {
primDelta = new PrimitivePullDelta(dstEdge, prevDstEdge, dataName); // a primitive component obtaining delta
} else {
primDelta = new PrimitivePullDelta(dstEdge, prevDstEdge, dataName, true, false); // a primitive component obtaining delta
}
if (delta == null) {
delta = new Delta(primDelta);
} else {
delta = delta.combine(primDelta);
}
if (!prevDstEdge.toMany()) {
prevDstEdge = new ReferenceEdge(srcObj, dstObj, dataName);
} else {
prevDstEdge = new ReferenceEdge(srcObj, dstObj, dataName, prevDstEdge.getKeyTypeName());
}
}
} else {
prevDstEdge = dstEdge;
}
}
if (delta != null) deltaStack.push(delta); // add a component obtaining SIMPLEX delta
if (prevDstEdge != null) {
if (!prevReference.isIdentical()) {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) prevDstEdge.getDestination();
String dataName = toVariableName(prevDstEdge.getName());
delta = new Delta(new PrimitivePullDelta(prevReference, prevDstEdge, dataName, prevDstEdge.toMany()));
if (delta != null)
deltaStack.push(delta); // add a component obtaining SIMPLEX delta
if (!prevDstEdge.toMany()) {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
} else {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName, prevDstEdge.getKeyTypeName());
}
} else {
prevReference = prevDstEdge;
}
}
// 2) Create container passing deltas.
delta = null;
boolean oneTo = true;
for (int i = 0; i < newSrcHierarchy.getDepth(); i++) {
ReferenceEdge srcEdge = newSrcHierarchy.getEdge(i);
if (srcHierarchy != null && i < srcHierarchy.getDepth()) {
if (!srcHierarchy.getEdge(i).equals(srcEdge)) {
throw new IllegalRelationException();
}
} else {
srcHierarchy.addEdge(srcEdge);
if (srcEdge.toMany()) {
oneTo = false;
}
srcObj = (ObjectNode) srcEdge.getDestination();
dstObj = (ObjectNode) prevReference.getDestination();
String dataName = toVariableName(prevReference.getName());
if (!prevReference.isIdentical() && !dstHierarchy.contains(srcObj)) {
PrimitiveDelta primDelta = null;
if (toOne) {
primDelta = new PrimitivePullPushDelta(prevReference, srcEdge, dataName); // a container passing primitive delta
} else {
primDelta = new PrimitivePullPushDelta(prevReference, srcEdge, dataName, true); // a container passing primitive delta
}
if (delta == null) {
delta = new Delta(primDelta);
} else {
if (oneTo) {
delta = delta.combine(primDelta);
} else {
if (delta != null) {
deltaStack.push(delta); // add a container passing SIMPLEX delta
}
delta = new Delta(primDelta);
}
}
}
if (toOne) {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
} else {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName, prevReference.getKeyTypeName());
}
}
}
if (delta != null) deltaStack.push(delta); // add a container passing SIMPLEX delta
// 3) Create a component selecting delta.
for (ReferenceEdge dstEdge : manyDestinations) {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) dstEdge.getDestination();
String dataName = toVariableName(dstEdge.getName());
PrimitivePullDelta componentSelectingDelta = null;
componentSelectingDelta = new PrimitivePullDelta(prevReference, dstEdge, dataName);
delta = new Delta(componentSelectingDelta);
deltaStack.push(delta); // add a component selecting delta
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
}
}
}
}
if (useShortcut) {
// 4) Create the bottom (data transfer) delta.
Delta dataTransferDelta = null;
if (transferStyle == TransferStyle.PUSH) {
// PUSH transfer
if (synchronizationContext.isTransferToOne()) {
// Simple PUSH
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullPushDelta primDelta = new PrimitivePullPushDelta(dataEdge, prevReference, dataName); // PUSH data transfer
if (synchronizationContext.getSyncronizationRelation().toMany()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
} else {
// Broadcasting
prevReference = new ReferenceEdge(prevReference);
// prevReference.setKeyTypeName(synchronizationContext.getDstObjectHierarchy().getEdges().getLast().getKeyTypeName());
// prevReference.setMultiplicity(MultiplicityValue.OneToMany);
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullPushDelta primDelta = new PrimitivePullPushDelta(dataEdge, prevReference, dataName); // PUSH data transfer
if (synchronizationContext.getDstObjectHierarchy().getEdges().getLast().toMany()) {
primDelta.setMultipleDefinition(true);
}
if (synchronizationContext.getSyncronizationRelation().toMany()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
}
} else {
if (synchronizationContext.isTransferOneTo()) {
// Simple PULL
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getDestination();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullDelta primDelta = new PrimitivePullDelta(prevReference, dataEdge, dataName); // PULL data transfer
if (synchronizationContext.getSyncronizationRelation().manyTo()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
} else {
// Data collecting
prevReference = new ReferenceEdge(prevReference);
// prevReference.setKeyTypeName(synchronizationContext.getSrcObjectHierarchy().getEdges().getLast().getKeyTypeName());
// prevReference.setMultiplicity(MultiplicityValue.OneToMany);
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getDestination();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullDelta primDelta = new PrimitivePullDelta(prevReference, dataEdge, dataName, true); // PULL data transfer
if (synchronizationContext.getSyncronizationRelation().manyTo()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
}
}
deltaStack.push(dataTransferDelta);
}
return deltaStack;
}
/*
* construct default deltas that do not satisfy the law of demeter.
*
* @param synchronizationContext a synchronization context in data synchronization model
* @return generated deltas
*/
private Stack<Delta> constructDefaultDeltas2(DataSynchronizationContext synchronizationContext) throws IllegalRelationException {
Stack<Delta> deltaStack = new Stack<>();
TransferStyle transferStyle = synchronizationContext.getTransferStyle();
ObjectNode srcObj = null;
ObjectNode dstObj = null;
if (transferStyle == TransferStyle.PUSH) {
srcObj = synchronizationContext.getSrcTopObject();
dstObj = synchronizationContext.getDstTopObject();
} else {
srcObj = synchronizationContext.getDstTopObject();
dstObj = synchronizationContext.getSrcTopObject();
}
String refName = toVariableName(dstObj.getName());
ReferenceEdge prevReference = new ReferenceEdge(srcObj, dstObj, refName);
boolean hasDiagonalRelation = false;
if (!synchronizationContext.isFlat()) {
boolean toOne = true; // identifiable multiplicity
ObjectHierarchy srcHierarchy = null;
ObjectHierarchy dstHierarchy = null;
List<Relation> allRelations = new ArrayList<>(synchronizationContext.getIntermediateRelations());
for (Relation relation: allRelations) {
if (synchronizationContext.getSrcObjectHierarchy().isPrefixOf(relation.getSrcObjectHierarchy())
|| synchronizationContext.getDstObjectHierarchy().isPrefixOf(relation.getDstObjectHierarchy())) {
hasDiagonalRelation = true;
break;
}
}
if (!hasDiagonalRelation) {
allRelations.add(synchronizationContext.getSyncronizationRelation().getPrevRelation());
} else {
Relation lastRelation = allRelations.getLast();
Relation bottomRelation = null;
if (!synchronizationContext.getSrcObjectHierarchy().isPrefixOf(lastRelation.getSrcObjectHierarchy())) {
bottomRelation = new Relation(synchronizationContext.getSrcObjectHierarchy().getPrevObjectHierarchy(),
synchronizationContext.getSrcObjectHierarchy(),
synchronizationContext.getTransferMultiplicity());
allRelations.add(bottomRelation);
} else if (!synchronizationContext.getDstObjectHierarchy().isPrefixOf(lastRelation.getDstObjectHierarchy())) {
bottomRelation = new Relation(synchronizationContext.getSrcObjectHierarchy(),
synchronizationContext.getDstObjectHierarchy().getPrevObjectHierarchy(),
synchronizationContext.getTransferMultiplicity());
allRelations.add(bottomRelation);
}
}
for (Relation relation: allRelations) {
ObjectHierarchy newSrcHierarchy = null;
ObjectHierarchy newDstHierarchy = null;
if (transferStyle == TransferStyle.PUSH) {
newSrcHierarchy = relation.getSrcObjectHierarchy();
newDstHierarchy = relation.getDstObjectHierarchy();
} else {
newSrcHierarchy = relation.getDstObjectHierarchy();
newDstHierarchy = relation.getSrcObjectHierarchy();
}
if ((dstHierarchy == null || dstHierarchy.getDepth() < newDstHierarchy.getDepth()) || (srcHierarchy == null || srcHierarchy.getDepth() < newSrcHierarchy.getDepth())) {
List<ReferenceEdge> oneDestinations = new ArrayList<>();
List<ReferenceEdge> manyDestinations = new ArrayList<>();
boolean nextToOne = toOne;
for (int i = 0; i < newDstHierarchy.getDepth(); i++) {
ReferenceEdge dstEdge = newDstHierarchy.getEdge(i);
if (dstHierarchy != null && i < dstHierarchy.getDepth()) {
if (!dstHierarchy.getEdge(i).equals(dstEdge)) {
throw new IllegalRelationException();
}
} else {
if (dstEdge.toMany()) {
nextToOne = false;
}
if (nextToOne) {
oneDestinations.add(dstEdge);
} else {
manyDestinations.add(dstEdge);
}
}
}
// 1) Create container passing simplex deltas.
List<PrimitiveDelta> primitiveDeltaList = new ArrayList<>();
for (ReferenceEdge dstEdge: oneDestinations) {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) dstEdge.getDestination();
String dataName = toVariableName(dstObj.getName());
if (!prevReference.isIdentical()) {
primitiveDeltaList.add(new PrimitivePullDelta(prevReference, dstEdge, dataName)); // a component obtaining primitive delta
}
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
}
for (int i = 0; i < newSrcHierarchy.getDepth(); i++) {
ReferenceEdge srcEdge = newSrcHierarchy.getEdge(i);
if (srcHierarchy != null && i < srcHierarchy.getDepth()) {
if (!srcHierarchy.getEdge(i).equals(srcEdge)) {
throw new IllegalRelationException();
}
} else {
srcObj = (ObjectNode) srcEdge.getDestination();
dstObj = (ObjectNode) prevReference.getDestination();
String dataName = toVariableName(dstObj.getName());
if (!prevReference.isIdentical() && !prevReference.getDestination().equals(srcEdge.getDestination())) {
if (toOne) {
primitiveDeltaList.add(new PrimitivePullPushDelta(prevReference, srcEdge, dataName)); // a container passing primitive delta
} else {
primitiveDeltaList.add(new PrimitivePullPushDelta(prevReference, srcEdge, dataName, true)); // a container passing primitive delta
}
Delta delta = null;
for (PrimitiveDelta primDelta : primitiveDeltaList) {
if (delta == null) {
delta = new Delta(primDelta);
} else {
delta = new Delta(primDelta, delta);
}
}
deltaStack.push(delta); // add a container passing SIMPLEX delta
primitiveDeltaList.clear();
}
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
}
}
toOne = nextToOne;
if (!toOne) {
boolean multipleDefinition = false; // destination multiplicity of the defined reference
if ((transferStyle == TransferStyle.PUSH && relation.toOne()) || (transferStyle != TransferStyle.PUSH && relation.oneTo())) {
// If the specified multiplicity of destination objects does not match to their identifiable multiplicity,
// then the reference to select one destination object from identifiable multiple objects is needed.
toOne = true;
} else {
// If the specified multiplicity of destination objects and their identifiable multiplicity are both many,
// then the reference to select one destination object from identifiable multiple objects is needed.
multipleDefinition = true;
}
// 2) Create a component selecting simplex delta.
PrimitivePullDelta componentSelectingDelta = null;
for (ReferenceEdge dstEdge : manyDestinations) {
if (componentSelectingDelta == null) {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) dstEdge.getDestination();
String dataName = toVariableName(dstObj.getName());
componentSelectingDelta = new PrimitivePullDelta(prevReference, dstEdge, dataName, multipleDefinition);
primitiveDeltaList.add(componentSelectingDelta);
Delta delta = null;
for (PrimitiveDelta primDelta : primitiveDeltaList) {
if (delta == null) {
delta = new Delta(primDelta);
} else {
delta = new Delta(primDelta, delta);
}
}
deltaStack.push(delta); // add a component selecting SIMPLEX delta
primitiveDeltaList.clear();
if (!multipleDefinition) {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
} else {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName, dstEdge.getKeyTypeName());
}
} else {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) dstEdge.getDestination();
String dataName = toVariableName(dstObj.getName());
componentSelectingDelta = new PrimitivePullDelta(prevReference, dstEdge, dataName, multipleDefinition); // a component obtaining primitive delta
primitiveDeltaList.add(componentSelectingDelta);
if (!multipleDefinition) {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
} else {
prevReference = new ReferenceEdge(srcObj, dstObj, dataName, dstEdge.getKeyTypeName());
}
}
}
}
// 3) Create a component obtaining simplex delta.
if (primitiveDeltaList.size() > 0) {
Delta delta = null;
for (PrimitiveDelta primDelta: primitiveDeltaList) {
if (delta == null) {
delta = new Delta(primDelta);
} else {
delta = new Delta(primDelta, delta);
}
}
deltaStack.push(delta); // add a component obtaining SIMPLEX delta
}
} else {
throw new IllegalRelationException();
}
srcHierarchy = newSrcHierarchy;
dstHierarchy = newDstHierarchy;
}
}
if (!hasDiagonalRelation) {
// 4) Create the bottom (data transfer) delta.
Delta dataTransferDelta = null;
if (transferStyle == TransferStyle.PUSH) {
// PUSH transfer
if (synchronizationContext.isTransferToOne()) {
// Simple PUSH
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullPushDelta primDelta = new PrimitivePullPushDelta(dataEdge, prevReference, dataName); // PUSH data transfer
if (synchronizationContext.getSyncronizationRelation().toMany()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
} else {
// Broadcasting
prevReference = new ReferenceEdge(prevReference);
prevReference.setKeyTypeName(synchronizationContext.getDstObjectHierarchy().getEdges().getLast().getKeyTypeName());
// prevReference.setMultiplicity(MultiplicityValue.OneToMany);
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullPushDelta primDelta = new PrimitivePullPushDelta(dataEdge, prevReference, dataName); // PUSH data transfer
if (synchronizationContext.getDstObjectHierarchy().getEdges().getLast().toMany()) {
primDelta.setMultipleDefinition(true);
}
if (synchronizationContext.getSyncronizationRelation().toMany()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
}
} else {
if (synchronizationContext.isTransferOneTo()) {
// Simple PULL
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getDestination();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullDelta primDelta = new PrimitivePullDelta(prevReference, dataEdge, dataName); // PULL data transfer
if (synchronizationContext.getSyncronizationRelation().manyTo()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
} else {
// Data collecting
prevReference = new ReferenceEdge(prevReference);
prevReference.setKeyTypeName(synchronizationContext.getSrcObjectHierarchy().getEdges().getLast().getKeyTypeName());
// prevReference.setMultiplicity(MultiplicityValue.OneToMany);
// Add the data transfer delta.
srcObj = (ObjectNode) prevReference.getDestination();
dstObj = (ObjectNode) synchronizationContext.getSrcObjectHierarchy().getBottom();
String dataName = synchronizationContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullDelta primDelta = new PrimitivePullDelta(prevReference, dataEdge, dataName, true); // PULL data transfer
if (synchronizationContext.getSyncronizationRelation().manyTo()) {
primDelta.setMultipleTransfer(true);
}
dataTransferDelta = new Delta(primDelta);
}
}
deltaStack.push(dataTransferDelta);
}
return deltaStack;
}
private void setSynchronizationContexts(ArrayValue arrayValue) throws IllegalRelationException {
List<Value> values = arrayValue.getValues();
for (int i = 0; i<values.size(); i++) {
if (!(values.get(i) instanceof JsonValue)) {
throw new ExpectedJsonValue("contextsの中身がJsonではありません。");
}
if (i == 0) {
DataSynchronizationContext transferContext = new DataSynchronizationContext(values.get(i));
this.synchronizationContexts.add(transferContext);
this.deltaComplex = createDefaultDeltaComplex(transferContext);
} else {
DataSynchronizationContext transferContext = new DataSynchronizationContext(values.get(i));
addTransferContext(transferContext);
}
}
}
public DeltaComplex getDeltaComplex() {
return deltaComplex;
}
public void addTransferContext(DataSynchronizationContext transferContext) throws IllegalRelationException {
synchronizationContexts.add(transferContext);
deltaComplex.merge(createDefaultDeltaComplex(transferContext));
}
public List<DataSynchronizationContext> getSynchronizationContexts() {
return synchronizationContexts;
}
}