001/*
002 * Copyright (c) 1998-2012 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: barseghian $'
006 * '$Date: 2012-04-27 13:16:27 -0700 (Fri, 27 Apr 2012) $' 
007 * '$Revision: 29789 $'
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 */
029package org.kepler.data.datasource.dataone;
030
031import java.io.IOException;
032import java.io.InputStream;
033
034import org.apache.commons.io.IOUtils;
035import org.apache.log4j.Logger;
036import org.dataone.client.CNode;
037import org.dataone.client.D1Client;
038import org.dataone.client.MNode;
039import org.dataone.service.exceptions.InsufficientResources;
040import org.dataone.service.exceptions.InvalidToken;
041import org.dataone.service.exceptions.NotAuthorized;
042import org.dataone.service.exceptions.NotFound;
043import org.dataone.service.exceptions.NotImplemented;
044import org.dataone.service.exceptions.ServiceFailure;
045import org.dataone.service.types.v1.Identifier;
046import org.dataone.service.types.v1.ObjectFormatIdentifier;
047import org.dataone.service.types.v1.ObjectLocation;
048import org.dataone.service.types.v1.ObjectLocationList;
049import org.dataone.service.types.v1.SystemMetadata;
050import org.ecoinformatics.seek.datasource.DataSourceIcon;
051
052import ptolemy.actor.TypedIOPort;
053import ptolemy.actor.lib.LimitedFiringSource;
054import ptolemy.actor.parameters.PortParameter;
055import ptolemy.data.ArrayToken;
056import ptolemy.data.StringToken;
057import ptolemy.data.Token;
058import ptolemy.data.UnsignedByteToken;
059import ptolemy.data.expr.StringParameter;
060import ptolemy.data.type.ArrayType;
061import ptolemy.data.type.BaseType;
062import ptolemy.kernel.CompositeEntity;
063import ptolemy.kernel.util.IllegalActionException;
064import ptolemy.kernel.util.NameDuplicationException;
065
066/**
067 * @author Derik Barseghian
068 * @version $Id: DataOneActor.java 29789 2012-04-27 20:16:27Z barseghian $
069 */
070public class DataOneActor extends LimitedFiringSource {
071
072        private static final Logger logger = Logger.getLogger(DataOneActor.class);
073        private DataSourceIcon _icon;
074        private StringParameter nodeIdStringParameter;
075        private PortParameter pidPortParam;
076
077        /**
078         * Output sensorNameOutputPort
079         * 
080         * @UserLevelDocumentation The sensor name after parsing sensorId
081         */
082        public TypedIOPort formatIdOutputPort;
083
084        public DataOneActor(CompositeEntity container, String name)
085                        throws NameDuplicationException, IllegalActionException {
086                super(container, name);
087
088                _icon = new DataSourceIcon(this);
089
090                _attachText("_iconDescription", "<svg>\n" + "<rect x=\"0\" y=\"0\" "
091                                + "width=\"60\" height=\"20\" " + "style=\"fill:white\"/>\n"
092                                + "</svg>\n");
093
094                pidPortParam = new PortParameter(this, "PID");
095                pidPortParam.setStringMode(true);
096                pidPortParam.setTypeEquals(BaseType.STRING);
097                pidPortParam.getPort().setTypeEquals(BaseType.STRING);
098
099                // output.setDisplayName("output");
100                output.setTypeEquals(new ArrayType(BaseType.UNSIGNED_BYTE));
101                formatIdOutputPort = new TypedIOPort(this, "Format Id", false, true);
102                formatIdOutputPort.setTypeEquals(BaseType.STRING);
103        }
104
105        public void fire() throws IllegalActionException {
106                super.fire();
107                _icon.setBusy();
108
109                try {
110                        CNode cNode = D1Client.getCN();
111
112                        Identifier pid = new Identifier();
113                        pidPortParam.update();
114                        if (pidPortParam.getToken() != null) {
115                                pid.setValue(((StringToken) pidPortParam.getToken())
116                                                .stringValue());
117                        }
118
119                        // Only attempt to fetch pid if necessary
120                        if (output.numberOfSinks() > 0 && pid.getValue() != null
121                                        && !pid.getValue().equals("")) {
122
123                                ObjectLocationList objectLocationList = cNode.resolve(pid);
124
125                                // XXX Instead of first, use a specific node based on some
126                                // criteria?
127                                ObjectLocation objectLocation = objectLocationList
128                                                .getObjectLocation(0);
129                                MNode mnNode = D1Client.getMN(objectLocation
130                                                .getNodeIdentifier());
131                                InputStream inputStream = mnNode.get(pid);
132                                byte[] bytes = IOUtils.toByteArray(inputStream);
133                                logger.debug(" for pid:" + pid.getValue() + " got "
134                                                + bytes.length + " bytes.");
135                                String formatId = "unknown";
136                                SystemMetadata sysMeta = mnNode.getSystemMetadata(pid);
137                                
138                                if (sysMeta != null) {
139                                        ObjectFormatIdentifier objectFormat = sysMeta.getFormatId();
140                                        if (objectFormat != null) {
141                                                formatId = objectFormat.getValue();
142                                        }
143                                }
144                                // System.out.println("=====the format identifier is "+formatId);
145                                // XXX ByteArrayToken offers less overhead
146                                // but currently in ptolemy-excludes
147                                // ByteArrayToken token = new ByteArrayToken();
148                                Token byteTokens[] = new Token[bytes.length];
149                                for (int i = 0; i < bytes.length; i++) {
150                                        byteTokens[i] = new UnsignedByteToken(bytes[i]);
151                                }
152                                output.broadcast(new ArrayToken(byteTokens));
153                                formatIdOutputPort.send(0, new StringToken(formatId));
154                        }
155
156                } catch (InvalidToken e) {
157                        // TODO Auto-generated catch block
158                        e.printStackTrace();
159                        throw new IllegalActionException("InvalidToken: " + e.getDescription());
160                } catch (NotAuthorized e) {
161                        // TODO Auto-generated catch block
162                        e.printStackTrace();
163                        throw new IllegalActionException("NotAuthorized: " + e.getDescription());
164                } catch (NotImplemented e) {
165                        // TODO Auto-generated catch block
166                        e.printStackTrace();
167                        throw new IllegalActionException("NotImplemented: "     + e.getDescription());
168                } catch (ServiceFailure e) {
169                        // TODO Auto-generated catch block
170                        e.printStackTrace();
171                        throw new IllegalActionException("ServiceFailure: " + e.getDescription());
172                } catch (NotFound e) {
173                        // TODO Auto-generated catch block
174                        e.printStackTrace();
175                        throw new IllegalActionException("NotFound: " + e.getDescription());
176                } catch (IOException e) {
177                        // TODO Auto-generated catch block
178                        e.printStackTrace();
179                        throw new IllegalActionException("IOException: " + e.toString());
180                } catch (InsufficientResources e) {
181                        // TODO Auto-generated catch block
182                        e.printStackTrace();
183                        throw new IllegalActionException("InsufficientResources: " + e.toString());
184                } finally {
185                        _icon.setReady();
186                }
187
188                _icon.setReady();
189        }
190
191        public void preinitialize() throws IllegalActionException {
192                super.preinitialize();
193        }
194
195        /** The director told us to stop firing immediately. */
196        public void stop() {
197                super.stop();
198                _icon.setReady();
199        }
200
201        public void wrapup() throws IllegalActionException {
202                super.wrapup();
203        }
204
205}