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.metadata; 030 031import java.io.IOException; 032import java.io.InputStreamReader; 033import java.io.Reader; 034import java.io.UnsupportedEncodingException; 035import java.util.ArrayList; 036import java.util.List; 037import java.util.Vector; 038 039import org.apache.commons.io.IOUtils; 040import org.apache.log4j.Logger; 041import org.ecoinformatics.seek.datasource.eml.eml2.Eml200Parser; 042import org.kepler.configuration.ConfigurationManager; 043import org.kepler.configuration.ConfigurationNamespace; 044import org.kepler.configuration.ConfigurationProperty; 045import org.kepler.objectmanager.data.db.Attribute; 046import org.kepler.objectmanager.data.db.Entity; 047import org.xml.sax.InputSource; 048 049import ptolemy.actor.TypedIOPort; 050import ptolemy.actor.lib.LimitedFiringSource; 051import ptolemy.data.ArrayToken; 052import ptolemy.data.OrderedRecordToken; 053import ptolemy.data.StringToken; 054import ptolemy.data.Token; 055import ptolemy.data.type.ArrayType; 056import ptolemy.data.type.BaseType; 057import ptolemy.kernel.CompositeEntity; 058import ptolemy.kernel.util.IllegalActionException; 059import ptolemy.kernel.util.NameDuplicationException; 060 061/** 062 * @author Derik Barseghian 063 * @version $Id: MetadataParser.java 29789 2012-04-27 20:16:27Z barseghian $ 064 */ 065public class MetadataParser extends LimitedFiringSource { 066 067 private static final Logger logger = Logger.getLogger(MetadataParser.class); 068 private static final String CONFIGURATIONNAMESPACE = "metadataParser"; 069 private static final String MODULENAME = "actors"; 070 private static final String MAPPINGLIST = "mappingList"; 071 private static final String MAPPING = "mapping"; 072 private static final String TYPE = "type"; 073 private static final String CLASS = "class"; 074 private TypedIOPort metadataInputPort; 075 private TypedIOPort metadataTypeInputPort; 076 private Vector<MetadataTypeParserMap> metadataTypeClassMapList = null; 077 078 public MetadataParser(CompositeEntity container, String name) 079 throws NameDuplicationException, IllegalActionException { 080 super(container, name); 081 082 metadataInputPort = new TypedIOPort(this, "metadataInputPort", true, false); 083 metadataTypeInputPort = new TypedIOPort(this, "metadataTypeInputPort", true, false); 084 085 output.setTypeEquals(new ArrayType(BaseType.RECORD)); 086 metadataTypeClassMapList = getMetadataTypeParserMap(); 087 } 088 089 public void fire() throws IllegalActionException { 090 super.fire(); 091 092 if (metadataInputPort.numberOfSources() <= 0){ 093 return; 094 } 095 if (metadataTypeInputPort.numberOfSources() <= 0){ 096 return; 097 } 098 099 StringToken metadataTypeStringToken = (StringToken) metadataTypeInputPort.get(0); 100 String metadataType = metadataTypeStringToken.stringValue(); 101 102 ParserInterface parser = createParser(metadataType); 103 if(parser == null) { 104 throw new IllegalActionException("Kepler can't find a metadata parser for the type "+metadataType+". Please check the metadataParser.xml file."); 105 } 106 StringToken metadataStringToken = (StringToken) metadataInputPort.get(0); 107 108 //logger.debug("received on input port:\n"+metadataStringToken.stringValue()); 109 110 try { 111 // FIXME character encoding 112 InputStreamReader inputStreamReader = new InputStreamReader(IOUtils.toInputStream(metadataStringToken.stringValue(), "UTF-16"), "UTF-16"); 113 ArrayList<OrderedRecordToken> orderedRecordTokens = parsePackage(inputStreamReader, parser); 114 if (output.numberOfSinks() > 0){ 115 OrderedRecordToken[] ors = orderedRecordTokens.toArray(new OrderedRecordToken[orderedRecordTokens.size()]); 116 output.broadcast(new ArrayToken(ors)); 117 //for (int i=0; i<ors.length; i++){ 118 // output.send(0, ors[0]); 119 //} 120 } 121 } catch (UnsupportedEncodingException e) { 122 // TODO Auto-generated catch block 123 e.printStackTrace(); 124 } catch (IOException e) { 125 // TODO Auto-generated catch block 126 e.printStackTrace(); 127 } 128 129 130 } 131 132 public void preinitialize() throws IllegalActionException { 133 super.preinitialize(); 134 } 135 136 /** The director told us to stop firing immediately. */ 137 public void stop() { 138 super.stop(); 139 } 140 141 public void wrapup() throws IllegalActionException { 142 super.wrapup(); 143 } 144 145 146 /* 147 *Create a parser object from the metadataParser.xml configuration according to the metadata type. 148 *The null will be returned if no parser class can be found. 149 */ 150 private ParserInterface createParser(String metadataType) { 151 ParserInterface parser = null; 152 if(metadataType != null ) { 153 if(metadataTypeClassMapList != null ) { 154 for(MetadataTypeParserMap map : metadataTypeClassMapList) { 155 if(map != null) { 156 if(metadataType.equals(map.getMetadataType())) { 157 String className = map.getClassName(); 158 if(className != null) { 159 try { 160 Class classDefinition = Class.forName(className); 161 parser = (ParserInterface)classDefinition.newInstance(); 162 break; 163 } catch (InstantiationException e) { 164 logger.warn("MetadataPaser.createParser - can't get the parser object since "+e.getMessage()); 165 continue; 166 } catch (IllegalAccessException e) { 167 logger.warn("MetadataPaser.createParser - can't get the parser object since "+e.getMessage()); 168 continue; 169 } catch (ClassNotFoundException e) { 170 logger.warn("MetadataPaser.createParser - can't get the parser object since "+e.getMessage()); 171 continue; 172 } 173 } 174 } 175 } 176 } 177 } 178 } 179 return parser; 180 } 181 182 /* 183 * Get the the mapping between the parser class name and metadata type from the configuration file - metadataParser.xml 184 */ 185 private Vector<MetadataTypeParserMap> getMetadataTypeParserMap() { 186 Vector<MetadataTypeParserMap> mapping = new Vector <MetadataTypeParserMap>(); 187 ConfigurationManager manager = ConfigurationManager.getInstance(); 188 if(manager != null) { 189 ConfigurationProperty cp = manager.getProperty(ConfigurationManager.getModule(MODULENAME), 190 new ConfigurationNamespace(CONFIGURATIONNAMESPACE)); 191 if(cp != null) { 192 //System.out.println("==== the property file is not null"); 193 ConfigurationProperty mappingListProperty = cp.getProperty(MAPPINGLIST); 194 if (mappingListProperty != null) { 195 //System.out.println("==== the mapping list is not null"); 196 List<ConfigurationProperty> mappingProperties = mappingListProperty.getProperties(MAPPING); 197 if(mappingProperties != null) { 198 for(ConfigurationProperty mappingProperty : mappingProperties) { 199 //System.out.println("==== the mapping is not null"); 200 ConfigurationProperty metadataTypeProperty = mappingProperty.getProperty(TYPE); 201 ConfigurationProperty classProperty = mappingProperty.getProperty(CLASS); 202 if(metadataTypeProperty != null && classProperty != null ) { 203 MetadataTypeParserMap map = new MetadataTypeParserMap(); 204 //System.out.println("==== add class name "+classProperty.getValue()); 205 //System.out.println("==== add metadata type "+metadataTypeProperty.getValue()); 206 map.setClassName(classProperty.getValue()); 207 map.setMetadataType(metadataTypeProperty.getValue()); 208 mapping.add(map); 209 } 210 } 211 212 } 213 214 } 215 216 } 217 } 218 return mapping; 219 220 } 221 222 223 private ArrayList<OrderedRecordToken> parsePackage(Reader reader, ParserInterface parser) throws IllegalActionException { 224 Eml200Parser eml200Parser; 225 226 ArrayList<OrderedRecordToken> orderedRecordTokens = new ArrayList<OrderedRecordToken>(); 227 228 229 try { // parse the package for the names and types of the atts 230 //eml200Parser = new Eml200Parser(); 231 parser.parse(new InputSource(reader)); 232 //String namespace = eml200Parser.getNameSpace(); 233 234 logger.debug("entity count:"+parser.getEntityCount()); 235 236 //TODO check if eml parser be refactored to use generics / if this typing is safe: 237 List<Entity> entities = parser.getEntities(); 238 if(entities != null ) { 239 for (Entity entity: entities){ 240 ArrayList<String> labels = new ArrayList<String>(); 241 ArrayList<Token> tokens = new ArrayList<Token>(); 242 logger.debug("name:" + entity.getName() + " getAttributes().length:" + entity.getAttributes().length); 243 //logger.debug("key:"+key + " name:" + entity.getName() + " num attributes:" + entity.getAttributes().length + " entity:\n"+entity.toXml()); 244 245 labels.add("entityName"); 246 tokens.add(new StringToken(entity.getName())); 247 int numAttributes = entity.getAttributes().length; 248 249 if (numAttributes > 0){ 250 labels.add("attributeName"); 251 labels.add("attributeDataType"); 252 253 Token[] attributeNames = new Token[numAttributes]; 254 Token[] attributeDataTypes = new Token[numAttributes]; 255 256 for (int i=0; i< numAttributes; i++){ 257 Attribute a = entity.getAttributes()[i]; 258 logger.debug("attributeName:" + a.getName() + 259 " attributeDataType:" + a.getDataType()); 260 //" unit:" + a.getUnit() + 261 //" unitType:" + a.getUnitType() + 262 //" measurementScale:" + a.getMeasurementScale()); 263 attributeNames[i] = new StringToken(a.getName()); 264 attributeDataTypes[i] = new StringToken(a.getDataType()); 265 266 } 267 268 tokens.add(new ArrayToken(attributeNames)); 269 tokens.add(new ArrayToken(attributeDataTypes)); 270 } 271 272 String[] labelArray = labels.toArray(new String[labels.size()]); 273 Token[] tokenArray = tokens.toArray(new Token[tokens.size()]); 274 orderedRecordTokens.add(new OrderedRecordToken(labelArray, tokenArray)); 275 } 276 } 277 278 279 return orderedRecordTokens; 280 281 } catch (Exception e) { 282 e.printStackTrace(); 283 throw new IllegalActionException("Error parsing the eml package: " 284 + e.getMessage()); 285 } 286 287 } 288 289 /* 290 * A class represents the map between the metadata type and parser from the configuration file. 291 */ 292 private class MetadataTypeParserMap { 293 private String metadataType = null; 294 private String className = null; 295 296 /** 297 * Constructor 298 */ 299 public MetadataTypeParserMap() { 300 301 } 302 303 /** 304 * Set the metadata type. 305 * @param metadataType - the type of the metadata. 306 */ 307 public void setMetadataType(String metadataType) { 308 this.metadataType = metadataType; 309 } 310 311 /** 312 * Get the metadata type. It can be null. 313 * @return the type of the metadata. 314 */ 315 public String getMetadataType() { 316 return metadataType; 317 } 318 319 /** 320 * Set the class name. 321 * @param className - the name of the class. 322 */ 323 public void setClassName(String className) { 324 this.className = className; 325 } 326 327 /** 328 * Get the class name mapping the metadata type. It can be null. 329 * @return the class name. 330 */ 331 public String getClassName() { 332 return this.className; 333 } 334 } 335 336}