From: <ga...@us...> - 2011-05-26 00:48:49
|
Revision: 5304 http://jaffa.svn.sourceforge.net/jaffa/?rev=5304&view=rev Author: gautamj Date: 2011-05-26 00:48:42 +0000 (Thu, 26 May 2011) Log Message: ----------- Added support for scope and target-scope attributes in Graph Mapping files Modified Paths: -------------- trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/GraphMapping.java trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/MappingFilter.java Modified: trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/GraphMapping.java =================================================================== --- trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/GraphMapping.java 2011-05-26 00:10:51 UTC (rev 5303) +++ trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/GraphMapping.java 2011-05-26 00:48:42 UTC (rev 5304) @@ -55,11 +55,12 @@ import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.net.MalformedURLException; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -80,8 +81,6 @@ import org.xml.sax.SAXException; /** - * @version 2.0 - * @author PaulE */ public class GraphMapping { @@ -103,20 +102,17 @@ private static final String ATTR_ERROR_PARAMS = "error-params"; private static final String ATTR_READ_ONLY = "read-only"; private static final String ATTR_NO_CLONING = "no-cloning"; + private static final String ATTR_SCOPE = "scope"; + private static final String ATTR_TARGET_SCOPE = "target-scope"; private Class domainClass; private Class dataClass; - private Map<String, String> fieldMap; //gdo+do pairs - private Map<String, String> keyMap; //gdo+do pairs for the key-fields - private Map<String, String[]> foreignMap; //gdo+do[] pairs for the foreign-objects. The first element in the do[] is the getter for the foreign-object, while rest are foreign-fields - private Map<String, String> relatedMap; //gdo+do pairs for the related-objects - private Map<String, PropertyDescriptor> dataDescriptorMap; //propertyName+PropertyDescriptor pairs for the Graph class - private Map<String, PropertyDescriptor> domainDescriptorMap; //propertyName+PropertyDescriptor pairs for the Domain class - private Map<String, Field> dataFieldMap; //propertyName+Field pairs for the Graph class - private String dirtyReadDataFieldName; //dataFieldName to be used for dirty-read check - private String dirtyReadErrorLabelToken; //label-token to be used in the error-message for dirty-read check - private String[] dirtyReadErrorParams; //do[] to be used in the error-message for dirty-read check - private Collection readOnlyFields; //gdo having read-only==true - private Collection noCloningFields; //gdo having no-cloning==true + private DirtyReadInfo dirtyReadInfo; + private Map<String, BaseElement> elementMap; + private Set<String> keys; + private Map<String, Set<String>> fields; //fields per scope + private Map<String, Set<String>> foreignObjects; //foreignObjects per scope + private Map<String, Set<String>> relatedObjects; //relatedObjects per scope + private Map<String, PropertyDescriptor> domainPropertyDescriptors; //propertyName+PropertyDescriptor pairs for the Domain class public static PropertyDescriptor[] getPropertyDescriptors(Class clazz) { try { @@ -219,48 +215,49 @@ // Get the DAO class, and make sure the loaded one matches the supplied one! NodeList nl = document.getElementsByTagName(NODE_DAO_CLASS); if (nl.getLength() != 1) - throw new RuntimeException("Can't find node '" + NODE_DAO_CLASS + - "' in file " + filename); + throw new RuntimeException("Can't find node '" + NODE_DAO_CLASS + "' in file " + filename); Node n = nl.item(0).getAttributes().getNamedItem(ATTR_CLASS); if (n == null) - throw new RuntimeException("Node '" + NODE_DAO_CLASS + - "' has no attribute '" + ATTR_CLASS + "' in file " + filename); + throw new RuntimeException("Node '" + NODE_DAO_CLASS + "' has no attribute '" + ATTR_CLASS + "' in file " + filename); // String clazz = n.getNodeValue(); // if (!dataClass.getName().equals(clazz)) -// throw new RuntimeException("Expected '" + NODE_DAO_CLASS + -// "\\" + ATTR_CLASS + "' to have value '" + dataClass.getName() + "' not '" + clazz + "' in file " + filename); +// throw new RuntimeException("Expected '" + NODE_DAO_CLASS + "\\" + ATTR_CLASS + "' to have value '" + dataClass.getName() + "' not '" + clazz + "' in file " + filename); this.dataClass = dataClass; // Get the DO class, and make sure the loaded one matches the supplied one! nl = document.getElementsByTagName(NODE_DO_CLASS); if (nl.getLength() != 1) - throw new RuntimeException("Can't find node '" + NODE_DO_CLASS + - "' in file " + filename); + throw new RuntimeException("Can't find node '" + NODE_DO_CLASS + "' in file " + filename); n = nl.item(0).getAttributes().getNamedItem(ATTR_CLASS); if (n == null) - throw new RuntimeException("Node '" + NODE_DO_CLASS + - "' has no attribute '" + ATTR_CLASS + "' in file " + filename); + throw new RuntimeException("Node '" + NODE_DO_CLASS + "' has no attribute '" + ATTR_CLASS + "' in file " + filename); String clazz = n.getNodeValue(); try { domainClass = Class.forName(clazz); } catch (ClassNotFoundException e) { - throw new RuntimeException("Domain class '" + clazz + - "' not found in file " + filename); + throw new RuntimeException("Domain class '" + clazz + + "' not found in file " + filename); } // Set up descriptor details - dataDescriptorMap = getPropertyDescriptorMap(dataClass); - domainDescriptorMap = getPropertyDescriptorMap(domainClass); - dataFieldMap = getFieldMap(dataClass); + Map<String, Field> graphFields = getFieldMap(dataClass); + Map<String, PropertyDescriptor> graphPropertyDescriptors = getPropertyDescriptorMap(dataClass); + domainPropertyDescriptors = getPropertyDescriptorMap(domainClass); - // Initalize Maps - keyMap = new LinkedHashMap<String, String>(); - fieldMap = new HashMap<String, String>(); - foreignMap = new HashMap<String, String[]>(); - relatedMap = new HashMap<String, String>(); + // Initalize Fields + elementMap = new LinkedHashMap<String, BaseElement>(); + keys = new LinkedHashSet<String>(); + fields = new LinkedHashMap<String, Set<String>>(); + foreignObjects = new LinkedHashMap<String, Set<String>>(); + relatedObjects = new LinkedHashMap<String, Set<String>>(); + + //To avoid NPE in existing code, initialize the collections for default scope + fields.put(null, new LinkedHashSet<String>()) ; + foreignObjects.put(null, new LinkedHashSet<String>()) ; + relatedObjects.put(null, new LinkedHashSet<String>()) ; // Get The Key Fields nl = document.getElementsByTagName(NODE_MAP_KEYS); @@ -269,23 +266,13 @@ NodeList nl2 = el.getElementsByTagName(NODE_FIELD); for (int i = 0; i < nl2.getLength(); i++) { Element el2 = (Element) nl2.item(i); - // get do and dao attributes - Node nDao = el2.getAttributes().getNamedItem(ATTR_DAO_FIELD); - String daoField = null; - if (nDao != null) - daoField = nDao.getNodeValue(); - if (daoField == null) - throw new RuntimeException("Key field " + (i + 1) + " has missing attribute '" + - ATTR_DAO_FIELD + "' in file " + filename); - - Node nDo = el2.getAttributes().getNamedItem(ATTR_DO_FIELD); - String doField = null; - if (nDo != null) - doField = nDo.getNodeValue(); - if (doField == null) - doField = daoField; - keyMap.put(daoField, doField); - checkAttributes(daoField, el2); + BaseElement baseElement = new KeyField(readAttribute(el2, ATTR_DAO_FIELD), readAttribute(el2, ATTR_DO_FIELD), readAttribute(el2, ATTR_READ_ONLY), readAttribute(el2, ATTR_NO_CLONING)); + if (baseElement.getGraphFieldName() == null) + throw new RuntimeException("Key field " + (i + 1) + " has missing attribute '" + ATTR_DAO_FIELD + "' in file " + filename); + baseElement.graphPropertyDescriptor = graphPropertyDescriptors.get(baseElement.getGraphFieldName()); + baseElement.graphField = graphFields.get(baseElement.getGraphFieldName()); + elementMap.put(baseElement.getGraphFieldName(), baseElement); + keys.add(baseElement.getGraphFieldName()); } } @@ -296,53 +283,16 @@ NodeList nl2 = el.getElementsByTagName(NODE_FIELD); for (int i = 0; i < nl2.getLength(); i++) { Element el2 = (Element) nl2.item(i); - // get do and dao attributes - Node nDao = el2.getAttributes().getNamedItem(ATTR_DAO_FIELD); - String daoField = null; - if (nDao != null) - daoField = nDao.getNodeValue(); - if (daoField == null) - throw new RuntimeException("Field " + (i + 1) + " has missing attribute '" + - ATTR_DAO_FIELD + "' in file " + filename); - - Node nDo = el2.getAttributes().getNamedItem(ATTR_DO_FIELD); - String doField = null; - if (nDo != null) - doField = nDo.getNodeValue(); - if (doField == null) - doField = daoField; - fieldMap.put(daoField, doField); - checkAttributes(daoField, el2); + BaseElement baseElement = new PlainField(readAttribute(el2, ATTR_DAO_FIELD), readAttribute(el2, ATTR_DO_FIELD), readAttribute(el2, ATTR_READ_ONLY), readAttribute(el2, ATTR_NO_CLONING), readAttribute(el2, ATTR_SCOPE)); + if (baseElement.getGraphFieldName() == null) + throw new RuntimeException("Field " + (i + 1) + " has missing attribute '" + ATTR_DAO_FIELD + "' in file " + filename); + baseElement.graphPropertyDescriptor = graphPropertyDescriptors.get(baseElement.getGraphFieldName()); + baseElement.graphField = graphFields.get(baseElement.getGraphFieldName()); + elementMap.put(baseElement.getGraphFieldName(), baseElement); + addNamePerScope(fields, baseElement); } } - // Get The Related Fields - nl = document.getElementsByTagName(NODE_MAP_RELATED); - if (nl.getLength() == 1) { - Element el = (Element) nl.item(0); - NodeList nl2 = el.getElementsByTagName(NODE_FIELD); - for (int i = 0; i < nl2.getLength(); i++) { - Element el2 = (Element) nl2.item(i); - // get do and dao attributes - Node nDao = el2.getAttributes().getNamedItem(ATTR_DAO_FIELD); - String daoField = null; - if (nDao != null) - daoField = nDao.getNodeValue(); - if (daoField == null) - throw new RuntimeException("Related Object " + (i + 1) + " has missing attribute '" + - ATTR_DAO_FIELD + "' in file " + filename); - - Node nDo = el2.getAttributes().getNamedItem(ATTR_DO_FIELD); - String doField = null; - if (nDo != null) - doField = nDo.getNodeValue(); - if (doField == null) - doField = daoField; - relatedMap.put(daoField, doField); - checkAttributes(daoField, el2); - } - } - // Get The Foreign Objects nl = document.getElementsByTagName(NODE_MAP_FOREIGN); if (nl.getLength() == 1) { @@ -350,46 +300,44 @@ NodeList nl2 = el.getElementsByTagName(NODE_FOREIGN_OBJECT); for (int i = 0; i < nl2.getLength(); i++) { Element el2 = (Element) nl2.item(i); - // get do and dao attributes - Node nDao = el2.getAttributes().getNamedItem(ATTR_DAO_FIELD); - String daoField = null; - if (nDao != null) - daoField = nDao.getNodeValue(); - if (daoField == null) - throw new RuntimeException("Foreign Object " + (i + 1) + " has missing attribute '" + - ATTR_DAO_FIELD + "' in file " + filename); + BaseElement baseElement = new ForeignObject(readAttribute(el2, ATTR_DAO_FIELD), readAttribute(el2, ATTR_DO_FIELD), readAttribute(el2, ATTR_READ_ONLY), readAttribute(el2, ATTR_NO_CLONING), readAttribute(el2, ATTR_SCOPE), readAttribute(el2, ATTR_TARGET_SCOPE)); + if (baseElement.getGraphFieldName() == null) + throw new RuntimeException("Foreign Object " + (i + 1) + " has missing attribute '" + ATTR_DAO_FIELD + "' in file " + filename); + baseElement.graphPropertyDescriptor = graphPropertyDescriptors.get(baseElement.getGraphFieldName()); + baseElement.graphField = graphFields.get(baseElement.getGraphFieldName()); + elementMap.put(baseElement.getGraphFieldName(), baseElement); + addNamePerScope(foreignObjects, baseElement); - Node nDo = el2.getAttributes().getNamedItem(ATTR_DO_FIELD); - String doField = null; - if (nDo != null) - doField = nDo.getNodeValue(); - if (doField == null) - doField = daoField; - - Collection<String> foreign = new LinkedList<String>(); - foreign.add(doField); - - // Now read the foreign key fields + //Determine the foreign-keys + List<String> foreignKeys = new LinkedList<String>(); NodeList nl3 = el2.getElementsByTagName(NODE_FOREIGN_KEY); if (nl3.getLength() == 0) - throw new RuntimeException("Foreign object '" + daoField + "' has nodes '" + - NODE_FOREIGN_KEY + "' in file " + filename); + throw new RuntimeException("Foreign object '" + baseElement.getGraphFieldName() + "' does not have nodes '" + NODE_FOREIGN_KEY + "' in file " + filename); for (int i2 = 0; i2 < nl3.getLength(); i2++) { Element el3 = (Element) nl3.item(i2); - - Node nf = el3.getAttributes().getNamedItem(ATTR_DO_FIELD); - String dof = null; - if (nf != null) - dof = nf.getNodeValue(); - if (dof == null) - throw new RuntimeException("Foreign object '" + daoField + "\\" + - (i + 1) + " has missing attribute '" + ATTR_DO_FIELD + "' in file " + filename); - - foreign.add(dof); + String foreignKey = readAttribute(el3, ATTR_DO_FIELD); + if (foreignKey == null) + throw new RuntimeException("Foreign object '" + baseElement.getGraphFieldName() + "\\" + (i + 1) + " has missing attribute '" + ATTR_DO_FIELD + "' in file " + filename); + foreignKeys.add(foreignKey); } + ((ForeignObject) baseElement).foreignKeys = foreignKeys; + } + } - foreignMap.put(daoField, foreign.toArray(new String[foreign.size()])); - checkAttributes(daoField, el2); + // Get The Related Fields + nl = document.getElementsByTagName(NODE_MAP_RELATED); + if (nl.getLength() == 1) { + Element el = (Element) nl.item(0); + NodeList nl2 = el.getElementsByTagName(NODE_FIELD); + for (int i = 0; i < nl2.getLength(); i++) { + Element el2 = (Element) nl2.item(i); + BaseElement baseElement = new RelatedObject(readAttribute(el2, ATTR_DAO_FIELD), readAttribute(el2, ATTR_DO_FIELD), readAttribute(el2, ATTR_READ_ONLY), readAttribute(el2, ATTR_NO_CLONING), readAttribute(el2, ATTR_SCOPE), readAttribute(el2, ATTR_TARGET_SCOPE)); + if (baseElement.getGraphFieldName() == null) + throw new RuntimeException("Related Object " + (i + 1) + " has missing attribute '" + ATTR_DAO_FIELD + "' in file " + filename); + baseElement.graphPropertyDescriptor = graphPropertyDescriptors.get(baseElement.getGraphFieldName()); + baseElement.graphField = graphFields.get(baseElement.getGraphFieldName()); + elementMap.put(baseElement.getGraphFieldName(), baseElement); + addNamePerScope(relatedObjects, baseElement); } } @@ -397,20 +345,10 @@ nl = document.getElementsByTagName(NODE_DIRTY_READ); if (nl.getLength() == 1) { Element el = (Element) nl.item(0); - n = el.getAttributes().getNamedItem(ATTR_DAO_FIELD); - if (n != null) - dirtyReadDataFieldName = n.getNodeValue(); - else + dirtyReadInfo = new DirtyReadInfo(readAttribute(el, ATTR_DAO_FIELD), readAttribute(el, ATTR_ERROR_LABEL_TOKEN), readAttribute(el, ATTR_ERROR_PARAMS)); + if (dirtyReadInfo.dirtyReadDataFieldName == null) throw new RuntimeException("Element '" + NODE_DIRTY_READ + "' has missing attribute '" + ATTR_DAO_FIELD + "' in file " + filename); - - n = el.getAttributes().getNamedItem(ATTR_ERROR_LABEL_TOKEN); - if (n != null) - dirtyReadErrorLabelToken = n.getNodeValue(); - - n = el.getAttributes().getNamedItem(ATTR_ERROR_PARAMS); - if (n != null) - dirtyReadErrorParams = n.getNodeValue().split(","); - else + if (dirtyReadInfo.dirtyReadErrorParams == null) throw new RuntimeException("Element '" + NODE_DIRTY_READ + "' has missing attribute '" + ATTR_ERROR_PARAMS + "' in file " + filename); } @@ -440,40 +378,43 @@ throws InstantiationError { // Check all mapped fields have valid descriptors String[] names = getDataFieldNames(); - for (int i = 0; i < names.length; i++) { - String name = names[i]; - PropertyDescriptor d = getDataFieldDescriptor(name); - if (d == null) - throw new InstantiationError("Missing GraphDataObject Property : " + name + " on " + getDataClassShortName()); - if (d.getReadMethod() == null) - throw new InstantiationError("Missing GraphDataObject getter for : " + name + " on " + getDataClassShortName()); - if (d.getWriteMethod() == null) - throw new InstantiationError("Missing GraphDataObject setter for : " + name + " on " + getDataClassShortName()); - d = getDomainFieldDescriptor(name); - if (d == null) - throw new InstantiationError("Missing DomainObject Property : " + getDomainFieldName(name) + " on " + getDomainClassShortName()); - if (d.getReadMethod() == null) - throw new InstantiationError("Missing DomainObject getter for : " + getDomainFieldName(name) + " on " + getDomainClassShortName()); - //if(d.getWriteMethod() == null) - // throw new InstantiationError("Missing DO setter for : " + getDomainFieldName(name) + " on " + getDomainClassShortName()); - } - // Check all foreign key fields - for (Iterator it = getForeignFields().iterator(); it.hasNext();) { - String field = (String) it.next(); - List foreignKeys = getForeignKeys(field); - for (Iterator k = foreignKeys.iterator(); k.hasNext();) { - String name = (String) k.next(); - PropertyDescriptor d = getRealDomainFieldDescriptor(name); - + if (names != null) { + for (int i = 0; i < names.length; i++) { + String name = names[i]; + PropertyDescriptor d = getDataFieldDescriptor(name); if (d == null) - throw new InstantiationError("Missing DO Property : " + name + " on " + getDomainClassShortName() + " for foreign object " + field); + throw new InstantiationError("Missing GraphDataObject Property : " + name + " on " + getDataClassShortName()); if (d.getReadMethod() == null) - throw new InstantiationError("Missing DO getter for : " + name + " on " + getDomainClassShortName() + " for foreign object " + field); + throw new InstantiationError("Missing GraphDataObject getter for : " + name + " on " + getDataClassShortName()); if (d.getWriteMethod() == null) - throw new InstantiationError("Missing DO setter for : " + name + " on " + getDomainClassShortName() + " for foreign object " + field); + throw new InstantiationError("Missing GraphDataObject setter for : " + name + " on " + getDataClassShortName()); + d = getDomainFieldDescriptor(name); + if (d == null) + throw new InstantiationError("Missing DomainObject Property : " + getDomainFieldName(name) + " on " + getDomainClassShortName()); + if (d.getReadMethod() == null) + throw new InstantiationError("Missing DomainObject getter for : " + getDomainFieldName(name) + " on " + getDomainClassShortName()); + //if(d.getWriteMethod() == null) + // throw new InstantiationError("Missing DO setter for : " + getDomainFieldName(name) + " on " + getDomainClassShortName()); } } + // Check all foreign key fields + Set<String> foreignFields = getForeignFields(); + if (foreignFields != null) { + for (String field : foreignFields) { + List foreignKeys = getForeignKeys(field); + for (Iterator k = foreignKeys.iterator(); k.hasNext();) { + String name = (String) k.next(); + PropertyDescriptor d = getRealDomainFieldDescriptor(name); + if (d == null) + throw new InstantiationError("Missing DO Property : " + name + " on " + getDomainClassShortName() + " for foreign object " + field); + if (d.getReadMethod() == null) + throw new InstantiationError("Missing DO getter for : " + name + " on " + getDomainClassShortName() + " for foreign object " + field); + if (d.getWriteMethod() == null) + throw new InstantiationError("Missing DO setter for : " + name + " on " + getDomainClassShortName() + " for foreign object " + field); + } + } + } } public Class getDataClass() { @@ -485,7 +426,7 @@ } public String getDataClassShortName() { - return shortName(getDataClassName()); + return dataClass.getSimpleName(); } public Class getDomainClass() { @@ -497,116 +438,137 @@ } public String getDomainClassShortName() { - return shortName(getDomainClassName()); + return domainClass.getSimpleName(); } public String[] getDataFieldNames() { - Collection<String> a = new LinkedList<String>(); - a.addAll(keyMap.keySet()); - a.addAll(fieldMap.keySet()); - a.addAll(foreignMap.keySet()); - a.addAll(relatedMap.keySet()); - return a.toArray(new String[a.size()]); + return getDataFieldNames(null); } + public String[] getDataFieldNames(String targetScope) { + Collection<String> dataFieldNames = null; + if (targetScope == null) { + dataFieldNames = elementMap != null ? elementMap.keySet() : null; + } else { + dataFieldNames = new LinkedList<String>(); + Set set = getKeyFields(); + if (set != null) + dataFieldNames.addAll(set); + set = getFields(targetScope); + if (set != null) + dataFieldNames.addAll(set); + set = getForeignFields(targetScope); + if (set != null) + dataFieldNames.addAll(set); + set = getRelatedFields(targetScope); + if (set != null) + dataFieldNames.addAll(set); + } + return dataFieldNames != null ? dataFieldNames.toArray(new String[dataFieldNames.size()]) : null; + } + public boolean containsDataField(String dataFieldName) { - return isKeyField(dataFieldName) || isField(dataFieldName) || - isForeignField(dataFieldName) || isRelatedField(dataFieldName); + return elementMap != null && elementMap.containsKey(dataFieldName); } public boolean isKeyField(String dataFieldName) { - return keyMap.containsKey(dataFieldName); + return keys != null && keys.contains(dataFieldName); } public boolean hasKeyFields() { - return (keyMap != null && keyMap.size() > 0); + return keys != null && !keys.isEmpty(); } public Set getKeyFields() { - return keyMap.keySet(); + return keys; } public boolean isField(String dataFieldName) { - return fieldMap.containsKey(dataFieldName); + return containsDataField(dataFieldName) && elementMap.get(dataFieldName) instanceof PlainField; } public boolean hasFields() { - return (fieldMap != null && fieldMap.size() > 0); + return hasFields(null); } + public boolean hasFields(String targetScope) { + return fields != null && fields.get(targetScope) != null && !fields.get(targetScope).isEmpty(); + } + public Set getFields() { - return fieldMap.keySet(); + return getFields(null); } + public Set getFields(String targetScope) { + return fields != null ? fields.get(targetScope) : null; + } + public boolean isForeignField(String dataFieldName) { - return foreignMap.containsKey(dataFieldName); + return containsDataField(dataFieldName) && elementMap.get(dataFieldName) instanceof ForeignObject; } public List getForeignKeys(String dataFieldName) { - List l = new LinkedList(); - String[] x = foreignMap.get(dataFieldName); - if (x != null) { - for (int i = 1; i < x.length; i++) - l.add(x[i]); - } - return l; + return isForeignField(dataFieldName) ? ((ForeignObject) elementMap.get(dataFieldName)).getForeignKeys() : null; } public Set getForeignFields() { - return foreignMap.keySet(); + return getForeignFields(null); } + public Set getForeignFields(String targetScope) { + return foreignObjects != null ? foreignObjects.get(targetScope) : null; + } + public boolean hasForeignFields() { - return (foreignMap != null && foreignMap.size() > 0); + return hasForeignFields(null); } + public boolean hasForeignFields(String targetScope) { + return foreignObjects != null && foreignObjects.get(targetScope) != null && !foreignObjects.get(targetScope).isEmpty(); + } + public boolean isRelatedField(String dataFieldName) { - return relatedMap.containsKey(dataFieldName); + return containsDataField(dataFieldName) && elementMap.get(dataFieldName) instanceof RelatedObject; } public boolean hasRelatedFields() { - return (relatedMap != null && relatedMap.size() > 0); + return hasRelatedFields(null); } + public boolean hasRelatedFields(String targetScope) { + return relatedObjects != null && relatedObjects.get(targetScope) != null && !relatedObjects.get(targetScope).isEmpty(); + } + public Set getRelatedFields() { - return relatedMap.keySet(); + return getRelatedFields(null); } + public Set getRelatedFields(String targetScope) { + return relatedObjects != null ? relatedObjects.get(null) : null; + } + public String getDirtyReadDataFieldName() { - return dirtyReadDataFieldName; + return dirtyReadInfo != null ? dirtyReadInfo.dirtyReadDataFieldName : null; } public String getDirtyReadErrorLabelToken() { - return dirtyReadErrorLabelToken; + return dirtyReadInfo != null ? dirtyReadInfo.dirtyReadErrorLabelToken : null; } public String[] getDirtyReadErrorParams() { - return dirtyReadErrorParams; + return dirtyReadInfo != null ? dirtyReadInfo.dirtyReadErrorParams : null; } public boolean isReadOnly(String dataFieldName) { - return readOnlyFields != null && readOnlyFields.contains(dataFieldName); + return containsDataField(dataFieldName) && elementMap.get(dataFieldName).isReadOnly(); } public boolean isNoCloning(String dataFieldName) { - return noCloningFields != null && noCloningFields.contains(dataFieldName); + return containsDataField(dataFieldName) && elementMap.get(dataFieldName).isNoCloning(); } public String getDomainFieldName(String dataFieldName) { - String name = null; - if (keyMap.containsKey(dataFieldName)) - name = keyMap.get(dataFieldName); - else if (fieldMap.containsKey(dataFieldName)) - name = fieldMap.get(dataFieldName); - else if (foreignMap.containsKey(dataFieldName)) { - String[] x = foreignMap.get(dataFieldName); - if (x != null && x.length > 0) - name = x[0]; - } else if (relatedMap.containsKey(dataFieldName)) - name = relatedMap.get(dataFieldName); - else - return null; - return (name == null ? dataFieldName : name); + return containsDataField(dataFieldName) ? elementMap.get(dataFieldName).getDomainFieldName() : null; } /** Returns the Field object, if available, or the setter Method, corresponding to the input dataFieldName. @@ -614,7 +576,7 @@ * @return the Field object, if available, or the setter Method, corresponding to the input dataFieldName. */ public AccessibleObject getDataMutator(String dataFieldName) { - AccessibleObject accessibleObject = dataFieldMap.get(dataFieldName); + AccessibleObject accessibleObject = containsDataField(dataFieldName) ? elementMap.get(dataFieldName).getGraphField() : null; if (accessibleObject == null) { PropertyDescriptor pd = getDataFieldDescriptor(dataFieldName); if (pd != null) { @@ -627,33 +589,22 @@ } public PropertyDescriptor getDataFieldDescriptor(String dataFieldName) { - PropertyDescriptor pd = dataDescriptorMap.get(dataFieldName); + PropertyDescriptor pd = containsDataField(dataFieldName) ? elementMap.get(dataFieldName).getGraphPropertyDescriptor() : null; if (pd == null) log.error("Tried to access descriptor for invalid field " + getDataClassShortName() + "." + dataFieldName); return pd; } public PropertyDescriptor getDomainFieldDescriptor(String dataFieldName) { - if (containsDataField(dataFieldName)) { - String domain = getDomainFieldName(dataFieldName); - if (domain != null) - return domainDescriptorMap.get(domain); - } - return null; + return domainPropertyDescriptors != null ? domainPropertyDescriptors.get(getDomainFieldName(dataFieldName)) : null; } public PropertyDescriptor getRealDomainFieldDescriptor(String domainFieldName) { - if (domainFieldName != null) - return domainDescriptorMap.get(domainFieldName); - return null; + return domainPropertyDescriptors != null ? domainPropertyDescriptors.get(domainFieldName) : null; } - private String shortName(String s) { - int p = s.lastIndexOf("."); - if (p <= 0) - return s; - else - return s.substring(p + 1); + public String getTargetScope(String dataFieldName) { + return containsDataField(dataFieldName) ? elementMap.get(dataFieldName).getTargetScope() : null; } /** Returns the mapping file for the input class. @@ -687,32 +638,150 @@ return filename; } - /** - * Checks common attributes, like read-only and no-cloning for the input Element, - * and adds them to the appropriate Collection. - * @param fieldName the gdo name. - * @param element the Element - */ - private void checkAttributes(String fieldName, Element element) { - Node node = element.getAttributes().getNamedItem(ATTR_READ_ONLY); - if (node != null) { - Boolean value = Parser.parseBoolean(node.getNodeValue()); - if (value != null && value) { - if (readOnlyFields == null) - readOnlyFields = new HashSet(); - readOnlyFields.add(fieldName); + /** Returns an attribute from the element. A null is returned in case the attribute is not defined. */ + private static String readAttribute(Element element, String attributeName) { + String attribute = element.getAttribute(attributeName); + return attribute != null && attribute.length() > 0 ? attribute : null; + } + + /** Adds the name to the map for each scope. */ + private static void addNamePerScope(Map<String, Set<String>> map, BaseElement baseElement) { + // Always add the name to the default scope + Set<String> set = map.get(null); + if (set == null) { + set = new LinkedHashSet<String>(); + map.put(null, set); + } + set.add(baseElement.getGraphFieldName()); + + // Now add the name for each of the input scopes + if (baseElement.getScope() != null) { + for (String aScope : baseElement.getScope()) { + set = map.get(aScope); + if (set == null) { + set = new LinkedHashSet<String>(); + map.put(aScope, set); + } + set.add(baseElement.getGraphFieldName()); } } + } - node = element.getAttributes().getNamedItem(ATTR_NO_CLONING); - if (node != null) { - Boolean value = Parser.parseBoolean(node.getNodeValue()); - if (value != null && value) { - if (noCloningFields == null) - noCloningFields = new HashSet(); - noCloningFields.add(fieldName); + private static class DirtyReadInfo { + + private String dirtyReadDataFieldName; //dataFieldName to be used for dirty-read check + private String dirtyReadErrorLabelToken; //label-token to be used in the error-message for dirty-read check + private String[] dirtyReadErrorParams; //do[] to be used in the error-message for dirty-read check + + public DirtyReadInfo(String dirtyReadDataFieldName, String dirtyReadErrorLabelToken, String dirtyReadErrorParams) { + this.dirtyReadDataFieldName = dirtyReadDataFieldName; + this.dirtyReadErrorLabelToken = dirtyReadErrorLabelToken; + this.dirtyReadErrorParams = StringHelper.split(dirtyReadErrorParams, ','); + } + + public String getDirtyReadDataFieldName() { + return dirtyReadDataFieldName; + } + + public String getDirtyReadErrorLabelToken() { + return dirtyReadErrorLabelToken; + } + + public String[] getDirtyReadErrorParams() { + return dirtyReadErrorParams; + } + } + + private static abstract class BaseElement { + + private String graphFieldName; + private String domainFieldName; + private boolean readOnly; + private boolean noCloning; + private String[] scope; + private String targetScope; + private PropertyDescriptor graphPropertyDescriptor; + private Field graphField; + + public BaseElement(String graphFieldName, String domainFieldName, String readOnly, String noCloning, String scope, String targetScope) { + this.graphFieldName = graphFieldName; + this.domainFieldName = domainFieldName != null && domainFieldName.length() > 0 ? domainFieldName : graphFieldName; + Boolean b = Parser.parseBoolean(readOnly); + this.readOnly = b != null && b; + b = Parser.parseBoolean(noCloning); + this.noCloning = b != null && b; + if (scope != null && scope.length() > 0) { + String[] a = StringHelper.split(scope, ','); + Arrays.sort(a); + this.scope = a; } + this.targetScope = targetScope; } + + public String getGraphFieldName() { + return graphFieldName; + } + + public String getDomainFieldName() { + return domainFieldName; + } + + public boolean isReadOnly() { + return readOnly; + } + + public boolean isNoCloning() { + return noCloning; + } + + public String[] getScope() { + return scope; + } + + public String getTargetScope() { + return targetScope; + } + + public PropertyDescriptor getGraphPropertyDescriptor() { + return graphPropertyDescriptor; + } + + public Field getGraphField() { + return graphField; + } } + private static class KeyField extends BaseElement { + + public KeyField(String graphFieldName, String domainFieldName, String readOnly, String noCloning) { + super(graphFieldName, domainFieldName, readOnly, noCloning, null, null); + } + } + + private static class PlainField extends BaseElement { + + public PlainField(String graphFieldName, String domainFieldName, String readOnly, String noCloning, String scope) { + super(graphFieldName, domainFieldName, readOnly, noCloning, scope, null); + } + } + + private static class ForeignObject extends BaseElement { + + private List<String> foreignKeys; + + public ForeignObject(String graphFieldName, String domainFieldName, String readOnly, String noCloning, String scope, String targetScope) { + super(graphFieldName, domainFieldName, readOnly, noCloning, scope, targetScope); + } + + public List<String> getForeignKeys() { + return foreignKeys; + } + } + + private static class RelatedObject extends BaseElement { + + public RelatedObject(String graphFieldName, String domainFieldName, String readOnly, String noCloning, String scope, String targetScope) { + super(graphFieldName, domainFieldName, readOnly, noCloning, scope, targetScope); + } + } } Modified: trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/MappingFilter.java =================================================================== --- trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/MappingFilter.java 2011-05-26 00:10:51 UTC (rev 5303) +++ trunk/JaffaSOA/source/java/org/jaffa/soa/dataaccess/MappingFilter.java 2011-05-26 00:48:42 UTC (rev 5304) @@ -232,18 +232,18 @@ */ private static List<String> getFieldList(Class<? extends GraphDataObject> gdo) { List<String> out = new ArrayList<String>(); - getFieldList(gdo, out, null, true); + getFieldList(gdo, out, null, true, null); Collections.sort(out); return out; } - private static void getFieldList(Class<? extends GraphDataObject> gdo, List<String> out, String prefix, boolean includeKeys) { + private static void getFieldList(Class<? extends GraphDataObject> gdo, List<String> out, String prefix, boolean includeKeys, String targetScope) { GraphMapping mapper = MappingFactory.getInstance(gdo); if (mapper == null) { log.error("Can't find mapping for class " + gdo.getName()); return; } - String[] fields = mapper.getDataFieldNames(); + String[] fields = mapper.getDataFieldNames(targetScope); if (fields != null) { for (int i = 0; i < fields.length; i++) { String name = fields[i]; @@ -259,8 +259,12 @@ c = c.getComponentType(); if (GraphDataObject.class.isAssignableFrom(c)) { if (prefix == null || !repeatingPatternExists(fullName)) { - //Include key-fields for related-objects, both in 1-to-many and 1-to-1 relationships - getFieldList(c, out, fullName + ".", array || !mapper.isForeignField(name)); + //Include key-fields for related-objects, both in 1-to-many and 1-to-1 relationships + //Utilize the targetScope for the foreign/related object, if declared. Else use the input targetScope + String targetScopeToPass = mapper.getTargetScope(name); + if (targetScopeToPass == null) + targetScopeToPass = targetScope; + getFieldList(c, out, fullName + ".", array || !mapper.isForeignField(name), targetScopeToPass); if (array) fullName = "*" + fullName; else @@ -296,7 +300,7 @@ } private void calculateFilter(GraphMapping graph, String[] rules) { - m_rules = rules != null && rules.length > 0 ? rules : new String[] {"*"}; + m_rules = rules != null && rules.length > 0 ? rules : new String[]{"*"}; List<String> filteredFields = new ArrayList<String>(); List<String> relToCheck = new LinkedList<String>(); @@ -402,8 +406,7 @@ boolean exclude = m_filterTypes[i]; if (p != null && p.matcher(field).matches()) { if (log.isDebugEnabled()) - log.debug("field '" + field + "' has been " + (exclude ? "excluded" : "included") + " by pattern '" + p. - pattern() + "'"); + log.debug("field '" + field + "' has been " + (exclude ? "excluded" : "included") + " by pattern '" + p.pattern() + "'"); return !exclude; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |