001/*
002 * Copyright (c) 2003-2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2015-08-24 22:45:41 +0000 (Mon, 24 Aug 2015) $' 
007 * '$Revision: 33631 $'
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.objectmanager.cache;
031
032import java.io.ByteArrayInputStream;
033import java.io.ByteArrayOutputStream;
034import java.io.Externalizable;
035import java.io.IOException;
036import java.io.InputStream;
037import java.io.ObjectInput;
038import java.io.ObjectOutput;
039import java.io.StringReader;
040import java.util.Map;
041
042import javax.xml.parsers.DocumentBuilder;
043import javax.xml.parsers.DocumentBuilderFactory;
044
045import org.apache.commons.logging.Log;
046import org.apache.commons.logging.LogFactory;
047import org.kepler.moml.KeplerActorMetadata;
048import org.kepler.moml.KeplerMetadataExtractor;
049import org.kepler.moml.NamedObjId;
050import org.kepler.objectmanager.ActorMetadata;
051import org.kepler.objectmanager.lsid.KeplerLSID;
052import org.w3c.dom.Document;
053import org.w3c.dom.NamedNodeMap;
054import org.w3c.dom.Node;
055import org.w3c.dom.NodeList;
056import org.xml.sax.EntityResolver;
057import org.xml.sax.InputSource;
058import org.xml.sax.SAXException;
059
060import ptolemy.moml.MoMLParser;
061import ptolemy.util.MessageHandler;
062
063/**
064 *  Class that represents an object in the ObjectCache. This class should be
065 *  extended by each type of object that wants to control its own lifecycle
066 *  events and serialization events.
067 *
068 *@author     berkley
069 *@created    September 7, 2007
070 */
071
072/**
073 * Modified by Dan Higgins, Aug 9, 2007 to avoid instantiating all the actors
074 * when the ActorCacheObject is created. This is done be avoiding creating the
075 * ActorMetadata object and using the MoML parser. Instead a DOM parser is used
076 * to pull out just a few of parameters in the kar files MoML description of the
077 * actor, and the xml saved with the ActorCacheObject is exactly that in the kar
078 * file.
079 * 
080 *@author berkley
081 *@created September 7, 2007
082 */
083public class ActorCacheObject extends CacheObject implements Externalizable {
084
085        private static final Log log = LogFactory.getLog(ActorCacheObject.class
086                        .getName());
087        private static final boolean isDebugging = log.isDebugEnabled();
088
089        /**
090         * 
091         */
092        private ActorMetadata _actor = null;
093
094        /**
095         * 
096         */
097        private String _actorString;
098
099        /**
100         * 
101         */
102        private String _className;
103
104        /**
105         * 
106         */
107        private String _rootname;
108
109        /**
110         * Constructor for the ActorCacheObject object
111         */
112        public ActorCacheObject() {
113                super();
114                _actor = null;
115        }
116
117        /**
118         * construct a new CacheObject
119         * 
120         *@param name
121         *            Description of the Parameter
122         *@param lsid
123         *            Description of the Parameter
124         */
125        public ActorCacheObject(String name, KeplerLSID lsid) {
126                super(name, lsid);
127                if (isDebugging)
128                        log.debug("ActorCacheObject(" + name + "," + lsid + ")");
129        }
130
131        /**
132         * create an ActorCacheObject from a stream
133         * 
134         * @param actorStream
135         *            the stream of the actor moml
136         * @exception CacheException
137         *                Description of the Exception
138         */
139        public ActorCacheObject(InputStream actorStream) throws CacheException {
140                super();
141                if (isDebugging)
142                        log.debug("ActorCacheObject(" + actorStream.getClass().getName()
143                                        + ")");
144                
145                KeplerActorMetadata kam = null;
146                try {
147                        kam = KeplerMetadataExtractor
148                                .extractActorMetadata(actorStream);
149                } catch (Exception e1) {
150                        e1.printStackTrace();
151                }
152                
153                if (kam != null) {
154                        _actorString = kam.getActorString();
155                        this.setName( kam.getName() );
156                        this.setLSID( kam.getLsid() );
157                        _className = kam.getClassName();
158                        _rootname = kam.getRootName();
159                        setSemanticTypes( kam.getSemanticTypes() );
160                        
161                        Map<String,String> attributes = kam.getAttributes();
162                        if (attributes != null) {
163                                for (String attributeName : attributes.keySet()) {
164                                        String attributeValue = attributes.get(attributeName);
165                                        this.addAttribute(attributeName, attributeValue);
166
167                                }
168                        }
169                }
170        }
171
172        /**
173         * this returns an ActorMetadata object. It will need to be casted to be
174         * used
175         * 
176         *@return The object value
177         */
178        public Object getObject() {
179                if (isDebugging)
180                        log.debug("getObject()");
181                return getMetadata();
182        }
183
184        /**
185         * serialize this class
186         * 
187         *@param out
188         *            Description of the Parameter
189         *@exception IOException
190         *                Description of the Exception
191         */
192        public void writeExternal(ObjectOutput out) throws IOException {
193                if (isDebugging)
194                        log.debug("writeExternal(" + out.getClass().getName() + ")");
195                byte[] b = _actorString.getBytes();
196                out.write(b, 0, b.length);
197                out.flush();
198        }
199
200        /**
201         * deserialize this class
202         * 
203         *@param in
204         *            Description of the Parameter
205         *@exception IOException
206         *                Description of the Exception
207         *@exception ClassNotFoundException
208         *                Description of the Exception
209         */
210        public void readExternal(ObjectInput in) throws IOException,
211                        ClassNotFoundException {
212                if (isDebugging)
213                        log.debug("readExternal(" + in.getClass().getName() + ")");
214
215                ByteArrayOutputStream bos = new ByteArrayOutputStream();
216                byte[] b = new byte[1024];
217                int numread = in.read(b, 0, 1024);
218                while (numread != -1) {
219                        bos.write(b, 0, numread);
220                        numread = in.read(b, 0, 1024);
221                }
222                bos.flush();
223                _actorString = bos.toString();
224                try {
225                        StringReader strR = new StringReader(_actorString);
226                        InputSource xmlIn = new InputSource(strR);
227                        DocumentBuilderFactory factory = DocumentBuilderFactory
228                                        .newInstance();
229                        DocumentBuilder builder = factory.newDocumentBuilder();
230                        builder.setEntityResolver(new EntityResolver() {
231                                public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
232                                        if (MOML_PUBLIC_ID_1.equals(publicId)) {
233                                                return new InputSource(MoMLParser.class.getResourceAsStream("MoML_1.dtd"));
234                                        }
235                                        else {
236                                                return null;
237                                        }
238                                }
239                        });
240                        Document doc = builder.parse(xmlIn);
241                        Node rootNode = doc.getDocumentElement();
242                        _rootname = rootNode.getNodeName();
243                        NamedNodeMap nnm = rootNode.getAttributes();
244                        Node namenode = nnm.getNamedItem("name");
245                        String nameStr = namenode.getNodeValue();
246                        this._name = nameStr;
247                        NodeList probNodes = rootNode.getChildNodes();
248                        for (int i = 0; i < probNodes.getLength(); i++) {
249                                Node child = probNodes.item(i);
250                                if (child.hasAttributes()) {
251                                        NamedNodeMap childAttrs = child.getAttributes();
252                                        Node idNode = childAttrs.getNamedItem("name");
253                                        if (idNode != null) {
254                                                String nameval = idNode.getNodeValue();
255                                                if (nameval.equals(NamedObjId.NAME)) {
256                                                        Node idNode1 = childAttrs.getNamedItem("value");
257                                                        String idval = idNode1.getNodeValue();
258                                                        this._lsid = new KeplerLSID(idval);
259                                                }
260                                                if (nameval.equals("class")) {
261                                                        Node idNode3 = childAttrs.getNamedItem("value");
262                                                        String classname = idNode3.getNodeValue();
263                                                        this._className = classname;
264                                                }
265                                                if (nameval.startsWith("semanticType")) {
266                                                        Node idNode2 = childAttrs.getNamedItem("value");
267                                                        String semtype = idNode2.getNodeValue();
268                                                        _semanticTypes.add(semtype);
269                                                }
270                                        }
271                                }
272                        }
273                } catch (Exception e) {
274                        e.printStackTrace();
275                        throw new IOException("Error in ActorCacheObject(ReadExternal): "
276                                        + e.getMessage());
277                }
278        }
279
280        /**
281         * Return the ActorMetadata for this actor.
282         * 
283         *@return The metadata value
284         */
285        public ActorMetadata getMetadata() {
286                if (isDebugging)
287                        log.debug("getMetadata()");
288                if (_actor == null) {
289                        // added if actor has never been created - DFH
290                        try {
291                                byte[] bb = _actorString.getBytes();
292                                ByteArrayInputStream bytein = new ByteArrayInputStream(bb);
293                                _actor = new ActorMetadata(bytein);
294                        } catch (Exception e) {
295                                MessageHandler.error("Error parsing actor metadata.", e);
296                        }
297                }
298                return _actor;
299        }
300
301        /**
302         * Gets the className attribute of the ActorCacheObject object.
303         * 
304         *@return The className value
305         */
306        public String getClassName() {
307                return _className;
308        }
309
310        /**
311         * Gets the actorString attribute of the ActorCacheObject object.
312         * 
313         *@return The actorString value
314         */
315        public String getActorString() {
316                return _actorString;
317        }
318
319        /**
320         * Gets the rootName attribute of the ActorCacheObject object.
321         * 
322         *@return The rootName value
323         */
324        public String getRootName() {
325                return _rootname;
326        }
327
328        public static String MOML_PUBLIC_ID_1 = "-//UC Berkeley//DTD MoML 1//EN";       
329}