All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.nakeduml.javageneration.composition.CopyMethodImplementor Maven / Gradle / Ivy

package net.sf.nakeduml.javageneration.composition;

import java.util.ArrayList;
import java.util.List;

import net.sf.nakeduml.feature.visit.VisitAfter;
import net.sf.nakeduml.javageneration.AbstractJavaProducingVisitor;
import net.sf.nakeduml.javageneration.NakedStructuralFeatureMap;
import net.sf.nakeduml.javageneration.util.OJUtil;
import net.sf.nakeduml.javametamodel.OJBlock;
import net.sf.nakeduml.javametamodel.OJClass;
import net.sf.nakeduml.javametamodel.OJClassifier;
import net.sf.nakeduml.javametamodel.OJField;
import net.sf.nakeduml.javametamodel.OJForStatement;
import net.sf.nakeduml.javametamodel.OJIfStatement;
import net.sf.nakeduml.javametamodel.OJOperation;
import net.sf.nakeduml.javametamodel.OJPathName;
import net.sf.nakeduml.javametamodel.OJSimpleStatement;
import net.sf.nakeduml.javametamodel.annotation.OJAnnotatedField;
import net.sf.nakeduml.javametamodel.annotation.OJAnnotatedOperation;
import net.sf.nakeduml.javametamodel.generated.OJVisibilityKindGEN;
import net.sf.nakeduml.metamodel.core.INakedClassifier;
import net.sf.nakeduml.metamodel.core.INakedComplexStructure;
import net.sf.nakeduml.metamodel.core.INakedEntity;
import net.sf.nakeduml.metamodel.core.INakedEnumeration;
import net.sf.nakeduml.metamodel.core.INakedProperty;
import net.sf.nakeduml.metamodel.core.INakedSimpleType;
import net.sf.nakeduml.metamodel.core.INakedStructuredDataType;
import net.sf.nakeduml.name.NameConverter;
import nl.klasse.octopus.model.IModelElement;

public class CopyMethodImplementor extends AbstractJavaProducingVisitor {
	@VisitAfter(matchSubclasses = true)
	public void visitClass(INakedClassifier c) {
		OJPathName path = OJUtil.classifierPathname(c);
		OJClassifier myOwner = this.javaModel.findIntfOrCls(path);
		// NakedModelElement mew = (NakedModelElement)
		// nakedModel.lookup(c.getPathName());
		if (myOwner instanceof OJClass && (c instanceof INakedEntity || c instanceof INakedStructuredDataType)) {
			INakedComplexStructure nc = (INakedComplexStructure) c;
			OJClass ojClass = (OJClass) myOwner;
			implementCopyMethod(ojClass, nc);
			addCopyStateMethod(nc, ojClass);
			addShallowMakeCopyMethod(ojClass, nc);
			addShallowCopyStateMethod(nc, ojClass);
		}
	}

	private void addShallowMakeCopyMethod(OJClass owner, INakedComplexStructure classifier) {
		OJAnnotatedOperation oper = new OJAnnotatedOperation();
		oper.setName("makeShallowCopy");
		oper.setReturnType(OJUtil.classifierPathname(classifier));
		owner.addToOperations(oper);

		if (classifier.getIsAbstract() || owner.isAbstract()) {
			// Can NEVER instantiate abstract objects
			oper.setAbstract(true);
		} else {
			OJBlock body = oper.getBody();
			OJAnnotatedField result = new OJAnnotatedField();
			result.setName("result");
			result.setType(owner.getPathName());
			result.setInitExp("new " + owner.getName() + "()");
			body.addToLocals(result);
			body.addToStatements("copyShallowState((" + classifier.getMappingInfo().getJavaName() + ")this,result)");
			body.addToStatements(new OJSimpleStatement("result.setId(this.getId())"));
			body.addToStatements("return result");
		}
	}

	private void implementCopyMethod(OJClass owner, INakedClassifier classifier) {
		OJOperation oper = OJUtil.findOperation(owner, "makeCopy");
		if (oper == null) {
			oper = new OJAnnotatedOperation();
			oper.setName("makeCopy");
			oper.setReturnType(OJUtil.classifierPathname(classifier));
			owner.addToOperations(oper);
		} else {
			oper.setBody(new OJBlock());
		}
		if (classifier.getIsAbstract() || owner.isAbstract()) {
			// Can NEVER instantiate abstract objects
			oper.setAbstract(true);
		} else {
			OJBlock body = oper.getBody();
			OJAnnotatedField result = new OJAnnotatedField();
			result.setName("result");
			result.setType(owner.getPathName());
			result.setInitExp("new " + owner.getName() + "()");
			body.addToLocals(result);
			body.addToStatements("copyState((" + classifier.getMappingInfo().getJavaName() + ")this,result)");
			body.addToStatements("return result");
		}
	}

