From bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a Mon Sep 17 00:00:00 2001 From: dims Date: Tue, 17 Jun 2008 00:23:01 +0000 Subject: Move Tuscany from Incubator to top level. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68 --- .../kgoodson/mappingFramework/sdo-snapshot/pom.xml | 58 ++++ .../java/com/agfa/hap/sdo/DataAccessService.java | 83 +++++ .../src/main/java/com/agfa/hap/sdo/DataMapper.java | 107 ++++++ .../main/java/com/agfa/hap/sdo/ObjectFactory.java | 36 ++ .../com/agfa/hap/sdo/ObjectPropertyVisitor.java | 41 +++ .../main/java/com/agfa/hap/sdo/PropertyTree.java | 249 ++++++++++++++ .../java/com/agfa/hap/sdo/ReachableDefinition.java | 74 ++++ .../main/java/com/agfa/hap/sdo/SelectClause.java | 165 +++++++++ .../src/main/java/com/agfa/hap/sdo/Snapshot.java | 63 ++++ .../java/com/agfa/hap/sdo/SnapshotDefinition.java | 37 ++ .../com/agfa/hap/sdo/impl/BytesTypeConverter.java | 51 +++ .../com/agfa/hap/sdo/impl/DataAccessService.java | 30 ++ .../com/agfa/hap/sdo/impl/EnumTypeConverter.java | 40 +++ .../hap/sdo/impl/SerializableTypeConverter.java | 61 ++++ .../java/com/agfa/hap/sdo/impl/TypeConverter.java | 77 +++++ .../sdo/implementation/SnapshotImplementation.java | 377 +++++++++++++++++++++ .../agfa/hap/sdo/implementation/SnapshotUnion.java | 55 +++ .../hap/sdo/mapper/AbstractPropertyAccessor.java | 54 +++ .../agfa/hap/sdo/mapper/BeanPropertyAccessor.java | 98 ++++++ .../sdo/mapper/BeanPropertyAccessorBuilder.java | 81 +++++ .../agfa/hap/sdo/mapper/DelegatingDataMapper.java | 90 +++++ .../mapper/DelegatingPartialDataObjectMapper.java | 138 ++++++++ .../agfa/hap/sdo/mapper/FalsePropertyAccessor.java | 32 ++ .../mapper/FilteringPartialDataObjectMapper.java | 49 +++ .../com/agfa/hap/sdo/mapper/JavaBeanMapper.java | 140 ++++++++ .../sdo/mapper/ManyValuedBeanPropertyAccessor.java | 44 +++ .../agfa/hap/sdo/mapper/NullPropertyAccessor.java | 36 ++ .../hap/sdo/mapper/PartialDataObjectMapper.java | 97 ++++++ .../com/agfa/hap/sdo/mapper/PropertyAccessor.java | 45 +++ .../hap/sdo/mapper/PropertyAccessorBuilder.java | 72 ++++ .../agfa/hap/sdo/mapper/TruePropertyAccessor.java | 32 ++ .../java/com/agfa/hap/sdo/mapper/TypeMapper.java | 100 ++++++ 32 files changed, 2712 insertions(+) create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/pom.xml create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataAccessService.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataMapper.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectFactory.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/PropertyTree.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SelectClause.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/Snapshot.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java create mode 100644 sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java (limited to 'sandbox/kgoodson/mappingFramework') diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/pom.xml b/sandbox/kgoodson/mappingFramework/sdo-snapshot/pom.xml new file mode 100644 index 0000000000..2bb251e8f2 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/pom.xml @@ -0,0 +1,58 @@ + + + + 4.0.0 + org.apache.tuscany.sdo + tuscany-sdo-snapshot-framework + Tuscany SDO Snapshot Framework + A framwork to support interconversion between + SDO and othe Java representations + kgoodson-sandbox + + + + org.apache.tuscany.sdo + tuscany-sdo-impl + 1.0-incubating + compile + + + + + + junit + junit + 3.8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + + diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataAccessService.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataAccessService.java new file mode 100644 index 0000000000..26f86cb1e9 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataAccessService.java @@ -0,0 +1,83 @@ +/** + * + * 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 com.agfa.hap.sdo; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import com.agfa.hap.sdo.implementation.SnapshotImplementation; +import com.agfa.hap.sdo.mapper.PartialDataObjectMapper; + +public class DataAccessService { + private final static PartialDataObjectMapper MAPPER = new PartialDataObjectMapper(); + public static Snapshot createSnapShot(SnapshotDefinition def, PartialDataObject root) { + return createSnapShot(MAPPER, def, root); + } + + public static Snapshot createSnapShot(DataMapper mapper, SnapshotDefinition def, T root) { + List roots = new ArrayList(1); + roots.add(root); + return new SnapshotImplementation(mapper, def, roots); + } + + @SuppressWarnings("unchecked") + public static Snapshot createMultiSnapShot(SnapshotDefinition def, Collection root) { + return createMultiSnapShot((DataMapper) MAPPER, def, root); + } + + public static Snapshot createMultiSnapShot(DataMapper mapper, SnapshotDefinition def, Collection root) { + return new SnapshotImplementation(mapper, def, root); + } + + public static PartialDataObject getRootObject(Snapshot s) { + return getRootObject(MAPPER, s); + } + + /** + * @return The first and only root object of the snapshot. This is always a different + * instance than the object that was used to create the snapshot. + * @throws RuntimeException if there are no root objects or if there is more than one root object + */ + public static T getRootObject(DataMapper mapper, Snapshot s) { + List roots = getRootObjects(mapper, s); + if (roots.isEmpty()){ + throw new RuntimeException("snapshot is empty"); + } + if (roots.size() > 1){ + throw new RuntimeException("more than 1 rootobject:" + roots.size()); + } + return roots.get(0); + } + + public static List getRootObjects(Snapshot s) { + return getRootObjects(MAPPER, s); + } + + public static List getRootObjects(DataMapper mapper, Snapshot s) { + return s.extract(mapper); + } + + public static Iterator rootObjectsIterator(DataMapper mapper, Snapshot s) { + return getRootObjects(mapper, s).iterator(); + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataMapper.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataMapper.java new file mode 100644 index 0000000000..2b345791dd --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/DataMapper.java @@ -0,0 +1,107 @@ +/** + * + * 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 com.agfa.hap.sdo; + +import java.util.Collection; +import java.util.Iterator; + +import commonj.sdo.DataObject; + +/** + * Interface that allows any object to be exposed as {@link DataObject} instances. + * The implementation is guaranteed to work for DataObject instances as well. + * @author AMOCZ + */ +public interface DataMapper { + + /** + * @return The sdo type that corresponds with this object. It is assumed + * that for all properties of this type, appropriate values can be + * retrieved from the instance. + * @exception throws {@link IllegalArgumentException} in case no + * corresponding sdo type can be found. + */ + Type getType(T object); + + /** + * @return The sdo type that corresponds with this class. It is assumed + * that for all properties of this type, appropriate values can be + * retrieved from the instance. + * @return null if no sdo type can be found + * @exception throws {@link IllegalArgumentException} in case no + * corresponding sdo type can be found. + * TODO 1 mechanism for indication no type was found + */ + Type getCorrespondingType(Class clazz); + + /** + * @return An iterator over all values of this property of the given + * Object. Property should be a many-valued property. + */ + Iterator getObjects(T object, Property property); + + /** + * @return The value of the property for the given object. + */ + Object getProperty(T object, Property property); + + /** + * Assigns the given value to the property of the object. If the property + * is many-valued, adds the property to the collection of values. + */ + void setProperty(T object, Property property, Object value); + + /** + * @return if this property is a bulk property for the given implementation clazz. + * Bulk properties + * are accessed in bulk (@see {@link #getProperties(Collection, Property, SnapshotDefinition)} + * to allow more efficient retrieval. + */ + boolean isBulkProperty(Class clazz, Property property); + + /** + * Return the corresponding values for this bulk property for the given object. + * A snapshotdefinition is passed as indication for which child objects are + * needed as well. + */ + Collection getProperties(Collection object, Property bulkProperty, SnapshotDefinition def); + + /** + * Marks a property as unavailable ({@see {@link PartialDataObject#isAvailable(Property)}}. + */ + void setUnavailable(T object, Property property); + + boolean isProxy(T object); + + /** + * @return A newly created instance of which the class corresponds to the given type. + * @return null if the datamapper is unable to create a class for the given type + * @see DataMapper#getCorrespondingType(Class) + */ + T create(Type type); + + /** + * Create a new proxy. The type is passed as parameter as this accessor might + * be usable for multiple types. + * @return null if the datamapper is unable to create a proxy for the given type + */ + T newProxy(Type type, Object identity); + +} \ No newline at end of file diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectFactory.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectFactory.java new file mode 100644 index 0000000000..613d2f60c1 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectFactory.java @@ -0,0 +1,36 @@ +/** + * + * 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 com.agfa.hap.sdo; + + +public interface ObjectFactory { + + /** + * @return A newly created instance of which the class corresponds to the given type. + * @see DataMapper#getCorrespondingType(Class) + */ + T create(Type type); + + /** + * Create a new proxy. The type is passed as parameter as this accessor might + * be usable for multiple types. + */ + T newProxy(Type type, Object identity); +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java new file mode 100644 index 0000000000..0365cc1b50 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java @@ -0,0 +1,41 @@ +/** + * + * 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 com.agfa.hap.sdo; + + +/** + * Visitor interface for visiting all properties belong to a snapshot. + * @author AMOCZ + * @see SnapshotDefinition + */ +public interface ObjectPropertyVisitor { + void startDataObject(Object instance, Type type) throws Exception; + boolean visitProperty(Object instance, Property property, Object value) throws Exception; + void visitProxyProperty(Object instance, Property property, Object identity) throws Exception; + void endDataObject(Object instance, Type type) throws Exception; + + /** + * Bulk properties are properties that are heavy to retrieve and as such should + * be visited in bulk. A typical example is a property that can only be filled in + * by doing a query. + * Bulk properties are visited after all other objects have been visited. + */ + void visitBulkProperty(Object instance, Property property, SnapshotDefinition subselect); +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/PropertyTree.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/PropertyTree.java new file mode 100644 index 0000000000..07f20762bf --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/PropertyTree.java @@ -0,0 +1,249 @@ +/** + * + * 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 com.agfa.hap.sdo; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + + +/** + * Helper class for {@link SelectClause} that represents + * a comma-separated list of properties in a structured form. + * @author AMOCZ + * + */ +public abstract class PropertyTree { + + public abstract String asCommmaSeparatedString(); + + public abstract PropertyTree getProperty(String property); + + public abstract PropertyTree getProperty(Property property); + + public abstract boolean containsProperty(Property property); + + public abstract boolean containsProperty(String property); + + public static PropertyTree newPropertyTree(Type type, String selectClause) { + PropertyTree result = new MapBasedPropertyTree(type); + String[] parts = selectClause.split(","); + for (String part : parts) { + if (part.length() > 0) { + result = result.extend(part); + } + } + return result; + } + + protected PropertyTree extend(String property) { + property = property.trim(); + int index = property.indexOf('.'); + if (index < 0) { + if (property.length() == 1 && property.charAt(0) == '*') { + return STAR_PROPERTYTREE; + } + if (property.length() == 2 && property.charAt(0) == '*' && property.charAt(1) == '*') { + return STARSTAR_PROPERTYTREE; + } + addSimpleProperty(property); + } else { + addComposedProperty(property.substring(0, index), property.substring(index+1)); + } + return this; + } + + protected void addSimpleProperty(String propertyName) { + // ok + } + + protected void addComposedProperty(String ownerName, String childName) { + // ok + } + + final static PropertyTree EMPTY_PROPERTYTREE = new PropertyTree() { + public PropertyTree getProperty(String property) { + return null; + } + + public PropertyTree getProperty(Property property) { + return null; + } + + public boolean containsProperty(Property property) { + return false; + } + + public boolean containsProperty(String property) { + return false; + } + + @Override + public String asCommmaSeparatedString() { + return ""; + } + + }; + + final static PropertyTree STAR_PROPERTYTREE = new PropertyTree() { + public PropertyTree getProperty(String property) { + return EMPTY_PROPERTYTREE; + } + + public PropertyTree getProperty(Property property) { + return EMPTY_PROPERTYTREE; + } + + public boolean containsProperty(Property property) { + return true; + } + + public boolean containsProperty(String property) { + return true; + } + + @Override + public String asCommmaSeparatedString() { + throw new UnsupportedOperationException(); + } + + + + }; + + final static PropertyTree STARSTAR_PROPERTYTREE = new PropertyTree() { + public PropertyTree getProperty(String property) { + return this; + } + + public PropertyTree getProperty(Property property) { + return this; + } + + public boolean containsProperty(Property property) { + return true; + } + + public boolean containsProperty(String property) { + return true; + } + + @Override + public String asCommmaSeparatedString() { + throw new UnsupportedOperationException(); + } + + }; + + static class MapBasedPropertyTree extends PropertyTree { + private Map properties; + private Type type; + + public MapBasedPropertyTree(Type type) { + this.type = type; + properties = new HashMap(); + } + + public Type getType() { + return type; + } + + public Set> getProperties() { + return properties.entrySet(); + } + + public PropertyTree getProperty(String property) { + return properties.get(type.getProperty(property)); + } + + public PropertyTree getProperty(Property property) { + return properties.get(property); + } + + public boolean containsProperty(Property property) { + return properties.containsKey(property); + } + + public boolean containsProperty(String property) { + return properties.containsKey(type.getProperty(property)); + } + + @Override + protected void addSimpleProperty(String property) { + Property prop = type.getProperty(property); + if (prop == null) { + throw new IllegalArgumentException("Unknown property " + property + " in type " + type.getName()); + } + if (!prop.getType().isDataType() && !properties.containsKey(prop)) { + properties.put(prop, new MapBasedPropertyTree(prop.getType())); + } + } + + @Override + protected void addComposedProperty(String owner, String child) { + Property prop = type.getProperty(owner); + if (prop == null) { + throw new IllegalArgumentException("Unknown property " + owner + " in type " + type.getName()); + } + if (!prop.getType().isDataType()) { + PropertyTree children = properties.get(prop); + if (children == null) { + children = newPropertyTree(prop.getType(), child); + properties.put(prop, children); + } else { + children.extend(child); + } + } + } + + public Collection propertyPaths() { + Collection paths = new ArrayList(); + for (Entry entry : this.getProperties()){ + String rootPropName = entry.getKey().getName(); + MapBasedPropertyTree tree = (MapBasedPropertyTree) entry.getValue(); + Collection childPaths = tree.propertyPaths(); + if (childPaths.isEmpty()){ + paths.add(rootPropName); + } else { + for (String childPath : childPaths){ + paths.add(rootPropName + "." + childPath); + } + } + } + return paths; + } + + public String asCommmaSeparatedString(){ + StringBuilder builder = new StringBuilder(); + for(String path : this.propertyPaths()){ + builder.append(path); + builder.append(','); + } + builder.setLength(builder.length()-1); //remove last , + return builder.toString(); + } + + } + +} \ No newline at end of file diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java new file mode 100644 index 0000000000..2fee73a3a8 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java @@ -0,0 +1,74 @@ +/** + * + * 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 com.agfa.hap.sdo; + +import java.util.Iterator; + + +/** + * {@link SnapshotDefinition} that includes everything that is reachable + * from the root object. + * starting from the root object all child properties are visited + * properties that are considered "proxy" by the datamapper are + * visited as proxies and will be serialized as sdo . (ie when using a HibernateDataMapper lazily retrieved objects that are "unitialized" + * will be serialized as a sdo proxy) + * @author AMOCZ + */ +public class ReachableDefinition implements SnapshotDefinition { + + public void visit(DataMapper mapper, ObjectPropertyVisitor visitor, T root) throws Exception { + Type type = mapper.getType(root); + visitor.startDataObject(root, type); + for (Property p : type.getProperties()) { + try { + if (p.isMany()) { + Iterator it = mapper.getObjects(root, p); + while (it.hasNext()) { + visitChild(mapper, visitor, root, p, it.next()); + } + } else { + visitChild(mapper, visitor, root, p, mapper.getProperty(root, p)); + } + } catch (PropertyNotAvailableException e) { + // ok; + } + } + visitor.endDataObject(root, type); + } + + private void visitChild(DataMapper mapper, ObjectPropertyVisitor visitor, T parent, Property property, Object value) throws Exception { + if (value != null) { + if (!property.getType().isDataType()) { + T child = (T) value; + if (mapper.isProxy(child)) { + Type childType = mapper.getType(child); + Object identity = mapper.getProperty(child, childType.getIdentityProperty()); + visitor.visitProxyProperty(parent, property, identity); + return; + } + } + boolean recurse = visitor.visitProperty(parent, property, value); + if (recurse) { + visit(mapper, visitor, (T) value); + } + } + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SelectClause.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SelectClause.java new file mode 100644 index 0000000000..259c6d12de --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SelectClause.java @@ -0,0 +1,165 @@ +/** + * + * 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 com.agfa.hap.sdo; + +import java.util.Iterator; +import java.util.Map.Entry; + +import com.agfa.hap.sdo.PropertyTree.MapBasedPropertyTree; +import commonj.sdo.Type; + + +/** + * SnapshotDefinition defined by a comma-separated list of + * property paths. Datatype properties (e.g. strings, dates etc) are included by default + * and should not be part of the select clause. Many-valued properties that are not part of + * the select string will be unavailable. Single-valued properties that are not part of + * the select string will be available as proxies when they have their Identity property filled + * in. Otherwise, they will not be part of the snapshot. + *

+ * Using '*' as the name of a property indicates all properties of that type. + * Using '**' indicates all properties recursively. This means all child + * properties including all properties of those child properties (in case + * they are not datatypes) recursively. This is similar to {@link ReachableDefinition}. + *

+ * Ex. address, serviceRequests, medicalCase.* for the Patient type will return all + * basic properties of Patient, its address, its serviceRequests. And also its complete + * medicalCase including many-valued properties and all its direct links. + *

+ * Properties that are part of the definition but are not available when creating the snapshot + * will be accessed. That may result in {@link PropertyNotAvailableException} being thrown or + * might result in lazy retrieval of data (e.g. when working with Hibernate proxies). + * @author AMOCZ + */ +public class SelectClause implements SnapshotDefinition { + + private PropertyTree propertyTree; + + protected SelectClause(PropertyTree propertyTree) { + this.propertyTree = propertyTree; + } + + public SelectClause(Type mainType) { + this(mainType, ""); + } + + public SelectClause(Type mainType, String clause) { + this.propertyTree = PropertyTree.newPropertyTree((com.agfa.hap.sdo.Type) mainType, clause); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof SelectClause)) { + return false; + } + return ((SelectClause) other).propertyTree == propertyTree; + } + + @Override + public int hashCode() { + return propertyTree.hashCode(); + } + + public void visit(DataMapper mapper, ObjectPropertyVisitor visitor, T dataObject) throws Exception { + visit(mapper, visitor, dataObject, propertyTree); + } + + private void visit(DataMapper mapper, ObjectPropertyVisitor visitor, T dataObject, PropertyTree propertyTree) throws Exception { + com.agfa.hap.sdo.Type type = mapper.getType(dataObject); + if (type == null) { + throw new IllegalArgumentException("Can't visit an object which doesn't have an sdo type. dataObject=" + dataObject); + } + visitor.startDataObject(dataObject, type); + if (propertyTree != null) { + for (Property property : type.getProperties()) { + if (property.getType().isDataType()) { + visitChild(mapper, visitor, dataObject, property, null); + } else { + PropertyTree tree = propertyTree.getProperty(property); + if (tree == null) { + visitProxy(mapper, visitor, dataObject, property); + } else { + visitChildObject(mapper, visitor, dataObject, property, tree); + } + } + } + } + visitor.endDataObject(dataObject, type); + } + + protected void visitProxy(DataMapper mapper, ObjectPropertyVisitor visitor, T dataObject, Property property) throws Exception { + if (property.isMany()) { + visitor.visitProxyProperty(dataObject, property, null); + } else { + Property idProp = property.getType().getIdentityProperty(); + if (idProp != null) { + T child = (T) mapper.getProperty(dataObject, property); + if (child != null) { + Object identity = mapper.getProperty(child, idProp); + if (identity != null) { // link doesn't have an identity, so no use to proxy + visitor.visitProxyProperty(dataObject, property, identity); + } + } + } + } + } + + protected void visitChildObject(DataMapper mapper, ObjectPropertyVisitor visitor, T dataObject, Property property, PropertyTree tree) throws Exception { + if (mapper.isBulkProperty(dataObject.getClass(), property)) { + visitor.visitBulkProperty(dataObject, property, new SelectClause(tree)); + return; + } + if (property.isMany()) { + Iterator it = mapper.getObjects(dataObject, property); + while (it.hasNext()) { + visitChild(mapper, visitor, dataObject, property, it.next(), tree); + } + } else { + visitChild(mapper, visitor, dataObject, property, tree); + } + } + + protected void visitChild(DataMapper mapper, ObjectPropertyVisitor visitor, T parent, Property property, PropertyTree propertyTree) throws Exception { + if (mapper.isBulkProperty(parent.getClass(), property)) { + visitor.visitBulkProperty(parent, property, new SelectClause(propertyTree)); + return; + } + Object value = mapper.getProperty(parent, property); + visitChild(mapper, visitor, parent, property, value, propertyTree); + } + + private void visitChild(DataMapper mapper, ObjectPropertyVisitor visitor, T parent, Property property, Object value, PropertyTree propertyTree) throws Exception { + if (value != null) { + boolean recurse = visitor.visitProperty(parent, property, value); + if (recurse) { + visit(mapper, visitor, (T) value, propertyTree); + } + } + } + + public PropertyTree getPropertyTree() { + return propertyTree; + } + + public String asCommaSeparatedString(){ + return this.getPropertyTree().asCommmaSeparatedString(); + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/Snapshot.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/Snapshot.java new file mode 100644 index 0000000000..4420bced2a --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/Snapshot.java @@ -0,0 +1,63 @@ +/** + * + * 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 com.agfa.hap.sdo; + +import java.io.Serializable; +import java.util.List; + + +/** + * Collection of structured data at a given moment in time. + * You can think of this as a set of name-value pairs + * where the names correspond to various {@link Property} instances. + * The actual content (i.e. which properties are contained) has been defined based on + * a {@link SnapshotDefinition}. + *
+ * The difference with a DataGraph is that a Snapshot contains the state of a + * set of dataobjects at a certain moment in time. As such it is immutable. + * Another difference is that is defines its content based on a definition as opposed + * to the datagraph that uses the containment relation + * defined by sdo ({@see {@link Property#isContainment()}). + *
+ * The data can be extracted either as a set of {@link ProxyDataObject} instances. + * The data can also be returned as a set of objects (POJOs). The latter case assumes + * appropriate classes can be + * found that correspond to the different {@link Type}s that are used. + *
+ * Warning: + * Serialized objects of this class will not be compatible with + * future hap.SDO releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of hap.sdo. + * + * @author AMOCZ + * @see DataAccessService + * @see DataMapper + */ +public interface Snapshot extends Serializable { + + /** + * Extracts the objects from the snapshots + * @param factory + * @return A list containing new objects with appropriate properties filled in. + */ + List extract(DataMapper mapper); + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java new file mode 100644 index 0000000000..30f67f8c7f --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java @@ -0,0 +1,37 @@ +/** + * + * 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 com.agfa.hap.sdo; + +import org.omg.CORBA.Any; + +/** + * Defines which properties belong to the {@link Snapshot}. + * @author AMOCZ + */ +public interface SnapshotDefinition { + + /** + * Visits all properties of the object that are part + * of the definition. + * @exception Any exception that is thrown by the visitor + */ + void visit(DataMapper mapper, ObjectPropertyVisitor visitor, T root) throws Exception; + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java new file mode 100644 index 0000000000..28b1e8bc28 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java @@ -0,0 +1,51 @@ +/** + * + * 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 com.agfa.hap.sdo.impl; + + +public class BytesTypeConverter extends TypeConverter{ + //TODO suboptimal implementation + @Override + public byte[] parse(String hexString) { + byte[] bytes = new byte[hexString.length()/3]; + for (int i = 0; i < bytes.length; i++){ + String hexFor1Byte = hexString.substring(i*3, i*3+3); + if (hexFor1Byte.startsWith("0")){ //strip zero for - + hexFor1Byte = hexFor1Byte.substring(1); + } + bytes[i] = (byte) Integer.parseInt(hexFor1Byte, 16); + } + return bytes; + } + + @Override + public String toString(byte[] instance) { + StringBuilder sb = new StringBuilder(instance.length * 2); + for(int x = 0 ; x < instance.length ; x++) + { + String hex = Integer.toString(instance[x], 16); + for (int i = hex.length(); i < 3; i++){ + sb.append("0"); + } + sb.append(hex); + } + return sb.toString(); + } +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java new file mode 100644 index 0000000000..7c0e96e6fc --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java @@ -0,0 +1,30 @@ +/** + * + * 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 com.agfa.hap.sdo.impl; + +import com.agfa.hap.sdo.implementation.DataGraphImplementation; +import commonj.sdo.DataGraph; + +public class DataAccessService { + + public static DataGraph createDataGraph() { + return new DataGraphImplementation(); + } +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java new file mode 100644 index 0000000000..fa705f2981 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java @@ -0,0 +1,40 @@ +/** + * + * 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 com.agfa.hap.sdo.impl; + +public class EnumTypeConverter extends TypeConverter { + + private Class enumClazz; + + public EnumTypeConverter(Class enumClazz) { + this.enumClazz = enumClazz; + } + + @Override + public T parse(String str) { + return Enum.valueOf(enumClazz, str); + } + + @Override + public String toString(T instance) { + return instance.name(); + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java new file mode 100644 index 0000000000..affa199b04 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java @@ -0,0 +1,61 @@ +/** + * + * 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 com.agfa.hap.sdo.impl; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +public class SerializableTypeConverter extends TypeConverter { + + @Override + public Serializable parse(String str) { + byte[] bytes = bytesTypeConverter.parse(str); + ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + try { + ObjectInput in = new ObjectInputStream(bis); + return (Serializable) in.readObject(); + } catch(IOException e) { + throw new RuntimeException(e); + } catch (ClassNotFoundException cnfe) { + throw new RuntimeException(cnfe); + } + } + + @Override + public String toString(Serializable instance) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + try { + ObjectOutput out = new ObjectOutputStream(bos); + out.writeObject(instance); + out.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return bytesTypeConverter.toString(bos.toByteArray()); + } + + private BytesTypeConverter bytesTypeConverter = new BytesTypeConverter(); +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java new file mode 100644 index 0000000000..973266e525 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java @@ -0,0 +1,77 @@ +/** + * + * 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 com.agfa.hap.sdo.impl; + +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.agfa.hap.sdo.Type; + +/** + * Class that provides + * an implementation to convert instances from and to a string. This is typically + * used in sdo xml conversions and snapshots. + *

+ * A custom sdo basic type can register an appropriate typeConverter. + */ +public abstract class TypeConverter { + + /** + * Parse the string and return an instance of the implementation class + * with a value that is represented by the string parameter. + */ + public abstract T parse(String str); + + /** + * Convert the instance to a string. The instance is guaranteed to be of type + * T. + */ + public abstract String toString(T instance); + + /** + * @return The type converter instance registered with that name or null if nothing + * is found. + */ + @SuppressWarnings("unchecked") + public static TypeConverter get(Type type) { + return registry.get(type); + } + + public static void register(Type type, TypeConverter converter) { + registry.put(type, converter); + } + + /** + * Returns the default TypeConverter for the given clazz. Checks for Enums + * and classes that implement {@link Serializable}. + */ + public static TypeConverter getDefaultConverter(Class clazz) { + if (clazz.isEnum()) { + return new EnumTypeConverter(clazz); + } + if (Serializable.class.isAssignableFrom(clazz)) { + return (TypeConverter) new SerializableTypeConverter(); + } + return null; + } + + private static Map registry = new ConcurrentHashMap(); +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java new file mode 100644 index 0000000000..efd7fa008d --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java @@ -0,0 +1,377 @@ +/** + * + * 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 com.agfa.hap.sdo.implementation; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.StreamCorruptedException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.ObjectPropertyVisitor; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.Snapshot; +import com.agfa.hap.sdo.SnapshotDefinition; +import com.agfa.hap.sdo.Type; +import com.agfa.hap.sdo.helper.TypeHelper; +import com.agfa.hap.sdo.impl.TypeConverter; + +public class SnapshotImplementation implements Snapshot { + + private static Logger logger = Logger.getLogger(SnapshotImplementation.class); + private static final long serialVersionUID = 5403046473375751795L; + + private transient byte[] serializedContent; + + //workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6554519 + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + out.writeInt(serializedContent.length); + out.write(serializedContent); + } + +// workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6554519 + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + int size = in.readInt(); + serializedContent = new byte[size]; + int index = 0; + int remaining = size; + int read = 0; + while (index < size && remaining > 0){ + read = in.read(serializedContent, index, remaining); + index += read; + remaining -= read; + } + if (remaining != 0){ + throw new StreamCorruptedException("read=" + read + " index=" + index + + " remaining=" + remaining + " size=" + size + " serializedcontent=" + serializedContent); + } + } + + public SnapshotImplementation(DataMapper mapper, SnapshotDefinition definition, Collection roots) { + buildSerializedContent(mapper, definition, roots); + } + + public List extract(DataMapper mapper) { + return extractRoots(mapper); + } + + private List extractRoots(DataMapper mapper) { + ByteArrayInputStream bis = new ByteArrayInputStream(serializedContent); + DataInputStream dis = new DataInputStream(bis); + SnapshotSerializer serializer = new SnapshotSerializer(mapper); + try { + return serializer.read(dis); + } catch (IOException e) { + throw new SdoImplementationException(e); + } + } + + private void buildSerializedContent(DataMapper mapper, SnapshotDefinition definition, Collection targets) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(bos); + SnapshotSerializer serializer = new SnapshotSerializer(mapper); + try { + serializer.write(definition, targets, out); + out.close(); + } catch (Exception e) { + throw new SdoImplementationException("definition=" + definition + ":targets=" + targets, e); + } + serializedContent = bos.toByteArray(); + } + + static class SnapshotSerializer implements ObjectPropertyVisitor { + //protected visibility for testing purposes + public static final int MAX_UTF_LENGTH = 65535; + private DataOutput out; + private DataMapper mapper; + private List serializedObjects; + private Map> bulkProperties; + + public SnapshotSerializer(DataMapper mapper) { + this.mapper = mapper; + } + + protected T create(Type type) { + T result = mapper.create(type); + serializedObjects.add(result); + return result; + } + + public List read(DataInput in) throws IOException { + this.serializedObjects = new ArrayList(); + return readFromStream(in); + } + + private List readFromStream(DataInput in) throws IOException { + int nrOfObjects = in.readInt(); + if (nrOfObjects < 1){ + return new ArrayList(); + } + List result = basicReadFromStream(in, nrOfObjects); + readBulkProperties(in); + return result; + } + + private List basicReadFromStream(DataInput in, int nrOfObjects) throws IOException { + List result = new ArrayList(nrOfObjects); + for (int i = 0; i < nrOfObjects; i++){ + result.add(readObject(in)); + } + return result; + } + + private T readObject(DataInput in) throws IOException { + Type type = TypeHelper.INSTANCE.getType(in.readUTF(), in.readUTF()); + T instance = create(type); + int propIndex = in.readInt(); + while (propIndex != Integer.MIN_VALUE) { + if (propIndex < 0) { + Property property = type.getProperty(-propIndex-1); + if (property.isMany()) { + mapper.setUnavailable(instance, property); + } else { + Object identity = read(in, null, property.getType().getIdentityProperty()); + mapper.setProperty(instance, property, mapper.newProxy(property.getType(), identity)); + } + } else { + Property prop = type.getProperty(propIndex); + Object value = read(in, instance, prop); + mapper.setProperty(instance, prop, value); + } + propIndex = in.readInt(); + } + return instance; + } + + private Object read(DataInput in, Object parent, Property prop) throws IOException { + if (prop.getType().isDataType()) { + String value = this.readPotentiallyLongUTF(in); + try { + return TypeConverter.get(prop.getType()).parse(value); + } catch (RuntimeException e){ + logger.error("unable to parse " + value + "for property " + prop + " parent=" + parent, e); + throw e; + } + } else { + return readChildObject(in, prop, parent); + } + + } + + String readPotentiallyLongUTF(DataInput in) throws IOException { + //package visibility for testing purposes + StringBuilder builder = new StringBuilder(); + while (true){ + String buf = in.readUTF(); + builder.append(buf); + if (buf.length() < MAX_UTF_LENGTH){ + break; + } + String finalOrContinue = in.readUTF(); + if ("F".equals(finalOrContinue)){ + break; + } + } + return builder.toString(); + } + + protected Object readChildObject(DataInput in, Property prop, Object parent) throws IOException { + int index = in.readInt(); + if (index < 0) { + return readObject(in); + } else { + return serializedObjects.get(index); + } + } + + public void write(SnapshotDefinition def, Collection roots, DataOutput out) throws Exception { + this.out = out; + this.serializedObjects = new ArrayList(); + out.writeInt(roots.size()); + for (T root : roots){ + def.visit(mapper, this, root); + } + writeBulkProperties(out); + } + + protected void writeBulkProperties(DataOutput out) throws Exception { + if (bulkProperties != null) { + while (!bulkProperties.isEmpty()){ + //we can't just simply iterate over the bulkproperties.values, because while writing a bulkproperty we might visit an additional bulk property in the subselect + BulkProperty bp = bulkProperties.values().iterator().next(); + BulkProperty emptyBulkProperty = new BulkProperty(bp.property, bp.subselect); + bulkProperties.put(bp.property, emptyBulkProperty); //replace the bulk property that we are going to write with a copy of itself, but withouth instances + writeBulkProperty(bp); + if (emptyBulkProperty.instances.isEmpty()){ + bulkProperties.remove(bp.property); //if no new instances were added (through some nested bulkproperties) than we can remove the bulkproperty from the map of bulk properties to be processed + } + } + } + out.writeInt(-1); + } + + protected void writeBulkProperty(BulkProperty bp) throws Exception { + Collection values = this.mapper.getProperties(bp.instances, bp.property, bp.subselect); + Iterator valuesIt = values.iterator(); + Iterator parents = bp.instances.iterator(); + while (parents.hasNext()) { + Object parent = parents.next(); + T value = valuesIt.next(); + if (bp.property.isMany()) { + Collection children = (Collection) value; + for (T child : children) { + writeBulkPropertyValue(bp, parent, child); + } + } else { + writeBulkPropertyValue(bp, parent, value); + } + } + } + + protected void writeBulkPropertyValue(BulkProperty bp, Object parent, T value) throws IOException, Exception { + out.writeInt(serializedObjects.indexOf(parent)); + if (this.visitProperty(parent, bp.property, value)) { + bp.subselect.visit(mapper, this, value); + } + } + + protected void readBulkProperties(DataInput in) throws IOException { + while (readBulkProperty(in)) { + } + } + + protected boolean readBulkProperty(DataInput in) throws IOException { + int index = in.readInt(); + if (index < 0) { + return false; + } + T parent = (T) serializedObjects.get(index); + index = in.readInt(); + if (index < 0){ //null value + Property property = mapper.getType(parent).getProperty(-index-1); + mapper.setProperty(parent, property, null); + return true; + } + Property property = mapper.getType(parent).getProperty(index); + Object value = read(in, parent, property); + mapper.setProperty(parent, property, value); + return true; + } + + public void startDataObject(Object dataObject, Type type) throws IOException { + serializedObjects.add(dataObject); + out.writeUTF(type.getURI()); + out.writeUTF(type.getName()); + } + + public boolean visitProperty(Object dataObject, Property property, Object value) throws IOException { + if (value == null) { + out.writeInt(-property.getIndex()-1); + return false; + } + out.writeInt(property.getIndex()); + if (property.getType().isDataType()) { + writePotentiallyLongStringUTF(TypeConverter.get(property.getType()).toString(value), out); + return false; + } else { + int index = serializedObjects.indexOf(value); + out.writeInt(index); + return index < 0; + } + } + + void writePotentiallyLongStringUTF(String stringValue, DataOutput out) throws IOException { + //package visibilty for testing purposes + int totalLength = stringValue.length(); + if (totalLength < MAX_UTF_LENGTH){ + out.writeUTF(stringValue); + return; + } + int lastPossibleMaxSubstringBeginIndex = totalLength - MAX_UTF_LENGTH; + int substringBeginIndex = 0; + for (; substringBeginIndex <= lastPossibleMaxSubstringBeginIndex; substringBeginIndex += MAX_UTF_LENGTH ){ + out.writeUTF(stringValue.substring(substringBeginIndex, substringBeginIndex + MAX_UTF_LENGTH)); + if (substringBeginIndex == lastPossibleMaxSubstringBeginIndex){ + out.writeUTF("F"); //final + } else { + out.writeUTF("C"); //continue + } + } + if (substringBeginIndex != totalLength -1){ + out.writeUTF(stringValue.substring(substringBeginIndex, totalLength)) ; + } + } + + public void visitProxyProperty(Object instance, Property property, Object identity) throws Exception { + out.writeInt(-property.getIndex()-1); + if (identity != null) { + out.writeUTF(TypeConverter.get(property.getType().getIdentityProperty().getType()).toString(identity)); + } + } + + public void endDataObject(Object dataObject, Type type) throws IOException { + out.writeInt(Integer.MIN_VALUE); + } + + public void visitBulkProperty(Object instance, Property property, SnapshotDefinition subselect) { + getInstancesForBulkProperty(property, subselect).add((T)instance); + } + + protected List getInstancesForBulkProperty(Property property, SnapshotDefinition subselect) { + if (bulkProperties == null) { + bulkProperties = new HashMap>(); + } + BulkProperty bp = bulkProperties.get(property); + if (bp == null) { + bp = new BulkProperty(property, subselect); + bulkProperties.put(property, bp); + } else { + if (!bp.subselect.equals(subselect)) { + throw new IllegalArgumentException("Different subselects not yet supported!"); + } + } + return bp.instances; + } + + } + + static class BulkProperty { + BulkProperty(Property property, SnapshotDefinition subselect) { + this.property = property; + this.subselect = subselect; + this.instances = new ArrayList(); + } + Property property; + List instances; + SnapshotDefinition subselect; + } +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java new file mode 100644 index 0000000000..eea85e3d1a --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java @@ -0,0 +1,55 @@ +/** + * + * 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 com.agfa.hap.sdo.implementation; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Snapshot; + +public class SnapshotUnion implements Snapshot { + + /** + * + */ + private static final long serialVersionUID = 2888458945891090081L; + Collection snapshots; + + public SnapshotUnion(Collection snapshots){ + this.snapshots = snapshots; + } + + public SnapshotUnion(Snapshot firstSnapshot, Snapshot secondSnapshot) { + this(new LinkedList(Arrays.asList(new Snapshot[]{firstSnapshot, secondSnapshot}))); //linkedlist instead of arraylist because of a jboss bug + } + + public List extract(DataMapper mapper) { + List extraction = new ArrayList(); + for (Snapshot snapshot : snapshots){ + extraction.addAll(snapshot.extract(mapper)); + } + return extraction; + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java new file mode 100644 index 0000000000..34eaa3ec5f --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java @@ -0,0 +1,54 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.util.Collection; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.SnapshotDefinition; + +/** + * Abstract shell implementation for {@link PropertyAccessor}. + * @author AMOCZ + */ +public abstract class AbstractPropertyAccessor implements PropertyAccessor { + + public Object getValue(Object instance, Property property, + DataMapper dataMapper) { + return null; + } + + public Collection getValues(Collection instances, Property property, + SnapshotDefinition def, DataMapper dataMapper) { + throw new NotImplementedException(); + } + + public boolean isBulkAccessor() { + return false; + } + + public void setValue(Object instance, Property property, Object value, + DataMapper dataMapper) { + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java new file mode 100644 index 0000000000..010d9aea11 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java @@ -0,0 +1,98 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.SnapshotDefinition; + +/** + * PropertyAccessor that follows bean conventions (i.e. getX() methods) to get values. + * @author AMOCZ + */ +public class BeanPropertyAccessor implements PropertyAccessor { + + private static final Object[] EMPTY_ARGS = new Object[0]; + + public Object getValue(Object instance, Property property, DataMapper dataMapper) { + if (!isReadable()) { + throw new IllegalArgumentException(instance.getClass() + " doesn't have a getter for property " + property.getName()); + } + try { + return getter.invoke(instance, EMPTY_ARGS); + } catch (InvocationTargetException e) { + throw new IllegalArgumentException("Couldn't access property " + property.toString(), e.getTargetException()); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Couldn't access property " + property.toString(), e); + } + } + + /** + * Sets the value of this property for the specified Object. + * @throws IllegalArgumentException + */ + public void setValue(Object instance, Property property, Object newValue, DataMapper dataMapper) { + if (!isWritable()) { + throw new IllegalArgumentException(instance.getClass() + " doesn't have a setter for property " + property.getName()); + } + try { + setter.invoke(instance, new Object[] { newValue }); + } catch (InvocationTargetException e) { + throw new IllegalArgumentException("Couldn't access property " + property.toString(), e.getTargetException()); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Couldn't access property " + property.toString(), e); + } + } + + public void setGetter(Method method) { + this.getter = method; + } + + public void setSetter(Method method) { + this.setter = method; + } + + public boolean isReadable() { + return getter != null; + } + + public boolean isWritable() { + return setter != null; + } + + + public Collection getValues(Collection instances, Property property, SnapshotDefinition def, DataMapper dataMapper) { + throw new NotImplementedException(); + } + + public boolean isBulkAccessor() { + return false; + } + + + private Method setter; + private Method getter; +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java new file mode 100644 index 0000000000..0f8add6e7e --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java @@ -0,0 +1,81 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.lang.reflect.Method; + +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.Type; + +/** + * PropertyAccessorBuilder that uses Java Bean conventions to extract properties from an object. + * @author AMOCZ + */ +public class BeanPropertyAccessorBuilder extends PropertyAccessorBuilder { + + public BeanPropertyAccessorBuilder() { + super(); + } + + public BeanPropertyAccessorBuilder(PropertyAccessorBuilder next) { + super(next); + } + + @Override + protected boolean accepts(Class cls, Type type) { + return true; + } + + @Override + protected PropertyAccessor createPropertyAccessor(Class cls, Property prop) { + String propertyName = Character.toUpperCase(prop.getName().charAt(0)) + prop.getName().substring(1); + String methodName; + if (prop.getType().getInstanceClass() == Boolean.class) { + if (propertyName.startsWith("Is")){ + methodName = prop.getName(); + } else { + methodName = "is" + propertyName; + } + } else { + methodName = "get" + propertyName; + } + BeanPropertyAccessor property = prop.isMany() ? new ManyValuedBeanPropertyAccessor() : new BeanPropertyAccessor(); + try { + Method method = cls.getMethod(methodName, (Class[]) null); + property.setGetter(method); + method = getSetMethod(cls, propertyName); + property.setSetter(method); + return property; + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Can't find property " + prop.getName() + " on class " + cls.getName(), e); + } + } + + // we assume there is no type overloading + private Method getSetMethod(Class cls, String propertyName) { + String methodName = "set" + propertyName; + for (Method m : cls.getMethods()) { + if (m.getName().equals(methodName)) { + return m; + } + } + return null; + } +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java new file mode 100644 index 0000000000..53b297dfcc --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java @@ -0,0 +1,90 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.util.Collection; +import java.util.Iterator; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.SnapshotDefinition; +import com.agfa.hap.sdo.Type; + +public class DelegatingDataMapper implements DataMapper { + + private DataMapper principalMapper; + private DataMapper secondaryMapper; + + public DelegatingDataMapper(DataMapper principalMapper, DataMapper secondaryMapper){ + this.principalMapper = principalMapper; + this.secondaryMapper = secondaryMapper; + } + + public T create(Type type) { + T newlyCreated = principalMapper.create(type); + if (newlyCreated == null){ + return secondaryMapper.create(type); + } + return newlyCreated; + } + + public Type getCorrespondingType(Class clazz) { + return principalMapper.getCorrespondingType(clazz); + } + + public Iterator getObjects(T object, Property property) { + return principalMapper.getObjects(object, property); + } + + public Object getProperty(T object, Property property) { + return principalMapper.getProperty(object, property); + } + + public Type getType(T object) { + return principalMapper.getType(object); + } + + public boolean isProxy(T object) { + return principalMapper.isProxy(object); + } + + public T newProxy(Type type, Object identity) { + return principalMapper.newProxy(type, identity); + } + + public void setProperty(T object, Property property, Object value) { + principalMapper.setProperty(object, property, value); + + } + + public void setUnavailable(T object, Property property) { + principalMapper.setUnavailable(object, property); + + } + + public Collection getProperties(Collection object, Property bulkProperty, SnapshotDefinition def) { + return principalMapper.getProperties(object, bulkProperty, def); + } + + public boolean isBulkProperty(Class clazz, Property property) { + return principalMapper.isBulkProperty(clazz, property); + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java new file mode 100644 index 0000000000..5976aa2b57 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java @@ -0,0 +1,138 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.util.Collection; +import java.util.Iterator; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.PartialDataObject; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.SnapshotDefinition; +import com.agfa.hap.sdo.Type; + +/** + * @author awvjz + * + * this datamapper wraps another datamapper and delegates to this second mapper in case the object it has to work with are not partialdataobjects + * + */ +public class DelegatingPartialDataObjectMapper implements DataMapper { + private DataMapper delegate; + private PartialDataObjectMapper defaultMapper = new PartialDataObjectMapper(); + + public DelegatingPartialDataObjectMapper(DataMapper delegateDataMapper){ + delegate = delegateDataMapper; + } + + public T create(Type type) { + T instance = delegate.create(type); + if (instance == null){ + return (T) defaultMapper.create(type); + } + return instance; + } + + public Type getCorrespondingType(Class clazz) { + Type type = null; + try { + type = delegate.getCorrespondingType(clazz); + } catch (IllegalArgumentException e){ + //no type was found + } + if (type == null){ + return defaultMapper.getCorrespondingType(clazz); + } + return type; + } + + + public Object getProperty(T object, Property property) { + if (object instanceof PartialDataObject){ + return defaultMapper.getProperty((PartialDataObject) object, property); + } + return delegate.getProperty(object, property); + } + + + public T newProxy(Type type, Object identity) { + T proxy = delegate.newProxy(type, identity); + if (proxy == null){ + return (T) defaultMapper.newProxy(type, identity); + } + return proxy; + } + + + public Iterator getObjects(T object, Property property) { + if (object instanceof PartialDataObject){ + return (Iterator) defaultMapper.getObjects((PartialDataObject) object, property); + } + return delegate.getObjects(object, property); + } + + + public Type getType(T object) { + if (object instanceof PartialDataObject){ + return defaultMapper.getType((PartialDataObject) object); + } + return delegate.getType(object); + } + + + public boolean isProxy(T object) { + if (object instanceof PartialDataObject){ + return defaultMapper.isProxy((PartialDataObject) object); + } + return delegate.isProxy(object); + } + + + public void setProperty(T object, Property property, Object value) { + if (object instanceof PartialDataObject){ + defaultMapper.setProperty((PartialDataObject) object, property, value); + } else { + delegate.setProperty(object, property, value); + } + } + + + public void setUnavailable(T object, Property property) { + if (object instanceof PartialDataObject){ + defaultMapper.setUnavailable((PartialDataObject) object, property); + } else { + delegate.setUnavailable(object, property); + } + } + + public Collection getProperties(Collection object, Property bulkProperty, SnapshotDefinition def) { + return delegate.getProperties(object, bulkProperty, def); + } + + public boolean isBulkProperty(Class clazz, Property property) { + if (PartialDataObject.class.isAssignableFrom(clazz)) { + return false; + } + return delegate.isBulkProperty(clazz, property); + } + + + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java new file mode 100644 index 0000000000..f66d6899ca --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java @@ -0,0 +1,32 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; + +public class FalsePropertyAccessor extends AbstractPropertyAccessor { + + public Object getValue(Object instance, Property property, + DataMapper dataMapper) { + return Boolean.FALSE; + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java new file mode 100644 index 0000000000..15a7a2026e --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java @@ -0,0 +1,49 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import com.agfa.hap.sdo.PartialDataObject; +import com.agfa.hap.sdo.Type; + +/** + * ObjectMapper that always considers certain types to be proxies + * + */ +public class FilteringPartialDataObjectMapper extends PartialDataObjectMapper { + Set typesToConsiderAsProxies; + + public FilteringPartialDataObjectMapper(Collection typesToConsiderAsProxies){ + this.typesToConsiderAsProxies = new HashSet(typesToConsiderAsProxies); + } + + @Override + public boolean isProxy(PartialDataObject partialDataObject) { + if (typesToConsiderAsProxies.contains(partialDataObject.getType())){ + return true; + } + return super.isProxy(partialDataObject); + } + + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java new file mode 100644 index 0000000000..f2c78af410 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java @@ -0,0 +1,140 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.SnapshotDefinition; +import com.agfa.hap.sdo.Type; + +/** + * DataMapper that uses Java Bean conventions to access data on java classes. + * This mapper assumes that for each {@link Property} there are appropriately named + * accessors defined on the corresponding class. + * Each {@link Type} is mapped to the java class with the same name. It is also possible + * to register a class as corresponding to a type. + *

+ * This DataMapper ensures that opposite properties are properly filled in. As such, objects will + * not be added multiple times to a many-valued property if that property has an opposite property. + * @author AMOCZ + */ +public class JavaBeanMapper implements DataMapper { + + public JavaBeanMapper(TypeMapper typeMapper) { + this.typeMapper = typeMapper; + } + + public Iterator getObjects(Object object, Property property) { + PropertyAccessor propertyAccessor = typeMapper.property(object.getClass(), property); + if (propertyAccessor == null){ + throw new RuntimeException("no property accessor for sdo property " + property); + } + return ((Collection) propertyAccessor.getValue(object, property, this)).iterator(); + } + + public Object getProperty(Object object, Property property) { + PropertyAccessor propertyAccessor = typeMapper.property(object.getClass(), property); + if (propertyAccessor == null){ + throw new RuntimeException("no property accessor for sdo property " + property); + } + return propertyAccessor.getValue(object, property, this); + } + + public void setProperty(Object object, Property property, Object value) { + PropertyAccessor propertyAccessor = typeMapper.property(object.getClass(), property); + if (propertyAccessor == null){ + throw new RuntimeException("no property accessor for sdo property " + property); + } + propertyAccessor.setValue(object, property, value, this); + if (property.getOpposite() != null && value != null) { + setOpposite(object, property, value); + } + } + + protected void setOpposite(Object object, Property property, Object value) { + typeMapper.property(value.getClass(), property.getOpposite()).setValue(value, property.getOpposite(), object, this); + } + + public void setUnavailable(Object object, Property property) { + } + + public Type getType(Object object) { + return typeMapper.getCorrespondingType(object.getClass()); + } + + public Type getCorrespondingType(Class clazz) { + return typeMapper.getCorrespondingType(clazz); + } + + public TypeMapper getTypeMapper() { + return typeMapper; + } + + public Object create(Type type) { + Constructor constructor = typeMapper.getConstructor(type); + if (constructor == null){ + return null; + } + try { + return constructor.newInstance((Object[]) null); + } catch (InstantiationException e) { + throw new IllegalArgumentException("Unable to create new instance of bean class corresponding to " + type.getName(), e); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Unable to create new instance of bean class corresponding to " + type.getName(), e); + } catch (InvocationTargetException e) { + throw new IllegalArgumentException("Unable to create new instance of bean class corresponding to " + type.getName(), e); + } + } + + public Object newProxy(Type type, Object identity) { + return null; + } + + public boolean isProxy(Object instance) { + return false; + } + + + public Collection getProperties(Collection objects, Property bulkProperty, SnapshotDefinition def) { + Iterator it = objects.iterator(); + if (!it.hasNext()) { + return Collections.emptyList(); + } + return (Collection) typeMapper.property(it.next().getClass(), bulkProperty).getValues(objects, bulkProperty, def, this); + } + + public boolean isBulkProperty(Class clazz, Property property) { + PropertyAccessor propertyAccessor = typeMapper.property(clazz, property); + if (propertyAccessor == null){ + throw new RuntimeException("no property accessor for sdo property " + property); + } + return propertyAccessor.isBulkAccessor(); + } + + + private final TypeMapper typeMapper; + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java new file mode 100644 index 0000000000..d9a8a640dd --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java @@ -0,0 +1,44 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.util.Collection; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; + +public class ManyValuedBeanPropertyAccessor extends BeanPropertyAccessor { + + /** + * Sets the value of this property for the specified Object. + * @throws IllegalArgumentException + */ + public void setValue(Object instance, Property property, Object newValue, DataMapper dataMapper) { + Collection coll = (Collection) super.getValue(instance, property, dataMapper); + if (property.getOpposite() == null || !coll.contains(newValue)) { + coll.add(newValue); + } + } + + public void initialize(Object instance, Collection value) { + super.setValue(instance, null, value, null); + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java new file mode 100644 index 0000000000..2ed9a1ac58 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java @@ -0,0 +1,36 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; + +/** + * {@link PropertyAccessor} that allows returns null. + * @author AMOCZ + */ +public class NullPropertyAccessor extends AbstractPropertyAccessor { + + public Object getValue(Object instance, Property property, + DataMapper dataMapper) { + return null; + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java new file mode 100644 index 0000000000..ce4d446629 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java @@ -0,0 +1,97 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import sun.reflect.generics.reflectiveObjects.NotImplementedException; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.PartialDataFactory; +import com.agfa.hap.sdo.PartialDataObject; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.SnapshotDefinition; +import com.agfa.hap.sdo.Type; + +/** + * Default implementation that only support object that are instances + * of {@link PartialDataObject}. + * @author AMOCZ + */ +public class PartialDataObjectMapper implements DataMapper { + + @SuppressWarnings("unchecked") + public Iterator getObjects(PartialDataObject object, Property property) { + return object.getList(property).iterator(); + } + + public Object getProperty(PartialDataObject object, Property property) { + return object.get(property); + } + + public Type getType(PartialDataObject object) { + return object.getType(); + } + + public Type getCorrespondingType(Class clazz) { + throw new IllegalArgumentException("No sdo type for class " + clazz.getName()); + } + + public void setProperty(PartialDataObject object, Property property, Object value) { + if (property.isMany()) { + if (property.getOpposite() != null) { + ((PartialDataObject) value).set(property.getOpposite(), object); + } else { + object.getList(property).add(value); + } + } else { + object.set(property, value); + } + } + + public void setUnavailable(PartialDataObject object, Property property) { + object.setUnavailable(property); + } + + public PartialDataObject create(Type type) { + return PartialDataFactory.INSTANCE.create(type); + } + + public PartialDataObject newProxy(Type type, Object identity) { + return PartialDataFactory.INSTANCE.createProxy(type, identity); + } + + public boolean isProxy(PartialDataObject object) { + return object.isProxy(); + } + + public Collection getProperties(Collection object, Property bulkProperty, SnapshotDefinition def) { + throw new NotImplementedException(); + } + + public boolean isBulkProperty(Class clazz, Property property) { + return false; + } + + + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java new file mode 100644 index 0000000000..242d111f3f --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java @@ -0,0 +1,45 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.util.Collection; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.SnapshotDefinition; + +/** + * Interface that allows property values to be accessed in a generic way from any instance. + * Typically propertyaccessors will be registered in a sdo-propertyaccessors.properties file which is read by ExtendablePropertyAccessorBuilder + * + * To allow for efficient retrieval, some properties are always accessed in bulk. A typical + * example is a property for which a query needs to be made. + * + * @author AMOCZ + * + */ +public interface PropertyAccessor { + + Object getValue(Object instance, Property property, DataMapper dataMapper); + void setValue(Object instance, Property property, Object value, DataMapper dataMapper); + + boolean isBulkAccessor(); + Collection getValues(Collection instances, Property property, SnapshotDefinition def, DataMapper dataMapper); +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java new file mode 100644 index 0000000000..5a6627af14 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java @@ -0,0 +1,72 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.Type; + +/** + * Factory class to build a map containing all {@link PropertyAccessor} instances for a given class. + * @author AMOCZ + */ +public abstract class PropertyAccessorBuilder { + + public PropertyAccessorBuilder() { + this(null); + } + + public PropertyAccessorBuilder(PropertyAccessorBuilder next) { + this.next = next; + } + + public PropertyAccessor[] buildMap(Class cls, Type type) { + if (!accepts(cls, type)) { + return next == null ? null : next.buildMap(cls, type); + } + PropertyAccessor[] result = new PropertyAccessor[type.getProperties().size()]; + for (Property prop : type.getProperties()) { + PropertyAccessor property = createPropertyAccessor(cls, prop); + result[prop.getIndex()] = property; + } + return result; + } + + /** + * @return If this propertyAccessorBuilder can create propertyAccessors for this class/type + * combination. + */ + protected abstract boolean accepts(Class cls, Type type); + + protected abstract PropertyAccessor createPropertyAccessor(Class cls, Property property); + + protected PropertyAccessorBuilder next; + + public PropertyAccessor createPropertyAccessorOrDelegate(Class cls, Property property){ + if (this.accepts(cls, property.getContainingType())){ + return this.createPropertyAccessor(cls, property); + } else { + if (next == null){ + return null; + } + return next.createPropertyAccessor(cls, property); + } + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java new file mode 100644 index 0000000000..a62824a0f1 --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java @@ -0,0 +1,32 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import com.agfa.hap.sdo.DataMapper; +import com.agfa.hap.sdo.Property; + +public class TruePropertyAccessor extends AbstractPropertyAccessor { + + public Object getValue(Object instance, Property property, + DataMapper dataMapper) { + return true; + } + +} diff --git a/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java new file mode 100644 index 0000000000..40bc42443a --- /dev/null +++ b/sandbox/kgoodson/mappingFramework/sdo-snapshot/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java @@ -0,0 +1,100 @@ +/** + * + * 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 com.agfa.hap.sdo.mapper; + +import java.lang.reflect.Constructor; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.agfa.hap.sdo.Property; +import com.agfa.hap.sdo.Type; +import com.agfa.hap.sdo.helper.TypeHelper; + +/** + * Maps classes onto sdo Type instances. + *

+ * This implementation only on classes that are registered + * ({@see {@link #register(Class, String, String)}). + * + *

+ * This class is thread safe and can be concurrently accessed by multiple threads. + * @author AMOCZ + */ +public class TypeMapper { + + public TypeMapper() { + this(new BeanPropertyAccessorBuilder()); + } + + public TypeMapper(PropertyAccessorBuilder builder) { + this.propertyAccessorBuilder = builder; + } + + /** + * Locates a property accessor + */ + public PropertyAccessor property(Class cls, Property property) { + PropertyAccessor[] properties = buildMap(cls); + PropertyAccessor propertyAccessor = properties[property.getIndex()]; + if (propertyAccessor == null) { + throw new IllegalArgumentException("Can't access property " + property.getName() + " on " + cls.getName() + "."); + } + return propertyAccessor; + } + + private PropertyAccessor[] buildMap(Class cls) { + String clsName = cls.getName(); + PropertyAccessor[] props = keyedByPropertyNameCache.get(clsName); + if (props == null) { + // we don't care too much if it is computed more than once under some race conditions + props = propertyAccessorBuilder.buildMap(cls, getCorrespondingType(cls)); + keyedByPropertyNameCache.put(clsName, props); + } + return props; + } + + public Type getCorrespondingType(Class clazz) { + String[] exc = exceptions.get(clazz); + if (exc != null) { + return TypeHelper.INSTANCE.getType(exc[0], exc[1]); + } + return null; + } + + public void register(Class clazz, String uri, String typeName) { + exceptions.put(clazz, new String[] { uri, typeName }); + try { + factories.put(typeName, clazz.getConstructor((Class[]) null)); + } catch (SecurityException e) { + } catch (NoSuchMethodException e) { + } + } + + public Constructor getConstructor(Type type) { + return factories.get(type.getName()); + } + + private final Map> factories = new ConcurrentHashMap>(); + private final Map, String[]> exceptions = new ConcurrentHashMap, String[]>(); + private final Map keyedByPropertyNameCache = + new ConcurrentHashMap(); + protected final PropertyAccessorBuilder propertyAccessorBuilder; + +} -- cgit v1.2.3