Commit a1d4f22f authored by Philip Makedonski's avatar Philip Makedonski
Browse files

+ Improved completion for TO, #230

- Improved completion support on top-level for data references
- Improved overall handling of collections, members, simple vs structured data types
- Added filtering for imported and compatible types
- Improved overall handling of collections, members, simple vs structured data types
- Added filtering for imported and compatible types
- Improved tracing
parent 25a00876
Loading
Loading
Loading
Loading
+170 −44
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import java.util.Collections;
import java.util.List;

import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.emf.common.util.ECollections;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.preference.IPreferenceStore;
@@ -31,6 +32,7 @@ import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor;
import org.eclipse.xtext.util.Strings;
import org.etsi.mts.tdl.CastDataUse;
import org.etsi.mts.tdl.CollectionDataType;
import org.etsi.mts.tdl.ComponentInstance;
import org.etsi.mts.tdl.Connection;
import org.etsi.mts.tdl.DataElementUse;
import org.etsi.mts.tdl.DataInstance;
@@ -38,17 +40,25 @@ import org.etsi.mts.tdl.DataType;
import org.etsi.mts.tdl.ElementImport;
import org.etsi.mts.tdl.FormalParameter;
import org.etsi.mts.tdl.Function;
import org.etsi.mts.tdl.GateInstance;
import org.etsi.mts.tdl.Member;
import org.etsi.mts.tdl.MemberAssignment;
import org.etsi.mts.tdl.MemberReference;
import org.etsi.mts.tdl.Message;
import org.etsi.mts.tdl.NamedElement;
import org.etsi.mts.tdl.PackageableElement;
import org.etsi.mts.tdl.Package;
import org.etsi.mts.tdl.Parameter;
import org.etsi.mts.tdl.ParameterBinding;
import org.etsi.mts.tdl.SimpleDataType;
import org.etsi.mts.tdl.StructuredDataInstance;
import org.etsi.mts.tdl.StructuredDataType;
import org.etsi.mts.tdl.structuredobjectives.DataReference;
import org.etsi.mts.tdl.structuredobjectives.EntityBinding;
import org.etsi.mts.tdl.structuredobjectives.EntityReference;
import org.etsi.mts.tdl.structuredobjectives.EventOccurrenceSpecification;
import org.etsi.mts.tdl.structuredobjectives.EventSpecificationTemplate;
import org.etsi.mts.tdl.structuredobjectives.EventTemplateOccurrence;

