You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2014/03/18 21:36:13 UTC
svn commit: r1579031 - in /uima/uimaj/trunk/uimaj-core/src:
main/java/org/apache/uima/analysis_engine/impl/
main/java/org/apache/uima/resource/metadata/
main/java/org/apache/uima/resource/metadata/impl/
main/java/org/apache/uima/util/ test/java/org/apa...
Author: schor
Date: Tue Mar 18 20:36:12 2014
New Revision: 1579031
URL: http://svn.apache.org/r1579031
Log:
[UIMA-3684] improve caching of bean info for xml parsing
Added:
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/ConcurrentHashMapWithProducer.java
Modified:
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/MetaDataObject.java
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameterSettings_impl.java
uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/MetaDataObject_impl.java
uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java
uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitBagObject.java
uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitObject.java
Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java?rev=1579031&r1=1579030&r2=1579031&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_impl.java Tue Mar 18 20:36:12 2014
@@ -21,6 +21,7 @@ package org.apache.uima.analysis_engine.
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
+import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
@@ -36,6 +37,7 @@ import java.util.TreeMap;
import org.apache.uima.Constants;
import org.apache.uima.UIMAFramework;
+import org.apache.uima.UIMARuntimeException;
import org.apache.uima.analysis_engine.AnalysisEngine;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.metadata.AnalysisEngineMetaData;
@@ -82,21 +84,29 @@ import org.xml.sax.SAXException;
public class AnalysisEngineDescription_impl extends ResourceCreationSpecifier_impl implements
AnalysisEngineDescription {
+ static final private Method getterForAEwImports;
+ static {
+ try {
+ getterForAEwImports = AnalysisEngineDescription_impl.class.getDeclaredMethod("getDelegateAnalysisEngineSpecifiersWithImports");
+ } catch (Exception e) {
+ throw new UIMARuntimeException(e);
+ }
+ }
/**
* Name of the "delegateAnalysisEngineSpecifiers" property. Change this if interface changes.
*/
- protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
-
+ final protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
+
/**
* Name of the "delegateAnalysisEngineSpecifiersWithImports" property. Change this if interface
* changes.
*/
- protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS = "delegateAnalysisEngineSpecifiersWithImports";
+ final protected String PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS = "delegateAnalysisEngineSpecifiersWithImports";
/**
* Name of the "delegateAnalysisEngineSpecifiers" XML Element. Change this if schema changes.
*/
- protected String ELEM_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
+ final protected String ELEM_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS = "delegateAnalysisEngineSpecifiers";
private String mFrameworkImplementation;
@@ -630,6 +640,16 @@ public class AnalysisEngineDescription_i
}
return false;
}
+
+ @Override
+ public List<MetaDataAttr> getAdditionalAttributes() {
+ return Collections.singletonList(
+ new MetaDataAttr(
+ PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS,
+ getterForAEwImports,
+ null, // no writer
+ Map.class));
+ }
/**
* Overridden to add Delegate AE Specifiers to the result list. Default introspection
@@ -637,7 +657,9 @@ public class AnalysisEngineDescription_i
* import/export methods, though, so that set methods are not required.
*
* @see MetaDataObject#listAttributes()
+ * @deprecated never called anymore - getAdditionalAttributes called instead
*/
+ @Deprecated
public List<NameClassPair> listAttributes() {
List<NameClassPair> result = super.listAttributes();
result.add(new NameClassPair(PROP_DELEGATE_ANALYSIS_ENGINE_SPECIFIERS_WITH_IMPORTS, Map.class
Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/MetaDataObject.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/MetaDataObject.java?rev=1579031&r1=1579030&r2=1579031&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/MetaDataObject.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/MetaDataObject.java Tue Mar 18 20:36:12 2014
@@ -52,7 +52,9 @@ public interface MetaDataObject extends
* contains the name of a parameter and the Class of its value. For primitive types, the
* wrapper classes will be returned (e.g. <code>java.lang.Integer</code> instead of
* int).
+ * @deprecated - use getAttributes() instead, don't override it, use getAdditionalAttributes to specify additional ones
*/
+ @Deprecated
public List<NameClassPair> listAttributes();
/**
Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameterSettings_impl.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameterSettings_impl.java?rev=1579031&r1=1579030&r2=1579031&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameterSettings_impl.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/ConfigurationParameterSettings_impl.java Tue Mar 18 20:36:12 2014
@@ -19,11 +19,14 @@
package org.apache.uima.resource.metadata.impl;
+import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.apache.uima.UIMARuntimeException;
import org.apache.uima.UIMA_IllegalArgumentException;
import org.apache.uima.resource.metadata.ConfigurationParameterSettings;
import org.apache.uima.resource.metadata.MetaDataObject;
@@ -48,6 +51,14 @@ public class ConfigurationParameterSetti
static final long serialVersionUID = 3476535733588304983L;
+ private static final Method methodGetSettingsForGroups;
+ static {
+ try {
+ methodGetSettingsForGroups = ConfigurationParameterSettings.class.getDeclaredMethod("getSettingsForGroups");
+ } catch (Exception e) {
+ throw new UIMARuntimeException(e);
+ }
+ }
/**
* Settings for parameters that are not in any group.
*/
@@ -216,13 +227,25 @@ public class ConfigurationParameterSetti
return XMLIZATION_INFO;
}
+ @Override
+ public List<MetaDataAttr> getAdditionalAttributes() {
+ return Collections.singletonList(
+ new MetaDataAttr(
+ "settingsForGroups",
+ methodGetSettingsForGroups,
+ null, // no writer
+ Map.class));
+ }
+
/**
* Overridden to add the settingsForGroups property to the result list. Default introspection
* implementation won't return it because it has no set method. We've also overridden the XML
* import/export methods, though, so that set methods are not required.
*
* @see MetaDataObject#listAttributes()
+ * @deprecated - use getAdditionalAttributes instead
*/
+ @Deprecated
public List<NameClassPair> listAttributes() {
List<NameClassPair> result = super.listAttributes();
result.add(new NameClassPair("settingsForGroups", Map.class.getName()));
Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/MetaDataObject_impl.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/MetaDataObject_impl.java?rev=1579031&r1=1579030&r2=1579031&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/MetaDataObject_impl.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/resource/metadata/impl/MetaDataObject_impl.java Tue Mar 18 20:36:12 2014
@@ -33,18 +33,18 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import org.apache.uima.UIMARuntimeException;
import org.apache.uima.UIMA_IllegalArgumentException;
import org.apache.uima.UIMA_UnsupportedOperationException;
import org.apache.uima.internal.util.XMLUtils;
import org.apache.uima.resource.metadata.MetaDataObject;
+import org.apache.uima.util.ConcurrentHashMapWithProducer;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.NameClassPair;
import org.apache.uima.util.XMLParser;
@@ -79,10 +79,9 @@ import org.xml.sax.helpers.AttributesImp
* Therefore subclasses of this class must be valid JavaBeans and either use the standard naming
* conventions for getters and setters. BeanInfo augmentation is ignored; the implementation here
* uses the flag IGNORE_ALL_BEANINFO. See <a href="http://java.sun.com/docs/books/tutorial/javabeans/">
- * The Java Beans Tutorial</a> for more
- * information.
+ * The Java Beans Tutorial</a> for more information.
*
- * To support XML Comments, which can occur inbetween any sub-elements, including array values,
+ * To support XML Comments, which can occur between any sub-elements, including array values,
* the "data" for all objects is stored in a pair of ArrayLists; one holds the "name" of the slot,
* the other the value; comments are interspersed within this list where they occur.
*
@@ -102,11 +101,69 @@ public abstract class MetaDataObject_imp
private static final Attributes EMPTY_ATTRIBUTES = new AttributesImpl();
- // Class level cache (static) for introspection - 30x speedup in CDE for large descriptor
- private static transient ConcurrentMap<Class<? extends MetaDataObject_impl>, PropertyDescriptor[]> mPropertyDescriptorsMap =
- new ConcurrentHashMap<Class<? extends MetaDataObject_impl>, PropertyDescriptor[]>();
-// Collections.synchronizedMap(new IdentityHashMap<Class<? extends MetaDataObject_impl>, PropertyDescriptor[]>());
+ /*
+ * Cache for Java Bean lookup
+ *
+ * Key: the Class object of the MetaDataObject, corresponds to some XML element
+ * Value: a list of objects, one for each "attribute", holding:
+ * the attribute name
+ * the reader (a Method)
+ * the writer (a Method)
+ * the java Class of the data type of this attribute <converted to a wrapper class for primitives>
+ */
+
+ public static class MetaDataAttr {
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((clazz == null) ? 0 : clazz.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ MetaDataAttr other = (MetaDataAttr) obj;
+ if (clazz == null) {
+ if (other.clazz != null)
+ return false;
+ } else if (!clazz.equals(other.clazz))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+ final String name;
+ final Method reader;
+ final Method writer;
+ final Class clazz;
+
+ public MetaDataAttr(String name, Method reader, Method writer, Class clazz) {
+ this.name = name;
+ this.reader = reader;
+ this.writer = writer;
+ this.clazz = clazz;
+ }
+ }
+
+ private static final List<MetaDataAttr> ATTRIBUTE_0 = new ArrayList<MetaDataObject_impl.MetaDataAttr>(0);
+
+ // Cache for Java Bean info lookup
+ // Class level cache (static) for introspection - 30x speedup in CDE for large descriptor
+ private static final transient ConcurrentHashMapWithProducer<Class<? extends MetaDataObject_impl>, MetaDataAttr[]> class2attrsMap =
+ new ConcurrentHashMapWithProducer<Class<? extends MetaDataObject_impl>, MetaDataAttr[]>();
+
private transient URL mSourceUrl;
// This is only used if we are capturing comments and ignorable whitespace in the XML
@@ -127,6 +184,60 @@ public abstract class MetaDataObject_imp
}
/**
+ * Override this method to include additional attributes
+ * @return additional attributes
+ */
+ public List<MetaDataAttr> getAdditionalAttributes() {
+ return ATTRIBUTE_0;
+ }
+
+ /**
+ * On first call, looks up the information using JavaBeans introspection, but then
+ * caches the result for subsequent calls.
+ *
+ * Any class which wants to add additional parameters needs to implement / override
+ * getAdditionalParameters.
+ * @return an array of Attribute objects associated with this class
+ * @throws
+ */
+ MetaDataAttr[] getAttributes() {
+ final Class<? extends MetaDataObject_impl> clazz = this.getClass();
+ MetaDataAttr[] attrs = class2attrsMap.get(clazz), otherAttrs = null;
+ if (null == attrs) {
+ PropertyDescriptor[] pds;
+ try {
+ pds = Introspector.getBeanInfo(clazz, Introspector.IGNORE_ALL_BEANINFO).getPropertyDescriptors();
+ } catch (IntrospectionException e) {
+ throw new UIMARuntimeException(e);
+ }
+ ArrayList<MetaDataAttr> resultList = new ArrayList<MetaDataAttr>(pds.length);
+ for (PropertyDescriptor pd : pds) {
+ // only include properties with read and write methods,
+ // and don't include the SourceUrl property, which is for
+ // internal bookkeeping and shouldn't affect object equality
+ // and don't include infoset, which is for internal bookkeeping
+ // related to comments and whitespace
+ if (pd.getReadMethod() != null && pd.getWriteMethod() != null
+ && !pd.getName().equals(PROP_NAME_SOURCE_URL)
+ && !pd.getName().equals(PROP_NAME_INFOSET)) {
+ String propName = pd.getName();
+ Class<?> propClass = pd.getPropertyType();
+ // translate primitive types (int, boolean, etc.) to wrapper classes
+ if (propClass.isPrimitive()) {
+ propClass = getWrapperClass(propClass);
+ }
+ resultList.add(new MetaDataAttr(propName, pd.getReadMethod(), pd.getWriteMethod(), propClass));
+ }
+ }
+ resultList.addAll(getAdditionalAttributes());
+ attrs = resultList.toArray(new MetaDataAttr[resultList.size()]);
+ otherAttrs = class2attrsMap.putIfAbsent(clazz, attrs);
+ attrs = (otherAttrs != null) ? otherAttrs : attrs;
+ }
+ return attrs;
+ }
+
+ /**
* Returns a list of <code>NameClassPair</code> objects indicating the attributes of this object
* and the String names of the Classes of the attributes' values.
* For primitive types, the wrapper classes will be
@@ -135,8 +246,11 @@ public abstract class MetaDataObject_imp
* Several subclasses override this, to add additional items to the list.
*
* @see org.apache.uima.resource.metadata.MetaDataObject#listAttributes()
+ * @deprecated - use getAttributes
*/
+ @Deprecated
public List<NameClassPair> listAttributes() {
+
try {
PropertyDescriptor[] props = getPropertyDescriptors();
List<NameClassPair> resultList = new ArrayList<NameClassPair>(props.length);
@@ -164,17 +278,29 @@ public abstract class MetaDataObject_imp
}
}
+ private Object getAttributeValue(MetaDataAttr attr) {
+ final Method reader = attr.reader;
+ if (reader != null) {
+ try {
+ return reader.invoke(this);
+ } catch (Exception e) {
+ throw new UIMARuntimeException(e);
+ }
+ }
+ return null;
+ }
+
/**
* @see org.apache.uima.resource.metadata.MetaDataObject#getAttributeValue(String)
*/
public Object getAttributeValue(String aName) {
try {
- PropertyDescriptor[] props = getPropertyDescriptors();
- for (int i = 0; i < props.length; i++) {
- if (props[i].getName().equals(aName)) {
- Method reader = props[i].getReadMethod();
+ MetaDataAttr[] attrs = getAttributes();
+ for (MetaDataAttr attr : attrs) {
+ if (attr.name.equals(aName)) {
+ Method reader = attr.reader;
if (reader != null) {
- return reader.invoke(this, new Object[0]);
+ return reader.invoke(this);
}
}
}
@@ -195,18 +321,13 @@ public abstract class MetaDataObject_imp
* if there is no attribute with the given name.
*/
public Class getAttributeClass(String aName) {
- try {
- // note: listAttributes() is overridden in some subclasses to add additional items
- List<NameClassPair> attrList = listAttributes();
- for (NameClassPair ncp : attrList) {
- if (ncp.getName().equals(aName)) {
- return Class.forName(ncp.getClassName());
- }
+ MetaDataAttr[] attrList = getAttributes();
+ for (MetaDataAttr attr : attrList) {
+ if (attr.name.equals(aName)) {
+ return attr.clazz;
}
- return null;
- } catch (Exception e) {
- throw new UIMARuntimeException(e);
}
+ return null;
}
/**
@@ -218,15 +339,30 @@ public abstract class MetaDataObject_imp
return true;
}
+ private void setAttributeValue(MetaDataAttr attr, Object aValue) {
+ Method writer = attr.writer;
+ if (writer != null) {
+ try {
+ writer.invoke(this, aValue);
+ } catch (IllegalArgumentException e) {
+ throw new UIMA_IllegalArgumentException(
+ UIMA_IllegalArgumentException.METADATA_ATTRIBUTE_TYPE_MISMATCH, new Object[] {
+ aValue, attr.name }, e);
+ } catch (Exception e) {
+ throw new UIMARuntimeException(e);
+ }
+ }
+ }
+
/**
* @see org.apache.uima.resource.metadata.MetaDataObject#setAttributeValue(String, Object)
*/
public void setAttributeValue(String aName, Object aValue) {
try {
- PropertyDescriptor[] props = getPropertyDescriptors();
- for (int i = 0; i < props.length; i++) {
- if (props[i].getName().equals(aName)) {
- Method writer = props[i].getWriteMethod();
+ MetaDataAttr[] attrs = getAttributes();
+ for (MetaDataAttr attr : attrs) {
+ if (attr.name.equals(aName)) {
+ Method writer = attr.writer;
if (writer != null) {
try {
writer.invoke(this, new Object[] { aValue });
@@ -317,6 +453,8 @@ public abstract class MetaDataObject_imp
* Sets the URL from which this object was parsed. Typically only the XML parser sets this. This
* recursively sets the source URL of all descendants of this object.
*
+ * Recursion doesn't happen for sub arrays/maps of maps or arrays.
+ *
* @param aUrl
* the location of the XML file from which this object was parsed
*/
@@ -324,27 +462,23 @@ public abstract class MetaDataObject_imp
mSourceUrl = aUrl;
// set recursively on subobjects
- List<NameClassPair> attrs = listAttributes();
- Iterator<NameClassPair> i = attrs.iterator();
- while (i.hasNext()) {
- String attrName = ((NameClassPair) i.next()).getName();
- Object val = getAttributeValue(attrName);
+ MetaDataAttr[] attrs = getAttributes();
+ for (MetaDataAttr attr : attrs) {
+ Object val = getAttributeValue(attr);
if (val instanceof MetaDataObject_impl) {
((MetaDataObject_impl) val).setSourceUrl(aUrl);
} else if (val != null && val.getClass().isArray()) {
- int len = Array.getLength(val);
- for (int j = 0; j < len; j++) {
- Object arrayElem = Array.get(val, j);
- if (arrayElem instanceof MetaDataObject_impl) {
- ((MetaDataObject_impl) arrayElem).setSourceUrl(aUrl);
+ Object[] arrayVal = (Object[]) val;
+ for (Object item : arrayVal) {
+ if (item instanceof MetaDataObject_impl) {
+ ((MetaDataObject_impl) item).setSourceUrl(aUrl);
}
}
} else if (val instanceof Map) {
- Iterator valIter = ((Map) val).values().iterator();
- while (valIter.hasNext()) {
- Object mapVal = valIter.next();
- if (mapVal instanceof MetaDataObject_impl) {
- ((MetaDataObject_impl) mapVal).setSourceUrl(aUrl);
+ Collection values = ((Map) val).values();
+ for (Object value : values) {
+ if (value instanceof MetaDataObject_impl) {
+ ((MetaDataObject_impl) value).setSourceUrl(aUrl);
}
}
}
@@ -366,13 +500,13 @@ public abstract class MetaDataObject_imp
}
// now clone all values that are MetaDataObjects
- List<NameClassPair> attrs = listAttributes();
- for (NameClassPair ncp : attrs) {
- String attrName = ncp.getName();
- Object val = getAttributeValue(attrName);
+ MetaDataAttr[] attrs = getAttributes();
+ for (MetaDataAttr attr : attrs) {
+// String attrName = ncp.name;
+ Object val = getAttributeValue(attr);
if (val instanceof MetaDataObject) {
Object clonedVal = ((MetaDataObject) val).clone();
- clone.setAttributeValue(attrName, clonedVal);
+ clone.setAttributeValue(attr, clonedVal);
} else if (val != null && val.getClass().isArray()) {
// clone the array, and clone any MetaDataObjects in the array
Class componentType = val.getClass().getComponentType();
@@ -385,7 +519,7 @@ public abstract class MetaDataObject_imp
}
Array.set(arrayClone, j, component);
}
- clone.setAttributeValue(attrName, arrayClone);
+ clone.setAttributeValue(attr, arrayClone);
}
}
return clone;
@@ -397,12 +531,10 @@ public abstract class MetaDataObject_imp
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append(getClass().getName()).append(": \n");
- List<NameClassPair> attrList = listAttributes();
- Iterator<NameClassPair> i = attrList.iterator();
- while (i.hasNext()) {
- NameClassPair ncp = (NameClassPair) i.next();
- buf.append(ncp.getName() + " = ");
- Object val = getAttributeValue(ncp.getName());
+ MetaDataAttr[] attrList = getAttributes();
+ for (MetaDataAttr attr : attrList) {
+ buf.append(attr.name + " = ");
+ Object val = getAttributeValue(attr);
if (val == null)
buf.append("NULL");
else if (val instanceof Object[]) {
@@ -429,28 +561,28 @@ public abstract class MetaDataObject_imp
* @return true if and only if this object is equal to <code>aObj</code>
*/
public boolean equals(Object aObj) {
- if (!(aObj instanceof MetaDataObject)) {
+ if (!(aObj instanceof MetaDataObject_impl)) {
return false;
}
- MetaDataObject mdo = (MetaDataObject) aObj;
+ MetaDataObject_impl mdo = (MetaDataObject_impl) aObj;
// get the attributes (and classes) for the two objects
- List<NameClassPair> theseAttrs = this.listAttributes();
- List<NameClassPair> thoseAttrs = mdo.listAttributes();
+
+ MetaDataAttr[] theseAttrs = this.getAttributes();
+ MetaDataAttr[] thoseAttrs = mdo.getAttributes();
// attribute lists must be same length
- if (theseAttrs.size() != thoseAttrs.size()) {
+ if (theseAttrs.length != thoseAttrs.length) {
return false;
}
// iterate through all attributes in this object
- Iterator<NameClassPair> i = theseAttrs.iterator();
- while (i.hasNext()) {
- NameClassPair ncp = i.next();
+ List<MetaDataAttr> thoseAttrsAsList = Arrays.asList(thoseAttrs);
+ for (MetaDataAttr attr : theseAttrs) {
// other object must contain this attribute
- if (!thoseAttrs.contains(ncp)) {
+ if (!thoseAttrsAsList.contains(attr)) {
return false;
}
// get values and test equivalency
- Object val1 = this.getAttributeValue(ncp.getName());
- Object val2 = mdo.getAttributeValue(ncp.getName());
+ Object val1 = this.getAttributeValue(attr);
+ Object val2 = mdo.getAttributeValue(attr);
if (!valuesEqual(val1, val2)) {
return false;
}
@@ -533,34 +665,21 @@ public abstract class MetaDataObject_imp
int hashCode = 0;
// add the hash codes of all attributes
- List<NameClassPair> attrs = listAttributes();
- Iterator<NameClassPair> i = attrs.iterator();
- while (i.hasNext()) {
- String attrName = ((NameClassPair) i.next()).getName();
- Object val = getAttributeValue(attrName);
+ MetaDataAttr[] attrs = getAttributes();
+ for (MetaDataAttr attr : attrs) {
+ String attrName = attr.name;
+ Object val = getAttributeValue(attr);
if (val != null) {
if (val instanceof Object[]) {
- Object[] arr = (Object[]) val;
- for (int j = 0; j < arr.length; j++) {
- if (arr[j] != null) {
- hashCode += arr[j].hashCode();
- }
- }
- } else if (val instanceof Map) // only need to do this to handle Maps w/ array vals
- {
- Set entrySet = ((Map) val).entrySet();
- Iterator it = entrySet.iterator();
- while (it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
+ hashCode += Arrays.hashCode((Object[]) val);
+ } else if (val instanceof Map) {// only need to do this to handle Maps w/ array vals
+ // note doesn't handle maps whose values are maps.
+ Set<Map.Entry> entrySet = ((Map) val).entrySet();
+ for (Map.Entry entry : entrySet) {
hashCode += entry.getKey().hashCode();
Object subval = entry.getValue();
if (subval instanceof Object[]) {
- Object[] arr = (Object[]) subval;
- for (int j = 0; j < arr.length; j++) {
- if (arr[j] != null) {
- hashCode += arr[j].hashCode();
- }
- }
+ hashCode += Arrays.hashCode((Object[]) subval);
} else {
hashCode += subval.hashCode();
}
@@ -1367,14 +1486,12 @@ public abstract class MetaDataObject_imp
* <code>MetaDataObject_impl</code>.
*
* @throws IntrospectionException if introspection fails
+ * @deprecated - use getAttributes instead
*/
- protected PropertyDescriptor[] getPropertyDescriptors() throws IntrospectionException {
- PropertyDescriptor[] pd = mPropertyDescriptorsMap.get(this.getClass()), pdOther = null;
- if (null == pd) {
- pd = Introspector.getBeanInfo(this.getClass(), Introspector.IGNORE_ALL_BEANINFO).getPropertyDescriptors();
- pdOther = mPropertyDescriptorsMap.putIfAbsent(this.getClass(), pd);
- }
- return (pdOther != null) ? pdOther : pd;
+ @Deprecated
+ // never called, we hope. No longer caches anything.
+ protected PropertyDescriptor[] getPropertyDescriptors() throws IntrospectionException {
+ return Introspector.getBeanInfo(this.getClass(), Introspector.IGNORE_ALL_BEANINFO).getPropertyDescriptors();
}
Added: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/ConcurrentHashMapWithProducer.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/ConcurrentHashMapWithProducer.java?rev=1579031&view=auto
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/ConcurrentHashMapWithProducer.java (added)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/ConcurrentHashMapWithProducer.java Tue Mar 18 20:36:12 2014
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.uima.util;
+
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * A concurrent map supporting a value-creating get.
+ * There's a small window where the value producing function could be called multiple times
+ * on different threads, but the first one will be used and the others thrown away.
+ */
+public class ConcurrentHashMapWithProducer<K, V> extends ConcurrentHashMap<K, V> {
+
+ private static final long serialVersionUID = 1L;
+
+ public ConcurrentHashMapWithProducer() {
+ super();
+ }
+
+ public ConcurrentHashMapWithProducer(int initialCapacity, float loadFactor, int concurrencyLevel) {
+ super(initialCapacity, loadFactor, concurrencyLevel);
+ }
+
+
+ public ConcurrentHashMapWithProducer(int initialCapacity, float loadFactor) {
+ super(initialCapacity, loadFactor);
+ }
+
+
+ public ConcurrentHashMapWithProducer(int initialCapacity) {
+ super(initialCapacity);
+ }
+
+
+ public ConcurrentHashMapWithProducer(Map<? extends K, ? extends V> m) {
+ super(m);
+ }
+
+ public V get(K key, Callable<V> valueProducer) throws Exception {
+ V value = get(key), otherValue = null;
+ if (null == value) {
+ otherValue = putIfAbsent(key, value = valueProducer.call());
+ value = (otherValue != null) ? otherValue : value;
+ }
+ return value;
+ }
+}
Modified: uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java?rev=1579031&r1=1579030&r2=1579031&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/MetaDataObject_implTest.java Tue Mar 18 20:36:12 2014
@@ -22,7 +22,9 @@ package org.apache.uima.resource.metadat
import java.io.ByteArrayInputStream;
import java.io.StringWriter;
import java.io.Writer;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -35,6 +37,7 @@ import org.apache.uima.internal.util.Ser
import org.apache.uima.resource.metadata.ConfigurationParameterSettings;
import org.apache.uima.resource.metadata.MetaDataObject;
import org.apache.uima.resource.metadata.NameValuePair;
+import org.apache.uima.resource.metadata.impl.MetaDataObject_impl.MetaDataAttr;
import org.apache.uima.test.junit_extension.JUnitExtension;
import org.apache.uima.util.NameClassPair;
import org.apache.uima.util.XMLParser;
@@ -95,23 +98,47 @@ public class MetaDataObject_implTest ext
fruitBag.setAttributeValue("fruits", fruitArray);
}
+// /**
+// * Tests the {@link MetaDataObject#listAttributes()} method.
+// */
+// public void testListAttributes() throws Exception {
+// try {
+// HashSet<NameClassPair> apple1Attrs = new HashSet<NameClassPair>(apple1.listAttributes());
+// HashSet<NameClassPair> orangeAttrs = new HashSet<NameClassPair>(orange.listAttributes());
+// HashSet<NameClassPair> bagAttrs = new HashSet<NameClassPair>(fruitBag.listAttributes());
+//
+// Assert.assertEquals(TestFruitObject.getAttributeSet(), apple1Attrs);
+// Assert.assertEquals(TestFruitObject.getAttributeSet(), orangeAttrs);
+// Assert.assertEquals(TestFruitBagObject.getAttributeSet(), bagAttrs);
+// } catch (RuntimeException e) {
+// JUnitExtension.handleException(e);
+// }
+// }
+
/**
- * Tests the {@link MetaDataObject#listAttributes()} method.
+ * Test the getAttributes method
*/
- public void testListAttributes() throws Exception {
+ public void testGetAttributes() throws Exception {
try {
- HashSet<NameClassPair> apple1Attrs = new HashSet<NameClassPair>(apple1.listAttributes());
- HashSet<NameClassPair> orangeAttrs = new HashSet<NameClassPair>(orange.listAttributes());
- HashSet<NameClassPair> bagAttrs = new HashSet<NameClassPair>(fruitBag.listAttributes());
-
- Assert.assertEquals(TestFruitObject.getAttributeSet(), apple1Attrs);
- Assert.assertEquals(TestFruitObject.getAttributeSet(), orangeAttrs);
- Assert.assertEquals(TestFruitBagObject.getAttributeSet(), bagAttrs);
+ HashSet<MetaDataAttr> apple1Attrs = new HashSet<MetaDataAttr>(Arrays.asList(apple1.getAttributes()));
+ HashSet<MetaDataAttr> orangeAttrs = new HashSet<MetaDataAttr>(Arrays.asList(orange.getAttributes()));
+ HashSet<MetaDataAttr> bagAttrs = new HashSet<MetaDataAttr>(Arrays.asList(fruitBag.getAttributes()));
+
+ Set<MetaDataAttr> r = TestFruitObject.getMetaDataAttrSet();
+ for (MetaDataAttr r1 : r) {
+ if (!apple1Attrs.contains(r1)) {
+ System.out.println("found bad one");
+ }
+ }
+ System.out.println(r.equals (apple1Attrs));
+ assertEquals(TestFruitObject.getMetaDataAttrSet(), apple1Attrs);
+ assertEquals(TestFruitObject.getMetaDataAttrSet(), orangeAttrs);
+ assertEquals(TestFruitBagObject.getMetaDataAttrSet(), bagAttrs);
} catch (RuntimeException e) {
- JUnitExtension.handleException(e);
+ JUnitExtension.handleException(e);
}
}
-
+
/**
* Tests the {@link MetaDataObject#equals(Object)} method.
*/
Modified: uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitBagObject.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitBagObject.java?rev=1579031&r1=1579030&r2=1579031&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitBagObject.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitBagObject.java Tue Mar 18 20:36:12 2014
@@ -22,18 +22,14 @@ package org.apache.uima.resource.metadat
import java.util.HashSet;
import java.util.Set;
-import org.apache.uima.util.NameClassPair;
-
/**
* A simple concrete MetaDataObject implementation for use in testing the MetaDataObject_impl class.
*/
public class TestFruitBagObject extends MetaDataObject_impl {
-
+
static final private XmlizationInfo XMLIZATION_INFO = new XmlizationInfo("fruitBag",
new PropertyXmlInfo[] { new PropertyXmlInfo("fruits") });
- private String mName;
-
private TestFruitObject[] mFruits;
public TestFruitBagObject() {
@@ -48,13 +44,26 @@ public class TestFruitBagObject extends
mFruits = aFruits;
}
- /**
- * For testing purposes - a hardcoded attribute set. Should be compared with the results of
- * {@link #listAttributes()}.
- */
- static public Set<NameClassPair> getAttributeSet() {
- Set<NameClassPair> result = new HashSet<NameClassPair>();
- result.add(new NameClassPair("fruits", TestFruitObject[].class.getName()));
+// /**
+// * For testing purposes - a hardcoded attribute set. Should be compared with the results of
+// * {@link #listAttributes()}.
+// */
+// static public Set<NameClassPair> getAttributeSet() {
+// Set<NameClassPair> result = new HashSet<NameClassPair>();
+// result.add(new NameClassPair("fruits", TestFruitObject[].class.getName()));
+// return result;
+// }
+
+ static public Set<MetaDataAttr> getMetaDataAttrSet() {
+ Set<MetaDataAttr> result = new HashSet<MetaDataAttr>();
+ try {
+ result.add(new MetaDataAttr("fruits",
+ TestFruitBagObject.class.getDeclaredMethod("getFruits"),
+ TestFruitBagObject.class.getDeclaredMethod("setFruits", TestFruitObject[].class),
+ TestFruitObject[].class));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
return result;
}
Modified: uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitObject.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitObject.java?rev=1579031&r1=1579030&r2=1579031&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitObject.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/test/java/org/apache/uima/resource/metadata/impl/TestFruitObject.java Tue Mar 18 20:36:12 2014
@@ -106,6 +106,45 @@ public class TestFruitObject extends Met
result.add(new NameClassPair("commonUses", String[].class.getName()));
return result;
}
+
+ static public Set<MetaDataAttr> getMetaDataAttrSet() {
+ HashSet<MetaDataAttr> result = new HashSet<MetaDataAttr>();
+ try {
+ result.add(new MetaDataAttr(
+ "name",
+ TestFruitObject.class.getDeclaredMethod("getName"),
+ TestFruitObject.class.getDeclaredMethod("setName", String.class),
+ String.class));
+ result.add(new MetaDataAttr(
+ "avgWeightLbs",
+ TestFruitObject.class.getDeclaredMethod("getAvgWeightLbs"),
+ TestFruitObject.class.getDeclaredMethod("setAvgWeightLbs", float.class),
+ Float.class));
+ result.add(new MetaDataAttr(
+ "color",
+ TestFruitObject.class.getDeclaredMethod("getColor"),
+ TestFruitObject.class.getDeclaredMethod("setColor", String.class),
+ String.class));
+ result.add(new MetaDataAttr(
+ "avgCostCents",
+ TestFruitObject.class.getDeclaredMethod("getAvgCostCents"),
+ TestFruitObject.class.getDeclaredMethod("setAvgCostCents", int.class),
+ Integer.class));
+ result.add(new MetaDataAttr(
+ "citrus",
+ TestFruitObject.class.getDeclaredMethod("isCitrus"),
+ TestFruitObject.class.getDeclaredMethod("setCitrus", boolean.class),
+ Boolean.class));
+ result.add(new MetaDataAttr(
+ "commonUses",
+ TestFruitObject.class.getDeclaredMethod("getCommonUses"),
+ TestFruitObject.class.getDeclaredMethod("setCommonUses", String[].class),
+ String[].class));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return result;
+ }
private String mName;