package org.cagrid.mms.service.impl.cadsr; import gov.nih.nci.cadsr.umlproject.domain.Project; import gov.nih.nci.cadsr.umlproject.domain.UMLAssociationMetadata; import gov.nih.nci.cadsr.umlproject.domain.UMLClassMetadata; import gov.nih.nci.cagrid.metadata.dataservice.DomainModel; import gov.nih.nci.cagrid.metadata.dataservice.DomainModel.ExposedUMLAssociationCollection; import gov.nih.nci.cagrid.metadata.dataservice.DomainModel.ExposedUMLClassCollection; import gov.nih.nci.cagrid.metadata.dataservice.DomainModel.UmlGeneralizationCollection; import gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation; import gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation.SourceUMLAssociationEdge; import gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation.TargetUMLAssociationEdge; import gov.nih.nci.cagrid.metadata.dataservice.UMLAssociationEdge; import gov.nih.nci.cagrid.metadata.dataservice.UMLClass; import gov.nih.nci.cagrid.metadata.dataservice.UMLClassReference; import gov.nih.nci.cagrid.metadata.dataservice.UMLGeneralization; import gov.nih.nci.system.applicationservice.ApplicationException; import gov.nih.nci.system.applicationservice.ApplicationService; import gov.nih.nci.system.query.hibernate.HQLCriteria; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cagrid.mms.model.UMLAssociationExclude; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.ProjectionList; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.SimpleExpression; /** * DomainModelBuilder Builds a DomainModel using a thread pool for concurrent * requests to the remote ApplicationService. TODO: attempt to handle remote * connection refusals by sleeping for a few seconds and retrying? * * @author <A HREF="MAILTO:oster@bmi.osu.edu">Scott Oster</A> * @author <A HREF="MAILTO:ervin@bmi.osu.edu">David W. Ervin</A> * @created Jun 1, 2006 * @version $Id: DomainModelBuilder.java,v 1.1 2008-11-26 21:04:20 oster Exp $ */ public class DomainModelBuilder { private static final String EXCLUDE_WILDCARD = "*"; private static final int DEFAULT_POOL_SIZE = 5; protected static Log LOG = LogFactory.getLog(DomainModelBuilder.class.getName()); private ApplicationService cadsr = null; private ExecutorService workManager = null; public DomainModelBuilder(ApplicationService cadsr) { this.cadsr = cadsr; } /** * Gets a DomainModel that represents the entire project * * @param project * The project for which a domain model will be created * @return The domain model */ public DomainModel createDomainModel(Project project) throws DomainModelGenerationException { Project proj; try { proj = CaDSRUtils.findCompleteProject(this.cadsr, project); } catch (CaDSRGeneralException e) { throw new DomainModelGenerationException("Problem with specified project:" + e.getMessage(), e); } // get all classes in project, preloading attributes, semantic // metadata (current hibernate we are using doesn't process more // than 1 preload, but this should work when we move forward) HQLCriteria criteria = new HQLCriteria("SELECT DISTINCT c FROM UMLClassMetadata c " + "LEFT JOIN c.UMLAttributeMetadataCollection as atts " + "LEFT JOIN atts.semanticMetadataCollection " + "LEFT JOIN c.semanticMetadataCollection " + "WHERE c.project.id='" + proj.getId() + "'"); UMLClassMetadata classArr[]; try { classArr = getProjectClasses(proj, criteria); } catch (ApplicationException e) { throw new DomainModelGenerationException("Problem getting project's classes.", e); } UMLAssociationMetadata[] assocArr; try { assocArr = getProjectAssociationClosure(proj, classArr, null); } catch (ApplicationException e) { throw new DomainModelGenerationException("Problem getting project's associations.", e); } return buildDomainModel(proj, classArr, assocArr); } /** * Gets a DomainModel that represents the project and packages * * @param project * The project to build a domain model for * @param packageNames * The names of packages to include in the domain model * @return The domain model */ public DomainModel createDomainModelForPackages(Project project, String[] packageNames) throws DomainModelGenerationException { Project proj; try { proj = CaDSRUtils.findCompleteProject(this.cadsr, project); } catch (CaDSRGeneralException e) { throw new DomainModelGenerationException("Problem with specified project:" + e.getMessage(), e); } UMLClassMetadata classArr[] = null; UMLAssociationMetadata[] assocArr = null; if (packageNames != null && packageNames.length > 0) { // build up the OR for all the package names Set<String> namesSet = new HashSet<String>(); for (String pack : packageNames) { namesSet.add(pack); } String packageNameFilter = createFilter(namesSet); // get all classes in project (where package name IN // (packageNames[0], packageNames[1] ...), pre-loading attributes, // semantic metadata HQLCriteria criteria = new HQLCriteria("SELECT DISTINCT c FROM UMLClassMetadata c " + "LEFT JOIN c.UMLAttributeMetadataCollection as atts " + "LEFT JOIN atts.semanticMetadataCollection " + "LEFT JOIN c.semanticMetadataCollection " + "WHERE c.project.id='" + proj.getId() + "' " + "AND c.UMLPackageMetadata.name " + packageNameFilter); try { classArr = getProjectClasses(proj, criteria); } catch (ApplicationException e) { throw new DomainModelGenerationException("Problem getting project's classes.", e); } try { assocArr = getProjectAssociationClosure(proj, classArr, null); } catch (ApplicationException e) { throw new DomainModelGenerationException("Problem getting project's associations.", e); } } return buildDomainModel(proj, classArr, assocArr); } /** * Gets a DomainModel that represents the project and listed classes; * associations will all those between listed classes. * * @param project * The project to build a domain model for * @param exposedClasses * fully qualified name of classes to include * @return The domain model * @throws DomainModelGenerationException */ public DomainModel createDomainModelForClasses(Project project, String[] exposedClasses) throws DomainModelGenerationException { return createDomainModelForClassesWithExcludes(project, exposedClasses, null); } /** * Gets a DomainModel that represents the project and listed classes; * associations will all those between listed classes that are not in the * excludes list. * * @param project * The project to build a domain model for * @param fullClassNames * fully qualified name of classes to include * @param excludedAssociations * associations to not include * @return The domain model * @throws DomainModelGenerationException */ public DomainModel createDomainModelForClassesWithExcludes(Project project, String[] fullClassNames, UMLAssociationExclude[] excludedAssociations) throws DomainModelGenerationException { Project proj; try { proj = CaDSRUtils.findCompleteProject(this.cadsr, project); } catch (CaDSRGeneralException e) { throw new DomainModelGenerationException("Problem with specified project:" + e.getMessage(), e); } UMLClassMetadata classArr[] = null; UMLAssociationMetadata[] assocArr = null; if (fullClassNames != null && fullClassNames.length > 0) { Set<String> namesSet = new HashSet<String>(); for (String pack : fullClassNames) { namesSet.add(pack); } String fqnFilter = createFilter(namesSet); // get all classes in project (wherefullyQualifiedName IN // (fullClassNames[0], fullClassNames[1] ...), pre-loading // attributes, // semantic metadata HQLCriteria criteria = new HQLCriteria("SELECT DISTINCT c FROM UMLClassMetadata c " + "LEFT JOIN c.UMLAttributeMetadataCollection as atts " + "LEFT JOIN atts.semanticMetadataCollection " + "LEFT JOIN c.semanticMetadataCollection " + "WHERE c.project.id='" + proj.getId() + "' " + "AND c.fullyQualifiedName " + fqnFilter); try { classArr = getProjectClasses(proj, criteria); } catch (ApplicationException e) { throw new DomainModelGenerationException("Problem getting project's classes.", e); } try { assocArr = getProjectAssociationClosure(proj, classArr, excludedAssociations); } catch (ApplicationException e) { throw new DomainModelGenerationException("Problem getting project's associations.", e); } } return buildDomainModel(proj, classArr, assocArr); } private String createClassIDFilter(UMLClassMetadata[] classArr) { // create a list of class IDs for building closures Set<String> idSet = new HashSet<String>(); if (classArr != null) { for (UMLClassMetadata element : classArr) { idSet.add(element.getId()); } } return createFilter(idSet); } private String createFilter(Set<String> items) { String filter = ""; StringBuffer sb = new StringBuffer(); // now build the criteria from the set for (Iterator iter = items.iterator(); iter.hasNext();) { String item = (String) iter.next(); sb.append("'" + item + "'"); if (iter.hasNext()) { sb.append(", "); } } if (items.size() > 0) { filter = " IN (" + sb.toString() + ")"; } if (LOG.isDebugEnabled()) { LOG.debug("Filter was:" + filter); } return filter; } /** * Gets all of the associations of this project that are closed over the * classes specified in the classArr, and not present in the excludes list. * * @param proj * @param classArr * @param excludedAssociations * @return The UML Association metadata array * @throws ApplicationException */ private UMLAssociationMetadata[] getProjectAssociationClosure(Project proj, UMLClassMetadata[] classArr, UMLAssociationExclude[] excludedAssociations) throws ApplicationException { if (classArr == null || classArr.length <= 0) { return null; } // get all associations between classes we are exposing String classIDFilter = createClassIDFilter(classArr); String associationAlias = "assoc"; String excludesFilter = createAssociationExcludeFilter(excludedAssociations, associationAlias); // get all associations in project HQLCriteria hql = new HQLCriteria(("SELECT " + associationAlias + ", " + associationAlias + ".sourceRoleName, " + associationAlias + ".sourceUMLClassMetadata.id, " + associationAlias + ".targetRoleName, " + associationAlias + ".targetUMLClassMetadata.id " + "FROM UMLAssociationMetadata AS " + associationAlias + " WHERE " + associationAlias + ".project.id='" + proj.getId() + "' AND " + associationAlias + ".sourceUMLClassMetadata.id " + classIDFilter + " AND " + associationAlias + ".targetUMLClassMetadata.id " + classIDFilter + " " + excludesFilter).trim()); if (LOG.isDebugEnabled()) { LOG.debug("Issuing Association query:" + hql.getHqlString()); } // association, src role, src id, tar role, tar id long start = System.currentTimeMillis(); List rList = this.cadsr.query(hql, UMLAssociationMetadata.class.getName()); // the query incorrectly returns more than one association for the same // thing (the association ids are even different), so // I build up a unique set based on source and target ids and role names // I shouldn't have to do this (its a database view bug), but it creates // a lot of unnecessary processing so I'm cutting it out here Iterator iterator = rList.iterator(); Map<String, UMLAssociationMetadata> uniqMap = new HashMap<String, UMLAssociationMetadata>(); while (iterator.hasNext()) { Object[] res = (Object[]) iterator.next(); UMLAssociationMetadata assoc = (UMLAssociationMetadata) res[0]; String srcRole = (String) res[1]; String srcID = (String) res[2]; String targetRole = (String) res[3]; String targetID = (String) res[4]; String createdKey = srcRole + srcID + targetRole + targetID; LOG.debug("Created unique key:" + createdKey); uniqMap.put(createdKey, assoc); } Collection uniqList = uniqMap.values(); LOG.info("Association filtering eliminated " + (rList.size() - uniqList.size()) + " associations from returned list of:" + rList.size()); UMLAssociationMetadata assocArr[] = new UMLAssociationMetadata[uniqList.size()]; // caCORE's toArray(arr) is broken (cacore bug #1382), so need to do // this way System.arraycopy(uniqList.toArray(), 0, assocArr, 0, uniqList.size()); double duration = (System.currentTimeMillis() - start) / 1000.0; LOG.info(proj.getShortName() + "'s association fetch took " + duration + " seconds, and found " + assocArr.length + " associations."); return assocArr; } /** * @param excludedAssociations * @return An HQL fragment to exclude the specified associations */ private String createAssociationExcludeFilter(UMLAssociationExclude[] excludedAssociations, String alias) { if (excludedAssociations == null || excludedAssociations.length == 0) { return ""; } StringBuffer sb = new StringBuffer(); for (UMLAssociationExclude exclude : excludedAssociations) { int filterCount = 0; sb.append(" AND NOT("); // now only process non wildcards (because this criteria is "not"ed // so not filtering on the wildcards makes them be excluded) if (exclude.getSourceClassName()!=null && !exclude.getSourceClassName().equals(EXCLUDE_WILDCARD)) { if (filterCount++ > 0) { sb.append(" AND "); } sb.append(alias + ".sourceUMLClassMetadata.fullyQualifiedName='" + exclude.getSourceClassName() + "'"); } if (exclude.getTargetClassName()!=null && !exclude.getTargetClassName().equals(EXCLUDE_WILDCARD)) { if (filterCount++ > 0) { sb.append(" AND "); } sb.append(alias + ".targetUMLClassMetadata.fullyQualifiedName='" + exclude.getTargetClassName() + "'"); } if (exclude.getSourceRoleName()!=null && !exclude.getSourceRoleName().equals(EXCLUDE_WILDCARD)) { if (filterCount++ > 0) { sb.append(" AND "); } sb.append(alias + ".sourceRoleName='" + exclude.getSourceRoleName() + "'"); } if (exclude.getTargetRoleName()!=null && !exclude.getTargetRoleName().equals(EXCLUDE_WILDCARD)) { if (filterCount++ > 0) { sb.append(" AND "); } sb.append(alias + ".targetRoleName='" + exclude.getTargetRoleName() + "'"); } // check for all wildcards if (filterCount == 0) { // just stop processing and create a predicate thats never true, // because excluding // everything will obviously yeild no results return "AND 1=2"; } sb.append(")"); } return sb.toString(); } /** * @return Classes in a project * @throws ApplicationException */ private UMLClassMetadata[] getProjectClasses(Project proj, HQLCriteria classCriteria) throws ApplicationException { long start = System.currentTimeMillis(); List rList = this.cadsr.query(classCriteria, UMLClassMetadata.class.getName()); UMLClassMetadata classArr[] = new UMLClassMetadata[rList.size()]; // caCORE's toArray(arr) is broken (cacore bug #1382), so need to do // this way System.arraycopy(rList.toArray(), 0, classArr, 0, rList.size()); double duration = (System.currentTimeMillis() - start) / 1000.0; LOG.info(proj.getShortName() + "'s class fetch took " + duration + " seconds, and found " + classArr.length + " classes."); return classArr; } /** * Generates a DomainModel that represents the project and the given subset * of classes and associations * * @param proj * The project to build a domain model for * @param classes * The classes to include in the domain model * @param associations * The asociations to include in the domain model * @return The domain model * @throws DomainModelGenerationException * @throws RemoteException */ protected DomainModel buildDomainModel(final Project proj, UMLClassMetadata[] classes, UMLAssociationMetadata[] associations) throws DomainModelGenerationException { final DomainModel model = new DomainModel(); // project model.setProjectDescription(proj.getDescription()); model.setProjectLongName(proj.getLongName()); model.setProjectShortName(proj.getShortName()); model.setProjectVersion(proj.getVersion()); long start = System.currentTimeMillis(); LOG.info("Beginning processing of classes for project: " + proj.getShortName()); // classes ExposedUMLClassCollection exposedClasses = new ExposedUMLClassCollection(); if (classes != null) { List workList = new ArrayList(); Collection<Future<?>> futures = new LinkedList<Future<?>>(); ClassConversionWork[] workers = new ClassConversionWork[classes.length]; for (int i = 0; i < classes.length; i++) { final UMLClassMetadata classMD = classes[i]; ClassConversionWork work = new ClassConversionWork() { @Override public void run() { try { setUmlClass(CaDSRUtils.convertClassToDataUMLClass(DomainModelBuilder.this.cadsr, proj .getShortName(), proj.getVersion(), classMD)); } catch (Exception e) { LOG.error("Error converting class:" + classMD.getFullyQualifiedName(), e); } } }; workers[i] = work; try { futures.add(getWorkManager().submit(work)); } catch (Exception e) { LOG.error("Error scheduling class conversion work", e); throw new DomainModelGenerationException("Error sheduling class conversion work", e); } } // wait for work item's to complete try { for (Future<?> future:futures) { future.get(); } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } // now that they are done, access all the data from the workers UMLClass[] umlClasses = new UMLClass[classes.length]; for (int i = 0; i < workers.length; i++) { ClassConversionWork work = workers[i]; umlClasses[i] = work.getUmlClass(); if (umlClasses[i] == null) { throw new DomainModelGenerationException("Class converter returned null data!"); } } exposedClasses.getUMLClass().addAll(Arrays.asList(umlClasses)); } else { LOG.debug("Class array was null."); } model.setExposedUMLClassCollection(exposedClasses); double duration = (System.currentTimeMillis() - start) / 1000.0; LOG.info("Finished class conversion for project: " + proj.getShortName() + " in " + duration + " seconds."); start = System.currentTimeMillis(); LOG.info("Beginning processing of associations for project: " + proj.getShortName()); // associations ExposedUMLAssociationCollection exposedAssociations = new ExposedUMLAssociationCollection(); if (associations != null) { List workList = new ArrayList(); Collection<Future<?>> futures = new LinkedList<Future<?>>(); AssociationConversionWork[] workers = new AssociationConversionWork[associations.length]; for (int i = 0; i < associations.length; i++) { final UMLAssociationMetadata assocMD = associations[i]; AssociationConversionWork work = new AssociationConversionWork() { @Override public void run() { try { setUMLAssociation(convertAssociation(assocMD)); } catch (Exception e) { LOG.error("Error converting association:" + associationToString(assocMD), e); } } }; workers[i] = work; try { futures.add(getWorkManager().submit(work)); } catch (Exception e) { LOG.error("Error scheduling class conversion work", e); throw new DomainModelGenerationException("Error sheduling class conversion work", e); } } // wait for work item's to complete try { for (Future<?> future:futures) { future.get(); } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } // now that they are done, access all the data from the workers gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation[] umlAssociations = new gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation[associations.length]; for (int i = 0; i < workers.length; i++) { AssociationConversionWork work = workers[i]; umlAssociations[i] = work.getUMLAssociation(); if (umlAssociations[i] == null) { throw new DomainModelGenerationException("Association converter returned null data!"); } } exposedAssociations.getUMLAssociation().addAll(Arrays.asList(umlAssociations)); } else { LOG.debug("Association array was null."); } model.setExposedUMLAssociationCollection(exposedAssociations); duration = (System.currentTimeMillis() - start) / 1000.0; LOG.info("Finished association conversion for project: " + proj.getShortName() + " in " + duration + " seconds."); LOG.info("Beginning processing of generalizations for project: " + proj.getShortName()); start = System.currentTimeMillis(); UmlGeneralizationCollection genCollection = new UmlGeneralizationCollection(); if (classes != null && classes.length > 0) { // build generalizations UMLGeneralization[] genArr = buildGeneralizations(classes); LOG.info("Found " + genArr.length + " generalizations for project: " + proj.getShortName()); genCollection.getUMLGeneralization().addAll(Arrays.asList(genArr)); } model.setUmlGeneralizationCollection(genCollection); duration = (System.currentTimeMillis() - start) / 1000.0; LOG.info("Finished generalization processing for project: " + proj.getShortName() + " in " + duration + " seconds."); return model; } private UMLGeneralization[] buildGeneralizations(UMLClassMetadata[] classes) throws DomainModelGenerationException { // get all generalizations between classes we are exposing String classIDFilter = createClassIDFilter(classes); HQLCriteria hql = new HQLCriteria( "SELECT c.id, c.UMLGeneralizationMetadata.superUMLClassMetadata.id FROM UMLClassMetadata AS c WHERE c.id " + classIDFilter); LOG.debug("Issuing generialization query with HQL:" + hql.getHqlString()); try { List rList = this.cadsr.query(hql, "UMLClassMetadata"); UMLGeneralization genArr[] = new UMLGeneralization[rList.size()]; int ind = 0; for (Iterator resultsIterator = rList.iterator(); resultsIterator.hasNext();) { Object[] result = (Object[]) resultsIterator.next(); String subID = (String) result[0]; String superID = (String) result[1]; UMLGeneralization gen = new UMLGeneralization(); UMLClassReference ref = new UMLClassReference(); ref.setRefid(subID); UMLClassReference ref2 = new UMLClassReference(); ref2.setRefid(superID); gen.setSubClassReference(ref); gen.setSuperClassReference(ref2); genArr[ind++] = gen; } return genArr; } catch (Exception e) { LOG.error("Error creating Generalizations.", e); throw new DomainModelGenerationException("Error creating Generalizations.", e); } } private gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation convertAssociation( UMLAssociationMetadata coreAssociation) throws ApplicationException, DomainModelGenerationException { if (LOG.isDebugEnabled()) { LOG.debug("Converting association:" + associationToString(coreAssociation)); } gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation converted = new gov.nih.nci.cagrid.metadata.dataservice.UMLAssociation(); converted.setBidirectional(coreAssociation.getIsBidirectional().booleanValue()); // process the source SourceUMLAssociationEdge convertedSourceEdge = new SourceUMLAssociationEdge(); UMLAssociationEdge sourceEdge = new UMLAssociationEdge(); sourceEdge.setMaxCardinality(coreAssociation.getSourceHighCardinality().intValue()); sourceEdge.setMinCardinality(coreAssociation.getSourceLowCardinality().intValue()); sourceEdge.setRoleName(coreAssociation.getSourceRoleName()); if (sourceEdge.getRoleName() == null) { sourceEdge.setRoleName(""); } convertedSourceEdge.setUMLAssociationEdge(sourceEdge); converted.setSourceUMLAssociationEdge(convertedSourceEdge); // process the target TargetUMLAssociationEdge convertedTargetEdge = new TargetUMLAssociationEdge(); UMLAssociationEdge targetEdge = new UMLAssociationEdge(); targetEdge.setMaxCardinality(coreAssociation.getTargetHighCardinality().intValue()); targetEdge.setMinCardinality(coreAssociation.getTargetLowCardinality().intValue()); targetEdge.setRoleName(coreAssociation.getTargetRoleName()); if (targetEdge.getRoleName() == null) { targetEdge.setRoleName(""); } convertedTargetEdge.setUMLAssociationEdge(targetEdge); converted.setTargetUMLAssociationEdge(convertedTargetEdge); // umlproject.UMLAssociationMetadata is broken so need to issue // my own hibernate query to get associated UMLClasses (could have just // called getters otherwise) setUMLClassReferences(coreAssociation, converted); return converted; } private void setUMLClassReferences(UMLAssociationMetadata coreAssociation, UMLAssociation domainAssociation) throws ApplicationException, DomainModelGenerationException { SimpleExpression idRes = Restrictions.eq("id", coreAssociation.getId()); ProjectionList projection = Projections.projectionList().add(Projections.property("sourceUMLClassMetadata.id")) .add(Projections.property("targetUMLClassMetadata.id")); DetachedCriteria criteria = DetachedCriteria.forClass(UMLAssociationMetadata.class); criteria.add(idRes); criteria.setProjection(projection); long start = System.currentTimeMillis(); List rList = this.cadsr.query(criteria, UMLAssociationMetadata.class.getName()); Iterator iterator = rList.iterator(); if (iterator == null || !iterator.hasNext()) { throw new DomainModelGenerationException("Unable to located source and target ids for association!"); } // should have length 2, with src, target Object[] ids = (Object[]) iterator.next(); if (ids == null || ids.length != 2) { throw new DomainModelGenerationException("Unexpected result during query for association ids!"); } UMLClassReference ref = new UMLClassReference(); ref.setRefid(((String) ids[0])); domainAssociation.getSourceUMLAssociationEdge().getUMLAssociationEdge().setUMLClassReference( ref); UMLClassReference ref2 = new UMLClassReference(); ref2.setRefid(((String) ids[1])); domainAssociation.getTargetUMLAssociationEdge().getUMLAssociationEdge().setUMLClassReference( ref2); double duration = (System.currentTimeMillis() - start) / 1000.0; LOG.info("Association id fetch took " + duration + " seconds."); } private static String associationToString(UMLAssociationMetadata assoc) { return assoc.getSourceRoleName() + "(" + assoc.getSourceLowCardinality() + "..." + assoc.getSourceHighCardinality() + ")" + ((assoc.getIsBidirectional() != null && assoc.getIsBidirectional().booleanValue()) ? "<" : "") + " -->" + assoc.getTargetRoleName() + "(" + assoc.getTargetLowCardinality() + "..." + assoc.getTargetHighCardinality() + ")"; } public synchronized ExecutorService getWorkManager() { if (this.workManager == null) { this.workManager = Executors.newFixedThreadPool(DEFAULT_POOL_SIZE); } return this.workManager; } } abstract class ClassConversionWork implements Runnable { private UMLClass umlClass; public abstract void run(); public UMLClass getUmlClass() { return this.umlClass; } public void setUmlClass(UMLClass umlClass) { this.umlClass = umlClass; } public boolean isDaemon() { return false; } public void release() { // Do nothing } } abstract class AssociationConversionWork implements Runnable { private UMLAssociation umlAssociation; public abstract void run(); public UMLAssociation getUMLAssociation() { return this.umlAssociation; } public void setUMLAssociation(UMLAssociation umlAssociation) { this.umlAssociation = umlAssociation; } public boolean isDaemon() { return false; } public void release() { // Do nothing } }