diff options
author | dims <dims@13f79535-47bb-0310-9956-ffa450edef68> | 2008-06-17 00:23:01 +0000 |
---|---|---|
committer | dims <dims@13f79535-47bb-0310-9956-ffa450edef68> | 2008-06-17 00:23:01 +0000 |
commit | bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch) | |
tree | 38a92061c0793434c4be189f1d70c3458b6bc41d /sandbox/kgoodson/mappingFramework |
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sandbox/kgoodson/mappingFramework')
32 files changed, 2712 insertions, 0 deletions
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 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.tuscany.sdo</groupId>
+ <artifactId>tuscany-sdo-snapshot-framework</artifactId>
+ <name>Tuscany SDO Snapshot Framework</name>
+ <description>A framwork to support interconversion between
+ SDO and othe Java representations</description>
+ <version>kgoodson-sandbox</version>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.tuscany.sdo</groupId>
+ <artifactId>tuscany-sdo-impl</artifactId>
+ <version>1.0-incubating</version>
+ <scope>compile</scope>
+ </dependency>
+
+
+ <!-- dependencies for test cases -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8</version>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
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 <T> Snapshot createSnapShot(DataMapper<T> mapper, SnapshotDefinition def, T root) {
+ List<T> roots = new ArrayList<T>(1);
+ roots.add(root);
+ return new SnapshotImplementation(mapper, def, roots);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> Snapshot createMultiSnapShot(SnapshotDefinition def, Collection<? extends T> root) {
+ return createMultiSnapShot((DataMapper<T>) MAPPER, def, root);
+ }
+
+ public static <T> Snapshot createMultiSnapShot(DataMapper<T> mapper, SnapshotDefinition def, Collection<? extends T> 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> T getRootObject(DataMapper<T> mapper, Snapshot s) {
+ List<T> 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<PartialDataObject> getRootObjects(Snapshot s) {
+ return getRootObjects(MAPPER, s);
+ }
+
+ public static <T> List<T> getRootObjects(DataMapper<T> mapper, Snapshot s) {
+ return s.extract(mapper);
+ }
+
+ public static <T> Iterator<T> rootObjectsIterator(DataMapper<T> 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<T> {
+
+ /**
+ * @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<? extends T> 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<T> getProperties(Collection<T> 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<T> {
+
+ /**
+ * @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<Property, PropertyTree> properties;
+ private Type type;
+
+ public MapBasedPropertyTree(Type type) {
+ this.type = type;
+ properties = new HashMap<Property, PropertyTree>();
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public Set<Entry<Property, PropertyTree>> 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<String> propertyPaths() {
+ Collection<String> paths = new ArrayList<String>();
+ for (Entry<Property, PropertyTree> entry : this.getProperties()){
+ String rootPropName = entry.getKey().getName();
+ MapBasedPropertyTree tree = (MapBasedPropertyTree) entry.getValue();
+ Collection<String> 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 <T> void visit(DataMapper<T> 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<? extends T> 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 <T> void visitChild(DataMapper<T> 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.
+ * <p />
+ * 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}.
+ * <p />
+ * 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.
+ * <p />
+ * 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 <T> void visit(DataMapper<T> mapper, ObjectPropertyVisitor visitor, T dataObject) throws Exception {
+ visit(mapper, visitor, dataObject, propertyTree);
+ }
+
+ private <T> void visit(DataMapper<T> 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 <T> void visitProxy(DataMapper<T> 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 <T> void visitChildObject(DataMapper<T> 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<? extends T> it = mapper.getObjects(dataObject, property);
+ while (it.hasNext()) {
+ visitChild(mapper, visitor, dataObject, property, it.next(), tree);
+ }
+ } else {
+ visitChild(mapper, visitor, dataObject, property, tree);
+ }
+ }
+
+ protected <T> void visitChild(DataMapper<T> 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 <T> void visitChild(DataMapper<T> 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}.
+ * <br />
+ * 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()}).
+ * <br />
+ * 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.
+ * <br />
+ * <strong>Warning:</strong>
+ * 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.
+ */
+ <T> List<T> extract(DataMapper<T> 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
+ */
+ <T> void visit(DataMapper<T> 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<byte[]>{
+ //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<T extends Enum> extends TypeConverter<T> {
+
+ private Class<T> enumClazz;
+
+ public EnumTypeConverter(Class<T> enumClazz) {
+ this.enumClazz = enumClazz;
+ }
+
+ @Override
+ public T parse(String str) {
+ return Enum.<T>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<Serializable> {
+
+ @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.
+ * <P>
+ * A custom sdo basic type can register an appropriate typeConverter.
+ */
+public abstract class TypeConverter<T> {
+
+ /**
+ * 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 <U> TypeConverter<U> 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 <T> TypeConverter<T> getDefaultConverter(Class<T> clazz) {
+ if (clazz.isEnum()) {
+ return new EnumTypeConverter(clazz);
+ }
+ if (Serializable.class.isAssignableFrom(clazz)) {
+ return (TypeConverter<T>) new SerializableTypeConverter();
+ }
+ return null;
+ }
+
+ private static Map<Type, TypeConverter> registry = new ConcurrentHashMap<Type, TypeConverter>();
+}
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 <T> SnapshotImplementation(DataMapper<T> mapper, SnapshotDefinition definition, Collection<? extends T> roots) {
+ buildSerializedContent(mapper, definition, roots);
+ }
+
+ public <T> List<T> extract(DataMapper<T> mapper) {
+ return extractRoots(mapper);
+ }
+
+ private <T> List<T> extractRoots(DataMapper<T> mapper) {
+ ByteArrayInputStream bis = new ByteArrayInputStream(serializedContent);
+ DataInputStream dis = new DataInputStream(bis);
+ SnapshotSerializer<T> serializer = new SnapshotSerializer<T>(mapper);
+ try {
+ return serializer.read(dis);
+ } catch (IOException e) {
+ throw new SdoImplementationException(e);
+ }
+ }
+
+ private <T> void buildSerializedContent(DataMapper<T> mapper, SnapshotDefinition definition, Collection<? extends T> targets) {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(bos);
+ SnapshotSerializer<T> serializer = new SnapshotSerializer<T>(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<T> implements ObjectPropertyVisitor {
+ //protected visibility for testing purposes
+ public static final int MAX_UTF_LENGTH = 65535;
+ private DataOutput out;
+ private DataMapper<T> mapper;
+ private List<Object> serializedObjects;
+ private Map<Property, BulkProperty<T>> bulkProperties;
+
+ public SnapshotSerializer(DataMapper<T> mapper) {
+ this.mapper = mapper;
+ }
+
+ protected T create(Type type) {
+ T result = mapper.create(type);
+ serializedObjects.add(result);
+ return result;
+ }
+
+ public List<T> read(DataInput in) throws IOException {
+ this.serializedObjects = new ArrayList<Object>();
+ return readFromStream(in);
+ }
+
+ private List<T> readFromStream(DataInput in) throws IOException {
+ int nrOfObjects = in.readInt();
+ if (nrOfObjects < 1){
+ return new ArrayList<T>();
+ }
+ List<T> result = basicReadFromStream(in, nrOfObjects);
+ readBulkProperties(in);
+ return result;
+ }
+
+ private List<T> basicReadFromStream(DataInput in, int nrOfObjects) throws IOException {
+ List<T> result = new ArrayList<T>(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<? extends T> roots, DataOutput out) throws Exception {
+ this.out = out;
+ this.serializedObjects = new ArrayList<Object>();
+ 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<T> bp) throws Exception {
+ Collection<T> values = this.mapper.getProperties(bp.instances, bp.property, bp.subselect);
+ Iterator<T> valuesIt = values.iterator();
+ Iterator<?> parents = bp.instances.iterator();
+ while (parents.hasNext()) {
+ Object parent = parents.next();
+ T value = valuesIt.next();
+ if (bp.property.isMany()) {
+ Collection<T> children = (Collection<T>) 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<T> getInstancesForBulkProperty(Property property, SnapshotDefinition subselect) {
+ if (bulkProperties == null) {
+ bulkProperties = new HashMap<Property, BulkProperty<T>>();
+ }
+ BulkProperty<T> bp = bulkProperties.get(property);
+ if (bp == null) {
+ bp = new BulkProperty<T>(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<T> {
+ BulkProperty(Property property, SnapshotDefinition subselect) {
+ this.property = property;
+ this.subselect = subselect;
+ this.instances = new ArrayList<T>();
+ }
+ Property property;
+ List<T> 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<Snapshot> snapshots;
+
+ public SnapshotUnion(Collection<Snapshot> 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 <T> List<T> extract(DataMapper<T> mapper) {
+ List<T> extraction = new ArrayList<T>();
+ 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<T> implements DataMapper<T> {
+
+ private DataMapper<T> principalMapper;
+ private DataMapper<T> secondaryMapper;
+
+ public DelegatingDataMapper(DataMapper<T> principalMapper, DataMapper<T> 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<? extends T> 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<T> getProperties(Collection<T> 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<T> implements DataMapper<T> {
+ private DataMapper<T> delegate;
+ private PartialDataObjectMapper defaultMapper = new PartialDataObjectMapper();
+
+ public DelegatingPartialDataObjectMapper(DataMapper<T> 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<? extends T> getObjects(T object, Property property) {
+ if (object instanceof PartialDataObject){
+ return (Iterator<? extends T>) 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<T> getProperties(Collection<T> 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<Type> typesToConsiderAsProxies;
+
+ public FilteringPartialDataObjectMapper(Collection<Type> typesToConsiderAsProxies){
+ this.typesToConsiderAsProxies = new HashSet<Type>(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.
+ * <p/>
+ * 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<Object> {
+
+ 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<Object> getProperties(Collection<Object> objects, Property bulkProperty, SnapshotDefinition def) {
+ Iterator<Object> it = objects.iterator();
+ if (!it.hasNext()) {
+ return Collections.emptyList();
+ }
+ return (Collection<Object>) 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<Object> coll = (Collection<Object>) super.getValue(instance, property, dataMapper);
+ if (property.getOpposite() == null || !coll.contains(newValue)) {
+ coll.add(newValue);
+ }
+ }
+
+ public void initialize(Object instance, Collection<Object> 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<PartialDataObject> {
+
+ @SuppressWarnings("unchecked")
+ public Iterator<PartialDataObject> 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<PartialDataObject> getProperties(Collection<PartialDataObject> 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.
+ * <P/>
+ * This implementation only on classes that are registered
+ * ({@see {@link #register(Class, String, String)}).
+ *
+ * <P />
+ * 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<String, Constructor<?>> factories = new ConcurrentHashMap<String, Constructor<?>>();
+ private final Map<Class<?>, String[]> exceptions = new ConcurrentHashMap<Class<?>, String[]>();
+ private final Map<String, PropertyAccessor[]> keyedByPropertyNameCache =
+ new ConcurrentHashMap<String, PropertyAccessor[]>();
+ protected final PropertyAccessorBuilder propertyAccessorBuilder;
+
+}
|