From bdf3c7c2dd7e2148882741f84edfd4078af19e1f Mon Sep 17 00:00:00 2001
From: Simon Spinner <simon.spinner@uni-wuerzburg.de>
Date: Wed, 30 Mar 2016 15:12:52 +0200
Subject: [PATCH] Support delegation and requirements for skeletons in generic
 agent.

---
 .../prisma/agent/generic/GenericAgent.java    | 91 +++++++++++++++----
 1 file changed, 71 insertions(+), 20 deletions(-)

diff --git a/tools.descartes.prisma.agent.generic/src/tools/descartes/prisma/agent/generic/GenericAgent.java b/tools.descartes.prisma.agent.generic/src/tools/descartes/prisma/agent/generic/GenericAgent.java
index cc58e35..dd26b8a 100644
--- a/tools.descartes.prisma.agent.generic/src/tools/descartes/prisma/agent/generic/GenericAgent.java
+++ b/tools.descartes.prisma.agent.generic/src/tools/descartes/prisma/agent/generic/GenericAgent.java
@@ -1,23 +1,28 @@
 package tools.descartes.prisma.agent.generic;
 
 import java.io.File;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
 import org.apache.commons.cli.GnuParser;
 import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.Options;
+import org.eclipse.emf.cdo.CDOObject;
 import org.eclipse.emf.common.util.TreeIterator;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature.Setting;
 import org.eclipse.emf.ecore.resource.Resource;
 import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.equinox.app.IApplication;
 import org.eclipse.equinox.app.IApplicationContext;
 
@@ -26,13 +31,14 @@ import edu.kit.ipd.descartes.mm.resourcetype.ResourceType;
 import edu.kit.ipd.descartes.mm.resourcetype.ResourceTypeRepository;
 import edu.kit.ipd.descartes.mm.resourcetype.ResourcetypePackage;
 import tools.descartes.prisma.agent.generic.genericagent.GenericAgentConfiguration;
+import tools.descartes.prisma.agent.generic.genericagent.RequiredObject;
 import tools.descartes.prisma.core.ModelRepository;
 import tools.descartes.prisma.core.adapter.ModelSkeletonAdapter;
+import tools.descartes.prisma.core.adapter.ObjectMatcher;
 import tools.descartes.prisma.core.agent.AgentController;
 import tools.descartes.prisma.core.agent.DelegationProvider;
 import tools.descartes.prisma.core.impl.CDOModelRepository;
 import tools.descartes.prisma.model.scope.DelegatedObject;
