001/* 002 * Copyright (c) 2017 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2017-08-29 15:27:08 -0700 (Tue, 29 Aug 2017) $' 007 * '$Revision: 1392 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.webview.server; 031 032import java.lang.ref.WeakReference; 033import java.util.Collections; 034import java.util.HashMap; 035import java.util.Map; 036import java.util.concurrent.atomic.AtomicInteger; 037 038import org.kepler.webview.actor.WebViewAttribute; 039 040import ptolemy.kernel.util.IllegalActionException; 041import ptolemy.kernel.util.NameDuplicationException; 042import ptolemy.kernel.util.NamedObj; 043import ptolemy.kernel.util.Settable; 044import ptolemy.kernel.util.StringAttribute; 045import ptolemy.kernel.util.Workspace; 046 047public class WebViewId extends StringAttribute { 048 049 /** Create a new WebViewId in the specified container. This constructor is private 050 * since only WebViewId.getId() is allowed to create instances of this class. 051 */ 052 private WebViewId(NamedObj container) throws IllegalActionException, NameDuplicationException { 053 super(container, NAME); 054 055 // set a default value for the id. 056 _setExpression(null, false); 057 058 // set visibility to EXPERT since normally users do not change the id. 059 setVisibility(Settable.EXPERT); 060 } 061 062 /** Clone the WebViewId into the specified workspace. */ 063 @Override 064 public Object clone(Workspace workspace) throws CloneNotSupportedException { 065 WebViewId newObject = (WebViewId) super.clone(workspace); 066 // if the id was not set manually, generate a new id for the clone. 067 if(!newObject._setManually) { 068 try { 069 _setExpression(null, false); 070 } catch (IllegalActionException e) { 071 throw new CloneNotSupportedException("Error setting expression to new webview id: " + e.getMessage()); 072 } 073 } 074 return newObject; 075 } 076 077 /** Get the web view id for a NamedObj. If the NamedObj does not have a web view id, 078 * then a new one is created. 079 */ 080 public static String getId(NamedObj namedObj) throws IllegalActionException { 081 WebViewId id = (WebViewId) namedObj.getAttribute(NAME); 082 if(id == null) { 083 try { 084 id = new WebViewId(namedObj); 085 } catch(NameDuplicationException e) { 086 throw new IllegalActionException(namedObj, e, "Error creating WebViewId."); 087 } 088 } 089 090 String idStr; 091 092 NamedObj toplevel = namedObj.toplevel(); 093 if(toplevel == namedObj) { 094 idStr = id.getExpression(); 095 } else { 096 // TODO 097 idStr = getId(toplevel) + "-" + id.getExpression(); 098 } 099 100 // TODO need to delete NamedObjs from map when they are removed from workflow. 101 _idMap.put(idStr, new WeakReference<NamedObj>(namedObj)); 102 103 return idStr; 104 } 105 106 /** Get the NamedObj for a specific id. */ 107 public static NamedObj getNamedObj(String id) { 108 return _idMap.get(id).get(); 109 } 110 111 /** Remove all the ids inside of the a workflow. */ 112 public static void removeWorkflow(NamedObj model) { 113 114 synchronized(_idMap) { 115 Map<String,WeakReference<NamedObj>> mapCopy = new HashMap<String,WeakReference<NamedObj>>(_idMap); 116 for(Map.Entry<String, WeakReference<NamedObj>> entry : mapCopy.entrySet()) { 117 final NamedObj namedObj = entry.getValue().get(); 118 if(namedObj == null || namedObj == model || namedObj.toplevel() == model) { 119 _idMap.remove(entry.getKey()); 120 if(namedObj instanceof WebViewAttribute) { 121 ((WebViewAttribute)namedObj).unregisterHandler(); 122 } 123 } 124 } 125 } 126 } 127 128 /** Override the base class to remove an existing WebViewId in the 129 * container. This can occur since a WebViewId is created during 130 * the cloning process. 131 */ 132 @Override 133 public void setContainer(NamedObj container) throws IllegalActionException, NameDuplicationException { 134 135 if(container != null) { 136 // see if the container already has an id. 137 // this can occur during cloning since WebViewAttribute.setContainer() 138 // can create an id during registering the handle. 139 WebViewId containerId = (WebViewId) container.getAttribute(NAME); 140 if(containerId != null) { 141 // copy the values 142 _setExpression(containerId.getExpression(), containerId._setManually); 143 // remove the existing one. 144 containerId.setContainer(null); 145 } 146 } 147 148 super.setContainer(container); 149 } 150 151 /** Set the value of the id. */ 152 @Override 153 public void setExpression(String value) throws IllegalActionException { 154 _setExpression(value, true); 155 } 156 157 /** Set the value of the ID. 158 * @param value The value of the id. If null or empty, a new id is generated and setManually 159 * is ignored and assumed to be false. 160 * @param setManually If true, then this object is set persistent so that it is saved in the model. 161 */ 162 private void _setExpression(String value, boolean setManually) throws IllegalActionException { 163 164 if(value == null || value.trim().isEmpty()) { 165 value = String.valueOf(_counter.incrementAndGet()); 166 setManually = false; 167 } 168 169 super.setExpression(value); 170 _setManually = setManually; 171 setPersistent(setManually); 172 //System.out.println("_setExpression to " + value + " done manually = " + setManually); 173 } 174 175 private boolean _setManually = false; 176 177 private static final String NAME = "_webViewId"; 178 179 private static final AtomicInteger _counter = new AtomicInteger(0); 180 181 private static final Map<String,WeakReference<NamedObj>> _idMap = 182 Collections.synchronizedMap(new HashMap<String,WeakReference<NamedObj>>()); 183}