Newer
Older
DesignCraft / src / main / java / models / objectOrientedTransfer / DataTransferDesign.java
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;
	}
}