/**
 * See https://www.eclipse.org/Xtext/documentation/310_eclipse_support.html#content-assist
@@ -65,16 +75,16 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
	public static boolean superRule = false;
	public static boolean superReference = false;
	public static boolean superContainment = false;
	private static String trace = "";
	private static StringBuilder trace = new StringBuilder();

	
	private void trace(ContentAssistContext contentAssistContext, String methodName) {
		System.out.println(methodName);
		System.out.println("    context: "+NodeModelUtils.findActualNodeFor(contentAssistContext.getCurrentModel()).getText().trim()+" : "+contentAssistContext.getCurrentModel().eClass().getName());
		System.out.println("    replace: "+contentAssistContext.getReplaceRegion());
		trace += "\n"+methodName;
		trace += "\n"+"    context: "+NodeModelUtils.findActualNodeFor(contentAssistContext.getCurrentModel()).getText().trim()+" : "+contentAssistContext.getCurrentModel().eClass().getName();
		trace += "\n"+"    replace: "+contentAssistContext.getReplaceRegion();
		trace.append("\n"+methodName);
		trace.append("\n"+"    context: "+NodeModelUtils.findActualNodeFor(contentAssistContext.getCurrentModel()).getText().trim()+" : "+contentAssistContext.getCurrentModel().eClass().getName());
		trace.append("\n"+"    replace: "+contentAssistContext.getReplaceRegion());
	}
	
	private void preTrace(Assignment assignment, ContentAssistContext contentAssistContext) {
@@ -107,20 +117,24 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
	private void postTrace(ICompletionProposalAcceptor acceptor) {
		if (traceCompletions) {
			Object proposals = getProposals(acceptor);
			System.out.println("      proposals: "+proposals);
//			System.out.println("      proposals: "+proposals);
			List<String> proposalDescriptions = ((Collection<ICompletionProposal>)proposals).stream()
					.map(e->(ConfigurableCompletionProposal) e)
					.sorted(ConfigurableCompletionProposal::compareTo)
					.map(ICompletionProposal::getDisplayString)
					.filter(e -> !e.startsWith("--")).toList();
			trace += "\n      proposals: "+proposals;
			trace += "\n        "+String.join("\n        ", proposalDescriptions);
//			trace.append("\n      proposals: "+proposals);
			String proposalsList = String.join("\n        ", proposalDescriptions);
			System.out.println("      proposals: ");
			System.out.println("        "+proposalsList);
			trace.append("\n      proposals: ");
			trace.append("\n        "+proposalsList);

		}
	}

	private void traceUI(ContentAssistContext contentAssistContext, ICompletionProposalAcceptor acceptor,
			String name) {
			StringBuilder name) {
		ICompletionProposal proposal = createCompletionProposal("--TRACE", new StyledString("---TRACE"), null, 1000000001, "", contentAssistContext);
		if (proposal != null) { //TODO: why is this null all of a sudden? 
			((ConfigurableCompletionProposal)proposal).setAdditionalProposalInfo(trace);
@@ -163,7 +177,7 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
		superRule = true;
		superReference = true;
		superContainment = true;
		trace = "";
		trace = new StringBuilder();
		super.createProposals(context, acceptor);
		if (traceCompletionsInUI) {
			traceUI(context, acceptor, trace);
@@ -374,18 +388,25 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
		String prefix = "";
		String suffix = "( )";
		String collectionSuffix = "[ ]";
		completeAssignment(model, context, acceptor, type, prefix, suffix, collectionSuffix);
		completeAssignment(model, context, acceptor, type, prefix, suffix, collectionSuffix, true, true);
	}

	private void completeAssignment(EObject model, ContentAssistContext context, ICompletionProposalAcceptor acceptor, DataType type, String prefix, String suffix, String collectionSuffix) {
	private void completeAssignment(EObject model, ContentAssistContext context, ICompletionProposalAcceptor acceptor, DataType type, boolean named, boolean unnamed) {
		String prefix = "";
		String suffix = "( )";
		String collectionSuffix = "[ ]";
		completeAssignment(model, context, acceptor, type, prefix, suffix, collectionSuffix, named, unnamed);
	}

	private void completeAssignment(EObject model, ContentAssistContext context, ICompletionProposalAcceptor acceptor, DataType type, String prefix, String suffix, String collectionSuffix, boolean named, boolean unnamed) {
		List<NamedElement> namedElements = getAllElementsOfType(model, NamedElement.class);

		for (NamedElement ne : namedElements) {
			boolean accept = false;
			//TODO: priorities
			if (ne instanceof DataInstance && ((DataInstance)ne).getDataType().conformsTo(type)) {
			if (ne instanceof DataInstance && ((type == null) ||((DataInstance)ne).getDataType().conformsTo(type))) {
				accept = true;
			} else if (ne instanceof DataType && ((DataType) ne).conformsTo(type)) {
			} else if (ne instanceof DataType && ((type == null) || ((DataType) ne).conformsTo(type))) {
				//accept = true;
				if (ne instanceof SimpleDataType) {
					
@@ -394,14 +415,18 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
					if (ne instanceof CollectionDataType) {
						usedSuffix = collectionSuffix;
					}
					if (unnamed) {
						acceptor.accept(createCompletionProposal(usedSuffix, new StyledString(usedSuffix).append(" : new anonymous instance of type "+ne.getName(), StyledString.DECORATIONS_STYLER), getImage(ne), 1200, "", context));
					}
					if (named) {
						acceptor.accept(createCompletionProposal(prefix+ne.getName()+usedSuffix, new StyledString(prefix+ne.getName()+usedSuffix).append(" : new instance of type", StyledString.DECORATIONS_STYLER), getImage(ne), 1100, "", context));
					}
			} else if (ne instanceof Function && ((Function) ne).getReturnType().conformsTo(type)) {
				}
			} else if (ne instanceof Function && ((type == null) || ((Function) ne).getReturnType().conformsTo(type))) {
				accept = true;
			} else if (ne instanceof FormalParameter && EcoreUtil2.isAncestor(EcoreUtil2.getContainerOfType(model, PackageableElement.class), ne)) {
				accept = true;
			} else if (ne instanceof Parameter && ((Parameter) ne).getDataType().conformsTo(type) && ne.container() instanceof StructuredDataType) {
			} else if (ne instanceof Parameter && (((Parameter) ne).getDataType().conformsTo(type) && ne.container() instanceof StructuredDataType)) {
				StructuredDataType dt = ((StructuredDataType) ne.container());
				List<StructuredDataInstance> compatibleDataInstances = getAllElementsOfType(model, StructuredDataInstance.class).stream()
					.map(sdi -> (StructuredDataInstance) sdi)
@@ -418,11 +443,18 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
		}
	}
	private <T extends NamedElement> List<T> getAllElementsOfType(EObject model, Class<T> type) {
		List<T> namedElements = EcoreUtil2.getAllContentsOfType(model.eResource(), type);
		//TODO: filter imported if not all?
		EcoreUtil2.getAllContentsOfType(model.eResource(), ElementImport.class).stream()
			.map(e -> e.getImportedPackage())
			.forEach(e -> namedElements.addAll(EcoreUtil2.getAllContentsOfType(e.eResource(), type)));
		Package parentPackage = EcoreUtil2.getContainerOfType(model, Package.class);
		List<T> namedElements = EcoreUtil2.getAllContentsOfType(parentPackage, type);
		List<ElementImport> imports = EcoreUtil2.getAllContentsOfType(parentPackage, ElementImport.class);
		for (ElementImport i : imports) {
			List<T> elements = EcoreUtil2.getAllContentsOfType(i.getImportedPackage(), type);
			EList<PackageableElement> importedElements = i.getImportedElement();
			for (T e : elements) {
				if (importedElements.isEmpty() || importedElements.contains(e)) {
					namedElements.add(e);
				}
			}
		}
		return namedElements;
	}

@@ -522,17 +554,25 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
		if (superReference)
			super.completeMemberReference_Member(model, assignment, context, acceptor);
	}

	
	private void completeMemberReferenceForDataUse(EObject model, ContentAssistContext context, ICompletionProposalAcceptor acceptor, String prefix, String suffix, String description) {
		completeMemberReferenceForDataUse(model, context, acceptor, prefix, suffix, suffix, description, null);
	}
	
	private <T extends DataType> void completeMemberReferenceForDataUse(EObject model, ContentAssistContext context, ICompletionProposalAcceptor acceptor, String prefix, String suffix, String collectionSuffix, String description, Class<T> memberType) {
		if (model instanceof CastDataUse) {
			DataType dataType = ((CastDataUse) model).getDataType();
			//?TODO: why dpes this error out
			//?TODO: why does this error out
			if (dataType instanceof StructuredDataType) {
				for (Member m : ((StructuredDataType) dataType).allMembers()) {
					if (memberType == null || memberType.isInstance(m.getDataType())) {
						if (m.getDataType() instanceof CollectionDataType) {
							acceptor.accept(createCompletionProposal(m.getName()+collectionSuffix, new StyledString(prefix+m.getName()+collectionSuffix).append(description, StyledString.DECORATIONS_STYLER), getImage(m), 1000, "", context));
						} else {
							acceptor.accept(createCompletionProposal(m.getName()+suffix, new StyledString(prefix+m.getName()+suffix).append(description, StyledString.DECORATIONS_STYLER), getImage(m), 1000, "", context));
						}
					}
				}
			}
		} else if (model instanceof DataElementUse) {
			//TODO: add suffix? e.g. =
			NamedElement dataElement = ((DataElementUse) model).getDataElement();
@@ -546,6 +586,7 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
				//TODO: filter parentheses
				prefix = prefix.replace("(", "");
				suffix = suffix.replace(")", "");
				collectionSuffix = collectionSuffix.replace(")", "");
			}
			
			//TODO: a bit of a hack.. this belongs elsewhere -> affects the whole chain, should be applied selectively
@@ -556,23 +597,23 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
//				dataElement = reduction.get(reduction.size()-2).getMember().getDataType();
//			}
			if (dataElement instanceof StructuredDataType) { 
				acceptMembers(context, acceptor, prefix, suffix, description, assigned, (StructuredDataType) dataElement);
				acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, assigned, (StructuredDataType) dataElement, memberType);
			} else if (dataElement instanceof StructuredDataInstance) {
				acceptMembers(context, acceptor, prefix, suffix, description, assigned, (StructuredDataType) ((StructuredDataInstance)dataElement).getDataType());
				acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, assigned, (StructuredDataType) ((StructuredDataInstance)dataElement).getDataType(), memberType);
			} else if (dataElement instanceof FormalParameter) {
				DataType dataType = ((FormalParameter) dataElement).getDataType();
				if (dataType instanceof StructuredDataType) {
					acceptMembers(context, acceptor, prefix, suffix, description, assigned, (StructuredDataType) dataType);
					acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, assigned, (StructuredDataType) dataType, memberType);
				}
			} else if (dataElement instanceof Function) {
				DataType dataType = ((Function) dataElement).getReturnType();
				if (dataType instanceof StructuredDataType) {
					acceptMembers(context, acceptor, prefix, suffix, description, assigned, (StructuredDataType) dataType);
					acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, assigned, (StructuredDataType) dataType, memberType);
				}
			}
		} else if (model instanceof StructuredDataType) {
			//TODO: add already assigned
			acceptMembers(context, acceptor, prefix, suffix, description, Collections.emptyList(), (StructuredDataType) model);
			acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, Collections.emptyList(), (StructuredDataType) model, memberType);
			
		} else if (model instanceof StructuredDataInstance) {
			StructuredDataInstance instance = (StructuredDataInstance) model;
@@ -582,30 +623,40 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
				.map(e -> (Parameter) e)
				.toList();

			acceptMembers(context, acceptor, prefix, suffix, description, assigned, (StructuredDataType) instance.getDataType());
			acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, assigned, (StructuredDataType) instance.getDataType(), memberType);
		} else if (model instanceof MemberReference) {
			DataType dataType = ((MemberReference) model).getMember().getDataType();
			//TODO: add already assigned
			if (dataType instanceof StructuredDataType) {
				acceptMembers(context, acceptor, prefix, suffix, description, Collections.emptyList(), (StructuredDataType) dataType);
				acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, Collections.emptyList(), (StructuredDataType) dataType, memberType);
			}
		} else if (model instanceof Member) {
			DataType dataType = ((Member) model).getDataType();
			//TODO: add already assigned
			if (dataType instanceof StructuredDataType) {
				acceptMembers(context, acceptor, prefix, suffix, description, Collections.emptyList(), (StructuredDataType) dataType);
				acceptMembers(context, acceptor, prefix, suffix, collectionSuffix, description, Collections.emptyList(), (StructuredDataType) dataType, memberType);
			}
		}
	}

	private void acceptMembers(ContentAssistContext context, ICompletionProposalAcceptor acceptor, String prefix,
			String suffix, String description, List<Parameter> assigned, StructuredDataType type) {
			acceptMembers(context, acceptor, prefix, suffix, suffix, description, Collections.emptyList(), type, null);
	}
	private <T extends DataType> void acceptMembers(ContentAssistContext context, ICompletionProposalAcceptor acceptor, String prefix,
			String suffix, String collectionSuffix, String description, List<Parameter> assigned, StructuredDataType type, Class<T> memberType) {
		for (Member m : type.allMembers()) {
			if (!assigned.contains(m)) {
				if (memberType == null || memberType.isInstance(m.getDataType())) {
					if (m.getDataType() instanceof CollectionDataType) {
						acceptor.accept(createCompletionProposal(prefix+m.getName()+collectionSuffix, new StyledString(prefix+m.getName()+collectionSuffix).append(description, StyledString.DECORATIONS_STYLER), getImage(m), 100000, "", context));
					} else {
						acceptor.accept(createCompletionProposal(prefix+m.getName()+suffix, new StyledString(prefix+m.getName()+suffix).append(description, StyledString.DECORATIONS_STYLER), getImage(m), 100000, "", context));
					}
				}
			}
		}
	}
	
	@Override
	public void completeCollectionItemFragment_Item(EObject model, Assignment assignment, ContentAssistContext context,
@@ -777,7 +828,7 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {


	public void completeDataElementUse_DataElement(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		if (model instanceof ParameterBinding || model instanceof MemberAssignment || model instanceof MemberReference) {
		if (model instanceof ParameterBinding || model instanceof MemberAssignment || model instanceof MemberReference || model instanceof DataReference) {
//			complete_ParameterBinding(model, ruleCall, context, acceptor);
			return;
		}
@@ -786,7 +837,7 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
			super.completeDataElementUse_DataElement(model, assignment, context, acceptor);
	}
	public void complete_DataElementUse(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		if (model instanceof ParameterBinding || model instanceof MemberAssignment || model instanceof MemberReference) {
		if (model instanceof ParameterBinding || model instanceof MemberAssignment || model instanceof MemberReference || model instanceof DataReference) {
//			complete_ParameterBinding(model, ruleCall, context, acceptor);
			return;
		}
@@ -842,6 +893,60 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
	//copied from above -> reuse where no change
	//TODO: refer to base rules if nothing specific
	//---------------------------------------------------------------
	@Override
	public void completeDataReferenceFragment_Content(EObject model, Assignment assignment,
			ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		//TODO: check if top level and component reference
		//TODO: add constraint too
		if (model.eContainer() instanceof EventOccurrenceSpecification) {
			//TODO: extract and reuse
			EventOccurrenceSpecification eos = ((EventOccurrenceSpecification) model.eContainer());
			EList<EntityReference> entityReferences = ECollections.newBasicEList();
			entityReferences.add(eos.getEntityReference());
			entityReferences.addAll(eos.getOppositeEntityReference());
			EList<GateInstance> allGates = getAllGates(entityReferences);
			completeCompatibleDataElements(model, context, acceptor, allGates);
		} else if (model.eContainer() instanceof EventTemplateOccurrence) {
			EventTemplateOccurrence eto = ((EventTemplateOccurrence) model.eContainer());
			EList<EntityReference> entityReferences = ECollections.newBasicEList();
			for (EntityBinding b : eto.getEntityBinding()) {
				entityReferences.add(b.getOccurrenceEntity());
			}
			EList<GateInstance> allGates = getAllGates(entityReferences);
			completeCompatibleDataElements(model, context, acceptor, allGates);						
		} else {
			completeAssignment(model, context, acceptor, null, "", " containing { }", " including { }", true, false);
		}
		if (superContainment)
			super.completeDataReferenceFragment_Content(model, assignment, context, acceptor);
	}

	private EList<GateInstance> getAllGates(EList<EntityReference> entityReferences) {
		EList<GateInstance> allGates = ECollections.newBasicEList();
		for (EntityReference er : entityReferences) {
			if (er.getComponent() != null) {
				allGates.addAll(er.getComponent().getType().allGates());
			}
		}
		return allGates;
	}

	private void completeCompatibleDataElements(EObject model, ContentAssistContext context, ICompletionProposalAcceptor acceptor,
			EList<GateInstance> allGates) {
		EList<DataType> allDataTypes = ECollections.newBasicEList();
		for (GateInstance g : allGates) {
			allDataTypes.addAll(g.getType().allDataTypes());
		}
		if (allDataTypes.isEmpty()) {
			completeAssignment(model, context, acceptor, null, "", " containing { }", " including { }", true, false);
		} else {
			for (DataType d : allDataTypes) {
				//TODO: handle simple vs structured?
				completeAssignment(model, context, acceptor, d, "", " containing { }", " including { }", true, false);
			}
		}
	}
	
	public void complete_TODataElementUse(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
		complete_DataElementUse(model, ruleCall, context, acceptor);
	}
@@ -859,7 +964,16 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
	@Override
	public void completeTOParameterBinding_Parameter(EObject model, Assignment assignment, ContentAssistContext context,
			ICompletionProposalAcceptor acceptor) {
		completeParameterBinding_Parameter(model, assignment, context, acceptor);
//		completeParameterBinding_Parameter(model, assignment, context, acceptor);
		if (model instanceof DataElementUse) {
			completeMemberReferenceForDataUse(model, context, acceptor, "", " = ?", " : assign to member");
			//TODO: only for structured / collection
			completeMemberReferenceForDataUse(model, context, acceptor, "", " containing { }", " including { }", " : assign anonymous instance to member", StructuredDataType.class);
			completeMemberReferenceForDataUse(model, context, acceptor, "", " containing { }", " including { }", " : assign anonymous instance to member", CollectionDataType.class);
			return; 
		}
		if (superReference)
			super.completeParameterBinding_Parameter(model, assignment, context, acceptor);
	}

	@Override
@@ -877,14 +991,20 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
			//adapted for TO!
			var pb = ((ParameterBinding) model);
			var type = pb.getParameter().getDataType();
			completeAssignment(model, context, acceptor, type);
//			completeAssignment(model, context, acceptor, type);
			if (pb.getComment().isEmpty()) {
				completeAssignment(model, context, acceptor, type, "", " containing { }", " including { }", false, true);
				completeAssignment(model, context, acceptor, type, " = ", " containing { }", " including { }", true, false);
			} else {
				completeAssignment(model, context, acceptor, type, "", " containing { }", " including { }", true, false);
			}
			
			return;
		}

		//super: completeRuleCall
		if (superContainment)
			super.completeParameterBinding_DataUse(model, assignment, context, acceptor);
//		if (superContainment)
//			super.completeParameterBinding_DataUse(model, assignment, context, acceptor);
	}
	
	@Override
@@ -905,7 +1025,12 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
			//TODO: add anything that contains string fields?
			//start with 
			//TODO: handle containing / indicating value / etc.?
			completeAssignment(model, context, acceptor, type);
//			if (pb.getComment().isEmpty()) {
//				completeAssignment(model, context, acceptor, type, "", " containing { }", " including { }", false);
//				completeAssignment(model, context, acceptor, type, "= ", " containing { }", " including { }", true);
//			} else {
//				completeAssignment(model, context, acceptor, type, "", " containing { }", " including { }", true);
//			}
		}	
		if ((model instanceof DataElementUse)) {
			//NOTE: adapted for TO
@@ -933,7 +1058,8 @@ public class TDLtxProposalProvider extends AbstractTDLtxProposalProvider {
			if (dataElement instanceof CollectionDataType) {
				DataType itemType = ((CollectionDataType) dataElement).getItemType();
				//TODO: spacing issue / empty data element
				completeAssignment(model, context, acceptor, itemType, "", " containing { }", " including { }");
				//TODO: namedOnly?
				completeAssignment(model, context, acceptor, itemType, "", " containing { }", " including { }", true, false);
				return; //?
			}
		}