package models.objectOrientedTransfer;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* The final data transfer designs containing delta algebra and dependency injection.
*
* @author Nitta
*
*/
public class DataTransferDesign {
private DataTransferContext transferContext;
private DeltaComplex deltaComplex;
public DataTransferDesign(DataTransferContext transferContext) throws IllegalRelationException {
this.transferContext = transferContext;
this.deltaComplex = createDefaultDeltaComlex(transferContext);
}
public DeltaComplex createDefaultDeltaComlex(DataTransferContext transferContext) throws IllegalRelationException {
if (transferContext.getTransferStyle() == PushPullValue.PUSH) {
// PUSH transfer
if (transferContext.getTransferMultiplicity() == MultiplicityValue.ManyToOne
|| transferContext.getTransferMultiplicity() == MultiplicityValue.OneToOne) {
// Simple PUSH
// Construct all deltas.
Stack<Delta> deltaStack = new Stack<>();
ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack);
// Add the data transfer delta.
ObjectNode srcObj = (ObjectNode) bottomReference.getSource();
ObjectNode dstObj = (ObjectNode) transferContext.getDataType();
String dataName = transferContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullPushDelta primDelta = new PrimitivePullPushDelta(dataEdge, bottomReference, dataName); // PUSH data transfer
Delta dataTransferDelta = new Delta(primDelta);
DeltaComplex deltaComplex = new DeltaComplex(dataTransferDelta);
// Add initialization deltas.
while (!deltaStack.isEmpty()) {
deltaComplex.attach(deltaStack.pop());
}
return deltaComplex;
} else {
// Broadcasting
}
} else {
if (transferContext.getTransferMultiplicity() == MultiplicityValue.OneToMany
|| transferContext.getTransferMultiplicity() == MultiplicityValue.OneToOne) {
// Simple PULL
// Construct all deltas.
Stack<Delta> deltaStack = new Stack<>();
ReferenceEdge bottomReference = constructDefaultDeltas(transferContext, deltaStack);
// Add the data transfer delta.
ObjectNode srcObj = (ObjectNode) bottomReference.getDestination();
ObjectNode dstObj = (ObjectNode) transferContext.getDataType();
String dataName = transferContext.getDataName();
ReferenceEdge dataEdge = new ReferenceEdge(srcObj, dstObj, dataName);
PrimitivePullDelta primDelta = new PrimitivePullDelta(bottomReference, dataEdge, dataName); // PULL data transfer
Delta dataTransferDelta = new Delta(primDelta);
DeltaComplex deltaComplex = new DeltaComplex(dataTransferDelta);
// Add initialization deltas.
while (!deltaStack.isEmpty()) {
deltaComplex.attach(deltaStack.pop());
}
return deltaComplex;
} else {
// Data collecting
}
}
return null;
}
private ReferenceEdge constructDefaultDeltas(DataTransferContext transferContext, Stack<Delta> deltaStack) throws IllegalRelationException {
PushPullValue transferStyle = transferContext.getTransferStyle();
ObjectNode srcObj = null;
ObjectNode dstObj = null;
if (transferStyle == PushPullValue.PUSH) {
srcObj = (ObjectNode) transferContext.getSrcResource().getFirst().getSource();
dstObj = (ObjectNode) transferContext.getDstResource().getFirst().getSource();
} else {
srcObj = (ObjectNode) transferContext.getDstResource().getFirst().getSource();
dstObj = (ObjectNode) transferContext.getSrcResource().getFirst().getSource();
}
String refName = dstObj.getName().substring(0, 1).toLowerCase() + dstObj.getName().substring(1);
ReferenceEdge prevReference = new ReferenceEdge(srcObj, dstObj, refName);
boolean toOne = true; // potential multiplicity
List<ReferenceEdge> srcResource = new ArrayList<>();
List<ReferenceEdge> dstResource = new ArrayList<>();
List<Relation> allRelations = new ArrayList<>(transferContext.getRelations());
allRelations.add(transferContext.getTransferRelation());
for (Relation relation: allRelations) {
List<ReferenceEdge> newSrcResource = null;
List<ReferenceEdge> newDstResource = null;
if (transferStyle == PushPullValue.PUSH) {
newSrcResource = relation.getSrcResource();
newDstResource = relation.getDstResource();
} else {
newSrcResource = relation.getDstResource();
newDstResource = relation.getSrcResource();
}
if (dstResource.size() < newDstResource.size()) {
List<ReferenceEdge> oneDestination = new ArrayList<>();
List<ReferenceEdge> manyDestinations = new ArrayList<>();
for (int i = 0; i < newDstResource.size(); i++) {
if (i < dstResource.size()) {
if (!dstResource.get(i).equals(newDstResource.get(i))) {
throw new IllegalRelationException();
}
} else {
if (newDstResource.get(i).getMultiplicity() == MultiplicityValue.OneToMany) {
toOne = false;
}
if (toOne) {
oneDestination.add(newDstResource.get(i));
} else {
manyDestinations.add(newDstResource.get(i));
}
}
}
if (!toOne &&
((transferStyle == PushPullValue.PUSH && (relation.getMultiplicity() == MultiplicityValue.ManyToOne || relation.getMultiplicity() == MultiplicityValue.OneToOne))
|| (transferStyle != PushPullValue.PUSH && (relation.getMultiplicity() == MultiplicityValue.OneToMany || relation.getMultiplicity() == MultiplicityValue.OneToOne)))) {
// If the specified multiplicity of destination objects does not match to their potential multiplicity,
// then the reference to select one destination object from potential multiple objects is needed.
// 1) Create container passing deltas.
List<PrimitiveDelta> primitiveDeltaList = new ArrayList<>();
for (ReferenceEdge dstEdge: oneDestination) {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) dstEdge.getDestination();
String dataName = dstObj.getName();
dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1);
primitiveDeltaList.add(new PrimitivePullDelta(prevReference, dstEdge, dataName));
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
}
for (int i = 0; i < newSrcResource.size(); i++) {
ReferenceEdge srcEdge = newSrcResource.get(i);
if (i < srcResource.size()) {
if (!srcResource.get(i).equals(srcEdge)) {
throw new IllegalRelationException();
}
} else {
srcObj = (ObjectNode) srcEdge.getDestination();
dstObj = (ObjectNode) prevReference.getDestination();
String dataName = dstObj.getName();
dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1);
primitiveDeltaList.add(new PrimitivePullPushDelta(prevReference, srcEdge, dataName));
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 delta
primitiveDeltaList.clear();
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
}
}
// 2) Create a component identifying delta.
PrimitiveDelta componentSelectingDelta = null;
for (ReferenceEdge dstEdge: manyDestinations) {
if (componentSelectingDelta == null) {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) dstEdge.getDestination();
String dataName = dstObj.getName();
dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1);
componentSelectingDelta = new PrimitivePullDelta(prevReference, dstEdge, dataName);
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 identifying delta
primitiveDeltaList.clear();
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
} else {
srcObj = (ObjectNode) prevReference.getSource();
dstObj = (ObjectNode) dstEdge.getDestination();
String dataName = dstObj.getName();
dataName = dataName.substring(0, 1).toLowerCase() + dataName.substring(1);
primitiveDeltaList.add(new PrimitivePullDelta(prevReference, dstEdge, dataName));
prevReference = new ReferenceEdge(srcObj, dstObj, dataName);
}
}
// 3) Create a component obtaining 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 delta
}
toOne = true;
}
} else {
throw new IllegalRelationException();
}
srcResource = newSrcResource;
dstResource = newDstResource;
}
return prevReference;
}
public DeltaComplex getDeltaComplex() {
return deltaComplex;
}
public DataTransferContext getTransferContext() {
return transferContext;
}
}