/* * MicroJIAC - A Lightweight Agent Framework * This file is part of MicroJIAC Config. * * Copyright (c) 2007-2012 DAI-Labor, Technische Universität Berlin * * This library includes software developed at DAI-Labor, Technische * Universität Berlin (http://www.dai-labor.de) * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see <http://www.gnu.org/licenses/>. */ /* * $Id$ */ package de.jiac.micro.config.analysis; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import de.dailab.jiac.common.aamm.IItemType; import de.dailab.jiac.common.aamm.IModelBase; import de.dailab.jiac.common.aamm.IPropertyType; import de.dailab.jiac.common.aamm.ListPropertyType; import de.dailab.jiac.common.aamm.ReferencableAgentElementType; import de.dailab.jiac.common.aamm.ReferencableAgentType; import de.dailab.jiac.common.aamm.ReferencableNodeType; import de.dailab.jiac.common.aamm.ReferencableObjectType; import de.dailab.jiac.common.aamm.ReferenceType; import de.dailab.jiac.common.aamm.ext.Reference; import de.dailab.jiac.common.aamm.resolve.MergedConfiguration; import de.dailab.jiac.common.aamm.resolve.ResolutionException; import de.jiac.micro.config.util.MicroJIACToolContext; /** * @author Marcel Patzlaff * @version $Revision:$ */ public class ConventionEnforcer { private final MicroJIACToolContext _context; public ConventionEnforcer(MicroJIACToolContext context) { _context= context; } public synchronized void analyseAndEnforce(MergedConfiguration config) throws IOException, ResolutionException { ClassInfoPool infoPool= new ClassInfoPool(_context.getLoader()); infoPool.requestClassInfo("de.jiac.micro.core.scope.Scope$ScopeRunner"); for(Reference agentRef : config.agentsToUse) { ReferencableAgentType agent= config.getAgent(agentRef); infoPool.requestClassInfo(agent.getClazz()); for(IModelBase agentElementRef : agent.getAgentElements()) { ReferencableAgentElementType agentElement= config.getAgentElement(agentElementRef); infoPool.requestClassInfo(agentElement.getClazz()); } } for(Reference nodeRef : config.nodesToUse) { ReferencableNodeType node= config.getNode(nodeRef); for(IPropertyType property : node.getProperties()) { if(property instanceof ListPropertyType && property.getName().equals("nodeComponents")) { ListPropertyType nodeComponents= (ListPropertyType) property; for(IItemType item : nodeComponents.getItems()) { ReferencableObjectType nodeComponent= config.getObject(item); infoPool.requestClassInfo(nodeComponent.getClazz()); } } } } infoPool.buildPool(); dotNode(config, config.nodesToUse[0], infoPool); } private void dotNode(MergedConfiguration config, Reference nodeRef, ClassInfoPool infoPool) throws IOException, ResolutionException { ReferencableNodeType node= config.getNode(nodeRef); HashSet<ClassInfo> nodeComps= new HashSet<ClassInfo>(); for(IPropertyType property : node.getProperties()) { if(property instanceof ListPropertyType && property.getName().equals("nodeComponents")) { ListPropertyType nodeComponents= (ListPropertyType) property; for(IItemType item : nodeComponents.getItems()) { ReferencableObjectType nodeComponent= config.getObject(item); nodeComps.add(infoPool.getClassInfo(nodeComponent.getClazz())); } } } HashMap<String, HashSet<ClassInfo>> allAgentElements= new HashMap<String, HashSet<ClassInfo>>(); for(ReferenceType agentRef : node.getAgentRefs()) { ReferencableAgentType agent= config.getAgent(agentRef); HashSet<ClassInfo> elements= new HashSet<ClassInfo>(); for(IModelBase agentElementRef : agent.getAgentElements()) { ReferencableAgentElementType agentElement= config.getAgentElement(agentElementRef); ClassInfo info= infoPool.getClassInfo(agentElement.getClazz()); elements.add(info); } allAgentElements.put(agent.getId(), elements); } File file= File.createTempFile("testgraph_" + nodeRef.id, ".dot"); PrintStream printer= new PrintStream(new FileOutputStream(file)); printer.println("digraph references {"); printer.println(" graph [rankdir = \"LR\"];"); printer.println(" subgraph cluster_0 {"); for(ClassInfo ci : nodeComps) { printer.println(" \"" + nodeRef.id + ":" + ci.className + "\" [label = \"" + getSmallName(ci.className) + "\"];"); } printer.println(" label = \"" + nodeRef.id + "\";"); printer.println(" }"); printer.println(); Iterator<String> iter= allAgentElements.keySet().iterator(); for(int i= 1; iter.hasNext(); ++i) { printer.println(" subgraph cluster_" + i + "{"); String agentId= iter.next(); for(ClassInfo ci : allAgentElements.get(agentId)) { printer.println(" \"" + agentId + ":" + ci.className + "\" [label = \"" + getSmallName(ci.className) + "\"];"); } printer.println(" label = \"" + agentId + "\";"); printer.println(" }"); printer.println(); } // now draw the relations // system handles ClassInfo scopeInfo= infoPool.getClassInfo("de.jiac.micro.core.scope.Scope$ScopeRunner"); for(String indirectHandle : scopeInfo.indirectHandles) { printer.println(" \"SYSTEM\" -> \"" + getSmallName(indirectHandle) + "\" [label = \"INDIRECT\"];"); } // handle relations ClassInfo handleRoot= infoPool.getClassInfo("de.jiac.micro.core.IHandle"); HashSet<ClassInfo> handleInfos= infoPool.getDerivativeClassInfos(handleRoot); for(ClassInfo ci : handleInfos) { if(!ci.isInterface) { ClassInfo superClass= infoPool.getClassInfo(ci.superClassName); if(handleInfos.contains(superClass)) { printer.println(" \"" + getSmallName(ci.className) + "\" -> \"" + getSmallName(superClass.className) + "\";"); } } for(String intfName : ci.superInterfaceNames) { ClassInfo superInterface= infoPool.getClassInfo(intfName); if(handleInfos.contains(superInterface)) { printer.println(" \"" + getSmallName(ci.className) + "\" -> \"" + getSmallName(superInterface.className) + "\";"); } } } for(ClassInfo ci : nodeComps) { if(ci.getProvidedHandle() != null) { printer.println(" \"" + nodeRef.id + ":" + ci.className + "\" -> \"" + getSmallName(ci.getProvidedHandle()) + "\" [label = \"DIRECT\"];"); } for(String indirectHandle : ci.indirectHandles) { printer.println(" \"" + nodeRef.id + ":" + ci.className + "\" -> \"" + getSmallName(indirectHandle) + "\" [label = \"INDIRECT\"];"); } } for(String agentId : allAgentElements.keySet()) { for(ClassInfo ci : allAgentElements.get(agentId)) { if(ci.isActuator()) { printer.append(" \"" + agentId + ":" + ci.className + "\" -> \""); if(ci.getProvidedHandle() != null) { printer.append(getSmallName(ci.getProvidedHandle())); } else { printer.append("null"); } printer.println("\" [label = \"DIRECT\"];"); } for(String indirectHandle : ci.indirectHandles) { printer.append(" \"" + agentId + ":" + ci.className + "\" -> \""); printer.append(getSmallName(indirectHandle)).println("\" [label = \"INDIRECT\"];"); } for(MethodKey key : ci.referencedHandlesInMethods.keySet()) { for(String handleClassName : ci.referencedHandlesInMethods.get(key)) { printer.append(" \"" + agentId + ":" + ci.className + "\" -> \""); printer.println(getSmallName(handleClassName) + "\" [label = \"" + key.methodName + "\"];"); } } } } printer.println("}"); printer.close(); } private static String getSmallName(String className) { return className.substring(className.lastIndexOf('.') + 1); } }