-import tools.descartes.prisma.model.scope.ScopeConfiguration;
 import tools.descartes.prisma.model.skeleton.ModelSkeleton;
 
 public class GenericAgent implements IApplication {
@@ -41,19 +47,37 @@ public class GenericAgent implements IApplication {
 
 		private ModelSkeleton skeleton;
 
+		private final Set<EObject> delegatedObjects = new HashSet<>();
+
 		public GenericAgentController(ModelRepository repository, GenericAgentConfiguration configuration) {
 			super(repository, configuration.getScope().getPath(), configuration.getId());
 		}
+
+		@Override
+		protected void notifyAddDelegatedElement(EObject newElement, Map<String, String> additionalProperties) {
+			delegatedObjects.add(newElement);
+		}
+
+		@Override
+		protected void notifyRemoveDelegatedElement(EObject oldElement, Map<String, String> additionalProperties) {
+			delegatedObjects.remove(oldElement);
+		}
+
+		public Set<EObject> getDelegatedObjects() {
+			return delegatedObjects;
+		}
+
 	}
 
 	private class GenericDelegationProvider implements DelegationProvider {
 
 		private final Map<String, Map<String, String>> elements = new HashMap<>();
 
-		public GenericDelegationProvider(ScopeConfiguration configuration) {
+		public GenericDelegationProvider(GenericAgentConfiguration configuration) {
 			for (DelegatedObject curElement : configuration.getDelegatedObjects()) {
-				if (curElement.getObject() instanceof Identifier) {
-					elements.put(((Identifier) curElement).getId(), curElement.getAdditionalProperties().map());
+				EObject object = curElement.getObject();
+				if (object instanceof Identifier) {
+					elements.put(((Identifier) object).getId(), curElement.getAdditionalProperties().map());
 				}
 			}
 		}
@@ -114,11 +138,16 @@ public class GenericAgent implements IApplication {
 
 		ModelRepository repository = new CDOModelRepository(repositoryURL);
 		GenericAgentController agent = new GenericAgentController(repository, configuration);
+
+		agent.setDelegationProvider(new GenericDelegationProvider(configuration));
+
 		agent.start().get();
 
 		replacePublicResources(agent, configuration.getSkeleton());
 
-		agent.apply(configuration.getSkeleton());
+		if (resolveRequiredObjects(agent, configuration)) {
+			agent.apply(configuration.getSkeleton());
+		}
 		
 		agent.stop().get();
 
@@ -128,31 +157,27 @@ public class GenericAgent implements IApplication {
 	@Override
 	public void stop() {
 		// TODO Auto-generated method stub
-
 	}
 
 	private GenericAgentConfiguration loadConfiguration(String configurationPath) {
 		ResourceSet set = new ResourceSetImpl();
 		Resource res = set.getResource(URI.createFileURI(new File(configurationPath).getAbsolutePath()), true);
 		GenericAgentConfiguration configuration = (GenericAgentConfiguration) res.getContents().get(0);
-		return configuration;
-	}
 
-	private void integrateIntoSkeleton(ModelSkeleton skeleton, EObject root) {
-		for (EReference curReference : skeleton.eClass().getEAllContainments()) {
-			if (curReference.getEReferenceType().isSuperTypeOf(root.eClass())) {
-				if (curReference.isMany()) {
-					@SuppressWarnings("unchecked")
-					List<EObject> values = (List<EObject>) skeleton.eGet(curReference);
-					values.add(root);
-				} else {
-					skeleton.eSet(curReference, root);
-				}
-				return;
+		// IMPORTANT: resolve all cross-references
+		EcoreUtil.resolveAll(set);
+		Map<EObject, Collection<Setting>> unresolved = EcoreUtil.UnresolvedProxyCrossReferencer.find(set);
+		for (EObject problemObject : unresolved.keySet()) {
+			Collection<Setting> unresolvedSettings = unresolved.get(problemObject);
+			for (Setting curSetting : unresolvedSettings) {
+				System.out.println("Unresolved proxy: " + curSetting.getEStructuralFeature());
 			}
 		}
+
+		return configuration;
 	}
 
+
 	private void replacePublicResources(GenericAgentController agent, ModelSkeleton skeleton) {
 		// Resource types (e.g., CPU, HDD, DELAY) which are defined globally are
 		// not included in the model skeleton.
@@ -183,4 +208,30 @@ public class GenericAgent implements IApplication {
 		}
 	}
 
+	private boolean resolveRequiredObjects(GenericAgentController agent, GenericAgentConfiguration configuration) {
+		Set<RequiredObject> notResolved = new HashSet<>(configuration.getRequiredObjects());
+		for (EObject curDelegate : agent.getDelegatedObjects()) {
+			for (RequiredObject reqObject : notResolved) {
+				if (ObjectMatcher.matches(curDelegate, reqObject.getObject())) {
+					// Connect the two objects with each other
+					ModelSkeletonAdapter adapter = agent.getModelRepository().adapt(reqObject,
+							ModelSkeletonAdapter.class);
+					adapter.setRepositoryObject((CDOObject) curDelegate);
+
+					// Requirement is fulfilled
+					notResolved.remove(reqObject);
+					break;
+				}
+			}
+		}
+
+		if (!notResolved.isEmpty()) {
+			for (RequiredObject unresolvedObject : notResolved) {
+				System.err.println("Could not resolve required object: " + unresolvedObject.getObject());
+			}
+			return false;
+		}
+		return true;
+	}
+
 }
-- 
GitLab