Java tutorial
/* * Copyright (c) 2004-2010 The Regents of the University of California. * All rights reserved. * * '$Author: crawl $' * '$Date: 2013-01-17 19:25:48 -0800 (Thu, 17 Jan 2013) $' * '$Revision: 31348 $' * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the above * copyright notice and the following two paragraphs appear in all copies * of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. * */ package org.kepler.objectmanager.repository; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import javax.swing.JTree; import javax.swing.tree.TreePath; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.kepler.authentication.AuthenticationException; import org.kepler.gui.LibrarySearchPane; import org.kepler.gui.LibrarySearchResults; import org.kepler.gui.LibrarySearcher; import org.kepler.gui.RepositorySearcher; import org.kepler.kar.ModuleDependencyUtil; import org.kepler.kar.karxml.KarXml; import org.kepler.moml.DownloadableKAREntityLibrary; import org.kepler.moml.RemoteKARErrorEntityLibrary; import org.kepler.moml.RemoteRepositoryEntityLibrary; import org.kepler.objectmanager.cache.ActorCacheObject; import org.kepler.objectmanager.cache.CacheNamedObj; import org.kepler.objectmanager.cache.CacheObject; import org.kepler.sms.NamedOntClass; import org.kepler.sms.OntologyCatalog; import ptolemy.kernel.ComponentEntity; import ptolemy.kernel.CompositeEntity; import ptolemy.kernel.Entity; import ptolemy.kernel.util.ConfigurableAttribute; import ptolemy.kernel.util.IllegalActionException; import ptolemy.kernel.util.NameDuplicationException; import ptolemy.kernel.util.StringAttribute; import ptolemy.kernel.util.Workspace; import ptolemy.moml.EntityLibrary; /** * this abstract class is should be extended by all classes that provide a * search engine for the actory library. Any local variables in the extending * classes should be initialized in the init method because it is called from * the constructor of this class. * *@author berkley *@since November the ninth one thousand times two plus six */ public class EcogridRepositoryLibrarySearcher extends LibrarySearcher implements RepositorySearcher { private static final Log log = LogFactory.getLog(EcogridRepositoryLibrarySearcher.class.getName()); private static final boolean isDebugging = log.isDebugEnabled(); // the name of the repository private String repositoryName = "defaultRepository"; // the default name. // this can get reset in the constructor // the repository private Repository repository; private boolean skipOntology = false; /** * constructor * *@param library * Description of the Parameter *@param searchPane * Description of the Parameter */ public EcogridRepositoryLibrarySearcher(JTree library, LibrarySearchPane searchPane, String reposName) throws IllegalActionException { super(library, searchPane); try { if (reposName != null) { repositoryName = reposName; } if (isDebugging) { log.debug("repositoryName: " + repositoryName); } repository = RepositoryManager.getInstance().getRepository(repositoryName); if (isDebugging) { log.debug(repository.getClass()); } } catch (Exception e) { e.printStackTrace(); throw new IllegalActionException( "Could not get an instance of the " + "repository manager: " + e.getMessage()); } } /** * search a component hierarchy for a specific component in a specific * component returns null if the component is not found */ private CompositeEntity findEntity(String name, CompositeEntity entity) { if (entity.getName().trim().equals(name.trim())) { return entity; } else { Iterator pathItt = entity.entityList().iterator(); while (pathItt.hasNext()) { Entity nextEntity = (Entity) pathItt.next(); if (nextEntity instanceof CompositeEntity) { CompositeEntity newEntity = findEntity(name, (CompositeEntity) nextEntity); if (newEntity != null) { return newEntity; } } } } return null; } /** * build a path from the ontology tree from a given NamedOntClass */ private Object[] getTreePathObjectArray(NamedOntClass ontClass, Vector<String> v) { Iterator<NamedOntClass> itt = ontClass.getNamedSuperClasses(false); Object[] o = null; if (!itt.hasNext()) { v.addElement(ontClass.getName()); o = new Object[v.size()]; for (int i = 0; i < v.size(); i++) { o[i] = v.elementAt(i); } } else { while (itt.hasNext()) { NamedOntClass supClass = itt.next(); v.addElement(ontClass.getName()); return getTreePathObjectArray(supClass, v); } } // the array is backwards so it needs to be flipped Object[] result = new Object[o.length]; for (int i = 0; i < o.length; i++) { result[(result.length - 1) - i] = o[i]; } return result; } /** * provides any initialization needed prior to searching. It is called when * the class is constructed. Note that any local variables of extending * classes should be initialized in init since it is called be the * constructor of the super class (LibrarySearcher). */ @Override protected void init() { } /** * If we need to skip ontology display */ public void setSkipOntology(boolean skipOntology) { this.skipOntology = skipOntology; } /** * search for value in the library * *@param value * the value to search for *@return Description of the Return Value * @throws RepositoryException * @throws AuthenticationException */ @Override public LibrarySearchResults search(String value, boolean authenticate) throws IllegalActionException, RepositoryException, AuthenticationException { try { _results = new LibrarySearchResults(); TreePath path = _library.getPathForRow(0); // get the container Object[] pathComps = path.getPath(); EntityLibrary topLevel = (EntityLibrary) pathComps[0]; EntityLibrary remoteLevel = null; try { remoteLevel = new EntityLibrary(topLevel, "Remote Components"); } catch (NameDuplicationException nde) { Iterator itt = topLevel.entityList().iterator(); while (itt.hasNext()) { CompositeEntity entity = (CompositeEntity) itt.next(); if (entity.getName().equals("Remote Components")) { remoteLevel = (EntityLibrary) entity; remoteLevel.setContainer(null); remoteLevel = new EntityLibrary(topLevel, "Remote Components"); } } } // setup the remote components part of the tree Object[] o = new Object[2]; o[0] = topLevel; o[1] = remoteLevel; _results.add(new TreePath(o)); // get the results from the repository OntologyCatalog ontCatalog = OntologyCatalog.instance(); // search the repository //System.out.println("EcogridRepositoryLibrarySearcher search('" + value + "')"); Iterator repoResults = repository.search(value, authenticate); Iterator<EcogridRepositoryResults> castRepoResultsIterator = (Iterator<EcogridRepositoryResults>) repoResults; List<EcogridRepositoryResults> repoResultsList = iteratorToList(castRepoResultsIterator); //System.out.println("EcogridRepositoryLibrarySearcher found " + repoResultsList.size() + " results"); List<List<EcogridRepositoryResults>> groupedResults = groupResultsByIndex(repoResultsList); //System.out.println("having " + groupedResults.size() + " groups"); // System.out.println("Matched KARs:"); // for (List<EcogridRepositoryResults> resultGroup : groupedResults) { // System.out.println("* " + resultGroup.get(0).getKarEntry().getParent().getId()); // } if (repoResults != null) { EntityLibrary karLevel = null; EntityLibrary repositoryLevel = null; for (List<EcogridRepositoryResults> repoResultsGroup : groupedResults) { //System.out.println("A group has "+repoResultsGroup.size()+" EcogridResult"); boolean isDone = false; for (EcogridRepositoryResults repoResult : repoResultsGroup) { if (!isDone) { karLevel = createKarLevel(remoteLevel, repoResult); // Get the remote repository level repositoryLevel = getRepositoryLevel(remoteLevel, repoResult.getKarEntry().getParent()); isDone = true; } // get each result from the repository CacheObject co = repoResult.getCacheObject(); ActorCacheObject aco = (ActorCacheObject) co; KarXml.KarEntry karEntry = repoResult.getKarEntry(); Object leafObject; if (co == null) { // Not an actor String name = repoResult.getName(); if (name == null) { name = "unnamed"; } NondraggableTreeItem nti = new NondraggableTreeItem(name); if (karEntry.isWorkflow()) { nti.setWorkflowLSID(karEntry.getLsid()); nti.setWorkflowName(karEntry.getWorkflowName()); } StringAttribute alternateGetPopupActionAttribute = new StringAttribute(nti, "_alternateGetPopupAction"); alternateGetPopupActionAttribute.setExpression(RepositoryPopup.class.getName()); StringAttribute notDraggableAttribute = new StringAttribute(nti, "_notDraggable"); notDraggableAttribute.setExpression("true"); // Not strictly needed, but makes reading the MOML a little nicer. //FIXME hardcode to add-on module if ("org.kepler.reporting.roml.ReportLayout" .equals(repoResult.getKarEntry().getType())) { ConfigurableAttribute thumbnailAttribute = new ConfigurableAttribute(nti, "_thumbnailRasterIcon"); thumbnailAttribute.setExpression("/actorthumbs/basic-report-sm.gif"); } leafObject = nti; } else { // An actor CacheNamedObj cno = new CacheNamedObj(new CompositeEntity(new Workspace()), co); if (karEntry.isWorkflow()) { cno.setWorkflowLSID(karEntry.getLsid()); cno.setWorkflowName(karEntry.getWorkflowName()); } StringAttribute entityIdAttribute = new StringAttribute(cno, "entityId"); entityIdAttribute.setExpression(aco.getLSID().toString()); StringAttribute alternateGetMomlActionAttribute = new StringAttribute(cno, "_alternateGetMomlAction"); alternateGetMomlActionAttribute.setExpression(AlternateGetMoml.class.getName()); StringAttribute alternateGetPopupActionAttribute = new StringAttribute(cno, "_alternateGetPopupAction"); alternateGetPopupActionAttribute.setExpression(RepositoryPopup.class.getName()); ConfigurableAttribute thumbnailAttribute = new ConfigurableAttribute(cno, "_thumbnailRasterIcon"); thumbnailAttribute.setExpression("/actorthumbs/basic-actor-sm.gif"); leafObject = cno; } // find the semantic types and loop through them to place // the results if (!skipOntology) { Vector<String> semTypes = repoResult.getSemanticTypes(); for (int k = 0; k < semTypes.size(); k++) { String semType = (String) semTypes.elementAt(k); // find the class, search only the library ontologies NamedOntClass ontClass = ontCatalog.getNamedOntClass(semType, true); if (ontClass == null) { // skip this component if it // doesn't have a known class continue; } // get the tree path that goes with this semantic type Object[] treePathArray = getTreePathObjectArray(ontClass, new Vector()); // add the tree path to the topLevel and remoteLevel // objects to make the fullTreePath Object[] fullTreePath = new Object[treePathArray.length + 3]; fullTreePath[0] = topLevel; fullTreePath[1] = remoteLevel; for (int i = 2; i < fullTreePath.length - 1; i++) { // put the treepath together to be added to the // results vector this just adds EntityLibraries try { // adding a space to the treePathArray content // is a hack to keep // the tree from stealing results from the // remote part and putting // them back into the local part. I'm not sure // why it does this // but keeping the names unique seems to be the // only way to // prevent results seepage. treePathArray[i - 2] = (String) treePathArray[i - 2] + " "; fullTreePath[i] = new EntityLibrary((CompositeEntity) fullTreePath[i - 1], (String) treePathArray[i - 2]); } catch (NameDuplicationException nde) { // if we get a NDE, we need to search the // existing tree for the // correct parent fullTreePath[i] = findEntity((String) treePathArray[i - 2], (CompositeEntity) fullTreePath[i - 1]); if (fullTreePath[i] == null) { System.out.println("ERROR: no path found for fullTreePath[" + i + "]"); } } } fullTreePath[fullTreePath.length - 1] = leafObject; _results.add(new TreePath(fullTreePath)); } } Object[] containmentRepresentation = getContainmentRepresentation(topLevel, remoteLevel, repositoryLevel, karLevel, leafObject); if (containmentRepresentation == null) { log.warn("Could not generate containment representation: " + repoResult.getName()); } else { _results.add(new TreePath(containmentRepresentation)); } } } } if (_results.size() == 1) {// no results were added, so remove the // Remote Components result tree _results = new LibrarySearchResults(); } return _results; } catch (NameDuplicationException nde) { nde.printStackTrace(); throw new IllegalActionException( "Error building remote repository " + "search results: " + nde.getMessage()); } } private Object[] getContainmentRepresentation(EntityLibrary topLevel, EntityLibrary remoteLevel, EntityLibrary repositoryLevel, EntityLibrary karLevel, Object leafObject) { if (repositoryLevel != null) { Object[] newPath = new Object[5]; newPath[0] = topLevel; // Copy over "Search Results" top-level newPath[1] = remoteLevel; // Copy over "Remote Components" newPath[2] = repositoryLevel; newPath[3] = karLevel; newPath[4] = leafObject; // Copy over the component itself return newPath; } else { return null; } } private EntityLibrary getRepositoryLevel(EntityLibrary parent, KarXml karXml) { EntityLibrary repositoryLevel = null; try { repositoryLevel = new RemoteRepositoryEntityLibrary(parent, karXml.getRepositoryName()); } catch (IllegalActionException ex) { ex.printStackTrace(); } catch (NameDuplicationException ex) { // The containment level is already there. Find it. repositoryLevel = (EntityLibrary) findEntity(karXml.getRepositoryName(), (CompositeEntity) parent); } return repositoryLevel; } private EntityLibrary createKarLevel(EntityLibrary parentLibrary, EcogridRepositoryResults repoResult) { KarXml kx = repoResult.getKarEntry().getParent(); List<String> prefixes = Arrays.asList("urn:lsid:gamma.msi.ucsb.edu/OpenAuth/:", "urn:lsid:kepler-project.org/ns/:"); String rawId = kx.getName(); // Remove the prefix from the rawId before sanitizing. All that // boilerplate just gets in the way. for (String prefix : prefixes) { if (rawId.startsWith(prefix)) { rawId = rawId.substring(prefix.length()); break; } } String karLevelName = rawId; if (!karLevelName.endsWith(".kar")) { karLevelName += ".kar"; } EntityLibrary karLevel = null; Vector<String> modDeps = new Vector<String>(kx.getModuleDependencies()); boolean dependenciesSatisfied = ModuleDependencyUtil.checkIfModuleDependenciesSatisfied(modDeps); try { // replace periods in the name since they are not allowed in NamedObj String sanitizedName = karLevelName.replace(".", ","); if (dependenciesSatisfied) { karLevel = new DownloadableKAREntityLibrary(parentLibrary, sanitizedName, kx); } else { karLevel = new RemoteKARErrorEntityLibrary(parentLibrary, sanitizedName); ((RemoteKARErrorEntityLibrary) karLevel).setKarXml(kx); } // karLevel = new EntityLibrary(parentLibrary, karLevelName); // set the display name, which can have periods karLevel.setDisplayName(karLevelName); } catch (NameDuplicationException nde) { //System.out.println("name duplication exception "+nde.getMessage()); try { // add an appendix for the name if (kx != null && kx.getLsid() != null) { //add docid as an appendix karLevelName = karLevelName + "-(karId-" + transformLSIDtoDocid(kx.getLsid()) + ")" + "-(karXmlId-" + repoResult.getDocid().replace('.', ':') + ")"; } else { //add random number double number = Math.random(); long appendix = Math.round(number); karLevelName = karLevelName + "-(" + appendix + ")"; } // replace periods in the name since they are not allowed in NamedObj String sanitizedName = karLevelName.replace(".", ","); if (dependenciesSatisfied) { karLevel = new DownloadableKAREntityLibrary(parentLibrary, sanitizedName, kx); } else { karLevel = new RemoteKARErrorEntityLibrary(parentLibrary, sanitizedName); ((RemoteKARErrorEntityLibrary) karLevel).setKarXml(kx); } // set the display name, which can have periods karLevel.setDisplayName(karLevelName); } catch (NameDuplicationException ex) { log.warn("This shouldn't happen", ex); } catch (IllegalActionException ex) { log.error("Illegal action exception", ex); } /*Iterator<CompositeEntity> iterator = (Iterator<CompositeEntity>) parentLibrary.entityList().iterator(); while (iterator.hasNext()) { CompositeEntity entity = iterator.next(); if (entity.getName().equals(karLevelName)) { try { karLevel = (EntityLibrary) entity; karLevel.setContainer(null); if (dependenciesSatisfied) { karLevel = new DownloadableKAREntityLibrary(parentLibrary, karLevelName, karEntry.getParent()); } else { karLevel = new RemoteKARErrorEntityLibrary(parentLibrary, karLevelName); ((RemoteKARErrorEntityLibrary) karLevel).setKarXml(kx); } } catch(NameDuplicationException ex) { log.warn("This shouldn't happen", ex); } catch(IllegalActionException ex) { log.error("Illegal action exception", ex); } } }*/ } catch (IllegalActionException ex) { log.error("Illegal action exception", ex); } return karLevel; } /* *Transform a urn:lsid:kepler-project.org/ns/:2099:21:2 to 2099.21.2 */ private String transformLSIDtoDocid(String lsid) { String docid = null; char colon = ':'; int targetNumber = 3; if (lsid != null) { int index = 0; for (int i = 0; i < lsid.length(); i++) { char character = lsid.charAt(lsid.length() - 1 - i); if (character == colon) { index = index + 1; if (index == targetNumber) { docid = lsid.substring(lsid.length() - i); } } } } return docid; } private List<List<EcogridRepositoryResults>> groupResultsByIndex(List<EcogridRepositoryResults> repoResults) { Map<Integer, List<EcogridRepositoryResults>> resultsByIndex = new HashMap<Integer, List<EcogridRepositoryResults>>(); for (EcogridRepositoryResults repoResult : repoResults) { Integer indexValue = repoResult.getIndexValue(); if (!resultsByIndex.containsKey(indexValue)) { resultsByIndex.put(indexValue, new ArrayList<EcogridRepositoryResults>()); } resultsByIndex.get(indexValue).add(repoResult); } List<List<EcogridRepositoryResults>> results = new ArrayList<List<EcogridRepositoryResults>>(); for (Integer indexValue : resultsByIndex.keySet()) { if (indexValue == null) { // These aren't in a single group of 'not a group'. Add them // as separate lists. for (EcogridRepositoryResults repoResult : resultsByIndex.get(null)) { results.add(Collections.singletonList(repoResult)); } } else { results.add(resultsByIndex.get(indexValue)); } } return results; } private <T> List<T> iteratorToList(Iterator<T> iterator) { if (iterator == null) { return Collections.emptyList(); } List<T> list = new ArrayList<T>(); while (iterator.hasNext()) { list.add(iterator.next()); } return list; } public class NondraggableTreeItem extends ComponentEntity { private String workflowName = null; private String workflowLSID = null; public NondraggableTreeItem(String name) throws IllegalActionException, NameDuplicationException { super(new CompositeEntity(new Workspace()), name.replace('.', ',')); setDisplayName(name); } public String getWorkflowName() { return workflowName; } public void setWorkflowName(String workflowName) { this.workflowName = workflowName; } public String getWorkflowLSID() { return workflowLSID; } public void setWorkflowLSID(String workflowLSID) { this.workflowLSID = workflowLSID; } } }