From 1a31aa221188951ef3b89e1b81b33210200e5fd3 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Thu, 16 May 2013 11:13:17 -0500 Subject: [PATCH] Issue #1869 Rewrite dataURI property mappings. Change-Id: I1aa45aa5214c3d080766129a470903f2fc2e49b9 Former-commit-id: 9c3af2ce1f086bb15fa1f4e261a4d7a1a65bd956 --- .../res/spring/viz.xml | 13 + .../raytheon/uf/viz/core/RecordFactory.java | 91 ++-- .../common/dataplugin/IPluginClassMapper.java | 45 ++ .../common/dataplugin/PluginDataObject.java | 388 ++------------ .../dataplugin/annotations/DataURIUtil.java | 495 ++++++++++++++---- .../res/spring/database-common.xml | 13 + .../uf/edex/database/plugin/PluginDao.java | 23 +- .../edex/database/plugin/PluginFactory.java | 12 +- .../uf/edex/plugin/fssobs/FSSObsUtils.java | 8 +- .../ncinventory/NcInventoryUpdater.java | 38 +- 10 files changed, 575 insertions(+), 551 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/IPluginClassMapper.java diff --git a/cave/com.raytheon.uf.viz.core/res/spring/viz.xml b/cave/com.raytheon.uf.viz.core/res/spring/viz.xml index 184709ec6b..d717b020e3 100644 --- a/cave/com.raytheon.uf.viz.core/res/spring/viz.xml +++ b/cave/com.raytheon.uf.viz.core/res/spring/viz.xml @@ -54,5 +54,18 @@ + + + + + + com.raytheon.uf.common.dataplugin.annotations.DataURIUtil + + + setClassMapper + + + \ No newline at end of file diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/RecordFactory.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/RecordFactory.java index f928ae767d..2caf926800 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/RecordFactory.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/RecordFactory.java @@ -24,9 +24,9 @@ import java.util.HashMap; import java.util.Map; import java.util.TreeSet; +import com.raytheon.uf.common.dataplugin.IPluginClassMapper; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; -import com.raytheon.uf.common.dataplugin.annotations.DataURI; import com.raytheon.uf.common.dataplugin.annotations.DataURIUtil; import com.raytheon.uf.common.dataplugin.request.GetPluginRecordMapRequest; import com.raytheon.uf.common.status.IUFStatusHandler; @@ -50,11 +50,12 @@ import com.raytheon.uf.viz.core.requests.ThriftClient; * Mar 05, 2013 1753 njensen Improved debug message * Mar 29, 2013 1638 mschenke Added dataURI mapping methods * May 15, 2013 1869 bsteffen Move uri map creation to DataURIUtil. + * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * * * */ -public class RecordFactory { +public class RecordFactory implements IPluginClassMapper { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(RecordFactory.class); @@ -62,7 +63,7 @@ public class RecordFactory { private static RecordFactory instance = new RecordFactory(); /** Map containing the pluginName/Record class pairs */ - private Map> defMap = new HashMap>(); + private volatile Map> defMap = null; public static final String WILDCARD = "%"; @@ -79,35 +80,47 @@ public class RecordFactory { * Creates the singleton instance of the RecordFactory */ private RecordFactory() { - try { - loadDefMap(); - } catch (Exception e) { - statusHandler.handle(Priority.WARN, - "Failed to load plugin record definitions", e); - } + } @SuppressWarnings("unchecked") - private void loadDefMap() throws VizException { - GetPluginRecordMapRequest req = new GetPluginRecordMapRequest(); - Map pluginRecordMap = (Map) ThriftClient - .sendRequest(req); - for (Map.Entry entry : pluginRecordMap.entrySet()) { - String pluginName = entry.getKey(); - String record = entry.getValue(); - if (record != null) { - try { - Class clazz = (Class) Class - .forName(record); - defMap.put(pluginName, clazz); - } catch (ClassNotFoundException e) { - String msg = "Can't find record class for " + pluginName - + " plugin - alerts on " + pluginName - + " data will be ignored"; - statusHandler.handle(Priority.DEBUG, msg); + private Map> getDefMap() { + if (defMap == null) { + synchronized (this) { + if (defMap == null) { + Map> defMap = new HashMap>(); + GetPluginRecordMapRequest req = new GetPluginRecordMapRequest(); + try { + Map pluginRecordMap = (Map) ThriftClient + .sendRequest(req); + for (Map.Entry entry : pluginRecordMap + .entrySet()) { + String pluginName = entry.getKey(); + String record = entry.getValue(); + if (record != null) { + try { + Class clazz = (Class) Class + .forName(record); + defMap.put(pluginName, clazz); + } catch (ClassNotFoundException e) { + String msg = "Can't find record class for " + + pluginName + + " plugin - alerts on " + + pluginName + + " data will be ignored"; + statusHandler.handle(Priority.DEBUG, msg); + } + } + } + } catch (Exception e) { + statusHandler.handle(Priority.WARN, + "Failed to load plugin record definitions", e); + } + this.defMap = defMap; } } } + return defMap; } /** @@ -116,7 +129,7 @@ public class RecordFactory { * @return */ public Collection getSupportedPlugins() { - return new TreeSet(defMap.keySet()); + return new TreeSet(getDefMap().keySet()); } /** @@ -135,16 +148,10 @@ public class RecordFactory { return null; } - String[] tokens = dataURI.split(DataURI.SEPARATOR, 3); - String pluginName = tokens[1]; - try { - Map map = DataURIUtil.createDataURIMap(dataURI, - getPluginClass(pluginName)); + Map map = DataURIUtil.createDataURIMap(dataURI); map.put("dataURI", dataURI); return map; - } catch (NoPluginException e) { - throw e; } catch (Exception e) { throw new VizException("Unable to create property map for " + dataURI, e); @@ -162,8 +169,9 @@ public class RecordFactory { * If errors occur creating the field/value map */ public Class getPluginClass(String pluginName) - throws VizException { + throws NoPluginException { Class retVal = null; + Map> defMap = getDefMap(); if (defMap != null) { retVal = defMap.get(pluginName); } @@ -229,10 +237,21 @@ public class RecordFactory { + type, e); } try { - PluginDataObject.populateFromMap(record, map); + DataURIUtil + .populatePluginDataObject((PluginDataObject) record, map); } catch (PluginException e) { throw new VizException(e); } return record; } + + @Override + public Class getPluginRecordClass(String pluginName) + throws PluginException { + try { + return getPluginClass(pluginName); + } catch (NoPluginException e) { + throw new PluginException(e.getLocalizedMessage()); + } + } } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/IPluginClassMapper.java b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/IPluginClassMapper.java new file mode 100644 index 0000000000..cb03d67927 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/IPluginClassMapper.java @@ -0,0 +1,45 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.dataplugin; + + +/** + * Interface for any class that is capable of mapping a pluginName to a class + * which extends PluginDataObject. This interface exists in common so that + * different mechanisms can easily be used in different parts of the system. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * May 16, 2013 1869       bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public interface IPluginClassMapper { + + public Class getPluginRecordClass(String pluginName) + throws PluginException; +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java index 417f84f26c..202bbc97a4 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/PluginDataObject.java @@ -20,10 +20,7 @@ package com.raytheon.uf.common.dataplugin; -import java.lang.reflect.Field; import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; import javax.persistence.Column; import javax.persistence.Embedded; @@ -40,7 +37,6 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; -import org.apache.commons.beanutils.PropertyUtils; import org.hibernate.annotations.Index; import com.raytheon.uf.common.dataplugin.annotations.DataURI; @@ -52,9 +48,10 @@ import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.DataTime; -import com.raytheon.uf.common.time.util.TimeUtil; -import com.raytheon.uf.common.util.ConvertUtil; /** * Abstract class from which all plugin specific data types inherit. A plugin @@ -88,21 +85,24 @@ import com.raytheon.uf.common.util.ConvertUtil; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 7/24/07 353 bphillip Initial creation - * 20071129 472 jkorman Added getDecoderGettable(). - * 2/6/09 1990 bphillip Added database index on dataURI - * 3/18/09 2105 jsanchez Added getter for id. - * Removed unused getIdentfier(). - * Mar 29, 2013 1638 mschenke Added methods for loading from data map and creating data map from - * dataURI fields - * Apr 12, 2013 1857 bgonzale Changed to MappedSuperclass, named generator, - * GenerationType SEQUENCE, moved Indexes to getter - * methods. + * Jul 24, 2007 353 bphillip Initial creation + * Nov 29, 2007 472 jkorman Added getDecoderGettable(). + * Feb 06, 2009 1990 bphillip Added database index on dataURI + * Mar 18, 2009 2105 jsanchez Added getter for id. Removed unused + * getIdentfier(). + * Mar 29, 2013 1638 mschenke Added methods for loading from data map + * and creating data map from dataURI + * fields + * Apr 12, 2013 1857 bgonzale Changed to MappedSuperclass, named + * generator, GenerationType SEQUENCE, + * moved Indexes to getter methods. * Apr 15, 2013 1868 bsteffen Improved performance of createDataURIMap - * May 02, 2013 1970 bgonzale Moved Index annotation from getters to attributes. - * + * May 02, 2013 1970 bgonzale Moved Index annotation from getters to + * attributes. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. + * * */ @MappedSuperclass @@ -112,6 +112,9 @@ import com.raytheon.uf.common.util.ConvertUtil; public abstract class PluginDataObject extends PersistableDataObject implements ISerializableObject { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(PluginDataObject.class); + private static final long serialVersionUID = 1L; public static final String ID_GEN = "idgen"; @@ -159,12 +162,16 @@ public abstract class PluginDataObject extends PersistableDataObject implements * Default Constructor */ public PluginDataObject() { + } public PluginDataObject(String uri) { - String[] uriTokens = uri.split(DataURI.SEPARATOR); - pluginName = uriTokens[1]; - populateObject(this, uriTokens); + try { + DataURIUtil.populatePluginDataObject(this, uri); + } catch (PluginException e) { + // this should never happen operationally + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); + } this.dataURI = uri; } @@ -178,344 +185,19 @@ public abstract class PluginDataObject extends PersistableDataObject implements getDataURI(); } - /** - * Recursive method for generating a dataURI - * - * @param obj - * An object containing fields annotated with the DataURI - * annotation - * @param uriBuffer - * The dataURI StringBuffer - * @return The updated dataURI - */ - private void generateURI(Object obj, StringBuilder uriBuffer) { - - // Get the fields with @DataURI annotation - Field[] dataURIFields = DataURIUtil.getInstance().getDataURIFields( - obj.getClass()); - - /* - * Iterate through each field and assemble the dataURI - */ - for (Field field : dataURIFields) { - Object property = null; - try { - property = PropertyUtils.getProperty(obj, field.getName()); - } catch (Exception e) { - e.printStackTrace(); - } - if (field.getAnnotation(DataURI.class).embedded()) { - if (property == null) { - // Populate datauri with all "null" for null embedded - // objects. - int numFields = DataURIUtil.getInstance().getDataURIFields( - field.getClass()).length; - for (int f = 0; f < numFields; f += 1) { - uriBuffer.append(DataURI.SEPARATOR).append( - String.valueOf(null)); - } - } else { - // Recursive call to get dataURI elements from embedded - // object - generateURI(property, uriBuffer); - } - } else { - // Append to the dataURI buffer - uriBuffer.append(DataURI.SEPARATOR); - if (property == null) { - uriBuffer.append("null"); - } else if (property instanceof Calendar) { - uriBuffer.append(TimeUtil - .formatCalendar((Calendar) property)); - } else { - uriBuffer.append(String.valueOf(property).replaceAll( - DataURI.SEPARATOR, "_")); - } - } - } - } - - /** - * Populates the record object from a data map - * - * @param dataMap - * @throws PluginException - */ - public void populateFromMap(Map dataMap) - throws PluginException { - populateFromMap(this, dataMap); - } - - /** - * Creates a mapping of dataURI fields to objects set in the record - * - * @return - * @throws PluginException - */ - public Map createDataURIMap() throws PluginException { - try { - Class thisClass = this.getClass(); - Map map = new HashMap(); - map.put("pluginName", getPluginName()); - int index = 0; - String fieldName = PluginDataObject.getDataURIFieldName(thisClass, - index++); - while (fieldName != null) { - Object source = this; - int start = 0; - int end = fieldName.indexOf('.', start); - while (end >= 0) { - source = PropertyUtils.getProperty(source, - fieldName.substring(start, end)); - start = end + 1; - end = fieldName.indexOf('.', start); - } - source = PropertyUtils.getProperty(source, - fieldName.substring(start)); - map.put(fieldName, source); - fieldName = PluginDataObject.getDataURIFieldName(thisClass, - index++); - } - return map; - } catch (Exception e) { - throw new PluginException("Error constructing dataURI mapping", e); - } - } - - /** - * Populates object from data mapping - * - * @param object - * @param dataMap - */ - public static void populateFromMap(Object object, - Map dataMap) throws PluginException { - try { - for (String property : dataMap.keySet()) { - String[] nested = property.split("[.]"); - if (nested.length > 0) { - Object source = object; - for (int i = 0; i < nested.length - 1; ++i) { - String field = nested[i]; - Object obj = PropertyUtils.getProperty(source, field); - if (obj == null) { - obj = PropertyUtils.getPropertyType(source, field) - .newInstance(); - PropertyUtils.setProperty(source, field, obj); - } - source = obj; - } - String sourceProperty = nested[nested.length - 1]; - Object value = dataMap.get(property); - if (value != null) { - PropertyUtils - .setProperty(source, sourceProperty, value); - } - } - } - } catch (Exception e) { - throw new PluginException("Error populating record type: " - + (object != null ? object.getClass() : null) - + " from map: " + dataMap, e); - } - } - - /** - * Recursive method to populate an object from the elements in a dataURI - * string - * - * @param obj - * The object for which to populate fields from the dataURI - * string - * @param uriTokens - * The elements of the dataURI string - * @return An object populated from the elements of the dataURI string - */ - @SuppressWarnings("unchecked") - private Object populateObject(Object obj, String[] uriTokens) { - - // Get the fields annotated with the @DataURI annotation - Field[] dataURIFields = DataURIUtil.getInstance().getDataURIFields( - obj.getClass()); - - Field currentField = null; - String currentUriToken = null; - for (Field dataURIField : dataURIFields) { - currentUriToken = uriTokens[uriIndex]; - currentField = dataURIField; - - if (currentField.getAnnotation(DataURI.class).embedded()) { - // The current dataURI token refers to a field in an embedded - // object. Execute recursive call to populate embedded object - try { - if (obj instanceof Map) { - populateObject(obj, uriTokens); - } else { - PropertyUtils.setProperty( - obj, - currentField.getName(), - populateObject(currentField.getType() - .newInstance(), uriTokens)); - } - } catch (Exception e) { - e.printStackTrace(); - } - } else { - // The current dataURI token refers to field in the obj class. - // Assign the field and increment the uri index variable - uriIndex++; - try { - Object property = ConvertUtil.convertObject( - currentUriToken, currentField.getType()); - if (obj instanceof Map) { - ((Map) obj).put(currentField.getName(), - property); - } else { - try { - PropertyUtils.setProperty(obj, - currentField.getName(), property); - } catch (Throwable e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - return obj; - } - - /** - * Retrieves the name of the field represented by the specified index in the - * dataURI. The index starts at the dataTime in the dataURI and does not - * include the plugin name. - * - * @param clazz - * The class of the object to examine - * @param targetIndex - * The index in the dataURI - * @return The name of the field at the specified dataURI index - */ - public static String getDataURIFieldName(Class clazz, int targetIndex) { - return getDataURIFieldName(targetIndex, new int[] { 0 }, clazz, ""); - } - - /** - * Recursive method to get the dataURI field name - * - * @param targetIndex - * The index in the DataURI to get the field name for - * @param index - * The current index being examined. This field is necessary for - * recursive calls - * @param clazz - * The class being examined - * @param fieldName - * The current field name. This field is necessary for recursive - * calls. If the dataURI is specified in an embedded object, this - * field will take the form class1.class2.field i.e. for a grib - * record this could be modelInfo.modelName - * @return The fieldName - */ - private static String getDataURIFieldName(int targetIndex, int[] index, - Class clazz, String fieldName) { - // Get the fields annotated with the @DataURI annotation - Field[] dataURIFields = DataURIUtil.getInstance().getDataURIFields( - clazz); - - for (Field field : dataURIFields) { - - DataURI uriAnnotation = field.getAnnotation(DataURI.class); - if (uriAnnotation != null) { - if (uriAnnotation.embedded()) { - String tmp = getDataURIFieldName(targetIndex, index, - field.getType(), fieldName + field.getName() + "."); - if (tmp != null) { - return tmp; - } - } else { - if (index[0] == targetIndex) { - fieldName += field.getName(); - return fieldName; - } else { - index[0]++; - } - } - } - } - return null; - } - - /** - * Gets the value in the dataURI at the specified index - * - * @param index - * The index in the dataURI for which to get the value - * @param fieldName - * The name of the field - * @return The value in the dataURI at the specified index - * @throws Exception - */ - public Object getDataURIFieldValue(int index, String fieldName) - throws Exception { - return getDataURIFieldValue(index, new int[] { 0 }, this.getClass(), - fieldName); - } - - /** - * Recursive helper method to get a dataURI field value - * - * @param targetIndex - * The index in the dataURI for which to get the value - * @param index - * The current index in the dataURI being examined - * @param clazz - * The class to be examined - * @param fieldName - * The name of the field - * @return The value in the dataURI at the specified index - * @throws Exception - */ - private Object getDataURIFieldValue(int targetIndex, int[] index, - Class clazz, String fieldName) throws Exception { - // Get the fields annotated with the @DataURI annotation - Field[] dataURIFields = DataURIUtil.getInstance().getDataURIFields( - clazz); - - for (Field field : dataURIFields) { - DataURI uriAnnotation = field.getAnnotation(DataURI.class); - if (uriAnnotation != null) { - if (uriAnnotation.embedded()) { - Object tmp = getDataURIFieldValue(targetIndex, index, - field.getType(), fieldName); - if (tmp != null) { - return tmp; - } - } else { - if (index[0] == targetIndex) { - return ConvertUtil.convertObject(fieldName, - field.getType()); - } else { - index[0]++; - } - } - } - } - return null; - } - public DataTime getDataTime() { return dataTime; } public String getDataURI() { if (dataURI == null && pluginName != null) { - StringBuilder uriBuffer = new StringBuilder(160); - uriBuffer.append(DataURI.SEPARATOR).append(pluginName); - generateURI(this, uriBuffer); - this.dataURI = uriBuffer.toString().replaceAll(" ", "_"); + try { + this.dataURI = DataURIUtil.createDataURI(this); + } catch (PluginException e) { + // this should never happen operationally + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + } } return this.dataURI; } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java index 5416eb0d62..3a6ad3edcd 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/annotations/DataURIUtil.java @@ -23,14 +23,22 @@ package com.raytheon.uf.common.dataplugin.annotations; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Pattern; import org.apache.commons.beanutils.PropertyUtils; +import com.raytheon.uf.common.dataplugin.IPluginClassMapper; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.common.util.ConvertUtil; /** * Utility class for working with dataURIs @@ -45,6 +53,7 @@ import com.raytheon.uf.common.dataplugin.PluginException; * Apr 18, 2013 1638 mschenke Moved dataURI map generation into here * from PluginDataObject * May 15, 2013 1869 bsteffen Move uri map creation from RecordFactory. + * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * * * @@ -53,34 +62,208 @@ import com.raytheon.uf.common.dataplugin.PluginException; */ public class DataURIUtil { - /** The singleton instance */ - private static DataURIUtil instance; + private static final String PLUGIN_NAME_KEY = "pluginName"; - /** Map of classes and the DataURI annotated fields */ - private Map, Field[]> uriFieldMap; + private static final Pattern SEPARATOR_PATTERN = Pattern + .compile(DataURI.SEPARATOR); - /** - * Constructs the singleton instance + private static final Pattern UNDERSCORE_PATTERN = Pattern.compile("_"); + + private static final Pattern SPACE_PATTERN = Pattern.compile(" "); + + /* + * Compares two fields with the DataURI annotations based off the position. */ - private DataURIUtil() { - uriFieldMap = new HashMap, Field[]>(); - } + private static final Comparator dataURIAnnotationComparator = new Comparator() { - /** - * Gets the singleton instance - * - * @return The singleton instance - */ - public synchronized static DataURIUtil getInstance() { - if (instance == null) { - instance = new DataURIUtil(); + @Override + public int compare(Field f1, Field f2) { + int i1 = f1.getAnnotation(DataURI.class).position(); + int i2 = f2.getAnnotation(DataURI.class).position(); + return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1)); } - return instance; + + }; + + private static IPluginClassMapper classMapper; + + /* + * Internal cache to avoid constant reflection + */ + private static Map, DataURIFieldAccess[]> uriFieldMap = new ConcurrentHashMap, DataURIFieldAccess[]>(); + + /** + * The classMapper needs to be injected to allow this class to create new + * PDOs based off the pluginName in a dataURI or map. + * + * @param classMapper + */ + public static void setClassMapper(IPluginClassMapper classMapper) { + DataURIUtil.classMapper = classMapper; } /** - * Creates a DataURI map for the specified object based on {@link DataURI} - * annotations + * Build a new dataURI based off the dataURI fields in the PluginDataObject. + * + * @param pdo + * @return + * @throws PluginException + */ + public static String createDataURI(PluginDataObject pdo) + throws PluginException { + StringBuilder uri = new StringBuilder(160); + addToDataURI(uri, pdo.getPluginName()); + for (DataURIFieldAccess access : getAccess(pdo.getClass())) { + addToDataURI(uri, access.getFieldValue(pdo)); + } + return SPACE_PATTERN.matcher(uri).replaceAll("_"); + } + + /** + * Create a dataURI based off the dataURI fields in the dataMap. + * + * @param dataMap + * @return + * @throws PluginException + */ + public static String createDataURI(Map dataMap) + throws PluginException { + String pluginName = dataMap.get(PLUGIN_NAME_KEY).toString(); + StringBuilder uri = new StringBuilder(160); + addToDataURI(uri, pluginName); + for (DataURIFieldAccess access : getAccess(pluginName)) { + addToDataURI(uri, dataMap.get(access.getFieldName())); + } + return SPACE_PATTERN.matcher(uri).replaceAll("_"); + } + + /* + * Properly formats an arbitrary object into a dataURI. + */ + private static void addToDataURI(StringBuilder uri, Object property) { + uri.append("/"); + if (property == null) { + uri.append("null"); + } else if (property instanceof Calendar) { + uri.append(TimeUtil.formatCalendar((Calendar) property)); + } else { + uri.append(SEPARATOR_PATTERN.matcher(String.valueOf(property)) + .replaceAll("_")); + } + } + + /** + * Parse a dataURI and set the dataURIFields into a dataMap + * + * @param dataURI + * @return + * @throws PluginException + */ + public static Map createDataURIMap(String dataURI) + throws PluginException { + List tokens = tokenizeURI(dataURI); + Map dataMap = new HashMap( + (int) (tokens.size() / 0.75f + 1), 0.75f); + String pluginName = tokens.get(0); + tokens = tokens.subList(1, tokens.size()); + dataMap.put(PLUGIN_NAME_KEY, pluginName); + DataURIFieldAccess[] access = getAccess(pluginName); + for (int i = 0; i < access.length; i += 1) { + dataMap.put(access[i].getFieldName(), + access[i].getFieldValue(tokens.get(i))); + } + return dataMap; + } + + /** + * Populate a dataMap based off the dataURI fields in the PluginDataObject. + * + * @param pdo + * @return + * @throws PluginException + */ + public static Map createDataURIMap(PluginDataObject pdo) + throws PluginException { + return createDataURIMap((Object) pdo); + } + + /** + * Create a new PluginDataObject based off the dataURI. THe class of the + * result object is based off the pluginName in the dataURI and all fields + * present in the DataURI are set into the PDO. + * + * @param dataURI + * @return + * @throws PluginException + */ + public static PluginDataObject createPluginDataObject(String dataURI) + throws PluginException { + PluginDataObject pdo = null; + List tokens = tokenizeURI(dataURI); + Class clazz = getPluginRecordClass(tokens.get(0)); + try { + pdo = clazz.newInstance(); + } catch (Exception e) { + throw new PluginException(e); + } + populatePluginDataObject(pdo, tokens); + pdo.setDataURI(dataURI); + return pdo; + } + + /** + * Create a new PluginDataObject based off the dataMap. The class of the + * result object is based off the pluginName mapping and all dataURI fields + * present in the map are set into the PDO. + * + * @param dataMap + * @return + * @throws PluginException + */ + public static PluginDataObject createPluginDataObject( + Map dataMap) throws PluginException { + PluginDataObject pdo = null; + Class clazz = getPluginRecordClass(dataMap.get( + PLUGIN_NAME_KEY).toString()); + try { + pdo = clazz.newInstance(); + } catch (Exception e) { + throw new PluginException(e); + } + populatePluginDataObject(pdo, dataMap); + return pdo; + } + + /** + * Populate an existing PluginDataObjects with the DataURI fields from the + * dataMap. + * + * @param pdo + * @param dataMap + * @throws PluginException + */ + public static void populatePluginDataObject(PluginDataObject pdo, + Map dataMap) throws PluginException { + pdo.setPluginName(dataMap.get(PLUGIN_NAME_KEY).toString()); + populateObject(pdo, dataMap); + } + + /** + * Populate an existing PluginDataObject using fields parsed from the + * dataURI. + * + * @param pdo + * @param dataURI + * @throws PluginException + */ + public static void populatePluginDataObject(PluginDataObject pdo, + String dataURI) throws PluginException { + populatePluginDataObject(pdo, tokenizeURI(dataURI)); + pdo.setDataURI(dataURI); + } + + /** + * Create a dataURIMap from any object with dataURI annotations. * * @param object * @return @@ -88,110 +271,208 @@ public class DataURIUtil { */ public static Map createDataURIMap(Object object) throws PluginException { - try { - Map map = new HashMap(); - Field[] fields = DataURIUtil.getInstance().getAllDataURIFields( - object.getClass()); - for (int i = 0; i < fields.length; ++i) { - String fieldName = PluginDataObject.getDataURIFieldName( - object.getClass(), i); - String[] nested = fieldName.split("[.]"); - Object source = object; - if (nested.length > 0) { - for (int j = 0; j < nested.length && source != null; ++j) { - source = PropertyUtils.getProperty(source, nested[j]); - } - map.put(fieldName, source); - } - } - return map; - } catch (Exception e) { - throw new PluginException("Error constructing dataURI mapping", e); + DataURIFieldAccess[] accessArray = getAccess(object.getClass()); + Map dataMap = new HashMap( + (int) (accessArray.length / 0.75f + 2), 0.75f); + if (object instanceof PluginDataObject) { + dataMap.put(PLUGIN_NAME_KEY, + ((PluginDataObject) object).getPluginName()); } - } - - public static Map createDataURIMap(String dataURI, Class clazz) - throws PluginException { - Map map = new HashMap(); - - String[] tokens = dataURI.replaceAll("_", " ").split(DataURI.SEPARATOR); - - map.put("pluginName", tokens[1]); - PluginDataObject obj = null; - try { - obj = clazz.newInstance(); - - for (int i = 2; i < tokens.length; i++) { - String fieldName = PluginDataObject.getDataURIFieldName( - obj.getClass(), i - 2); - if (fieldName == null) { - continue; - } - Object value = obj.getDataURIFieldValue(i - 2, tokens[i]); - map.put(fieldName, value); - } - } catch (Exception e) { - throw new PluginException("Error constructing dataURI mapping", e); - } - return map; - } - - public Field[] getAllDataURIFields(Class obj) { - List fields = new ArrayList(); - getAllDataURIFields(obj, fields); - return fields.toArray(new Field[0]); - } - - private void getAllDataURIFields(Class obj, List fields) { - for (Field field : getDataURIFields(obj)) { - if (field.getAnnotation(DataURI.class).embedded()) { - getAllDataURIFields(field.getType(), fields); - } else { - fields.add(field); - } + for (DataURIFieldAccess access : accessArray) { + dataMap.put(access.getFieldName(), access.getFieldValue(object)); } + return dataMap; } /** - * Retrieves an ordered listing of all fields annotated as DataURI fields. + * Populate an existing object from the dataURI fields in dataMap. * - * @param obj - * The object to examine - * @return The ordered array of all fields annotated as DataURI fields + * @param object + * @param dataMap + * @throws PluginException */ - public Field[] getDataURIFields(Class obj) { - - // Check map first - if (uriFieldMap.containsKey(obj)) { - return uriFieldMap.get(obj); + public static void populateObject(Object object, Map dataMap) + throws PluginException { + for (DataURIFieldAccess access : getAccess(object.getClass())) { + access.setFieldValue(object, dataMap.get(access.getFieldName())); } + } - // Iterate through the class hierarchy + /* + * Populate a PDO with the tokens from a parsed DataURI + */ + private static void populatePluginDataObject(PluginDataObject pdo, + List uriTokens) throws PluginException { + pdo.setPluginName(uriTokens.get(0)); + uriTokens = uriTokens.subList(1, uriTokens.size()); + DataURIFieldAccess[] access = getAccess(pdo.getClass()); + for (int i = 0; i < access.length; i += 1) { + access[i].setFieldValue(pdo, + access[i].getFieldValue(uriTokens.get(i))); + } + } + + /* + * Split a URI on the seperator and remove empty first element. + */ + private static List tokenizeURI(String dataURI) { + dataURI = UNDERSCORE_PATTERN.matcher(dataURI).replaceAll(" "); + String[] tokens = SEPARATOR_PATTERN.split(dataURI); + return Arrays.asList(tokens).subList(1, tokens.length); + } + + private static DataURIFieldAccess[] getAccess(String pluginName) + throws PluginException { + return getAccess(getPluginRecordClass(pluginName)); + } + + private static DataURIFieldAccess[] getAccess(Class clazz) { + DataURIFieldAccess[] result = uriFieldMap.get(clazz); + if (result == null) { + result = getAccess(clazz, Collections. emptyList()) + .toArray(new DataURIFieldAccess[0]); + uriFieldMap.put(clazz, result); + } + return result; + } + + private static List getAccess(Class clazz, + List parents) { + List fields = getOrderedDataURIFields(clazz); + List accessors = new ArrayList(); + for (Field field : fields) { + List names = new ArrayList(parents); + names.add(field.getName()); + Class type = field.getType(); + if (field.getAnnotation(DataURI.class).embedded()) { + accessors.addAll(getAccess(type, names)); + } else { + accessors.add(new DataURIFieldAccess(names, type)); + } + } + return accessors; + } + + private static List getOrderedDataURIFields(Class clazz) { List fields = new ArrayList(); - Class currentClass = obj; + Class currentClass = clazz; while (currentClass != null) { - fields.addAll(Arrays.asList(currentClass.getDeclaredFields())); + for (Field field : currentClass.getDeclaredFields()) { + if (field.getAnnotation(DataURI.class) != null) { + fields.add(field); + } + } currentClass = currentClass.getSuperclass(); } + Collections.sort(fields, dataURIAnnotationComparator); + return fields; + } - // Count the fields annotated with the DataURI annotation - int fieldCount = 0; - for (Field field : fields) { - if (field.getAnnotation(DataURI.class) != null) { - fieldCount++; - } + public static Class getPluginRecordClass(String pluginName) + throws PluginException { + if (classMapper == null) { + throw new PluginException( + "No PluginClassMapper is registered with DataURIUtil."); } - // Sort the annotations into an array - Field[] annotatedFields = new Field[fieldCount]; - for (Field field : fields) { - DataURI annotation = field.getAnnotation(DataURI.class); - if (annotation != null) { - annotatedFields[annotation.position()] = field; + return classMapper.getPluginRecordClass(pluginName); + } + + /* + * Class which remembers the fieldNames and class of a dataURI field to make + * parsing faster. + */ + private static class DataURIFieldAccess { + + /** + * List of fieldNames, used for finding objects in a PDO, for example + * {"location", "longitude"} + */ + private final String[] fieldNames; + + /** + * Compiled field names, used as map keys, for example + * "location.longitude" + */ + private final String fieldName; + + /** + * Class of the oibject that is in the dataURI. + */ + private final Class fieldClass; + + public DataURIFieldAccess(List fieldNames, Class fieldClass) { + this.fieldNames = fieldNames.toArray(new String[0]); + StringBuilder fieldName = new StringBuilder(this.fieldNames[0]); + for (int i = 1; i < this.fieldNames.length; i += 1) { + fieldName.append(".").append(this.fieldNames[i]); + } + this.fieldName = fieldName.toString(); + this.fieldClass = fieldClass; + } + + public String getFieldName() { + return fieldName; + } + + /** + * Extract the field value from a PDO. + * + * @param pdo + * @return + * @throws PluginException + */ + public Object getFieldValue(Object pdo) throws PluginException { + try { + Object object = pdo; + for (String fieldName : fieldNames) { + object = PropertyUtils.getProperty(object, fieldName); + if (object == null) { + break; + } + } + return object; + } catch (Exception e) { + throw new PluginException(e); } } - // Put fields in map and return - uriFieldMap.put(obj, annotatedFields); - return annotatedFields; + /** + * Convert the provided string into the correct type for the field. + * + * @param stringValue + * @return + * @throws PluginException + */ + public Object getFieldValue(String stringValue) throws PluginException { + return ConvertUtil.convertObject(stringValue, fieldClass); + } + + /** + * Set the fieldValue into the PDO. + * + * @param pdo + * @param fieldValue + * @throws PluginException + */ + public void setFieldValue(Object pdo, Object fieldValue) + throws PluginException { + Object source = pdo; + try { + for (int i = 0; i < fieldNames.length - 1; i += 1) { + Object obj = PropertyUtils.getProperty(source, + fieldNames[i]); + if (obj == null) { + obj = PropertyUtils.getPropertyType(source, + fieldNames[i]).newInstance(); + PropertyUtils.setProperty(source, fieldNames[i], obj); + } + source = obj; + } + PropertyUtils.setProperty(source, + fieldNames[fieldNames.length - 1], fieldValue); + } catch (Exception e) { + throw new PluginException(e); + } + } } } diff --git a/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml b/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml index 5cad91e35b..2ae239d440 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml +++ b/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml @@ -45,5 +45,18 @@
+ + + + + + com.raytheon.uf.common.dataplugin.annotations.DataURIUtil + + + setClassMapper + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java index 48163e0892..84f531e8a5 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java @@ -50,6 +50,7 @@ import org.springframework.transaction.support.TransactionCallbackWithoutResult; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.annotations.DataURIUtil; import com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider; import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider; import com.raytheon.uf.common.dataplugin.persist.IPersistable; @@ -93,20 +94,23 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 2/6/09 1990 bphillip Initial creation - * 6/29/12 #828 dgilling Force getPurgeRulesForPlugin() - * to search only COMMON_STATIC. + * Feb 06, 2009 1990 bphillip Initial creation + * Jun 29, 2012 828 dgilling Force getPurgeRulesForPlugin() to search + * only COMMON_STATIC. * Oct 10, 2012 1261 djohnson Add some generics wildcarding. - * Jan 14, 2013 1469 bkowal No longer retrieves the hdf5 data directory - * from the environment. - * Feb 12, 2013 #1608 randerso Changed to call deleteDatasets - * Feb 26, 2013 1638 mschenke Moved OGC specific functions to OGC project + * Jan 14, 2013 1469 bkowal No longer retrieves the hdf5 data + * directory from the environment. + * Feb 12, 2013 1608 randerso Changed to call deleteDatasets + * Feb 26, 2013 1638 mschenke Moved OGC specific functions to OGC + * project * Mar 27, 2013 1821 bsteffen Remove extra store in persistToHDF5 for * replace only operations. - * Apr 04, 2013 djohnson Remove formerly removed methods that won't compile. + * Apr 04, 2013 djohnson Remove formerly removed methods that + * won't compile. * Apr 15, 2013 1868 bsteffen Rewrite mergeAll in PluginDao. * May 07, 2013 1869 bsteffen Remove dataURI column from * PluginDataObject. + * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * * * @@ -365,7 +369,8 @@ public abstract class PluginDao extends CoreDao { } } // This means dataURI is not a column. - for (Entry uriEntry : pdo.createDataURIMap().entrySet()) { + for (Entry uriEntry : DataURIUtil.createDataURIMap(pdo) + .entrySet()) { String key = uriEntry.getKey(); Object value = uriEntry.getValue(); if (key.equals("pluginName")) { diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginFactory.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginFactory.java index da8dd4c9c1..fb3024071d 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginFactory.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginFactory.java @@ -27,6 +27,7 @@ import javax.persistence.Table; import org.apache.commons.beanutils.ConstructorUtils; +import com.raytheon.uf.common.dataplugin.IPluginClassMapper; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.PluginProperties; @@ -44,17 +45,18 @@ import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 06/14/06 garmendariz Initial check-in - * 05/29/07 312 bphillip Removed unused methods - * 02/06/09 1990 bphillip Refactored to use spring container - * 03/20/09 njensen Refactored to use PluginProperties + * Jun 14, 2006 garmendariz Initial check-in + * May 29, 2007 312 bphillip Removed unused methods + * Feb 06, 2009 1990 bphillip Refactored to use spring container + * Mar 20, 2009 njensen Refactored to use PluginProperties + * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * * * * @author garmendariz * @version 1.0 */ -public class PluginFactory { +public class PluginFactory implements IPluginClassMapper { /** The instance of the PluginFactory class */ private static final PluginFactory instance = new PluginFactory(); diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java index 98e32b3ce0..93113bf8ed 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java @@ -26,7 +26,6 @@ import java.util.Map.Entry; import java.util.Scanner; import com.raytheon.edex.site.SiteUtil; -import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.annotations.DataURIUtil; import com.raytheon.uf.common.dataplugin.fssobs.FSSObsRecord; @@ -40,7 +39,6 @@ import com.raytheon.uf.common.pointdata.PointDataContainer; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; -import com.raytheon.uf.edex.database.plugin.PluginFactory; import com.raytheon.uf.edex.pointdata.PointDataQuery; /** @@ -55,6 +53,7 @@ import com.raytheon.uf.edex.pointdata.PointDataQuery; * Nov 12, 2010 skorolev Initial creation * Nov 26, 2012 1297 skorolev Changed ArrayList to List.Clean code * May 15, 2013 1869 bsteffen Remove DataURI column from ldadmesonet. + * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * * * @@ -198,11 +197,8 @@ public class FSSObsUtils { PointDataQuery request = null; PointDataContainer result = null; try { - Class clazz = PluginFactory.getInstance() - .getPluginRecordClass(plgn.ldadmesonet.toString()); Map rcMap = RequestConstraint - .toConstraintMapping(DataURIUtil.createDataURIMap(uri, - clazz)); + .toConstraintMapping(DataURIUtil.createDataURIMap(uri)); // Not actually in db rcMap.remove("pluginName"); request = new PointDataQuery(plgn.ldadmesonet.toString()); diff --git a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/ncinventory/NcInventoryUpdater.java b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/ncinventory/NcInventoryUpdater.java index 234513cc47..c4cfb76200 100644 --- a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/ncinventory/NcInventoryUpdater.java +++ b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/common/ncinventory/NcInventoryUpdater.java @@ -20,19 +20,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import com.raytheon.edex.uengine.tasks.query.MetadataCatalogQuery; import com.raytheon.edex.uengine.tasks.query.TableQuery; import com.raytheon.uf.common.dataplugin.PluginDataObject; -import com.raytheon.uf.common.dataplugin.PluginProperties; import com.raytheon.uf.common.dataplugin.annotations.DataURI; +import com.raytheon.uf.common.dataplugin.annotations.DataURIUtil; import com.raytheon.uf.common.dataplugin.message.DataURINotificationMessage; import com.raytheon.uf.common.dataplugin.radar.RadarRecord; -import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; import com.raytheon.uf.edex.database.DataAccessLayerException; -import com.raytheon.uf.edex.database.status.StatusConstants; /** * @@ -42,6 +36,7 @@ import com.raytheon.uf.edex.database.status.StatusConstants; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 02/20/12 #606 Greg Hull Created + * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * * * @@ -84,34 +79,7 @@ public class NcInventoryUpdater { PluginDataObject pdo = null; try { - PluginRegistry reg = PluginRegistry.getInstance(); - PluginProperties props = reg.getRegisteredObject(pluginName); - - if( props != null && props.getRecord() != null) { - pdo = props.getRecord().newInstance(); - } - - if( pdo == null ) { - throw new Exception( "Can't find PDO for plugin."); - } - - for( int i=2 ; i < tokens.length ; i++ ) { - if( !tokens[i].equals("%") && !tokens[i].trim().isEmpty() ) { - String fld = PluginDataObject.getDataURIFieldName( pdo.getClass(), i-2 ); - - if( fld == null ) { - throw new Exception("Unable to get field name"); - } - - Object value = pdo.getDataURIFieldValue( i-2, tokens[i] ); - - attrsMap.put( fld, value ); - } - else if( tokens[i].equals("%") ) { - String fld = PluginDataObject.getDataURIFieldName( pdo.getClass(), i-2 ); - attrsMap.put( fld, "%"); - } - } + attrsMap.putAll(DataURIUtil.createDataURIMap(dataURI)); attrsMap.put( "dataURI", dataURI );