	private void addCopyStateMethod(INakedClassifier classifier, OJClass owner) {
		OJOperation oper = new OJAnnotatedOperation();
		oper.setVisibility(OJVisibilityKindGEN.PUBLIC);
		oper.setName("copyState");
		oper.addParam("from", owner.getPathName());
		oper.addParam("to", owner.getPathName());
		addCopyStatements(classifier, owner, oper.getBody(), true, false);
		owner.addToOperations(oper);
	}

	private void addShallowCopyStateMethod(INakedClassifier classifier, OJClass owner) {
		OJOperation oper = new OJAnnotatedOperation();
		oper.setVisibility(OJVisibilityKindGEN.PUBLIC);
		oper.setName("copyShallowState");
		oper.addParam("from", owner.getPathName());
		oper.addParam("to", owner.getPathName());
		addCopyStatements(classifier, owner, oper.getBody(), false, true);
		owner.addToOperations(oper);
	}

	private void addCopyStatements(INakedClassifier classifier, OJClass owner, OJBlock body, boolean deep, boolean shallowCopy) {
		String copyMethodName = shallowCopy ? "makeShallowCopy" : "makeCopy";
		List properties = classifier.getEffectiveAttributes();
		// TODO implement containment by value (composition) vs containment
		// by reference logic
		// might be helpful for web service, for instance
		// give some more thought
		// maybe consider an input parameter specifying the number of levels to
		// include in a deep copy
		for (int i = 0; i < properties.size(); i++) {
			IModelElement a = (IModelElement) properties.get(i);
			if (a instanceof INakedProperty) {
				INakedProperty np = (INakedProperty) a;
				NakedStructuralFeatureMap map = new NakedStructuralFeatureMap(np);
				if (!(np.isDerived() || np.isReadOnly() || (np.getOtherEnd() != null && np.getOtherEnd().isComposite()))) {
					if (np.getNakedBaseType() instanceof INakedSimpleType || np.getNakedBaseType() instanceof INakedEnumeration) {
						if (map.isMany()) {
							body.addToStatements("to." + map.getter() + "().addAll(from." + map.getter() + "())");
						} else {
							body.addToStatements("to." + map.setter() + "(from." + map.getter() + "())");
						}
					} else if (np.getNakedBaseType() instanceof INakedEntity || np.getNakedBaseType() instanceof INakedStructuredDataType) {
						OJBlock forBlock = new OJBlock();
						if (np.getNakedBaseType() instanceof INakedStructuredDataType || (deep && np.isComposite())) {
							if (map.isMany()) {
								OJForStatement ws = new OJForStatement("", "", "child", "from." + map.getter() + "()");
								OJBlock whileBody = forBlock;
								ws.setBody(whileBody);
								ws.setElemType(map.javaBaseTypePath());
								whileBody.addToStatements("to." + map.adder() + "(child." + copyMethodName + "())");
								body.addToStatements(ws);
							} else {
								OJIfStatement ifNotNull = new OJIfStatement("from." + map.getter() + "()!=null", "to." + map.setter() + "(from." + map.getter()
										+ "()." + copyMethodName + "())");
								body.addToStatements(ifNotNull);
							}
						} else if (map.isOne() && !np.isInverse()) {
							OJIfStatement ifNotNull = new OJIfStatement("from." + map.getter() + "()!=null", "to." + map.setter() + "(from." + map.getter()
									+ "()." + copyMethodName + "())");
							body.addToStatements(ifNotNull);
						} else if (map.isManyToMany() && np.isInverse()) {

							String localCopyMethodName;
							if (shallowCopy) {
								localCopyMethodName = "copyShallowState";
							} else {
								localCopyMethodName = "copyState";
							}
							body.addToStatements("to." + map.allAdder() + "(" + localCopyMethodName + NameConverter.capitalize(map.umlName()) + "(from." + map.getter() + "()))");
							String operName = localCopyMethodName + NameConverter.capitalize(map.umlName());
							
							List params = new ArrayList();
							params.add(map.javaTypePath());
							OJOperation oper = owner.findOperation(operName, params);
							if (oper == null) {
								OJAnnotatedOperation copyMany = new OJAnnotatedOperation();
								copyMany.setName(operName);
								copyMany.setReturnType(map.javaTypePath());
								owner.addToOperations(copyMany);
								copyMany.addParam("from", map.javaTypePath());
								
								OJField result = new OJField();
								result.setName("result");
								result.setType(map.javaTypePath());
								result.setInitExp("new HashSet<" + map.javaBaseType() + ">()");
								copyMany.getBody().addToLocals(result);
								
								OJForStatement forS = new OJForStatement("","","entity","from");
								forS.setElemType(map.javaBaseTypePath());
								forS.setBody(forBlock);
								forBlock.addToStatements(new OJSimpleStatement("result.add(entity." + copyMethodName + "())"));
								copyMany.getBody().addToStatements(forS);
								
								copyMany.getBody().addToStatements("return result");
							}
						}
					}
				}
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy