001/* 002 * The node controller for actor instances. 003 * Copyright (c) 2010 The Regents of the University of California. 004 * All rights reserved. 005 * Permission is hereby granted, without written agreement and without 006 * license or royalty fees, to use, copy, modify, and distribute this 007 * software and its documentation for any purpose, provided that the above 008 * copyright notice and the following two paragraphs appear in all copies 009 * of this software. 010 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 011 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 012 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 013 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 014 * SUCH DAMAGE. 015 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 016 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 017 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 018 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 019 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 020 * ENHANCEMENTS, OR MODIFICATIONS. 021 * PT_COPYRIGHT_VERSION_2 022 * COPYRIGHTENDKEY 023 */ 024package org.kepler.kar.handlers; 025 026import java.io.InputStream; 027import java.util.Hashtable; 028import java.util.Vector; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.kepler.kar.KAREntry; 033import org.kepler.kar.KAREntryHandler; 034import org.kepler.kar.KAREntryHandlerFactory; 035import org.kepler.kar.KARFile; 036import org.kepler.kar.KARManager; 037import org.kepler.moml.NamedObjId; 038import org.kepler.objectmanager.ActorMetadata; 039import org.kepler.objectmanager.cache.ActorCacheObject; 040import org.kepler.objectmanager.cache.CacheManager; 041import org.kepler.objectmanager.cache.CacheObject; 042import org.kepler.objectmanager.cache.CacheObjectInterface; 043import org.kepler.objectmanager.lsid.KeplerLSID; 044 045import ptolemy.actor.TypedCompositeActor; 046import ptolemy.actor.gui.Configuration; 047import ptolemy.actor.gui.ModelDirectory; 048import ptolemy.actor.gui.PtolemyEffigy; 049import ptolemy.actor.gui.Tableau; 050import ptolemy.actor.gui.TableauFrame; 051import ptolemy.kernel.CompositeEntity; 052import ptolemy.kernel.util.IllegalActionException; 053import ptolemy.kernel.util.NameDuplicationException; 054import ptolemy.kernel.util.NamedObj; 055import ptolemy.moml.MoMLParser; 056 057/** 058 * @author Aaron Schultz 059 */ 060public class ActorMetadataKAREntryHandler implements KAREntryHandler { 061 062 private static final Log log = LogFactory 063 .getLog(ActorMetadataKAREntryHandler.class.getName()); 064 private static final boolean isDebugging = log.isDebugEnabled(); 065 066 // backwards compatibility type string 067 // KAR version 2.0 and 2.1 uses the binary class name as the type 068 public static final String TYPE = "actorMetadata"; 069 070 // The class types that we'll handle with this KAREntryHandler 071 private static Vector<Class> handledClassTypes; 072 073 static { 074 handledClassTypes = new Vector<Class>(5); 075 076 try { 077 handledClassTypes.add(Class 078 .forName("ptolemy.kernel.ComponentEntity")); 079 handledClassTypes 080 .add(Class 081 .forName("org.kepler.objectmanager.cache.ActorCacheObject")); 082 handledClassTypes.add(Class 083 .forName("ptolemy.actor.TypedAtomicActor")); 084 handledClassTypes.add(Class 085 .forName("ptolemy.actor.TypedCompositeActor")); 086 handledClassTypes.add(Class 087 .forName("ptolemy.kernel.CompositeEntity")); 088 handledClassTypes.add(Class 089 .forName("org.kepler.moml.CompositeClassEntity")); 090 } catch (ClassNotFoundException e) { 091 e.printStackTrace(); 092 } 093 } 094 095 public ActorMetadataKAREntryHandler() { 096 097 } 098 099 /** 100 * Method for backwards compatibility with KAR version 1.0 KAR version 2.0 101 * and 2.1 uses the binary class name as the type. 102 * 103 * @see org.kepler.kar.KAREntryHandler#getTypeName() 104 */ 105 public String getTypeName() { 106 return TYPE; 107 } 108 109 /** 110 * If the typeName is equal to or a subclass of any of the handled class 111 * types, then we return true. 112 */ 113 public boolean handlesType(String typeName) { 114 return handlesClass(typeName); 115 } 116 117 /** 118 * If the typeName is equal to or a subclass of any of the handled class 119 * types, then we return true. 120 */ 121 public static boolean handlesClass(String className) { 122 123 Class clazz; 124 try { 125 clazz = Class.forName(className); 126 } catch (ClassNotFoundException e) { 127 // e.printStackTrace(); 128 return false; 129 } 130 131 if (handledClassTypes.contains(clazz)) { 132 return true; 133 } 134 135 // check superclasses 136 Class superClazz = clazz.getSuperclass(); 137 while (superClazz != null) { 138 if (handledClassTypes.contains(superClazz)) { 139 return true; 140 } 141 superClazz = superClazz.getSuperclass(); 142 } 143 return false; 144 145 } 146 147 /* 148 * (non-Javadoc) 149 * 150 * @see org.kepler.kar.KAREntryHandler#initialize() 151 */ 152 public void initialize() { 153 if (isDebugging) { 154 log.debug("initialize()"); 155 } 156 } 157 158 /* 159 private static class KarEntryReference { 160 public KarEntryReference(KARFile karFile, KAREntry karEntry) { 161 this.karFile = karFile.getFileLocation(); 162 this.karEntryString = karEntry.getName(); 163 } 164 165 @Override 166 public boolean equals(Object o) { 167 if (this == o) return true; 168 if (o == null || getClass() != o.getClass()) return false; 169 170 KarEntryReference that = (KarEntryReference) o; 171 172 if (karEntryString != null ? !karEntryString.equals(that.karEntryString) : that.karEntryString != null) 173 return false; 174 if (karFile != null ? !karFile.equals(that.karFile) : that.karFile != null) return false; 175 176 return true; 177 } 178 179 @Override 180 public int hashCode() { 181 int result = karFile != null ? karFile.hashCode() : 0; 182 result = 31 * result + (karEntryString != null ? karEntryString.hashCode() : 0); 183 return result; 184 } 185 186 private final File karFile; 187 private String karEntryString; 188 } 189 */ 190 191 //private static Map<KarEntryReference, ActorCacheObject> acoCache = new HashMap<KarEntryReference, ActorCacheObject>(); 192 193 /* 194 * (non-Javadoc) 195 * 196 * @see org.kepler.kar.KAREntryHandler#cache(org.kepler.kar.KARFile, 197 * java.util.jar.JarEntry) 198 */ 199 public synchronized CacheObject cache(KARFile karFile, KAREntry entry) throws Exception { 200 if (isDebugging) { 201 log.debug("cache(" + karFile.toString() + "," + entry.toString() 202 + ")"); 203 } 204 // System.out.println("caching from amkeh" + karFile.toString() + "," + 205 // entry.toString()); 206 207 // NOTE: the hashCode for KarEntryReference relies on the LSID. 208 // Sometimes the entry contents change, but not the LSID, e.g., 209 // when the Display actor's window moves the LSID revision is not 210 // incremented. This results in the stale entry being found in 211 // acoCache and the updated entry not being updated in the cache. 212 /* 213 KarEntryReference ker = new KarEntryReference(karFile, entry); 214 if (acoCache.containsKey(ker)) { 215 return acoCache.get(ker); 216 } 217 */ 218 219 ActorCacheObject aco = new ActorCacheObject(karFile 220 .getInputStream(entry)); 221 //acoCache.put(ker, aco); 222 223 if (isDebugging) { 224 log.debug("created actor cache object: " + aco); 225 } 226 return aco; 227 228 } 229 230 /* 231 * (non-Javadoc) 232 * 233 * @see org.kepler.kar.KAREntryHandler#open(java.util.jar.JarEntry) 234 */ 235 public boolean open(KARFile karFile, KAREntry entry, TableauFrame tableauFrame) throws Exception { 236 if (isDebugging) { 237 log.debug("open(" + karFile.toString() + "," + entry.toString() 238 + ")"); 239 } 240 241 KeplerLSID lsid = entry.getLSID(); 242 if (isDebugging) 243 log.debug(lsid); 244 245 CacheManager cache = CacheManager.getInstance(); 246 247 // get the object from the cache (it is GraphicalActorMetadata even 248 // though it is a workflow) 249 CacheObjectInterface co = cache.getObject(lsid); 250 NamedObj entity = null; 251 252 if (co == null) { 253 if (isDebugging) 254 log.debug(lsid + " was not found in the cache"); 255 if (isDebugging) 256 log.debug("Opening from file"); 257 258 MoMLParser parser = new MoMLParser(); 259 InputStream stream = null; 260 try { 261 stream = karFile.getInputStream(entry); 262 entity = parser.parse(null, karFile.getFileLocation().getCanonicalPath(), stream); 263 } finally { 264 if(stream != null) { 265 stream.close(); 266 } 267 } 268 269 if (entity == null) { 270 return false; 271 } 272 } else { 273 Object o = co.getObject(); 274 if (o == null) { 275 return false; 276 } 277 if (isDebugging) 278 log.debug(o.getClass().getName()); 279 280 if (o instanceof ActorMetadata) { 281 ActorMetadata am = (ActorMetadata) o; 282 try { 283 // get the workflow from the metadata 284 entity = am.getActorAsNamedObj(null); 285 286 if (isDebugging) 287 log.debug(entity.getName() + " " 288 + NamedObjId.getIdFor(entity) + " " 289 + entity.getClass().getName()); 290 if (entity instanceof CompositeEntity 291 || entity instanceof TypedCompositeActor) { 292 if (isDebugging) 293 log.debug("Opening CompositeEntity"); 294 295 // get the xml representation - needs parsing to be 296 // correct! 297 String moml = entity.exportMoML(); 298 MoMLParser parser = new MoMLParser(); 299 entity = parser.parse(moml); 300 } else { 301 if (isDebugging) 302 log.debug("Not a CompositeEntity"); 303 return false; 304 } 305 } catch (Exception e) { 306 e.printStackTrace(); 307 log.error("error opening the workflow: " + e.getMessage()); 308 return false; 309 } 310 } 311 } 312 313 Configuration configuration = (Configuration) Configuration 314 .configurations().iterator().next(); 315 316 // TODO check on this 317 // ----begin questionable title bar code: 318 PtolemyEffigy effigy = new PtolemyEffigy(configuration.workspace()); 319 effigy.setModel(entity); 320 ModelDirectory directory = (ModelDirectory) configuration 321 .getEntity("directory"); 322 323 // is this the right name for the effigy? 324 effigy.setName(entity.getName()); 325 326 effigy.identifier.setExpression(entity.getName()); 327 if (directory != null) { 328 if (directory.getEntity(entity.getName()) != null) { 329 // Name is already taken. 330 int count = 2; 331 String newName = effigy.getName() + " " + count; 332 while (directory.getEntity(newName) != null) { 333 newName = effigy.getName() + " " + ++count; 334 } 335 effigy.setName(newName); 336 } 337 } 338 effigy.setContainer(directory); 339 // ---end questionable title bar code 340 341 // open a new window for the workflow 342 Tableau t = configuration.openModel(entity); 343 344 if (t != null) { 345 //if (isDebugging) 346 //log.debug(entity.getName() + " was opened successfully"); 347 348 // no need to put this in ObjectManager for ReportLayoutKAREntry's 349 // open, 350 // it gets in there somehow anyways 351 // ObjectManager.getInstance().addNamedObj(entity); 352 // ObjectManager.assignIdTo(entity, lsid); 353 354 //Add JFrame => KARFile mapping to KARManager 355 KARManager karManager = KARManager.getInstance(); 356 karManager.add(t.getFrame(), karFile); 357 358 return true; 359 } 360 361 return false; 362 363 } 364 365 /** 366 * The save method for ActorMetadataKAREntryHandler is not used since Actors 367 * and Workflows are not dependent on anything else. They are the top of the 368 * dependency tree for KARs and are therefore created by the 369 * KARBuilder.handleInitiatorList Method. However, the 370 * ActorMetadataKAREntryHandler is still listed as the handler that created 371 * the file in the KAR manifest since this handler is used for opening and 372 * cacheing. 373 * 374 * @see org.kepler.kar.KAREntryHandler#save(org.kepler.objectmanager.lsid.KeplerLSID 375 * ) 376 */ 377 public Hashtable<KAREntry, InputStream> save(Vector<KeplerLSID> lsids, 378 KeplerLSID karLsid, TableauFrame tableauFrame) throws Exception { 379 if (isDebugging) 380 log.debug("save(" + lsids + ")"); 381 382 return null; 383 } 384 385 /** 386 * A factory that creates a KAREntryHandler object. 387 * 388 *@author Aaron Schultz 389 */ 390 public static class Factory extends KAREntryHandlerFactory { 391 /** 392 * Create a factory with the given name and container. 393 * 394 *@param container 395 * The container. 396 *@param name 397 * The name of the entity. 398 *@exception IllegalActionException 399 * If the container is incompatible with this attribute. 400 *@exception NameDuplicationException 401 * If the name coincides with an attribute already in the 402 * container. 403 */ 404 public Factory(NamedObj container, String name) 405 throws IllegalActionException, NameDuplicationException { 406 super(container, name); 407 } 408 409 /** 410 * Create a library pane that displays the given library of actors. 411 * 412 * @return A new LibraryPaneTab that displays the library 413 */ 414 public KAREntryHandler createKAREntryHandler() { 415 if (isDebugging) 416 log.debug("createKAREntryHandler()"); 417 ActorMetadataKAREntryHandler amkeh = new ActorMetadataKAREntryHandler(); 418 return amkeh; 419 } 420 } 421}