summaryrefslogtreecommitdiffstats
path: root/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src')
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataAccessService.java64
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataMapper.java90
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectFactory.java17
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java29
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataFactory.java25
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataObject.java81
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Property.java56
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyNotAvailableException.java21
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyTree.java236
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java56
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SelectClause.java173
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Snapshot.java44
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java18
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Type.java50
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/core/IDataObjectService.java10
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/TypeHelper.java33
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/XsdScanner.java78
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java32
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java11
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java21
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/HelperProviderImpl.java114
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SdoImplementationFactory.java58
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java42
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java58
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeProvider.java29
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/XsdTypeProvider.java43
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractDataObject.java560
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractPartialDataObject.java211
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BinarySerializer.java115
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BulkProperty.java18
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ClassPathImplementationClassRepository.java46
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/CompleteSerializer.java74
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainedDataObject.java13
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainmentSerializer.java71
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataFactoryImpl.java52
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataGraphImplementation.java51
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectConverter.java147
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectHelper.java61
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectImplementation.java56
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectList.java131
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectStreamer.java178
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectXmlParser.java146
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/EqualityHelperImpl.java135
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/IDataObjectList.java10
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ImplementationClassRepository.java129
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/PropertyImplementation.java138
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SdoImplementationException.java26
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java377
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java36
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeHelperImpl.java435
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeImplementation.java267
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLDocumentImpl.java85
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLHelperImpl.java102
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XSDHelperImpl.java616
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java35
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java79
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java62
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java71
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java119
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilder.java75
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java13
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java30
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java125
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java25
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedNullPropertyAccessor.java23
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java17
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java77
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java26
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java53
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java13
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java81
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/CatalogIdentity.java51
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/Identity.java60
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/LongIdentity.java24
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/ObjectReference.java105
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/StringIdentity.java14
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/BundleClassHolder.java28
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/OsgiBasedImplementationClassRepository.java84
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/SdoActivator.java90
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassForNameClassHolder.java24
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassHolder.java14
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassLoaderBasedClassHolder.java24
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ResultSet.java133
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/ChangeSummary.java207
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataGraph.java76
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataObject.java1121
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Property.java121
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Sequence.java140
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Type.java166
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/CopyHelper.java85
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataFactory.java64
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataHelper.java214
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/EqualityHelper.java92
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/HelperContext.java67
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/TypeHelper.java96
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLDocument.java155
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLHelper.java202
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XSDHelper.java196
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/ExternalizableDelegator.java90
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/HelperProvider.java175
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/license.txt33
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/datagraph.xsd81
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xml53
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xsd88
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xml92
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xsd221
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xml40
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xsd56
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/configuration/config.ini6
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/BytesTypeConverterTest.java24
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/TestLongUTFSerialization.java56
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilderTest.java30
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/DummyPropertyAccessor.java14
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilderTest.java20
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/SomePojo.java26
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Sub.java13
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Super.java13
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/A.java91
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/B.java41
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/C.java42
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/DataObjectCreator.java26
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ExampleEnum.java7
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/FilteringPartialDataObjectMapperTest.java78
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/InheritedB.java14
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObject.java14
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObjectTypeConverter.java26
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ResultSetTest.java101
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SdoTestUtil.java30
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SerializableBasicObject.java23
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SomeType.java192
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestBulkProperties.java292
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDataObjectImpl.java173
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDefineTypeWithDataObject.java54
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEmptySnapshot.java18
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEqualityHelper.java76
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestObjectSnapShot.java148
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestPartialDataObject.java131
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestScanner.java23
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClause.java147
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClauseSnapshotSerialization.java129
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSerialization.java76
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshot.java194
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshotUnion.java54
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestTypeHelper.java124
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXMLHelper.java144
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXSDHelper.java179
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXsdHelperMultipleURI.java33
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithId.java26
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithoutId.java13
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo-propertyaccessors.properties1
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/implementationclasses.properties1
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/scanner/scan-types.xsd12
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-basictypes.xsd25
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-selectclause.xsd45
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types-forward.xsd18
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types.xsd64
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types1.xsd13
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types2.xsd11
-rw-r--r--sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-userrole-types.xsd18
159 files changed, 14410 insertions, 0 deletions
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataAccessService.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataAccessService.java
new file mode 100644
index 0000000000..4797db417f
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataAccessService.java
@@ -0,0 +1,64 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataMapper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataMapper.java
new file mode 100644
index 0000000000..e0987c72f4
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/DataMapper.java
@@ -0,0 +1,90 @@
+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.
+ * returns an "empty" iterator in case the property is null
+ * (SDO doesn't have the concept of a many valued property that can be null)
+ */
+ 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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectFactory.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectFactory.java
new file mode 100644
index 0000000000..dfdd865670
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectFactory.java
@@ -0,0 +1,17 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java
new file mode 100644
index 0000000000..e64a2eab6e
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ObjectPropertyVisitor.java
@@ -0,0 +1,29 @@
+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;
+ /**
+ * @param instance
+ * @param property
+ * @param value
+ * @return true if value can be further visited recursively
+ * @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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataFactory.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataFactory.java
new file mode 100644
index 0000000000..6568b0e4dc
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataFactory.java
@@ -0,0 +1,25 @@
+package com.agfa.hap.sdo;
+
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+
+/**
+ * DataFactory that creates {@link PartialDataObject} instances.
+ * @author AMOCZ
+ */
+public interface PartialDataFactory extends DataFactory {
+
+ PartialDataObject create(Type type);
+
+ PartialDataObject create(String uri, String typeName);
+
+ PartialDataObject createProxy(Type type, Object identity);
+
+ PartialDataObject createProxy(String uri, String typeName, Object identity);
+
+ /**
+ * The default PartialDataFactory.
+ */
+ PartialDataFactory INSTANCE = (PartialDataFactory) DataFactory.INSTANCE;
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataObject.java
new file mode 100644
index 0000000000..f837dcbd9b
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PartialDataObject.java
@@ -0,0 +1,81 @@
+package com.agfa.hap.sdo;
+
+import commonj.sdo.DataObject;
+
+/**
+ * HAP-specific extension to {@link commonj.sdo.DataObject}.
+ *
+ * A {@link DataObject} of which only a subset of its properties
+ * are available. Getting or setting a property which is not available
+ * results in an {@link PropertyNotAvailableException} being thrown.
+ * <br />
+ * A PartialDataObject that only has its identity property available is called a
+ * <i>proxy</i>.
+ * <br />
+ * PartialDataObjects are typically used (1) to allow dataobjects to have only a subset of their
+ * many-valued properties available and (2) to enable data object proxies.
+ * <br />
+ * Properties that are not available are also not set (i.e. {@link
+ * DataObject#isSet(int)} return false).
+ *
+ * @see Snapshot
+ * @author AMOCZ
+ */
+public interface PartialDataObject extends commonj.sdo.DataObject {
+
+ boolean isAvailable(commonj.sdo.Property property);
+
+ /**
+ * Strips the property such that is no longer available.
+ */
+ void setUnavailable(commonj.sdo.Property property);
+
+ /**
+ * @return If this data object is a proxy. Proxies only have their identity property
+ * available.
+ */
+ boolean isProxy();
+
+ /**
+ * Marker value for unavailable properties
+ */
+ public static final Object UNAVAILABLE_PROPERTY = new Object();
+
+ /**
+ * @return The value of the {@link Type#getIdentityProperty() identity property} for this
+ * instance.
+ */
+ Object getIdentity();
+
+ /**
+ * Sets the value of the {@link Type#getIdentityProperty() identity property} for this
+ * instance.
+ */
+ void setIdentity(Object object);
+
+ Type getType();
+
+ Property getContainmentProperty();
+
+ PartialDataObject getContainer();
+
+ PartialDataObject getDataObject(String name);
+
+ PartialDataObject getDataObject(commonj.sdo.Property property);
+
+ PartialDataObject getDataObject(int index);
+
+ PartialDataObject createDataObject(String name);
+
+ PartialDataObject createDataObject(int index);
+
+ PartialDataObject createDataObject(commonj.sdo.Property property);
+
+ PartialDataObject createDataObject(String propertyName, String namespaceURI, String typeName);
+
+ PartialDataObject createDataObject(int propertyIndex, String namespaceURI, String typeName);
+
+ PartialDataObject createDataObject(commonj.sdo.Property property, commonj.sdo.Type type);
+
+}
+
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Property.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Property.java
new file mode 100644
index 0000000000..54219f2c7d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Property.java
@@ -0,0 +1,56 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.0
+ * Licensed Materials - Property of BEA and IBM
+ *
+ * (c) Copyright BEA Systems, Inc. and International Business Machines Corp 2005. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package com.agfa.hap.sdo;
+
+import java.util.List;
+
+/**
+ * A representation of a Property in the {@link Type type} of a {@link DataObject data object}.
+ *
+ * We extend {@link commonj.sdo.Property} to have type safety (through generics) and to
+ * add functionality such as {@link #getIndex()}.
+ */
+public interface Property extends commonj.sdo.Property {
+
+ /**
+ * Returns the type of the Property.
+ * @return the Property type.
+ */
+ Type getType();
+
+ /**
+ * Returns the containing type of this Property.
+ * @return the Property's containing type.
+ * @see Type#getProperties()
+ */
+ Type getContainingType();
+
+ /**
+ * Returns the opposite Property if the Property is bi-directional or null otherwise.
+ * @return the opposite Property if the Property is bi-directional or null
+ */
+ Property getOpposite();
+
+ /**
+ * Return a list of alias names for this Property.
+ * @return a list of alias names for this Property.
+ */
+ List<String> getAliasNames();
+
+ /**
+ * Return the index in the list of properties of its containingtype.
+ * @return
+ */
+ int getIndex();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyNotAvailableException.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyNotAvailableException.java
new file mode 100644
index 0000000000..0003d2e4ae
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyNotAvailableException.java
@@ -0,0 +1,21 @@
+package com.agfa.hap.sdo;
+
+
+import commonj.sdo.Property;
+
+/**
+ * Exception throw when a property that is not filled in in accessed
+ * on a {@link ProxyDataObject}.
+ * @author AMOCZ
+ *
+ */
+public class PropertyNotAvailableException extends RuntimeException {
+
+ private static final long serialVersionUID = -1662462690347023219L;
+
+ public PropertyNotAvailableException(PartialDataObject source, Property prop) {
+ super("Property " + prop.getName() + " is not available on this instance of " + source.getType().getName()
+ + (source.getType().getIdentityProperty()==null?" id=null":" id=" + source.getIdentity()));
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyTree.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyTree.java
new file mode 100644
index 0000000000..f004276658
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/PropertyTree.java
@@ -0,0 +1,236 @@
+/**
+ *
+ */
+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(){
+ Collection<String> propertyPaths = this.propertyPaths();
+ if (propertyPaths.isEmpty()){
+ return "";
+ }
+ StringBuilder builder = new StringBuilder();
+ for(String path : 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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java
new file mode 100644
index 0000000000..919f68c98d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/ReachableDefinition.java
@@ -0,0 +1,56 @@
+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
+ */
+@Deprecated
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SelectClause.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SelectClause.java
new file mode 100644
index 0000000000..80457010af
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SelectClause.java
@@ -0,0 +1,173 @@
+package com.agfa.hap.sdo;
+
+import java.util.Iterator;
+
+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()) {
+ if (property.isMany()){
+ Iterator<? extends T> it = mapper.getObjects(dataObject, property);
+ while (it.hasNext()) {
+ visitChild(mapper, visitor, dataObject, property, it.next(), null);
+ }
+ } else {
+ 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);
+ }
+
+ /**
+ * this method is called if the property is not in the select clause
+ * when used with the default SnapshotSerializer :
+ * returning directly will result in property with value = null,
+ * calling visitProxyProperty with a null identity will result in a not available property
+ * calling visitProxyProperty with a non null identity will result in a property with isProxy=true
+ * @param <T>
+ * @param mapper
+ * @param visitor
+ * @param dataObject
+ * @param property
+ * @throws Exception
+ */
+ protected <T> void visitProxy(DataMapper<T> mapper, ObjectPropertyVisitor visitor, T dataObject, Property property) throws Exception {
+ if (property.isMany()) {
+ visitor.visitProxyProperty(dataObject, property, null); //result -> property not available
+ return;
+ }
+ Property idProp = property.getType().getIdentityProperty();
+ if (idProp == null) {
+ visitor.visitProxyProperty(dataObject, property, null); //result -> property not available
+ return;
+ }
+ T child = (T) mapper.getProperty(dataObject, property);
+ if (child == null) {
+ return; //result -> property null
+ }
+ Object identity = mapper.getProperty(child, idProp);
+ if (identity == null) {
+ visitor.visitProxyProperty(dataObject, property, null);
+ return; // link doesn't have an identity, so one could argue that it does not really exist and therefore the property should be null
+ // but this would not be consistent with the nonproxy case : there we treat it as a normal property
+ // also, this seems to be the most convenient choice for agility ris (ProcedureDefinitionType of qdoc requested procedures)
+ //result -> property not available
+ }
+ 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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Snapshot.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Snapshot.java
new file mode 100644
index 0000000000..35e22d869d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Snapshot.java
@@ -0,0 +1,44 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java
new file mode 100644
index 0000000000..ed9ea88fdd
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/SnapshotDefinition.java
@@ -0,0 +1,18 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Type.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Type.java
new file mode 100644
index 0000000000..a3c0813c10
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/Type.java
@@ -0,0 +1,50 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.0
+ * Licensed Materials - Property of BEA and IBM
+ *
+ * (c) Copyright BEA Systems, Inc. and International Business Machines Corp 2005. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package com.agfa.hap.sdo;
+
+import java.util.List;
+
+/**
+ * A representation of the type of a {@link Property property} of a {@link DataObject data object}.
+ *
+ * We extend the standard sdo type to have a more type-safe (generics) interface and to add
+ * specific functionality such as the {@link #getIdentityProperty()}.
+ *
+ * @see com.agfa.hap.sdo.helper.TypeHelper
+ * @see commonj.sdo.Type
+ */
+public interface Type extends commonj.sdo.Type {
+
+ /**
+ * This is a non-standard SDO property (but rumors are that is will appear in SDO2.1).
+ * The identity property typically maps on the ID attribute in xml.
+ * @return the identity property. This property can be used to distinguish a DataObject
+ * from all other DataObject having the same type.
+ */
+ Property getIdentityProperty();
+
+ // improve type safety
+
+ List<Property> getProperties();
+
+ Property getProperty(String propertyName);
+
+ Property getProperty(int index);
+
+ List<? extends Type> getBaseTypes();
+
+ List<? extends Property> getDeclaredProperties();
+
+ List<String> getAliasNames();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/core/IDataObjectService.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/core/IDataObjectService.java
new file mode 100644
index 0000000000..f7cd42b7b5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/core/IDataObjectService.java
@@ -0,0 +1,10 @@
+package com.agfa.hap.sdo.core;
+
+public interface IDataObjectService {
+
+ /**
+ * Returns an xsd defining the types for this uri.
+ */
+ String getTypes(String uri);
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/TypeHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/TypeHelper.java
new file mode 100644
index 0000000000..a418243edb
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/TypeHelper.java
@@ -0,0 +1,33 @@
+package com.agfa.hap.sdo.helper;
+
+import com.agfa.hap.sdo.Type;
+
+
+/**
+ * Redefinition of {@link commonj.sdo.helper.TypeHelper} to provide type-safe
+ * access to types.
+ * @author AMOCZ
+ * @see commonj.sdo.helper.TypeHelper
+ */
+public interface TypeHelper extends commonj.sdo.helper.TypeHelper {
+
+ /**
+ * Return the Type specified by typeName with the given uri,
+ * or null if not found.
+ * @param uri The uri of the Type - type.getURI();
+ * @param typeName The name of the Type - type.getName();
+ * @return the Type specified by typeName with the given uri,
+ * or null if not found.
+ */
+ Type getType(String uri, String typeName);
+
+ /**
+ * Return the Type for this interfaceClass or null if not found.
+ * @param interfaceClass is the interface for the DataObject's Type -
+ * type.getInstanceClass();
+ * @return the Type for this interfaceClass or null if not found.
+ */
+ Type getType(Class interfaceClass);
+
+ TypeHelper INSTANCE = (TypeHelper) commonj.sdo.helper.TypeHelper.INSTANCE;
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/XsdScanner.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/XsdScanner.java
new file mode 100644
index 0000000000..9dc88ab9b7
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/helper/XsdScanner.java
@@ -0,0 +1,78 @@
+package com.agfa.hap.sdo.helper;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Enumeration;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import commonj.sdo.helper.XSDHelper;
+
+/**
+ * This class scans the classpath for all sdo/*.xsd files and registers them
+ * using the type helper.
+ * @author AMOCZ
+ */
+public class XsdScanner {
+
+ private static final String ENCODING_NAME = System.getProperty("file.encoding");
+
+ private ClassLoader classLoader;
+
+ public XsdScanner(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public void scanClassPath(String path) throws IOException {
+ for (Enumeration<URL> e = classLoader.getResources(path); e.hasMoreElements();) {
+ URL next = e.nextElement();
+ String file = URLDecoder.decode(next.getFile(), ENCODING_NAME);
+ if ("jar".equals(next.getProtocol()) && file.startsWith("file:/")) {
+ scanArchive(file);
+ } else if ("file".equals(next.getProtocol())){
+ File classInfoDircectory = new File(file);
+ scanDirectory(classInfoDircectory);
+ }
+ }
+ }
+
+ protected void scanArchive(String file) throws IOException {
+ int exclamation = file.indexOf('!');
+ String library = file.substring(0, exclamation);
+ JarInputStream jar = new JarInputStream(new URL(library).openStream());
+ while (true) {
+ JarEntry nextEntry = jar.getNextJarEntry();
+ if (nextEntry == null) {
+ break;
+ }
+ String nextEntryName = nextEntry.getName();
+ if (nextEntryName.endsWith(".xsd")) {
+ URL url = classLoader.getResource(nextEntryName);
+ read(url.openStream());
+ }
+ }
+ }
+
+ protected void scanDirectory(File dir) throws IOException {
+ File[] files = dir.listFiles(new FileFilter() {
+ public boolean accept(File pathname) {
+ return pathname.getName().endsWith(".xsd");
+ }
+ });
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ read(new FileInputStream(files[i]));
+ }
+ }
+ }
+
+
+ protected void read(InputStream is) {
+ XSDHelper.INSTANCE.define(is, null);
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java
new file mode 100644
index 0000000000..a6590762aa
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/BytesTypeConverter.java
@@ -0,0 +1,32 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java
new file mode 100644
index 0000000000..15f8c942c9
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/DataAccessService.java
@@ -0,0 +1,11 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java
new file mode 100644
index 0000000000..f4fc3b012e
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/EnumTypeConverter.java
@@ -0,0 +1,21 @@
+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 (T) Enum.<T>valueOf(enumClazz, str);
+ }
+
+ @Override
+ public String toString(T instance) {
+ return instance.name();
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/HelperProviderImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/HelperProviderImpl.java
new file mode 100644
index 0000000000..1ea8e000d9
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/HelperProviderImpl.java
@@ -0,0 +1,114 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.0
+ * Licensed Materials - Property of BEA and IBM
+ *
+ * (c) Copyright BEA Systems, Inc. and International Business Machines Corp 2005. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package com.agfa.hap.sdo.impl;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.implementation.ContainmentSerializer;
+import com.agfa.hap.sdo.implementation.DataFactoryImpl;
+import com.agfa.hap.sdo.implementation.EqualityHelperImpl;
+import com.agfa.hap.sdo.implementation.TypeHelperImpl;
+import com.agfa.hap.sdo.implementation.XMLHelperImpl;
+import com.agfa.hap.sdo.implementation.XSDHelperImpl;
+import commonj.sdo.helper.CopyHelper;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.DataHelper;
+import commonj.sdo.helper.EqualityHelper;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XMLHelper;
+import commonj.sdo.helper.XSDHelper;
+import commonj.sdo.impl.ExternalizableDelegator.Resolvable;
+
+/**
+ * This class instantiates a HelperProviderImpl that returns concrete helpers.
+ * This class may be replaced by another implementation.
+ * <p>
+ * The current implementation tries to instantiate an instance of the class
+ * defined by the <i>commonj.sdo.helperprovider</i> system property. If that
+ * doesn't work it tries to instantiate an instance of
+ * <i>com.agfa.ris.client.sdo.impl.HelperProviderImpl</i>. If that doesn't work
+ * it tries <i>com.agfa.ris.server.sdo.HelperProviderImpl</i>. If all fails, it
+ * just uses {@link HelperProviderImpl}.
+ */
+public class HelperProviderImpl extends commonj.sdo.impl.HelperProvider {
+
+ protected TypeHelper typeHelper;
+ protected XSDHelper xsdHelper;
+ protected XMLHelper xmlHelper;
+ protected DataFactory dataFactory;
+ protected EqualityHelper equalityHelper;
+
+ protected HelperProviderImpl() {
+ typeHelper = createTypeHelper();
+ xsdHelper = createXSDHelper();
+ xmlHelper = createXMLHelper();
+ dataFactory = createDataFactory();
+ equalityHelper = createEqualityHelper();
+ }
+
+ protected EqualityHelper createEqualityHelper() {
+ return new EqualityHelperImpl();
+ }
+
+ protected DataFactory createDataFactory() {
+ return new DataFactoryImpl();
+ }
+
+ protected XMLHelper createXMLHelper() {
+ return new XMLHelperImpl();
+ }
+
+ protected XSDHelper createXSDHelper() {
+ return new XSDHelperImpl();
+ }
+
+ protected TypeHelper createTypeHelper() {
+ return new TypeHelperImpl();
+ }
+
+ protected CopyHelper copyHelper() {
+ return null;
+ }
+
+ protected DataFactory dataFactory() {
+ return dataFactory;
+ }
+
+ protected DataHelper dataHelper() {
+ return null;
+ }
+
+ protected EqualityHelper equalityHelper() {
+ return equalityHelper;
+ }
+
+ protected TypeHelper typeHelper() {
+ return typeHelper;
+ }
+
+ protected XMLHelper xmlHelper() {
+ return xmlHelper;
+ }
+
+ protected XSDHelper xsdHelper() {
+ return xsdHelper;
+ }
+
+ protected Resolvable resolvable() {
+ return new ContainmentSerializer();
+ }
+
+ protected Resolvable resolvable(Object target) {
+ return new ContainmentSerializer((PartialDataObject) target);
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SdoImplementationFactory.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SdoImplementationFactory.java
new file mode 100644
index 0000000000..ea1c5c7d02
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SdoImplementationFactory.java
@@ -0,0 +1,58 @@
+package com.agfa.hap.sdo.impl;
+
+import org.apache.log4j.Logger;
+
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * Class that is responsible for finding and choosing the correct SDO implementation.
+ * @author AMOCZ
+ */
+public class SdoImplementationFactory {
+
+ private static Class<? extends HelperProvider> implementationClass;
+
+ /**
+ * Use this to inject a suitable implementation class. This must happen BEFORE
+ * the sdo system is initialized.
+ * @param implementationClass
+ */
+ public static void setImplementationClass(Class<? extends HelperProvider> implementationClass) {
+ SdoImplementationFactory.implementationClass = implementationClass;
+ }
+
+ public static HelperProvider getHelperProviderImplementation() {
+ Logger logger = Logger.getLogger(SdoImplementationFactory.class);
+ try {
+ if (implementationClass != null) {
+ return implementationClass.newInstance();
+ }
+ String helperProviderClassname = System.getProperty("commonj.sdo.helperprovider",
+ "com.agfa.hap.rcp.sdo.impl.HelperProviderImpl");
+ try {
+ logger.debug("trying to load " + helperProviderClassname);
+ return (HelperProviderImpl) Class.forName(helperProviderClassname).newInstance();
+ } catch (ClassNotFoundException cnfe) {
+ try {
+ // client-side try contextclassloader as well -- this is
+ // needed for maven build
+ logger.debug("trying to load " + helperProviderClassname
+ + " through the contextclassloader");
+ return (HelperProviderImpl) Class.forName(
+ helperProviderClassname, true,
+ Thread.currentThread().getContextClassLoader())
+ .newInstance();
+ } catch (ClassNotFoundException e) {
+ logger
+ .debug("trying to load com.agfa.ris.server.sdo.HelperProviderImpl");
+ return (HelperProviderImpl) Class.forName("com.agfa.ris.server.sdo.HelperProviderImpl")
+ .newInstance();
+ }
+ }
+ } catch (Exception e) {
+ logger.warn("unable to load a special helperprovider, fallback to the default one", e);
+ return new HelperProviderImpl();
+ }
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java
new file mode 100644
index 0000000000..1956b151a5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/SerializableTypeConverter.java
@@ -0,0 +1,42 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java
new file mode 100644
index 0000000000..28f57600e6
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeConverter.java
@@ -0,0 +1,58 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeProvider.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeProvider.java
new file mode 100644
index 0000000000..a3bf901a81
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/TypeProvider.java
@@ -0,0 +1,29 @@
+package com.agfa.hap.sdo.impl;
+
+import commonj.sdo.impl.HelperProvider;
+
+
+public abstract class TypeProvider {
+
+ public static TypeProvider getInstance() {
+ if (instance == null) {
+ //TODO review is this still needed?
+ // force initialization of HelperProvider
+ HelperProvider.getTypeHelper();
+ }
+ return instance;
+ }
+
+ private static TypeProvider instance;
+
+ public static void setInstance(TypeProvider provider) {
+ instance = provider;
+ }
+
+ /**
+ * Returns the xsd describing the types for this uri.
+ * If the uri can't be interpreted, returns null.
+ */
+ public abstract String getTypes(String uri);
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/XsdTypeProvider.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/XsdTypeProvider.java
new file mode 100644
index 0000000000..f2423447d3
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/impl/XsdTypeProvider.java
@@ -0,0 +1,43 @@
+package com.agfa.hap.sdo.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Simple TypeProvider that gets its type info from xsd files.
+ * TypeInfo is cached once it is read.
+ * This class is thread-safe; it can be used in a concurrent environment.
+ * @author AMOCZ
+ */
+public class XsdTypeProvider extends TypeProvider {
+
+ private Map<String, String> cache = new ConcurrentHashMap<String, String>();
+
+ public XsdTypeProvider(){
+ }
+
+ public void register(String uri, String xsd) {
+ cache.put(uri, xsd);
+ }
+
+ public void register(String uri, InputStream is) throws IOException {
+ InputStreamReader reader = new InputStreamReader(is);
+ StringBuilder builder = new StringBuilder();
+ char[] cbuf = new char[10000];
+ int bytesRead;
+ while ((bytesRead = reader.read(cbuf)) > 0) {
+ builder.append(cbuf, 0, bytesRead);
+ }
+ register(uri, builder.toString());
+ }
+
+ @Override
+ public String getTypes(String uri) {
+ return cache.get(uri);
+ }
+
+}
+
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractDataObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractDataObject.java
new file mode 100644
index 0000000000..0b2d55be02
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractDataObject.java
@@ -0,0 +1,560 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import com.agfa.hap.sdo.PropertyNotAvailableException;
+import commonj.sdo.ChangeSummary;
+import commonj.sdo.DataGraph;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Sequence;
+import commonj.sdo.impl.ExternalizableDelegator;
+
+public abstract class AbstractDataObject implements DataObject, ContainedDataObject, Serializable {
+
+ public static Logger logger = Logger.getLogger(DataObject.class);
+
+ public AbstractDataObject(com.agfa.hap.sdo.Type type) {
+ this.type = type;
+ }
+
+ protected AbstractDataObject(com.agfa.hap.sdo.Type type, DataGraph dataGraph) {
+ this(type);
+ this.dataGraph = dataGraph;
+ }
+
+ public Object get(int propertyIndex) {
+ return get(type.getProperty(propertyIndex));
+ }
+
+ public Object get(String path) {
+ try {
+ Object propertyValue = get(getProperty(path));
+ return propertyValue;
+ } catch(PropertyNotAvailableException pna){
+ throw pna;
+ } catch (Exception e){
+ logger.error("unable to get value for property" + path + " for type=" + getType(), e);
+ return null; //ref SDO_2.1_DRAFT_20060726.pdf p26
+ }
+ }
+
+ public List getList(String path) {
+ try {
+ return getList(getProperty(path));
+ } catch(PropertyNotAvailableException pna){
+ throw pna;
+ } catch(Exception e){
+ logger.error("unable to get value for property" + path + " for type=" + getType(), e);
+ return null; //ref SDO_2.1_DRAFT_20060726.pdf p26
+ }
+ }
+
+ public void set(String path, Object value) {
+ try{
+ set(getProperty(path), value);
+ } catch(PropertyNotAvailableException pna){
+ throw pna;
+ }catch (Exception e){
+ logger.error("unable to set property " + path + "for type=" + getType(), e);
+ //ref SDO_2.1_DRAFT_20060726.pdf p26
+ }
+ }
+
+ public void set(int propertyIndex, Object value) {
+ set(getType().getProperties().get(propertyIndex), value);
+ }
+
+ public boolean isSet(String path) {
+ try {
+ return isSet(getProperty(path));
+ } catch (Exception e){
+ logger.warn("property=" + path + " type=" + getType(), e);
+ return false; //ref SDO_2.1_DRAFT_20060726.pdf p26
+ }
+ }
+
+ public boolean isSet(int propertyIndex) {
+ return isSet(type.getProperty(propertyIndex));
+ }
+
+ public void unset(int propertyIndex) {
+ unset(type.getProperty(propertyIndex));
+ }
+
+ public void unset(String path) {
+ unset(getProperty(path));
+ }
+
+ public List getList(int propertyIndex) {
+ return getList(type.getProperty(propertyIndex));
+ }
+
+ public List getList(Property property) {
+ return (List) get(property);
+ }
+
+
+ public BigDecimal getBigDecimal(int propertyIndex) {
+ return (BigDecimal) get(propertyIndex);
+ }
+
+ public BigDecimal getBigDecimal(Property property) {
+ return (BigDecimal) get(property);
+ }
+
+ public BigDecimal getBigDecimal(String path) {
+ return (BigDecimal) get(path);
+ }
+
+ public BigInteger getBigInteger(int propertyIndex) {
+ return (BigInteger) get(propertyIndex);
+ }
+
+ public BigInteger getBigInteger(Property property) {
+ return (BigInteger) get(property);
+ }
+
+ public BigInteger getBigInteger(String path) {
+ return (BigInteger) get(path);
+ }
+
+ public boolean getBoolean(int propertyIndex) {
+ return (Boolean) get(propertyIndex);
+ }
+
+ public boolean getBoolean(Property property) {
+ return (Boolean) get(property);
+ }
+
+ public boolean getBoolean(String path) {
+ return (Boolean) get(path);
+ }
+
+ public byte getByte(int propertyIndex) {
+ return (Byte) get(propertyIndex);
+ }
+
+ public byte getByte(Property property) {
+ return (Byte) get(property);
+ }
+
+ public byte getByte(String path) {
+ return (Byte) get(path);
+ }
+
+ public byte[] getBytes(int propertyIndex) {
+ return (byte[]) get(propertyIndex);
+ }
+
+ public byte[] getBytes(Property property) {
+ return (byte[]) get(property);
+ }
+
+ public byte[] getBytes(String path) {
+ return (byte[]) get(path);
+ }
+
+ public char getChar(int propertyIndex) {
+ return (Character) get(propertyIndex);
+ }
+
+ public char getChar(Property property) {
+ return (Character) get(property);
+ }
+
+ public char getChar(String path) {
+ return (Character) get(path);
+ }
+
+ public Date getDate(int propertyIndex) {
+ return (Date) get(propertyIndex);
+ }
+
+ public Date getDate(Property property) {
+ return (Date) get(property);
+ }
+
+ public Date getDate(String path) {
+ return (Date) get(path);
+ }
+
+ public double getDouble(int propertyIndex) {
+ return (Double) get(propertyIndex);
+ }
+
+ public double getDouble(Property property) {
+ return (Double) get(property);
+ }
+
+ public double getDouble(String path) {
+ return (Double) get(path);
+ }
+
+ public float getFloat(int propertyIndex) {
+ return (Float) get(propertyIndex);
+ }
+
+ public float getFloat(Property property) {
+ return (Float) get(property);
+ }
+
+ public float getFloat(String path) {
+ return (Float) get(path);
+ }
+
+ public List getInstanceProperties() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Property getInstanceProperty(String propertyName) {
+ throw new UnsupportedOperationException();
+ }
+
+ public int getInt(int propertyIndex) {
+ return (Integer) get(propertyIndex);
+ }
+
+ public int getInt(Property property) {
+ return (Integer) get(property);
+ }
+
+ public int getInt(String path) {
+ return (Integer) get(path);
+ }
+
+ public long getLong(int propertyIndex) {
+ return (Long) get(propertyIndex);
+ }
+
+ public long getLong(Property property) {
+ return (Long) get(property);
+ }
+
+ public long getLong(String path) {
+ return (Long) get(path);
+ }
+
+ public Property getProperty(String propertyName) {
+ return getType().getProperty(propertyName);
+ }
+
+ public Sequence getSequence() {
+ throw new UnsupportedOperationException();
+ }
+
+ public Sequence getSequence(int propertyIndex) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Sequence getSequence(Property property) {
+ throw new UnsupportedOperationException();
+ }
+
+ public Sequence getSequence(String path) {
+ throw new UnsupportedOperationException();
+ }
+
+ public short getShort(int propertyIndex) {
+ return (Short) get(propertyIndex);
+ }
+
+ public short getShort(Property property) {
+ return (Short) get(property);
+ }
+
+ public short getShort(String path) {
+ return (Short) get(path);
+ }
+
+ public String getString(int propertyIndex) {
+ return (String) get(propertyIndex);
+ }
+
+ public String getString(Property property) {
+ return (String) get(property);
+ }
+
+ public String getString(String path) {
+ return (String) get(path);
+ }
+
+ public void setBigDecimal(int propertyIndex, BigDecimal value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setBigDecimal(Property property, BigDecimal value) {
+ this.set(property, value);
+ }
+
+ public void setBigDecimal(String path, BigDecimal value) {
+ this.set(path, value);
+ }
+
+ public void setBigInteger(int propertyIndex, BigInteger value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setBigInteger(Property property, BigInteger value) {
+ this.set(property, value);
+ }
+
+ public void setBigInteger(String path, BigInteger value) {
+ this.set(path, value);
+ }
+
+ public void setBoolean(int propertyIndex, boolean value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setBoolean(Property property, boolean value) {
+ this.set(property, value);
+ }
+
+ public void setBoolean(String path, boolean value) {
+ this.set(path, value);
+ }
+
+ public void setByte(int propertyIndex, byte value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setByte(Property property, byte value) {
+ this.set(property, value);
+ }
+
+ public void setByte(String path, byte value) {
+ this.set(path, value);
+ }
+
+ public void setBytes(int propertyIndex, byte[] value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setBytes(Property property, byte[] value) {
+ this.set(property, value);
+ }
+
+ public void setBytes(String path, byte[] value) {
+ this.set(path, value);
+ }
+
+ public void setChar(int propertyIndex, char value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setChar(Property property, char value) {
+ this.set(property, value);
+ }
+
+ public void setChar(String path, char value) {
+ this.set(path, value);
+ }
+
+ public void setDataObject(int propertyIndex, DataObject value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setDataObject(Property property, DataObject value) {
+ this.set(property, value);
+ }
+
+ public void setDataObject(String path, DataObject value) {
+ this.set(path, value);
+ }
+
+ public void setDate(int propertyIndex, Date value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setDate(Property property, Date value) {
+ this.set(property, value);
+ }
+
+ public void setDate(String path, Date value) {
+ this.set(path, value);
+ }
+
+ public void setDouble(int propertyIndex, double value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setDouble(Property property, double value) {
+ this.set(property, value);
+ }
+
+ public void setDouble(String path, double value) {
+ this.set(path, value);
+ }
+
+ public void setFloat(int propertyIndex, float value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setFloat(Property property, float value) {
+ this.set(property, value);
+ }
+
+ public void setFloat(String path, float value) {
+ this.set(path, value);
+ }
+
+ public void setInt(int propertyIndex, int value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setInt(Property property, int value) {
+ this.set(property, value);
+ }
+
+ public void setInt(String path, int value) {
+ this.set(path, value);
+ }
+
+ public void setList(int propertyIndex, List value) {
+ this.setList(this.getType().getProperty(propertyIndex), value);
+ }
+
+ public void setList(Property property, List value) {
+ List list = this.getList(property);
+ list.clear();
+ list.addAll(value);
+ }
+
+ public void setList(String path, List value) {
+ this.setList(this.getProperty(path), value);
+ }
+
+ public void setLong(int propertyIndex, long value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setLong(Property property, long value) {
+ this.set(property, value);
+ }
+
+ public void setLong(String path, long value) {
+ this.set(path, value);
+ }
+
+ public void setShort(int propertyIndex, short value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setShort(Property property, short value) {
+ this.set(property, value);
+ }
+
+ public void setShort(String path, short value) {
+ this.set(path, value);
+ }
+
+ public void setString(int propertyIndex, String value) {
+ this.set(propertyIndex, value);
+ }
+
+ public void setString(Property property, String value) {
+ this.set(property, value);
+ }
+
+ public void setString(String path, String value) {
+ this.set(path, value);
+ }
+
+ public com.agfa.hap.sdo.Type getType() {
+ return type;
+ }
+
+ public String debugString(){
+ StringBuilder builder = new StringBuilder();
+ builder.append(this.toString());
+ builder.append(" {");
+ if (type != null){
+ builder.append("type=");
+ builder.append(type.getName());
+ builder.append(";properties=(");
+ for (Property property : type.getProperties()){
+ builder.append(property.getName());
+ builder.append("=");
+ Object value = get(property);
+ if (value instanceof AbstractDataObject){
+ AbstractDataObject dataObject = (AbstractDataObject) value;
+ builder.append(dataObject.debugString());
+ } else {
+ builder.append(value);
+ }
+ builder.append(",");
+ }
+ builder.append(")");
+ }
+
+ builder.append(" }");
+ return builder.toString() ;
+ }
+
+ public void delete() {
+ throw new UnsupportedOperationException();
+ }
+
+ public ChangeSummary getChangeSummary() {
+ throw new UnsupportedOperationException();
+ }
+
+ protected Object writeReplace() throws ObjectStreamException {
+ return new ExternalizableDelegator(this);
+ }
+
+ public void setDataGraph(DataGraph dataGraph) {
+ this.dataGraph = dataGraph;
+ }
+
+ public DataObject getContainer() {
+ return container;
+ }
+
+ public Property getContainmentProperty() {
+ return containmentProperty;
+ }
+
+ public DataGraph getDataGraph() {
+ return dataGraph;
+ }
+
+ public DataObject getRootObject() {
+ return container == null ? this : container.getRootObject();
+ }
+
+ public void detach() {
+ if (this.container != null) {
+ container.unset(containmentProperty);
+ }
+ this.container = null;
+ this.containmentProperty = null;
+ this.dataGraph = null;
+ }
+
+ protected void setContainment(AbstractDataObject container, Property prop) {
+ this.container = container;
+ this.containmentProperty = container == null ? null : prop;
+ DataGraph newDataGraph = container == null ? null : container.dataGraph;
+ dataGraph = newDataGraph;
+ }
+
+ protected boolean isContained(Property property) {
+ return property.isContainment();
+ }
+
+
+ protected com.agfa.hap.sdo.Type type;
+ private Property containmentProperty;
+ private DataObject container;
+ private DataGraph dataGraph;
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractPartialDataObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractPartialDataObject.java
new file mode 100644
index 0000000000..f923f3b1ae
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/AbstractPartialDataObject.java
@@ -0,0 +1,211 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.util.List;
+
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.PropertyNotAvailableException;
+
+import commonj.sdo.DataGraph;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+public abstract class AbstractPartialDataObject extends AbstractDataObject implements PartialDataObject {
+
+ protected boolean isSettingProperty;
+
+ protected AbstractPartialDataObject(com.agfa.hap.sdo.Type type) {
+ super(type);
+ }
+
+ protected AbstractPartialDataObject(com.agfa.hap.sdo.Type type, DataGraph dataGraph) {
+ super(type, dataGraph);
+ }
+
+ /**
+ * Returns the value of the property. In case the property is not accessible
+ * returns {@link PartialDataObject#UNAVAILABLE_PROPERTY}.
+ */
+ protected abstract Object basicGet(Property property);
+
+ protected abstract void basicSet(Property property, Object value);
+
+ public Object get(Property property) {
+ Object result = basicGet(property);
+ if (result == PartialDataObject.UNAVAILABLE_PROPERTY) {
+ throw new PropertyNotAvailableException(this, property);
+ }
+ return result;
+ }
+
+ public void set(Property property, Object value) {
+ if (property.isMany()) {
+ this.setList(property, (List) value);
+ return;
+ }
+ if (property.isReadOnly()) {
+ throw new IllegalArgumentException("Setting readonly properties is not allowed!");
+ }
+ if (isSettingProperty) {
+ return;
+ }
+ try {
+ isSettingProperty = true;
+ Object oldValue = basicGet(property);
+ if (oldValue == value) {
+ return;
+ }
+ if (oldValue != null && isContained(property) && oldValue != PartialDataObject.UNAVAILABLE_PROPERTY) {
+ ((AbstractDataObject) oldValue).setContainment(null, property);
+ }
+ if (value != null && value != PartialDataObject.UNAVAILABLE_PROPERTY && isContained(property)) {
+ ((AbstractDataObject) value).setContainment(this, property);
+ }
+ basicSet(property, value);
+ if (property.getOpposite() != null) {
+ if (oldValue != null && oldValue != PartialDataObject.UNAVAILABLE_PROPERTY) {
+ if (property.getOpposite().isMany()) {
+ PartialDataObject oldOpposite = (PartialDataObject) oldValue;
+ if (oldOpposite.isAvailable(property.getOpposite())) {
+ ((IDataObjectList) oldOpposite.getList(property.getOpposite())).removeForBidirectionalUpdate(this);
+ }
+ } else {
+ ((DataObject) oldValue).set(property.getOpposite(), null);
+ }
+ }
+ if (value != null && value != PartialDataObject.UNAVAILABLE_PROPERTY) {
+ if (property.getOpposite().isMany()) {
+ PartialDataObject opposite = (PartialDataObject) value;
+ if (opposite.isAvailable(property.getOpposite())) {
+ ((IDataObjectList) opposite.getList(property.getOpposite())).addForBidirectionalUpdate(this);
+ }
+ } else {
+ ((DataObject) value).set(property.getOpposite(), this);
+ }
+ }
+ }
+ } finally {
+ isSettingProperty = false;
+ }
+ }
+
+ public PartialDataObject createDataObject(String propertyName) {
+ return createDataObject(getType().getProperty(propertyName));
+ }
+
+ public PartialDataObject createDataObject(int propertyIndex) {
+ return createDataObject(getType().getProperties().get(propertyIndex));
+ }
+
+ public PartialDataObject createDataObject(Property property) {
+ return createDataObject(property, property.getType());
+ }
+
+ public PartialDataObject createDataObject(String propertyName, String namespaceURI, String typeName) {
+ return createDataObject(getType().getProperty(propertyName), TypeHelper.INSTANCE.getType(namespaceURI, typeName));
+ }
+
+ public PartialDataObject createDataObject(int propertyIndex, String namespaceURI, String typeName) {
+ return createDataObject(getType().getProperties().get(propertyIndex), TypeHelper.INSTANCE.getType(namespaceURI, typeName));
+ }
+
+ public PartialDataObject createDataObject(Property property, Type type) {
+ PartialDataObject result = PartialDataFactory.INSTANCE.create(type);
+ if (property.isMany()) {
+ safeGetList(property).add(result);
+ } else {
+ set(property, result);
+ }
+ return result;
+ }
+
+ // also works in case property is not available
+ protected List<Object> safeGetList(Property property) {
+ Object result = basicGet(property);
+ if (result == PartialDataObject.UNAVAILABLE_PROPERTY) {
+ result = initializeWithEmptyList(property);
+ }
+ return (List<Object>) result;
+ }
+
+ protected abstract List initializeWithEmptyList(Property property);
+
+ @Override
+ public void setList(Property property, List value) {
+ if (!isAvailable(property)) {
+ if (property.getOpposite() != null) {
+ // we have to do this to avoid exceptions saying that the element
+ // is already a part of the collection
+ for (Object element : value) {
+ AbstractDataObject ado = (AbstractDataObject) element;
+ ado.set(property.getOpposite(), null);
+ }
+ }
+ this.safeGetList(property); // ensure that it is available
+ }
+ super.setList(property, value);
+ }
+
+ public PartialDataObject getDataObject(int propertyIndex) {
+ return (PartialDataObject) get(propertyIndex);
+ }
+
+ public PartialDataObject getDataObject(Property property) {
+ return (PartialDataObject) get(property);
+ }
+
+ public PartialDataObject getDataObject(String path) {
+ return (PartialDataObject) get(path);
+ }
+
+ public com.agfa.hap.sdo.Property getContainmentProperty() {
+ return (com.agfa.hap.sdo.Property) super.getContainmentProperty();
+ }
+
+ public PartialDataObject getContainer() {
+ return (PartialDataObject) super.getContainer();
+ }
+
+ public Object getIdentity() {
+ return this.get(getType().getIdentityProperty());
+ }
+
+ public void setIdentity(Object value) {
+ this.set(getType().getIdentityProperty(), value);
+ }
+
+ void becomeProxy(Object identity) {
+ for (Property property : getType().getProperties()) {
+ setUnavailable(property);
+ }
+ setIdentity(identity);
+ this.isProxy = true;
+ }
+
+ public boolean isAvailable(Property property) {
+ return basicGet(property) != PartialDataObject.UNAVAILABLE_PROPERTY;
+ }
+
+ public void setUnavailable(Property property) {
+ basicSet(property, PartialDataObject.UNAVAILABLE_PROPERTY);
+ }
+
+ public boolean isSet(Property property) {
+ //TODO many valued props ref SDO_2.1_DRAFT_20060726.pdf page 18
+ Object value = basicGet(property);
+ return value != null && value != PartialDataObject.UNAVAILABLE_PROPERTY;
+ }
+
+ public void unset(Property property) {
+ basicSet(property, null);
+ }
+
+ public boolean isProxy() {
+ return isProxy;
+ }
+
+ private boolean isProxy;
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BinarySerializer.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BinarySerializer.java
new file mode 100644
index 0000000000..70a8b53194
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BinarySerializer.java
@@ -0,0 +1,115 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectStreamException;
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.impl.TypeConverter;
+import commonj.sdo.impl.ExternalizableDelegator.Resolvable;
+
+public abstract class BinarySerializer implements Resolvable {
+ private static Logger logger = Logger.getLogger(BinarySerializer.class);
+ private static final long serialVersionUID = -6762854727094260430L;
+
+ public BinarySerializer() {
+ }
+
+ public BinarySerializer(PartialDataObject dataObject) {
+ this.dataObject = dataObject;
+ }
+
+ protected transient PartialDataObject dataObject;
+
+ public Object readResolve() throws ObjectStreamException {
+ return dataObject;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ dataObject = read(in);
+ }
+
+ protected PartialDataObject create(String uri, String type) {
+ return PartialDataFactory.INSTANCE.create(uri, type);
+ }
+
+ protected PartialDataObject read(ObjectInput in) throws IOException {
+ String uri = in.readUTF();
+ String type = in.readUTF();
+ PartialDataObject result = create(uri, type);
+ int propIndex = in.readInt();
+ while (propIndex >= 0) {
+ Property prop = result.getType().getProperty(propIndex);
+ Object value = read(in, result, prop);
+ if (value != null) {
+ // can happen in case of sdo-ref
+ if (prop.isMany()) {
+ result.getList(prop).add(value);
+ } else {
+ result.set(prop, value);
+ }
+ }
+ propIndex = in.readInt();
+ }
+ return result;
+ }
+
+ private Object read(ObjectInput in, PartialDataObject parent, Property prop) throws IOException {
+ if (prop.getType().isDataType()) {
+ String value = in.readUTF();
+ 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 readChildDataObject(in, prop, parent);
+ }
+
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ write(out, dataObject);
+ }
+
+ protected void write(ObjectOutput out, PartialDataObject dataObject) throws IOException {
+ out.writeUTF(dataObject.getType().getURI());
+ out.writeUTF(dataObject.getType().getName());
+ for (Property prop : dataObject.getType().getProperties()) {
+ if (dataObject.isSet(prop)) {
+ if (prop.isMany()) {
+ Iterator<PartialDataObject> it = dataObject.getList(prop).iterator();
+ while (it.hasNext()) {
+ write(out, prop, it.next());
+ }
+ } else {
+ write(out, prop, dataObject.get(prop));
+ }
+ }
+ }
+ out.writeInt(-1);
+ }
+
+ protected void write(ObjectOutput out, Property prop, Object value) throws IOException {
+ if (prop.getOpposite() != null && prop.getOpposite().isContainment()) {
+ return;
+ }
+ out.writeInt(prop.getIndex());
+ if (prop.getType().isDataType()) {
+ out.writeUTF(TypeConverter.get(prop.getType()).toString(value));
+ } else {
+ writeChildDataObject(out, prop, (PartialDataObject) value);
+ }
+ }
+
+ protected abstract void writeChildDataObject(ObjectOutput out, Property prop, PartialDataObject child) throws IOException;
+ protected abstract PartialDataObject readChildDataObject(ObjectInput in, Property prop, PartialDataObject parent) throws IOException;
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BulkProperty.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BulkProperty.java
new file mode 100644
index 0000000000..3763b16963
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/BulkProperty.java
@@ -0,0 +1,18 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.SnapshotDefinition;
+
+public 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;
+ } \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ClassPathImplementationClassRepository.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ClassPathImplementationClassRepository.java
new file mode 100644
index 0000000000..820d7a0714
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ClassPathImplementationClassRepository.java
@@ -0,0 +1,46 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+
+import com.agfa.hap.sdo.util.ClassHolder;
+import com.agfa.hap.sdo.util.ClassLoaderBasedClassHolder;
+
+/**
+ * {@link ImplementationClassRepository} that gets its resources by searching at start-up
+ * the classpath for sdo/implementationclasses.properties files.
+ * @author AMOCZ
+ */
+public class ClassPathImplementationClassRepository extends ImplementationClassRepository {
+
+ @Override
+ protected void initialize() {
+ // this is needed e.g. during the maven build
+ initializeImplementationClasses(Thread.currentThread().getContextClassLoader());
+ // this is needed during normal runtime
+ initializeImplementationClasses(TypeHelperImpl.class.getClassLoader());
+ }
+
+ private void initializeImplementationClasses(final ClassLoader classLoader) {
+ if (classLoader == null) {
+ return;
+ }
+ try {
+ Enumeration<URL> urls = classLoader.getResources(IMPLEMENTATIONCLASS_RESOURCEFILE);
+ while (urls.hasMoreElements()){
+ URL url = urls.nextElement();
+ addImplementationClasses(url, new ClassHolderFactory() {
+
+ public ClassHolder createClassHolder(String className) {
+ return new ClassLoaderBasedClassHolder(className, classLoader);
+ }
+
+ });
+ }
+ } catch (IOException e) {
+ getLogger().warn("Could not read implementation classes.", e);
+ }
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/CompleteSerializer.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/CompleteSerializer.java
new file mode 100644
index 0000000000..944dc0fba4
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/CompleteSerializer.java
@@ -0,0 +1,74 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+
+/**
+ * BinarySerializer that serializes every object that it can reach in the graph.
+ * Implementation note: DataObjects are inlined the first time they are encountered.
+ * The second time an object is encountered a reference is stored.
+ * @author AMOCZ
+ */
+public class CompleteSerializer extends BinarySerializer {
+
+ private transient List<PartialDataObject> instances;
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ instances = new ArrayList<PartialDataObject>();
+ super.readExternal(in);
+ instances = null;
+ }
+
+ @Override
+ protected PartialDataObject readChildDataObject(ObjectInput in, Property prop,
+ PartialDataObject parent) throws IOException {
+ boolean isOnStream = in.readBoolean();
+ if (isOnStream) {
+ return read(in);
+ } else {
+ int index = in.readInt();
+ return instances.get(index);
+ }
+ }
+
+
+ @Override
+ protected PartialDataObject create(String uri, String type) {
+ PartialDataObject result = super.create(uri, type);
+ instances.add(result);
+ return result;
+ }
+
+ @Override
+ public void writeExternal(ObjectOutput out) throws IOException {
+ instances = new ArrayList<PartialDataObject>();
+ super.writeExternal(out);
+ instances = null;
+ }
+
+ @Override
+ protected void write(ObjectOutput out, PartialDataObject dataObject) throws IOException {
+ instances.add(dataObject);
+ super.write(out, dataObject);
+ }
+
+ @Override
+ protected void writeChildDataObject(ObjectOutput out, Property prop,
+ PartialDataObject child) throws IOException {
+ int index = instances.indexOf(child);
+ if (index >= 0) {
+ out.writeBoolean(false);
+ out.writeInt(index);
+ } else {
+ out.writeBoolean(true);
+ write(out, child);
+ }
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainedDataObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainedDataObject.java
new file mode 100644
index 0000000000..c512a15238
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainedDataObject.java
@@ -0,0 +1,13 @@
+package com.agfa.hap.sdo.implementation;
+
+import commonj.sdo.DataGraph;
+
+/**
+ * This interface is introduced to allow addition of dataobject to a datagraph in an
+ * implementation independent way.
+ */
+public interface ContainedDataObject {
+
+ void setDataGraph(DataGraph dataGraph);
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainmentSerializer.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainmentSerializer.java
new file mode 100644
index 0000000000..8a0b27a260
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ContainmentSerializer.java
@@ -0,0 +1,71 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectStreamException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.implementation.DataObjectHelper.Link;
+
+/**
+ * BinarySerializer that serializes all instances that it can reach through contained properties
+ * (as dictated by the sdo spec).
+ * @author AMOCZ
+ */
+public class ContainmentSerializer extends BinarySerializer {
+
+ private transient List<Link> links;
+
+ public ContainmentSerializer() {
+ }
+
+ public ContainmentSerializer(PartialDataObject dataObject) {
+ super(dataObject);
+ }
+
+ public Object readResolve() throws ObjectStreamException {
+ processLinks();
+ return super.readResolve();
+ }
+
+ protected void writeChildDataObject(ObjectOutput out, Property prop, PartialDataObject child) throws IOException {
+ if (prop.isContainment()) {
+ write(out, child);
+ } else {
+ out.writeUTF(DataObjectHelper.getSdoRef(child));
+ }
+ }
+
+ @Override
+ protected PartialDataObject readChildDataObject(ObjectInput in, Property prop, PartialDataObject parent) throws IOException {
+ if (prop.isContainment()) {
+ return read(in);
+ } else {
+ String sdoRef = in.readUTF();
+ addLink(parent, prop, sdoRef);
+ return null;
+ }
+ }
+
+ private void addLink(PartialDataObject target, Property prop, String sdoRef) {
+ if (links == null) {
+ links = new ArrayList<Link>();
+ }
+ links.add(new Link(target, prop, sdoRef));
+ }
+
+ private void processLinks() {
+ if (links == null) {
+ return;
+ }
+ for (Link link : links) {
+ link.apply();
+ }
+ links = null;
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataFactoryImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataFactoryImpl.java
new file mode 100644
index 0000000000..b8a62b3ca2
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataFactoryImpl.java
@@ -0,0 +1,52 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+public class DataFactoryImpl implements PartialDataFactory {
+
+ public PartialDataObject create(String uri, String typeName) {
+ return create(TypeHelper.INSTANCE.getType(uri, typeName));
+ }
+
+ public PartialDataObject create(Class interfaceClass) {
+ return create(TypeHelper.INSTANCE.getType(interfaceClass));
+ }
+
+ public PartialDataObject create(commonj.sdo.Type type) {
+ Constructor<? extends PartialDataObject> instanceConstructor = ((TypeImplementation) type).getInstanceConstructor();
+ if (instanceConstructor != null) {
+ try {
+ return instanceConstructor.newInstance(type);
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException("Can't instantiate objects of type " + type.getName(), e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Can't instantiate objects of type " + type.getName(), e);
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException("Can't instantiate objects of type " + type.getName(), e);
+ }
+ }
+ return createDefaultDataObjectInstance(type);
+ }
+
+ protected PartialDataObject createDefaultDataObjectInstance(commonj.sdo.Type type) {
+ return new DataObjectImplementation((Type) type);
+ }
+
+ public PartialDataObject createProxy(String uri, String typeName, Object identity) {
+ return createProxy(TypeHelper.INSTANCE.getType(uri, typeName), identity);
+ }
+
+ public PartialDataObject createProxy(commonj.sdo.Type type, Object identity) {
+ PartialDataObject result = create(type);
+ ((AbstractPartialDataObject) result).becomeProxy(identity);
+ return result;
+ }
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataGraphImplementation.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataGraphImplementation.java
new file mode 100644
index 0000000000..cef56d67a8
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataGraphImplementation.java
@@ -0,0 +1,51 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.Serializable;
+
+import commonj.sdo.ChangeSummary;
+import commonj.sdo.DataGraph;
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.TypeHelper;
+
+public class DataGraphImplementation implements DataGraph, Serializable {
+
+ private static final long serialVersionUID = 6144199477779992429L;
+
+ public DataGraphImplementation() {
+ }
+
+ public DataGraphImplementation(DataObject rootObject) {
+ this.rootObject = rootObject;
+ ((ContainedDataObject) rootObject).setDataGraph(this);
+ }
+
+ public DataObject getRootObject() {
+ return rootObject;
+ }
+
+ public ChangeSummary getChangeSummary() {
+ throw new UnsupportedOperationException();
+ }
+
+ public commonj.sdo.Type getType(String uri, String typeName) {
+ return TypeHelper.INSTANCE.getType(uri, typeName);
+ }
+
+ public DataObject createRootObject(String namespaceURI, String typeName) {
+ return createRootObject(getType(namespaceURI, typeName));
+ }
+
+ public DataObject createRootObject(commonj.sdo.Type type) {
+ rootObject = DataFactory.INSTANCE.create(type);
+ ((ContainedDataObject) rootObject).setDataGraph(this);
+ return rootObject;
+ }
+
+ DataObject createObject(Type type) {
+ return DataFactory.INSTANCE.create(type);
+ }
+
+ private DataObject rootObject;
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectConverter.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectConverter.java
new file mode 100644
index 0000000000..6b8c90026d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectConverter.java
@@ -0,0 +1,147 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+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 com.agfa.hap.sdo.DataMapper;
+import com.agfa.hap.sdo.ObjectPropertyVisitor;
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.SnapshotDefinition;
+import com.agfa.hap.sdo.Type;
+import commonj.sdo.DataObject;
+
+/**
+*
+* the same functionality as SnapshotSerializer except that this outputs to a list of DataObjects
+*/
+public class DataObjectConverter<T> implements ObjectPropertyVisitor{
+
+ private DataMapper<T> mapper;
+ private Map<Object, DataObject> source2do = new HashMap<Object, DataObject>();
+ private Map<Property, BulkProperty<T>> bulkProperties;
+
+ public DataObjectConverter(DataMapper<T> mapper){
+ this.mapper = mapper;
+ }
+
+ public void endDataObject(Object instance, Type type) throws Exception {
+ //do nothing
+ }
+
+ public void startDataObject(Object instance, Type type) throws Exception {
+ DataObject dataObject = source2do.get(instance);
+ if (dataObject == null){
+ dataObject = PartialDataFactory.INSTANCE.create(type);
+ source2do.put(instance, dataObject);
+ }
+ }
+
+ 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;
+ }
+
+ public boolean visitProperty(Object instance, Property property, Object value) throws Exception {
+ DataObject dataObject = source2do.get(instance);
+ if (property.getType().isDataType() || value == null){
+ dataObject.set(property, value); //if many valued and datatype, then value will be a List, so this is ok
+ return false;
+ } else {
+ DataObject convertedValue = source2do.get(value);
+ if (convertedValue == null){
+ source2do.put(value, dataObject.createDataObject(property));
+ return true;
+ } else {
+ if (property.isMany()){
+ List manyValuedValue = dataObject.getList(property);
+ if (!manyValuedValue.contains(value)){
+ manyValuedValue.add(convertedValue);
+ }
+ } else {
+ dataObject.set(property, convertedValue);
+ }
+ return false; //was already visited, so no need to recurse
+ }
+ }
+ }
+
+ public void visitProxyProperty(Object instance, Property property, Object identity) throws Exception {
+ if (identity == null){ //eg when it is a many valued property
+ return;
+ }
+ DataObject dataObject = source2do.get(instance);
+ dataObject.set(property, PartialDataFactory.INSTANCE.createProxy(property.getType(), identity));
+ }
+
+ public List<DataObject> convert(SnapshotDefinition def, Collection<? extends T> roots) throws Exception {
+ for (T root : roots){
+ def.visit(mapper, this, root);
+ }
+ processBulkProperties();
+ List<DataObject> pdos = new ArrayList<DataObject>(roots.size());
+ for (T root : roots){
+ pdos.add(source2do.get(root));
+ }
+ return pdos;
+ }
+
+ protected void processBulkProperties() 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
+ processBulkProperty(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
+ }
+ }
+ }
+ }
+
+ private void processBulkProperty(BulkProperty bp) throws IOException, 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) {
+ processBulkPropertyValue(bp, parent, child);
+ }
+ } else {
+ processBulkPropertyValue(bp, parent, value);
+ }
+ }
+ }
+
+ protected void processBulkPropertyValue(BulkProperty bp, Object parent, T value) throws IOException, Exception {
+ if (this.visitProperty(parent, bp.property, value)) {
+ bp.subselect.visit(mapper, this, value);
+ }
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectHelper.java
new file mode 100644
index 0000000000..be19099150
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectHelper.java
@@ -0,0 +1,61 @@
+package com.agfa.hap.sdo.implementation;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+
+class DataObjectHelper {
+
+ public static String getSdoRef(PartialDataObject target) {
+ StringBuilder builder = new StringBuilder();
+ Property prop = target.getContainmentProperty();
+ while (prop != null) {
+ target.getContainmentProperty();
+ if (prop.isMany()) {
+ builder.insert(0,']');
+ builder.insert(0, target.getContainer().getList(prop).indexOf(target));
+ builder.insert(0,'[');
+ }
+ builder.insert(0, prop.getName());
+ builder.insert(0, '/');
+ target = target.getContainer();
+ prop = target.getContainmentProperty();
+ }
+ return builder.toString();
+ }
+
+ public static PartialDataObject deref(PartialDataObject obj, String sdoRef) {
+ if (obj.getContainer() != null) {
+ return deref(obj.getContainer(), sdoRef);
+ }
+ String[] props = sdoRef.split("/");
+ for (String propertyName : props) {
+ if (propertyName.length() > 0) {
+ int index = 0;
+ if (propertyName.endsWith("]")) {
+ int bracketIndex = propertyName.lastIndexOf('[');
+ index = Integer.parseInt(propertyName.substring(bracketIndex+1, propertyName.length()-1));
+ propertyName = propertyName.substring(0, bracketIndex);
+ }
+ Property prop = obj.getType().getProperty(propertyName);
+ obj = prop.isMany() ? (PartialDataObject) obj.getList(prop).get(index) : obj.getDataObject(prop);
+ }
+ }
+ return obj;
+ }
+
+ public static class Link {
+ private PartialDataObject target;
+ private Property property;
+ private String sdoRef;
+ Link(PartialDataObject target, Property property, String sdoRef) {
+ this.target = target;
+ this.property = property;
+ this.sdoRef = sdoRef;
+ }
+ void apply() {
+ PartialDataObject link = DataObjectHelper.deref(target, sdoRef);
+ target.set(property, link);
+ }
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectImplementation.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectImplementation.java
new file mode 100644
index 0000000000..1f0467451c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectImplementation.java
@@ -0,0 +1,56 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import commonj.sdo.Property;
+
+public class DataObjectImplementation extends AbstractPartialDataObject {
+
+ private static final long serialVersionUID = -3807872778273860980L;
+
+ protected DataObjectImplementation(com.agfa.hap.sdo.Type type, DataGraphImplementation dataGraph) {
+ super(type, dataGraph);
+ }
+
+ protected DataObjectImplementation(com.agfa.hap.sdo.Type type) {
+ super(type);
+ this.properties = new Object[type.getProperties().size()];
+ }
+
+
+ @Override
+ protected Object basicGet(Property property) {
+ Object result = properties[property.getIndex()];
+ if (property.isMany() && result == null) {
+ if (property.getType().isDataType()){
+ result = new ArrayList();
+ } else {
+ result = new DataObjectList(this, property);
+ }
+ properties[property.getIndex()] = result;
+ }
+ return result;
+ }
+
+ @Override
+ protected void basicSet(Property property, Object value) {
+ properties[property.getIndex()] = value;
+ }
+
+ @Override
+ protected List initializeWithEmptyList(Property property) {
+ List emptyList;
+ if (property.getType().isDataType()){
+ emptyList = new ArrayList();
+ } else {
+ emptyList = new DataObjectList(this, property);
+ }
+ basicSet(property, emptyList);
+ return emptyList;
+ }
+
+ private Object[] properties;
+
+}
+
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectList.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectList.java
new file mode 100644
index 0000000000..a12a3c6dba
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectList.java
@@ -0,0 +1,131 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import commonj.sdo.Property;
+
+/**
+ * List that performs AbstractDataObject bidirectional updates. If a dataobject is added/removed
+ * from this list, the opposite property of the dataobject is also set/reset. Also
+ * updates the containment relationship.
+ * @author AMOCZ
+ *
+ */
+public class DataObjectList extends ArrayList<AbstractDataObject> implements IDataObjectList<AbstractDataObject>{
+
+ private static final long serialVersionUID = -3893408567235500837L;
+
+ private final AbstractDataObject owner;
+ private final Property listProperty;
+ private boolean bidirUpdateInProgress;
+
+ public DataObjectList(AbstractDataObject owner, Property listProperty) {
+ this.owner = owner;
+ this.listProperty = listProperty;
+ }
+
+ @Override
+ public AbstractDataObject set(int index, AbstractDataObject element) {
+ AbstractDataObject oldValue = super.set(index, element);
+ performBidirectionalUpdate(element, owner);
+ if (oldValue != null) {
+ performBidirectionalUpdate(oldValue, null);
+ }
+ return oldValue;
+ }
+
+ public void removeForBidirectionalUpdate(AbstractDataObject o) {
+ if (!bidirUpdateInProgress) {
+ super.remove(o);
+ }
+ }
+
+ public void addForBidirectionalUpdate(AbstractDataObject o) {
+ if (!bidirUpdateInProgress) {
+ super.add(o);
+ }
+ }
+
+ @Override
+ public boolean add(AbstractDataObject o) {
+ if (bidirUpdateInProgress) {
+ return false;
+ }
+ if (listProperty.getOpposite() != null && o.getDataObject(listProperty.getOpposite()) == owner) {
+ throw new IllegalArgumentException("Can't add this object to the list because it is already present.");
+ }
+ boolean result = super.add(o);
+ performBidirectionalUpdate(o, owner);
+ return result;
+ }
+
+ @Override
+ public void add(int index, AbstractDataObject element) {
+ super.add(index, element);
+ performBidirectionalUpdate(element, owner);
+ }
+
+ @Override
+ public AbstractDataObject remove(int index) {
+ AbstractDataObject result = super.remove(index);
+ if (result != null) {
+ performBidirectionalUpdate(result, null);
+ }
+ return result;
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ if (bidirUpdateInProgress) {
+ return false;
+ }
+ boolean result = super.remove(o);
+ if (result) {
+ performBidirectionalUpdate((AbstractDataObject) o, null);
+ }
+ return result;
+ }
+
+ protected void performBidirectionalUpdate(AbstractDataObject source, AbstractDataObject target) {
+ bidirUpdateInProgress = true;
+ if (listProperty.getOpposite() != null) {
+ source.set(listProperty.getOpposite(), target);
+ }
+ if (listProperty.isContainment()) {
+ source.setContainment(target, listProperty);
+ }
+ bidirUpdateInProgress = false;
+ }
+
+ @Override
+ public void clear() {
+ for (AbstractDataObject d : this) {
+ performBidirectionalUpdate(d, null);
+ }
+ super.clear();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends AbstractDataObject> c) {
+ boolean result = super.addAll(c);
+ if (result) {
+ for (AbstractDataObject d : c) {
+ performBidirectionalUpdate(d, owner);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean addAll(int index, Collection<? extends AbstractDataObject> c) {
+ boolean result = super.addAll(index, c);
+ if (result) {
+ for (AbstractDataObject d : c) {
+ performBidirectionalUpdate(d, owner);
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectStreamer.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectStreamer.java
new file mode 100644
index 0000000000..978c031dbe
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectStreamer.java
@@ -0,0 +1,178 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.impl.TypeConverter;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XMLDocument;
+
+class DataObjectStreamer {
+
+ private static SAXParserFactory parserFactory;
+
+ static final String XSI_URI = "http://www.w3.org/2001/XMLSchema-instance";
+ static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
+
+ static {
+ parserFactory = SAXParserFactory.newInstance();
+ parserFactory.setNamespaceAware(true);
+ }
+
+ public XMLDocument fromXml(Reader r) throws IOException, SAXException {
+ return fromXml(new InputSource(r));
+ }
+
+ public XMLDocument fromXml(InputStream is) throws IOException, SAXException {
+ return fromXml(new InputSource(is));
+ }
+
+ public XMLDocument fromXml(InputSource input) throws IOException, SAXException {
+ try {
+ SAXParser parser = parserFactory.newSAXParser();
+ DataObjectXmlParser dox = new DataObjectXmlParser();
+ parser.parse(input, dox);
+ return dox.getXMLDocument();
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void toXml(XMLDocument doc, Writer os) {
+ try {
+ toXml(doc, new StreamResult(os));
+ } catch (TransformerConfigurationException e) {
+ throw new RuntimeException(e);
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void toXml(XMLDocument doc, OutputStream os) {
+ try {
+ toXml(doc, new StreamResult(os));
+ } catch (TransformerConfigurationException e) {
+ throw new RuntimeException(e);
+ } catch (SAXException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ void toXml(XMLDocument doc, Result result) throws SAXException, TransformerConfigurationException {
+ SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance();
+ TransformerHandler hd = tf.newTransformerHandler();
+ Transformer serializer = hd.getTransformer();
+ serializer.setOutputProperty(OutputKeys.ENCODING, doc.getEncoding());
+ // serializer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM,"users.dtd");
+ serializer.setOutputProperty(OutputKeys.INDENT,"yes");
+ hd.setResult(result);
+ hd.startDocument();
+// hd.startPrefixMapping("xmlns", XMLNS_URI);
+ // hd.startPrefixMapping("", doc.getRootElementURI());
+ hd.startPrefixMapping("xsi", XSI_URI);
+ AttributesImpl attrs = new AttributesImpl();
+ Map<String, String> uriToNamespace = createUriToNamespace();
+ if (doc.getRootElementURI() != null) {
+ uriToNamespace.put(doc.getRootElementURI(), "tns");
+ }
+ for (String uri : uriToNamespace.keySet()) {
+ String ns = uriToNamespace.get(uri);
+ attrs.addAttribute(XMLNS_URI, ns, "xmlns:" + ns, "CDATA", uri);
+ }
+ String qualifiedName = uriToNamespace.get(doc.getRootObject().getType().getURI());
+ if (qualifiedName == null) {
+ qualifiedName = "";
+ } else {
+ qualifiedName = qualifiedName + ":";
+ }
+ attrs.addAttribute(XSI_URI, "type", "xsi:type", "CDATA", qualifiedName + doc.getRootObject().getType().getName());
+ hd.startElement(doc.getRootElementURI(), doc.getRootElementName(), doc.getRootElementName(), attrs);
+ toXml(hd, (PartialDataObject) doc.getRootObject(), uriToNamespace);
+ hd.endElement(doc.getRootElementURI(), doc.getRootElementName(), doc.getRootElementName());
+ hd.endPrefixMapping("xsi");
+ // hd.endPrefixMapping("");
+// hd.endPrefixMapping("xmlns");
+ hd.endDocument();
+ }
+
+ Map<String, String> createUriToNamespace() {
+ Map<String, String> result = new HashMap<String, String>();
+ result.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
+ result.put("commonj.sdo", "sdo");
+ int i = 1;
+ for (String uri : ((TypeHelperImpl) TypeHelper.INSTANCE).getKnownUris()) {
+ if (!result.containsKey(uri)) {
+ result.put(uri, "ns" + i++);
+ }
+ }
+ return result;
+ }
+
+ void toXml(TransformerHandler hd, PartialDataObject dataObject, Map<String, String> uriToNamespace) throws SAXException {
+ if (dataObject == null) {
+ return;
+ }
+ for (Property prop : dataObject.getType().getProperties()) {
+ if (dataObject.isSet(prop) && (prop.getType().isDataType() || prop.isContainment() || prop.getOpposite() == null)) {
+ if (prop.isMany()) {
+ Iterator<PartialDataObject> it = dataObject.getList(prop).iterator();
+ while (it.hasNext()) {
+ toXml(hd, it.next(), prop, uriToNamespace);
+ }
+ } else {
+ toXml(hd, dataObject.get(prop), prop, uriToNamespace);
+ }
+ }
+ }
+ }
+
+ private void toXml(TransformerHandler hd, Object value, Property prop, Map<String, String> uriToNamespace) throws SAXException {
+ AttributesImpl attrs = new AttributesImpl();
+ if (!prop.isContainment() && !prop.getType().isDataType() && prop.getOpposite() == null) {
+ attrs.addAttribute("commonj.sdo", "ref", "sdo:ref", "CDATA", DataObjectHelper.getSdoRef((PartialDataObject) value));
+ }
+ if (!prop.getType().isDataType()) {
+ Type valueType = ((DataObject) value).getType();
+ if (prop.getType() != valueType) {
+ attrs.addAttribute(XSI_URI, "type", "xsi:type", "CDATA", uriToNamespace.get(valueType.getURI()) + ":" + valueType.getName());
+ }
+ }
+ hd.startElement("", prop.getName(), prop.getName(), attrs);
+ if (prop.getType().isDataType()) {
+ String output = value == null ? "" : TypeConverter.get(prop.getType()).toString(value);
+ hd.characters(output.toCharArray(), 0, output.length());
+ } else {
+ if (prop.isContainment()) {
+ toXml(hd, (PartialDataObject) value, uriToNamespace);
+ }
+ }
+ hd.endElement("", prop.getName(), prop.getName());
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectXmlParser.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectXmlParser.java
new file mode 100644
index 0000000000..8993286fb6
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/DataObjectXmlParser.java
@@ -0,0 +1,146 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.impl.TypeConverter;
+import com.agfa.hap.sdo.implementation.DataObjectHelper.Link;
+
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XMLDocument;
+
+class DataObjectXmlParser extends DefaultHandler {
+
+ private PartialDataObject currentObject;
+ private Property currentProperty;
+ private String nameSpaceURI;
+ private String rootElement;
+ private List<Link> links;
+ private StringBuilder currentValueCharacters;
+ private Map<String, String> prefixMapping;
+
+ public DataObjectXmlParser() {
+ prefixMapping = new HashMap<String, String>();
+ }
+
+
+ @Override
+ public void endPrefixMapping(String prefix) throws SAXException {
+ prefixMapping.remove(prefix);
+ }
+
+
+ @Override
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ prefixMapping.put(prefix, uri);
+ }
+
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (currentProperty != null && currentProperty.getType().isDataType()) {
+ if (currentValueCharacters == null){
+ currentValueCharacters = new StringBuilder();
+ }
+ currentValueCharacters.append(ch, start, length);
+ }
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ processLinks();
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (currentProperty == null) {
+ if (currentObject.getContainer() != null) {
+ currentObject = currentObject.getContainer();
+ }
+ } else {
+ Object currentValue = currentValueCharacters == null ? null : this.convert(currentValueCharacters.toString());
+ currentObject.set(currentProperty, currentValue);
+ currentProperty = null;
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if (rootElement == null) {
+ rootElement = localName;
+ nameSpaceURI = uri;
+ currentObject = PartialDataFactory.INSTANCE.create(resolve(attributes.getValue(DataObjectStreamer.XSI_URI, "type")));
+ } else {
+ currentValueCharacters = null;
+ currentProperty = currentObject.getType().getProperty(localName);
+ if (!currentProperty.getType().isDataType()) {
+ String sdoRef = attributes.getValue("sdo:ref");
+ if (sdoRef != null) {
+ addLink(sdoRef);
+ } else {
+ String xsiType = attributes.getValue("xsi:type");
+ Type type = currentProperty.getType();
+ if (xsiType != null) {
+ type = resolve(xsiType);
+ }
+ currentObject = currentObject.createDataObject(currentProperty, type);
+ currentProperty = null;
+ }
+ }
+ }
+ }
+
+ protected Type resolve(String xsiType) {
+ int index = xsiType.indexOf(':');
+ String uri = nameSpaceURI;
+ if (index >= 0) {
+ String prefix = xsiType.substring(0, index);
+ uri = prefixMapping.get(prefix);
+ xsiType = xsiType.substring(index+1);
+ }
+ return TypeHelper.INSTANCE.getType(uri, xsiType);
+ }
+
+ public XMLDocument getXMLDocument() {
+ return new XMLDocumentImpl(currentObject, nameSpaceURI, rootElement);
+ }
+
+ private Object convert(String value) {
+ if (value.length() == 0) {
+ return null;
+ }
+ TypeConverter type = TypeConverter.get(currentProperty.getType());
+ if (type == null) {
+ throw new IllegalArgumentException("No basic data type defined for type " + currentProperty.getType());
+ }
+ return type.parse(value);
+ }
+
+ private void addLink(String sdoRef) {
+ if (links == null) {
+ links = new ArrayList<Link>();
+ }
+ links.add(new Link(currentObject, currentProperty, sdoRef));
+ }
+
+ private void processLinks() {
+ if (links == null) {
+ return;
+ }
+ for (Link link : links) {
+ link.apply();
+ }
+ links = null;
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/EqualityHelperImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/EqualityHelperImpl.java
new file mode 100644
index 0000000000..a9ef6d7e78
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/EqualityHelperImpl.java
@@ -0,0 +1,135 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.util.Iterator;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.EqualityHelper;
+
+public class EqualityHelperImpl implements EqualityHelper {
+
+ public boolean equal(DataObject dataObject1, DataObject dataObject2) {
+ return equal((PartialDataObject) dataObject1, (PartialDataObject) dataObject2);
+ }
+
+ public boolean equal(PartialDataObject dataObject1, PartialDataObject dataObject2) {
+ if (dataObject1 == null) {
+ return dataObject2 == null;
+ }
+ if (dataObject2 == null) {
+ return false;
+ }
+ if (!dataObject1.getType().equals(dataObject2.getType())) {
+ return false;
+ }
+ for (Property prop : dataObject1.getType().getProperties()) {
+ if (!dataObject1.isSet(prop) && !dataObject2.isSet(prop)) {
+ continue;
+ }
+ if (!dataObject1.isAvailable(prop) && !dataObject2.isAvailable(prop)) {
+ continue;
+ }
+ if (prop.getType().isDataType()) {
+ Object value1 = dataObject1.get(prop);
+ Object value2 = dataObject2.get(prop);
+ if (value1 == null) {
+ if (value2 != null) {
+ return false;
+ }
+ } else {
+ if (value1 instanceof byte[]){
+ if (value2 instanceof byte[]){
+ if ((((byte[])value1).length) == (((byte[])value2).length)){
+ for (int i = 0; i < (((byte[])value1).length); i++ ){
+ if ((((byte[])value1)[i]) != (((byte[])value2)[i])){
+ return false;
+ }
+ }
+ }
+ } else {
+ return false;
+ }
+ } else if (!value1.equals(value2)) {
+ return false;
+ }
+ }
+ } else {
+ if (prop.getOpposite() != null && prop.getOpposite().isContainment()) {
+ continue;
+ }
+ if (prop.isMany()) {
+ Iterator<PartialDataObject> dataObject1It = dataObject1.getList(prop).iterator();
+ Iterator<PartialDataObject> dataObject2It = dataObject2.getList(prop).iterator();
+ while (dataObject1It.hasNext()) {
+ if (!dataObject2It.hasNext()) {
+ return false;
+ }
+ if (!compareChild(prop, dataObject1It.next(), dataObject2It.next())) {
+ return false;
+ }
+ }
+ if (dataObject2It.hasNext()) {
+ return false;
+ }
+ } else {
+ if (!compareChild(prop, dataObject1.getDataObject(prop), dataObject2.getDataObject(prop))) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean compareChild(Property prop, PartialDataObject child1, PartialDataObject child2) {
+ if (prop.isContainment()) {
+ if (!equal(child1, child2))
+ return false;
+ } else {
+ String id1 = DataObjectHelper.getSdoRef(child1);
+ String id2 = DataObjectHelper.getSdoRef(child2);
+ if (!id1.equals(id2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean equalShallow(DataObject dataObject1, DataObject dataObject2) {
+ return equalShallow((PartialDataObject) dataObject1, (PartialDataObject) dataObject2);
+ }
+
+ public boolean equalShallow(PartialDataObject dataObject1, PartialDataObject dataObject2) {
+ if (dataObject1 == null) {
+ return dataObject2 == null;
+ }
+ if (dataObject2 == null) {
+ return false;
+ }
+ if (!dataObject1.getType().equals(dataObject2.getType())) {
+ return false;
+ }
+ for (Property prop : dataObject1.getType().getProperties()) {
+ if (!prop.getType().isDataType()) {
+ continue;
+ }
+ if (!dataObject1.isSet(prop) && !dataObject2.isSet(prop)) {
+ continue;
+ }
+ Object value1 = dataObject1.get(prop);
+ Object value2 = dataObject2.get(prop);
+ if (value1 == null) {
+ if (value2 != null) {
+ return false;
+ }
+ } else {
+ if (!value1.equals(value2)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/IDataObjectList.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/IDataObjectList.java
new file mode 100644
index 0000000000..49211cb42f
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/IDataObjectList.java
@@ -0,0 +1,10 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.util.List;
+
+public interface IDataObjectList<T extends AbstractDataObject> extends List<T> {
+
+ void removeForBidirectionalUpdate(T o);
+ void addForBidirectionalUpdate(T o);
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ImplementationClassRepository.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ImplementationClassRepository.java
new file mode 100644
index 0000000000..d89c827e0d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/ImplementationClassRepository.java
@@ -0,0 +1,129 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.log4j.Logger;
+
+import com.agfa.hap.sdo.util.ClassHolder;
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+/**
+ * Class that provides access to implementation classes for SDO types.
+ * @author AMOCZ
+ */
+public abstract class ImplementationClassRepository {
+
+ protected final String IMPLEMENTATIONCLASS_RESOURCEFILE = "sdo/implementationclasses.properties";
+
+ public interface ClassHolderFactory {
+ ClassHolder createClassHolder(String className);
+ }
+
+ private static ImplementationClassRepository INSTANCE;
+
+ public static ImplementationClassRepository getInstance() {
+ if (INSTANCE == null) {
+ setInstance(new ClassPathImplementationClassRepository());
+ }
+ return INSTANCE;
+ }
+
+ public static void setInstance(ImplementationClassRepository instance) {
+ INSTANCE = instance;
+ instance.initialize();
+ }
+
+ private Map<QualifiedName, ClassHolder> typeName2ImplementationClass;
+
+ public ImplementationClassRepository() {
+ typeName2ImplementationClass = new ConcurrentHashMap<QualifiedName, ClassHolder>();
+ }
+
+ public ClassHolder getImplementationClass(Type type) {
+ return getImplementationClass(type.getURI(), type.getName());
+ }
+
+ public ClassHolder getImplementationClass(String uri, String name) {
+ QualifiedName qname = new QualifiedName(uri, name);
+ return typeName2ImplementationClass.get(qname);
+ }
+
+ public Type getTypeForImplementationClass(String name) {
+ // could be optimized but might not be worth it
+ for (Entry<QualifiedName, ClassHolder> entry : typeName2ImplementationClass.entrySet()) {
+ if (entry.getValue().getClassName().equals(name)) {
+ return TypeHelper.INSTANCE.getType(entry.getKey().getUri(), entry.getKey().getName());
+ }
+ }
+ return null;
+ }
+
+ protected abstract void initialize();
+
+ protected static Logger getLogger() {
+ return Logger.getLogger(ImplementationClassRepository.class);
+ }
+
+ protected void addImplementationClasses(URL propertyFile, ClassHolderFactory factory) {
+ try {
+ Properties props = new Properties();
+ props.load(propertyFile.openStream());
+ addImplementationClasses(props, factory);
+ } catch (Exception e) {
+ getLogger().warn("Could not read implementation classes from stream " + propertyFile, e);
+ }
+ }
+
+ protected void addImplementationClasses(Properties instanceProps, ClassHolderFactory factory) {
+ for (Map.Entry<Object, Object> entry : instanceProps.entrySet()) {
+ this.registerImplementationClassForType(factory.createClassHolder((String) entry.getKey()), (String) entry.getValue());
+ }
+ }
+
+ public void registerImplementationClassForType(ClassHolder classHolder, String qname) {
+ this.typeName2ImplementationClass.put(new QualifiedName(qname), classHolder);
+ }
+
+ public void registerImplementationClassForType(ClassHolder classHolder, String uri, String name) {
+ this.typeName2ImplementationClass.put(new QualifiedName(uri, name), classHolder);
+ }
+
+ private static class QualifiedName {
+ private final String uri;
+ private final String name;
+ public QualifiedName(String qName) {
+ int index = qName.lastIndexOf('$');
+ this.uri = qName.substring(0, index);
+ this.name = qName.substring(index+1);
+ }
+ public QualifiedName(String uri, String name) {
+ this.uri = uri;
+ this.name = name;
+ }
+ public String getUri() {
+ return uri;
+ }
+ public String getName() {
+ return name;
+ }
+ public boolean equals(Object other) {
+ if (other == null || other.getClass() != QualifiedName.class) {
+ return false;
+ }
+ QualifiedName otherQN = (QualifiedName) other;
+ return uri.equals(otherQN.uri) && name.equals(otherQN.name);
+ }
+ public int hashCode() {
+ return uri.hashCode() + name.hashCode();
+ }
+ public String toString() {
+ return uri + "/" + name;
+ }
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/PropertyImplementation.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/PropertyImplementation.java
new file mode 100644
index 0000000000..eaddc6a324
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/PropertyImplementation.java
@@ -0,0 +1,138 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.Type;
+
+public class PropertyImplementation implements Property, Serializable {
+
+ private static final long serialVersionUID = 1234L;
+
+ public PropertyImplementation(String name, Type type, Type container, int index) {
+ this.name = name;
+ this.containingType = container;
+ this.type = type;
+ this.index = index;
+ }
+
+ public List<String> getAliasNames() {
+ return Collections.emptyList();
+ }
+
+ public Type getContainingType() {
+ return containingType;
+ }
+
+ public Object getDefault() {
+ return null;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Property getOpposite() {
+ if (oppositeName != null && oppositeProperty == null) {
+ setOpposite((PropertyImplementation) getType().getProperty(oppositeName));
+ }
+ return oppositeProperty;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public boolean isContainment() {
+ return isContainment;
+ }
+
+ public void setIsContainment(boolean isContainment) {
+ this.isContainment = isContainment;
+ }
+
+ public boolean isMany() {
+ return isMany;
+ }
+
+ public void setIsMany(boolean isMany) {
+ this.isMany = isMany;
+ }
+
+ public boolean isReadOnly() {
+ return isReadOnly;
+ }
+
+ public void setIsReadOnly(boolean isReadOnly) {
+ this.isReadOnly = isReadOnly;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ void setIndex(int index) {
+ this.index = index;
+ }
+
+ public String toString() {
+ return getContainingType().getName() + "." + name;
+ }
+
+ public void setOppositeName(String oppositeName) {
+ this.oppositeName = oppositeName;
+ }
+
+ void setOpposite(PropertyImplementation opposite) {
+ this.oppositeProperty = opposite;
+ opposite.oppositeProperty = this;
+ }
+
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ void createOppositeProperty() {
+ if (oppositeProperty != null) {
+ return;
+ }
+ if (oppositeName == null || !isContainment()) {
+ return;
+ }
+ PropertyImplementation opp = (PropertyImplementation) type.getProperty(oppositeName);
+ if (opp == null) {
+ opp = ((TypeImplementation) type).addProperty(oppositeName, this.getContainingType());
+ }
+ setOpposite(opp);
+ }
+
+
+ public Object get(commonj.sdo.Property property) {
+ return null;
+ }
+
+ public List getInstanceProperties() {
+ return Collections.EMPTY_LIST;
+ }
+
+ public boolean isNullable() {
+ return true;
+ }
+
+ public boolean isOpenContent() {
+ return false;
+ }
+
+
+ private Property oppositeProperty;
+ private boolean isReadOnly;
+ private boolean isMany;
+ private boolean isContainment;
+ private Type type;
+ private String oppositeName;
+ private final Type containingType;
+ private final String name;
+ private int index;
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SdoImplementationException.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SdoImplementationException.java
new file mode 100644
index 0000000000..868e0a3597
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SdoImplementationException.java
@@ -0,0 +1,26 @@
+package com.agfa.hap.sdo.implementation;
+
+/**
+ * Thrown when something went wrong in the sdo implementation.
+ * @author AMOCZ
+ */
+public class SdoImplementationException extends RuntimeException {
+
+ private static final long serialVersionUID = -3690342870276215465L;
+
+ public SdoImplementationException() {
+ }
+
+ public SdoImplementationException(String message) {
+ super(message);
+ }
+
+ public SdoImplementationException(Throwable cause) {
+ super(cause);
+ }
+
+ public SdoImplementationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java
new file mode 100644
index 0000000000..7e3685de22
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotImplementation.java
@@ -0,0 +1,377 @@
+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.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+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 static final Snapshot EMPTY_SNAPSHOT = new SnapshotImplementation(null, null, Collections.emptyList()) ;
+ private transient byte[] serializedContent;
+
+ public static Snapshot emptySnapshot(){
+ return EMPTY_SNAPSHOT;
+ }
+
+ //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 {
+ 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=" + Arrays.toString(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;
+ public static final String ID_ISNULL = ""; //the assumption here is that this will never be a valid value for an identity
+ 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 Collections.<T>emptyList();
+ }
+ 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 if (property.getType().getIdentityProperty() == null){
+ mapper.setUnavailable(instance, property);
+ } else {
+ Object identity = readIdentityValue(in, null, property.getType().getIdentityProperty());
+ if (identity == null){
+ mapper.setUnavailable(instance, property);
+ } else {
+ 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);
+ }
+
+ }
+
+ private Object readIdentityValue(DataInput in, Object parent, Property prop) throws IOException {
+ String value = in.readUTF();
+ if (ID_ISNULL.equals(value)){
+ return null;
+ }
+ 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;
+ }
+ }
+
+ 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) {
+ if (property.getType().getIdentityProperty() != null && !property.isMany()){
+ out.writeUTF(ID_ISNULL); //a bit of a hack in order to be able to set a property unavailabe, where the property is of an type with an id but where the id value is null. The deserialization mechanism expects a value for the identity when reading a proxy for a type with an identityproperty
+ }
+ return;
+ }
+ 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;
+ }
+
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java
new file mode 100644
index 0000000000..c94517f506
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/SnapshotUnion.java
@@ -0,0 +1,36 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeHelperImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeHelperImpl.java
new file mode 100644
index 0000000000..c62e570522
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeHelperImpl.java
@@ -0,0 +1,435 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.apache.log4j.Logger;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.impl.BytesTypeConverter;
+import com.agfa.hap.sdo.impl.TypeConverter;
+import com.agfa.hap.sdo.impl.TypeProvider;
+import com.agfa.hap.sdo.model.CatalogIdentity;
+import com.agfa.hap.sdo.model.LongIdentity;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.XSDHelper;
+
+public class TypeHelperImpl implements TypeHelper {
+
+ private static Logger logger = Logger.getLogger(TypeHelperImpl.class);
+
+ protected static final String HAP_BASIC_TYPE_URI = "com.agfa.hap";
+ private static final String PROPERTY_OPPOSITE = "opposite";
+ private static final String PROPERTY_TYPE = "type";
+ private static final String PROPERTY_CONTAINMENT = "containment";
+ private static final String PROPERTY_MANY = "many";
+ private static final String TYPE_DATA_TYPE = "dataType";
+ private static final String TYPE_NAME = "name";
+ private static final String TYPE_ALIAS_NAME = "aliasName";
+ private static final String TYPE_PROPERTY = "property";
+ private static final String TYPE_BASE_TYPE = "baseType";
+ private static final String TYPE_IDENTIFIERPROPERTY = "identityProperty";
+ private static final String TYPE_URI = "uri";
+
+ public TypeHelperImpl() {
+ types = new ConcurrentHashMap<String, TypeImplementation>();
+ providedURIs = new HashSet<String>();
+ allURIs = new CopyOnWriteArraySet<String>();
+ instanceClass2Type = new HashMap<Class, TypeImplementation>();
+ initializeTypes();
+ }
+
+ private void initializeTypes() {
+ providedURIs.add("commonj.sdo");
+ registerBasicType(String.class, new TypeConverter<String>() {
+ @Override
+ public String parse(String str) {
+ return str;
+ }
+ @Override
+ public String toString(String instance) {
+ return instance;
+ }
+ });
+ registerBasicType(char.class, new TypeConverter<Character>() {
+ @Override
+ public Character parse(String str) {
+ return str.charAt(0);
+ }
+ @Override
+ public String toString(Character instance) {
+ return instance.toString();
+ }
+ });
+ registerBasicType(Integer.class, new TypeConverter<Integer>() {
+ @Override
+ public Integer parse(String str) {
+ return Integer.parseInt(str);
+ }
+ @Override
+ public String toString(Integer instance) {
+ return Integer.toString(instance.intValue());
+ }
+ });
+ registerBasicType(Long.class, new TypeConverter<Long>() {
+ @Override
+ public Long parse(String str) {
+ return Long.parseLong(str);
+ }
+ @Override
+ public String toString(Long instance) {
+ return Long.toString(instance.longValue());
+ }
+ });
+ registerBasicType(Short.class, new TypeConverter<Short>() {
+ @Override
+ public Short parse(String str) {
+ return Short.parseShort(str);
+ }
+ @Override
+ public String toString(Short instance) {
+ return Short.toString(instance.shortValue());
+ }
+ });
+ registerBasicType(Double.class, new TypeConverter<Double>() {
+ @Override
+ public Double parse(String str) {
+ return Double.parseDouble(str);
+ }
+ @Override
+ public String toString(Double instance) {
+ return Double.toString(instance.doubleValue());
+ }
+ });
+ registerBasicType(Float.class, new TypeConverter<Float>() {
+ @Override
+ public Float parse(String str) {
+ return Float.parseFloat(str);
+ }
+ @Override
+ public String toString(Float instance) {
+ return Float.toString(instance.floatValue());
+ }
+ });
+ registerBasicType(Boolean.class, new TypeConverter<Boolean>() {
+ @Override
+ public Boolean parse(String str) {
+ return Boolean.parseBoolean(str);
+ }
+ @Override
+ public String toString(Boolean instance) {
+ return Boolean.toString(instance.booleanValue());
+ }
+ });
+ registerBasicType(Byte.class, new TypeConverter<Byte>() {
+ @Override
+ public Byte parse(String str) {
+ return Byte.parseByte(str);
+ }
+ @Override
+ public String toString(Byte instance) {
+ return Byte.toString(instance.byteValue());
+ }
+ });
+ registerBasicType(URI.class, new TypeConverter<URI>() {
+ @Override
+ public URI parse(String str) {
+ try {
+ return new URI(str);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Illegal uri syntax: " + str);
+ }
+ }
+ @Override
+ public String toString(URI instance) {
+ return instance.toString();
+ }
+ });
+ registerBasicType(Date.class, new TypeConverter<Date>() {
+ @Override
+ public Date parse(String str) {
+ return new Date(Long.parseLong(str));
+ }
+ @Override
+ public String toString(Date instance) {
+ return Long.toString(instance.getTime());
+ }
+ });
+ this.registerBasicType("Bytes", "commonj.sdo", byte[].class, new BytesTypeConverter());
+ registerBasicType(LongIdentity.class, HAP_BASIC_TYPE_URI, new TypeConverter<LongIdentity>() {
+ @Override
+ public LongIdentity parse(String str) {
+ return LongIdentity.fromString(str);
+ }
+ @Override
+ public String toString(LongIdentity instance) {
+ return instance.toString();
+ }
+ });
+ registerBasicType(CatalogIdentity.class, HAP_BASIC_TYPE_URI, new TypeConverter<CatalogIdentity>() {
+ @Override
+ public CatalogIdentity parse(String str) {
+ return CatalogIdentity.fromString(str);
+ }
+ @Override
+ public String toString(CatalogIdentity instance) {
+ return CatalogIdentity.toString(instance);
+ }
+ });
+ providedURIs.add(HAP_BASIC_TYPE_URI);
+ // other basic types from the spec
+// sdoTypeNameToClass.put("DateTime", String.class);
+// sdoTypeNameToClass.put("Int", int.class);
+// sdoTypeNameToClass.put("Month", String.class);
+// sdoTypeNameToClass.put("MonthDay", String.class);
+// sdoTypeNameToClass.put("Object", Object.class);
+// sdoTypeNameToClass.put("Strings", List<String>.class);
+// sdoTypeNameToClass.put("Year", String.class);
+// sdoTypeNameToClass.put("YearMonth", String.class);
+// sdoTypeNameToClass.put("YearMonthDay", String.class);
+ register(new TypeImplementation(Object.class, "commonj.sdo", "Object"));
+ intializeTypeAndPropertyTypes();
+ intializeDataObjectType();
+ }
+
+ private void intializeTypeAndPropertyTypes() {
+ TypeImplementation typeType = define("commonj.sdo", "Type");
+ TypeImplementation propertyType = define("commonj.sdo", "Property");
+ typeType.addProperty(TYPE_BASE_TYPE, typeType).setIsMany(true);
+ PropertyImplementation typeProperties = typeType.addProperty(TYPE_PROPERTY, propertyType);
+ typeProperties.setIsMany(true);
+ typeType.addProperty(TYPE_ALIAS_NAME, getType(String.class)); // should be many
+ typeType.addProperty(TYPE_NAME, getType(String.class));
+ typeType.addProperty("uri", getType(String.class));
+ typeType.addProperty(TYPE_DATA_TYPE, getType(Boolean.class));
+ typeType.addProperty("open", getType(Boolean.class));
+ typeType.addProperty("sequenced", getType(Boolean.class));
+ typeType.addProperty("abstract", getType(Boolean.class));
+ typeType.addProperty(TYPE_IDENTIFIERPROPERTY, getType(String.class));
+ propertyType.addProperty(TYPE_ALIAS_NAME, getType(String.class)); // many=true ,
+ propertyType.addProperty(TYPE_NAME , getType(String.class));
+ propertyType.addProperty(PROPERTY_MANY , getType(Boolean.class));
+ propertyType.addProperty(PROPERTY_CONTAINMENT , getType(Boolean.class));
+ propertyType.addProperty(PROPERTY_TYPE , typeType);
+ typeProperties.setIsContainment(true);
+ propertyType.addProperty("default" , getType("commonj.sdo", "Object"));
+ propertyType.addProperty("readOnly", getType(Boolean.class));
+ propertyType.addProperty(PROPERTY_OPPOSITE, propertyType);
+ }
+
+ private void intializeDataObjectType() {
+ TypeImplementation type = define("commonj.sdo", "DataObject");
+ type.setInstanceClass(DataObject.class);
+ type.setIsDataType(false);
+ type.setIsAbstract(true);
+ }
+
+ public synchronized void register(Type type) {
+ TypeImplementation typeImpl = (TypeImplementation) type;
+ typeImpl.setImplementationClass(ImplementationClassRepository.getInstance().getImplementationClass(typeImpl));
+ types.put(typeImpl.getName(), typeImpl);
+ if (typeImpl.getInstanceClass() != null) {
+ instanceClass2Type.put(typeImpl.getInstanceClass(), typeImpl);
+ }
+ if (typeImpl.isDataType()) {
+ types.put(typeImpl.getInstanceClass().getName(), typeImpl);
+ }
+ allURIs.add(type.getURI());
+ }
+
+ protected void registerBasicType(Class clazz, TypeConverter type) {
+ String typeName = null;
+ if (clazz.getName().startsWith("java.lang.")){
+ typeName = clazz.getName().substring(10);
+ } else {
+ typeName= clazz.getName();
+ }
+ this.registerBasicType(typeName, "commonj.sdo", clazz, type);
+ }
+
+ protected void registerBasicType(Class clazz, String uri, TypeConverter type) {
+ this.registerBasicType(clazz.getName(), uri, clazz, type);
+ }
+
+ protected TypeImplementation registerBasicType(String typeName, String uri, Class instanceClass, TypeConverter type){
+ TypeImplementation typeImp = new TypeImplementation(instanceClass, uri, typeName);
+ register(typeImp);
+ TypeConverter.register(typeImp, type);
+ return typeImp;
+ }
+
+ void register(Iterator<Type> types) {
+ while (types.hasNext()) {
+ TypeImplementation type = (TypeImplementation) types.next();
+ register(type);
+ }
+ }
+
+ public com.agfa.hap.sdo.Type getType(String uri, String typeName) {
+ synchronized(this) {
+ com.agfa.hap.sdo.Type result = types.get(typeName);
+ if (result != null) {
+ return result;
+ }
+ }
+ return getTypeFromProvider(uri, typeName);
+ }
+
+ private TypeImplementation getTypeFromProvider(String uri, String typeName) {
+ if (uri == null) {
+ return null;
+ }
+ if (TypeProvider.getInstance() == null) {
+ return null;
+ }
+ synchronized(this) {
+ if (providedURIs.contains(uri)) {//ok, some other caller will have loaded the types just before us
+ return types.get(typeName);
+ }
+ Set<String> urisToLoad = new HashSet<String>();
+ urisToLoad.add(uri);
+ while (!urisToLoad.isEmpty()){
+ String nextUri = urisToLoad.iterator().next();
+ String xsd = TypeProvider.getInstance().getTypes(nextUri);
+ if (xsd == null) {
+ logger.debug("unable to load sdo types for uri " + nextUri + " from type provider " + TypeProvider.getInstance());
+ return null; //this is not always an exceptional situation (eg when defining a type with a dataobject)
+ }
+ List<com.agfa.hap.sdo.Type> newTypes =XSDHelper.INSTANCE.define(xsd);
+ Set<String> extraURIsToLoad = this.referencedURIs(newTypes);
+ extraURIsToLoad.removeAll(providedURIs);
+ urisToLoad.addAll(extraURIsToLoad);
+ urisToLoad.remove(nextUri);
+ providedURIs.add(uri);
+ }
+ }
+ return types.get(typeName);
+ }
+
+ private Set<String> referencedURIs(List<com.agfa.hap.sdo.Type> types) {
+ Set<String> uris = new HashSet<String>();
+ for (com.agfa.hap.sdo.Type type : types){
+ for (Type baseType : type.getBaseTypes()){
+ uris.add(baseType.getURI());
+ }
+ for (Property property : type.getDeclaredProperties()){
+ uris.add(property.getType().getURI());
+ }
+ }
+ return uris;
+ }
+
+
+
+ public com.agfa.hap.sdo.Type getType(Class interfaceClass) {
+ com.agfa.hap.sdo.Type result = getTypeForInstanceClass(interfaceClass);
+ if (result != null) {
+ return result;
+ }
+ result = getType(null, interfaceClass.getName());
+ if (result != null) {
+ return result;
+ }
+ return getTypeForImplementationClass(interfaceClass.getName());
+ }
+
+ protected synchronized TypeImplementation getTypeForInstanceClass(Class instanceClass) {
+ return instanceClass2Type.get(instanceClass);
+ }
+
+ public com.agfa.hap.sdo.Type getTypeForImplementationClass(String name) {
+ return (com.agfa.hap.sdo.Type) ImplementationClassRepository.getInstance().getTypeForImplementationClass(name);
+ }
+
+ public synchronized com.agfa.hap.sdo.Type define(DataObject type) {
+ TypeImplementation result = (TypeImplementation) getType((String) type.get(TYPE_URI), (String) type.get(TYPE_NAME));
+ if (result != null && result.getProperties().size() == 0) {
+ return result;
+ }
+ result = new TypeImplementation((String) type.get(TYPE_URI), (String) type.get(TYPE_NAME));
+ if (type.isSet(TYPE_DATA_TYPE)) {
+ result.setIsDataType((Boolean) type.get(TYPE_DATA_TYPE));
+ }
+ register(result);
+ Iterator<PartialDataObject> it = type.getList(TYPE_PROPERTY).iterator();
+ while (it.hasNext()) {
+ DataObject property = it.next();
+ com.agfa.hap.sdo.Type propType = define(property.getDataObject(PROPERTY_TYPE));
+ PropertyImplementation prop = result.addProperty((String) property.get(TYPE_NAME), propType);
+ Boolean isMany = (Boolean) property.get(PROPERTY_MANY);
+ prop.setIsMany(isMany != null && isMany.booleanValue());
+ Boolean containment = (Boolean) property.get(PROPERTY_CONTAINMENT);
+ prop.setIsContainment(containment != null && containment.booleanValue());
+ String opposite = (String) property.get(PROPERTY_OPPOSITE);
+ prop.setOppositeName(opposite);
+ }
+ String idProp = (String) type.get(TYPE_IDENTIFIERPROPERTY);
+ if (idProp != null) {
+ result.setIdentityProperty(result.getProperty(idProp));
+ }
+ return result;
+ }
+
+ synchronized com.agfa.hap.sdo.Type defineInstanceClass(String interfaceClassName) {
+ com.agfa.hap.sdo.Type result = getType(null, interfaceClassName);
+ if (result == null) {
+ throw new IllegalArgumentException("Couldn't find class " + interfaceClassName);
+ }
+ return result;
+ }
+
+ synchronized TypeImplementation define(String uri, String name) {
+ TypeImplementation result = types.get(name);
+ if (result == null) {
+ result = new TypeImplementation(uri, name);
+ register(result);
+ }
+ return result;
+ }
+
+ public synchronized List define(List types) {
+ Iterator it = types.iterator();
+ List<Type> result = new ArrayList<Type>();
+ while (it.hasNext()) {
+ result.add(define((DataObject) it.next()));
+ }
+ return result;
+ }
+
+
+ public Collection<String> getKnownUris() {
+ return allURIs;
+ }
+
+
+ public Property defineOpenContentProperty(String uri, DataObject property) {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+ public Property getOpenContentProperty(String uri, String propertyName) {
+ throw new UnsupportedOperationException();
+ }
+
+
+ private final Map<String, TypeImplementation> types;
+ private final Set<String> providedURIs;
+ private final Set<String> allURIs;
+ private Map<Class, TypeImplementation> instanceClass2Type;
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeImplementation.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeImplementation.java
new file mode 100644
index 0000000000..3ac3e5ecca
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/TypeImplementation.java
@@ -0,0 +1,267 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.util.ClassHolder;
+
+import commonj.sdo.DataObject;
+
+public class TypeImplementation implements Type {
+ private static Logger logger = Logger.getLogger(TypeImplementation.class);
+
+ private static final Class[] CONSTRUCTOR_PARAMS = new Class[] { Type.class };
+
+ public TypeImplementation(Class instanceClass) {
+ this.instanceClass = instanceClass;
+ this.isDataType = true;
+ this.name = instanceClass.getName();
+ if (this.name.startsWith("java.lang.")) {
+ this.name = this.name.substring(10);
+ this.uri = "commonj.sdo";
+ } else {
+ logger.warn("no uri for sdo datatype " + instanceClass);
+ }
+ this.properties = Collections.emptyList();
+ this.declaredProperties = Collections.emptyList();
+ this.baseTypes = Collections.emptyList();
+ }
+
+ public TypeImplementation(Class instanceClass, String uri) {
+ this(instanceClass, uri, instanceClass.getName());
+ }
+
+ public TypeImplementation(Class instanceClass, String uri, String name) {
+ this.instanceClass = instanceClass;
+ this.isDataType = true;
+ this.name = name;
+ this.uri = uri;
+ this.properties = Collections.emptyList();
+ this.declaredProperties = Collections.emptyList();
+ this.baseTypes = Collections.emptyList();
+ }
+
+ public void setInstanceClass(Class instanceClass) {
+ this.instanceClass = instanceClass;
+ }
+
+
+
+ public TypeImplementation(String uri, String name) {
+ this.instanceClass = DataObject.class;
+ this.isDataType = false;
+ this.properties = new ArrayList<Property>();
+ this.declaredProperties = new ArrayList<Property>();
+ this.baseTypes = new ArrayList<TypeImplementation>();
+ this.name = name;
+ this.uri = uri;
+ }
+
+ public void setBaseType(TypeImplementation baseType) {
+ if (baseTypes.size() != 0) {
+ throw new IllegalArgumentException("Single inheritance only!");
+ }
+ baseTypes.add(baseType);
+ }
+
+ public void normalizeTypeHierarchy() {
+ if (baseTypes.size() == 0) {
+ return;
+ }
+ TypeImplementation baseType = baseTypes.get(0);
+ baseType.normalizeTypeHierarchy();
+ if (this.implementationClassHolder == null) {
+ this.implementationClassHolder = baseType.implementationClassHolder;
+ }
+ if (baseType.getProperties().size() == 0) {
+ return;
+ }
+ if (properties.size() > 0 && baseType.getProperties().get(0) == properties.get(0)) {
+ // already normalized
+ return;
+ }
+ for (Property prop: baseType.getProperties()) {
+ properties.add(prop.getIndex(), prop);
+ }
+ for (int i = 0; i < properties.size(); i++) {
+ ((PropertyImplementation) properties.get(i)).setIndex(i);
+ }
+ if (baseType.getIdentityProperty() != null && identityProperty == null) {
+ this.identityProperty = baseType.getIdentityProperty();
+ }
+ }
+
+ public PropertyImplementation addProperty(String propertyName, Type type) {
+ PropertyImplementation prop = new PropertyImplementation(propertyName, type, this, properties.size());
+ properties.add(prop);
+ declaredProperties.add(prop);
+ return prop;
+ }
+
+ void addProperty(PropertyImplementation prop) {
+ properties.add(prop);
+ declaredProperties.add(prop);
+ }
+
+ public List<String> getAliasNames() {
+ return Collections.emptyList();
+ }
+
+ public List<TypeImplementation> getBaseTypes() {
+ return baseTypes;
+ }
+
+ public List<Property> getDeclaredProperties() {
+ return declaredProperties;
+ }
+
+ public Class getInstanceClass() {
+ return instanceClass;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<Property> getProperties() {
+ return properties;
+ }
+
+ public Property getProperty(String propertyName) {
+ Iterator it = properties.iterator();
+ while (it.hasNext()) {
+ Property prop = (Property) it.next();
+ if (prop.getName().equals(propertyName)) {
+ return prop;
+ }
+ }
+ return null;
+ }
+
+ public Property getProperty(int index) {
+ return properties.get(index);
+ }
+
+ public String getURI() {
+ return uri;
+ }
+
+ public boolean isAbstract() {
+ return isAbstract;
+ }
+
+ public void setIsAbstract(boolean isAbstract) {
+ this.isAbstract = isAbstract;
+ }
+
+ public boolean isDataType() {
+ return isDataType;
+ }
+
+ public void setIsDataType(boolean isDataType) {
+ this.isDataType = isDataType;
+ }
+
+ public boolean isInstance(Object object) {
+ if (object instanceof DataObject) {
+ return ((DataObject) object).getType().equals(this);
+ }
+ return false;
+ }
+
+ public boolean isOpen() {
+ return false;
+ }
+
+ public boolean isSequenced() {
+ return false;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ }
+ if (other.getClass() != TypeImplementation.class) {
+ return false;
+ }
+ return ((TypeImplementation) other).name.equals(name);
+ }
+
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ public void changePropertyTypes(Map<String, Type> typenameToSpecializingType){
+ for (Property prop : this.getProperties()){
+ if (typenameToSpecializingType.containsKey(prop.getType().getName())){
+ ((PropertyImplementation) prop).setType(typenameToSpecializingType.get(prop.getType().getName()));
+ }
+ }
+ }
+
+ /**
+ * Sets the implementation class. The datafactory will create instances of this
+ * class when creating objects of this type.
+ */
+ public void setImplementationClass(ClassHolder implementationClassName) {
+ this.implementationClassHolder = implementationClassName;
+ }
+
+ public ClassHolder getImplementationClass() {
+ return implementationClassHolder;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Constructor<? extends PartialDataObject> getInstanceConstructor() {
+ if (instanceConstructor == null && implementationClassHolder != null) {
+ try {
+ this.instanceConstructor = implementationClassHolder.resolveClass().getConstructor(CONSTRUCTOR_PARAMS);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Could not find a constructor with a Type parameter for class " + implementationClassHolder);
+ }
+ }
+ return instanceConstructor;
+ }
+
+ public Property getIdentityProperty() {
+ return identityProperty;
+ }
+
+ public void setIdentityProperty(commonj.sdo.Property identityProperty) {
+ this.identityProperty = (Property) identityProperty;
+ }
+
+ public Object get(commonj.sdo.Property property) {
+ throw new UnsupportedOperationException();
+ }
+
+ public List getInstanceProperties() {
+ return Collections.EMPTY_LIST;
+ }
+
+ private boolean isDataType;
+ private transient Class instanceClass; //the instanceclasses don't get serialized, in order to avoid some potential client/server issues
+ private String name;
+ private String uri;
+ private List<Property> properties;
+ private List<Property> declaredProperties;
+ private List<TypeImplementation> baseTypes;
+ private boolean isAbstract;
+ private transient Constructor<? extends PartialDataObject> instanceConstructor;
+ private Property identityProperty;
+ private ClassHolder implementationClassHolder;
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLDocumentImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLDocumentImpl.java
new file mode 100644
index 0000000000..e03e04435c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLDocumentImpl.java
@@ -0,0 +1,85 @@
+package com.agfa.hap.sdo.implementation;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.XMLDocument;
+
+class XMLDocumentImpl implements XMLDocument {
+
+ private DataObject rootObject;
+ private String rootElementURI;
+ private String rootElementName;
+ private String encoding;
+
+
+ public XMLDocumentImpl(DataObject root, String uri, String name) {
+ this();
+ rootObject = root;
+ rootElementName = name;
+ rootElementURI = uri;
+ }
+
+ public XMLDocumentImpl() {
+ encoding = "UTF-8";
+ }
+
+ public DataObject getRootObject() {
+ return rootObject;
+ }
+
+ public String getRootElementURI() {
+ return rootElementURI;
+ }
+
+ public String getRootElementName() {
+ return rootElementName;
+ }
+
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public boolean isXMLDeclaration() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void setXMLDeclaration(boolean xmlDeclaration) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String getXMLVersion() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setXMLVersion(String xmlVersion) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String getSchemaLocation() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setSchemaLocation(String schemaLocation) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String getNoNamespaceSchemaLocation() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setNoNamespaceSchemaLocation(String schemaLocation) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLHelperImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLHelperImpl.java
new file mode 100644
index 0000000000..f6a2d1aca5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XMLHelperImpl.java
@@ -0,0 +1,102 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+
+import org.xml.sax.SAXException;
+
+import sun.reflect.generics.reflectiveObjects.NotImplementedException;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.XMLDocument;
+import commonj.sdo.helper.XMLHelper;
+
+public class XMLHelperImpl implements XMLHelper {
+
+ private DataObjectStreamer dataObjectStreamer;
+
+ public XMLHelperImpl() {
+ dataObjectStreamer = new DataObjectStreamer();
+ }
+
+ public XMLDocument load(String inputString) {
+ try {
+ return load(new StringReader(inputString), null, null);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public XMLDocument load(InputStream inputStream) throws IOException {
+ return load(inputStream, null, null);
+ }
+
+ public XMLDocument load(InputStream inputStream, String locationURI,
+ Object options) throws IOException {
+ try {
+ return dataObjectStreamer.fromXml(inputStream);
+ } catch (SAXException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public XMLDocument load(Source inputSource, String locationURI, Object options) throws IOException {
+ throw new NotImplementedException();
+ }
+
+
+ public XMLDocument load(Reader inputReader, String locationURI,
+ Object options) throws IOException {
+ try {
+ return dataObjectStreamer.fromXml(inputReader);
+ } catch (SAXException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public String save(DataObject dataObject, String rootElementURI,
+ String rootElementName) {
+ StringWriter stringWriter = new StringWriter();
+ try {
+ save(createDocument(dataObject, rootElementURI, rootElementName), stringWriter, null);
+ } catch (IOException e) {
+ throw new RuntimeException("Should not happen!");
+ }
+ return stringWriter.toString();
+ }
+
+ public void save(DataObject dataObject, String rootElementURI,
+ String rootElementName, OutputStream outputStream)
+ throws IOException {
+ save(createDocument(dataObject, rootElementURI, rootElementName), outputStream, null);
+ }
+
+ public void save(XMLDocument xmlDocument, OutputStream outputStream,
+ Object options) throws IOException {
+ dataObjectStreamer.toXml(xmlDocument, outputStream);
+ }
+
+ public void save(XMLDocument xmlDocument, Writer outputWriter,
+ Object options) throws IOException {
+ dataObjectStreamer.toXml(xmlDocument, outputWriter);
+ }
+
+ public XMLDocument createDocument(DataObject dataObject,
+ String rootElementURI, String rootElementName) {
+ return new XMLDocumentImpl(dataObject, rootElementURI, rootElementName);
+ }
+
+ public void save(XMLDocument xmlDocument, Result outputResult, Object options) throws IOException {
+ throw new NotImplementedException();
+ }
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XSDHelperImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XSDHelperImpl.java
new file mode 100644
index 0000000000..4d8c0f3de6
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/implementation/XSDHelperImpl.java
@@ -0,0 +1,616 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.impl.TypeConverter;
+import com.agfa.hap.sdo.util.ClassHolder;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.XSDHelper;
+
+public class XSDHelperImpl implements XSDHelper {
+
+ private static final String IDENTITY_PROPERTY = "identityProperty";
+
+ private static final String AGFA_SDO_URI = "com.agfa.ris/sdo";
+
+ private static Logger logger = Logger.getLogger(XSDHelperImpl.class);
+
+ final static String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
+ final static String SDO_JAVA_URI = "commonj.sdo/java";
+ final static String SDO_URI = "commonj.sdo/xml"; //ref SDO_2.1_DRAFT_20060726.pdf p82
+ final static String SDO_PROPERTYTYPE = "propertyType";
+ final static String XSD_ANYURI = "anyURI";
+
+ public XSDHelperImpl() {
+ initializeXsdTypes();
+ }
+
+ public String getLocalName(Type type) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getLocalName(Property property) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getNamespaceURI(Property property) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean isAttribute(Property property) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isElement(Property property) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isMixed(Type type) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isXSD(Type type) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public Property getGlobalProperty(String uri, String propertyName,
+ boolean isElement) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getAppinfo(Type type, String source) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getAppinfo(Property property, String source) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public List define(String xsd) {
+ StringReader reader = new StringReader(xsd);
+ return define(reader, null);
+ }
+
+ public List define(Reader xsdReader, String schemaLocation) {
+ try {
+ return readXsd(new InputSource(xsdReader));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public List define(InputStream xsdInputStream, String schemaLocation) {
+ try {
+ return readXsd(new InputSource(xsdInputStream));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String generate(List typeList) {
+ //ref SDO_2.1_DRAFT_20060726.pdf p109-114
+ List<com.agfa.hap.sdo.Type> types = typeList;
+ String uri;
+ if (types.isEmpty()){
+ uri = "";
+ } else {
+ uri = types.get(0).getURI();
+ }
+
+ Map<com.agfa.hap.sdo.Type, String> type2URIsToImport = new HashMap<com.agfa.hap.sdo.Type, String>();
+ Map<String, String> uri2Namespace = new HashMap<String, String>();
+ Set<com.agfa.hap.sdo.Type> typesToGenerate = new HashSet<com.agfa.hap.sdo.Type>();
+ for (com.agfa.hap.sdo.Type type : types){
+ this.collectTypes(type, typesToGenerate, type2URIsToImport, uri);
+ }
+ List<com.agfa.hap.sdo.Type> typesToGenerateAlphabetical = new ArrayList<com.agfa.hap.sdo.Type>(typesToGenerate);
+ Collections.sort(typesToGenerateAlphabetical, new Comparator<Type>(){
+ public int compare(Type type1, Type type2) {
+ return type1.getName().compareTo(type2.getName());
+ }});
+ StringWriter stringWriter = new StringWriter();
+ Result result = new StreamResult(stringWriter);
+ try {
+ SAXTransformerFactory tf = (SAXTransformerFactory) TransformerFactory.newInstance();
+ TransformerHandler hd = tf.newTransformerHandler();
+ Transformer serializer = hd.getTransformer();
+ serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ serializer.setOutputProperty(OutputKeys.INDENT,"yes");
+ hd.setResult(result);
+ hd.startDocument();
+ AttributesImpl schemaAttributes = new AttributesImpl();
+ String attribURI = "";
+ hd.startPrefixMapping("sdo", SDO_URI);
+ hd.startPrefixMapping("sdoJava", SDO_JAVA_URI);
+ hd.startPrefixMapping("agfaSdo", AGFA_SDO_URI);
+ if (uri != null){
+ schemaAttributes.addAttribute(attribURI, "targetNamespace", "targetNamespace", "CDATA", uri);
+ hd.startPrefixMapping("tns", uri);
+ }
+ Set<String> urisToImport = new HashSet<String>(type2URIsToImport.values());
+ logger.debug("URIs to import = " + urisToImport);
+ int i = 1;
+ for (String importedURI : urisToImport){
+ String namespace = "ns" + i;
+ hd.startPrefixMapping(namespace, importedURI);
+ uri2Namespace.put(importedURI, namespace);
+ i++;
+ }
+ uri2Namespace.put(uri, "tns");
+ hd.startElement(XML_SCHEMA_URI , "schema", "xsd:schema", schemaAttributes);
+ for (com.agfa.hap.sdo.Type type : typesToGenerateAlphabetical){
+ generateXsdForType(hd, type, uri2Namespace);
+ }
+ hd.endElement(XML_SCHEMA_URI, "schema", "xsd:schema");
+ hd.endDocument();
+ } catch (Exception e){
+ throw new SdoImplementationException("", e);
+ }
+ for (com.agfa.hap.sdo.Type type : typesToGenerate){
+ if (!types.contains(type)){
+ types.add(type);
+ }
+ }
+ return stringWriter.toString();
+ }
+
+ private void collectTypes(com.agfa.hap.sdo.Type type, Set<com.agfa.hap.sdo.Type> typesToGenerate, Map<com.agfa.hap.sdo.Type, String> typesToImport, String uri) {
+ if (typesToGenerate.contains(type)){
+ return;
+ }
+ if ("commonj.sdo".equals(type.getURI())){
+ return;
+ }
+ if (!uri.equals(type.getURI())){
+ typesToImport.put(type, type.getURI());
+ return;
+ }
+ typesToGenerate.add(type);
+ for (com.agfa.hap.sdo.Property prop : type.getDeclaredProperties()){
+ this.collectTypes(prop.getType(), typesToGenerate, typesToImport, uri);
+ }
+
+ }
+
+ private void generateXsdForType(TransformerHandler hd, com.agfa.hap.sdo.Type type, Map<String, String> uri2Namespace) throws SAXException {
+ String namespaceURI= "";
+ AttributesImpl typeAttributes = new AttributesImpl();
+ typeAttributes.addAttribute(namespaceURI, "name", "name", "CDATA", type.getName());
+ if (type.isAbstract()) {
+ typeAttributes.addAttribute(namespaceURI, "abstract", "abstract", "CDATA", Boolean.toString(type.isAbstract()));
+ }
+ if (type.isSequenced()){
+ typeAttributes.addAttribute(namespaceURI, "mixed", "mixed", "CData", "true");
+ }
+ if (type.getIdentityProperty() != null) {
+ typeAttributes.addAttribute(namespaceURI, IDENTITY_PROPERTY, IDENTITY_PROPERTY, "CData", type.getIdentityProperty().getName());
+ }
+ hd.startElement(namespaceURI, "complexType", "xsd:complexType", typeAttributes);
+ if (type.getBaseTypes() != null && !type.getBaseTypes().isEmpty()){
+ hd.startElement(namespaceURI, "complexContent", "xsd:complexContent", new AttributesImpl());
+ AttributesImpl extensionAttributes = new AttributesImpl();
+ Type baseType = type.getBaseTypes().get(0);
+ extensionAttributes.addAttribute(namespaceURI, "base", "base", "CDATA", uri2Namespace.get(baseType.getURI())+ ":" + baseType.getName());
+ hd.startElement(namespaceURI, "extension", "xsd:extension", extensionAttributes );
+ hd.endElement(namespaceURI, "extension", "xsd:extension");
+ hd.endElement(namespaceURI, "complexContent", "xsd:complexContent");
+ }
+ List<Property> elementProperties = new ArrayList<Property>();
+ List<Property> attributeProperties = new ArrayList<Property>();
+ for (Property prop : type.getDeclaredProperties()){
+ if (prop.isContainment() || prop.isMany()){
+ //create an element
+ elementProperties.add(prop);
+ } else if (prop.getOpposite() != null && prop.getOpposite().isContainment()){
+ //do nothing
+ } else {
+ //create an attribute
+ attributeProperties.add(prop);
+ }
+ }
+ if (!elementProperties.isEmpty()){
+ if (type.isSequenced()){
+ hd.startElement(namespaceURI, "sequence", "xsd:sequence", null);
+ } else {
+ AttributesImpl choiceAttributes = new AttributesImpl();
+ choiceAttributes.addAttribute(namespaceURI, "maxOccurs", "maxOccurs", "CDATA", "unbounded");
+ hd.startElement(namespaceURI, "choice", "xsd:choice", choiceAttributes);
+ }
+ for (Property prop : elementProperties){
+ AttributesImpl elementAttributes = new AttributesImpl();
+ elementAttributes.addAttribute(namespaceURI, "name", "name", "CDATA", prop.getName());
+ elementAttributes.addAttribute(namespaceURI, "minOccurs", "name", "CDATA", prop.getName());
+ if (!prop.getAliasNames().isEmpty()){
+ StringBuilder aliasNames = new StringBuilder();
+ for (Object aliasName : prop.getAliasNames()){
+ aliasNames.append(aliasName);
+ aliasNames.append(' ');
+ }
+ if (aliasNames.length() != 0) {
+ aliasNames.setLength(aliasNames.length() - 1);
+ }
+ elementAttributes.addAttribute(namespaceURI, "aliasName", "sdo:aliasName", "CDATA", aliasNames.toString());
+ }
+ elementAttributes.addAttribute(namespaceURI, "readOnly", "sdo:readOnly", "CDATA", Boolean.toString(prop.isReadOnly()));
+ if (prop.isMany()){
+ elementAttributes.addAttribute(namespaceURI, "maxOccurs", "maxOccurs", "CDATA", "unbounded");
+ }
+ if (prop.getType().isDataType()){
+ elementAttributes.addAttribute(namespaceURI, "type", "type", "CDATA", "xsd:" + this.xsdTypeForSDOType(prop.getType().getName()));
+ } else if (prop.isContainment()){
+ elementAttributes.addAttribute(namespaceURI, "type", "type", "CDATA", uri2Namespace.get(prop.getType().getURI()) + ":" + prop.getType().getName());
+ } else {
+ elementAttributes.addAttribute(namespaceURI, "type", "type", "CDATA", "xsd:anyUri");
+ elementAttributes.addAttribute(namespaceURI, "propertyType", "sdo:propertyType", "CDATA", uri2Namespace.get(prop.getType().getURI()) + ":" + prop.getType().getName());
+ }
+ if (prop.getOpposite() != null){
+ elementAttributes.addAttribute(namespaceURI, "oppositeProperty", "sdo:oppositeProperty", "CDATA", prop.getOpposite().getName());
+ }
+ hd.startElement(namespaceURI, "element", "xsd:element", elementAttributes);
+ hd.endElement(namespaceURI, "element", "xsd:element");
+ }
+ if (type.isSequenced()){
+ hd.endElement(namespaceURI, "sequence", "xsd:sequence");
+ } else {
+ hd.endElement(namespaceURI, "choice", "xsd:choice");
+ }
+ }
+
+ for (Property prop : attributeProperties){
+ AttributesImpl attributeAttributes = new AttributesImpl();
+ attributeAttributes.addAttribute(namespaceURI, "name", "name", "CDATA", prop.getName());
+ if (!prop.getAliasNames().isEmpty()){
+ StringBuilder aliasNames = new StringBuilder();
+ for (Object aliasName : prop.getAliasNames()){
+ aliasNames.append(aliasName);
+ aliasNames.append(' ');
+ }
+ if (aliasNames.length() != 0) {
+ aliasNames.setLength(aliasNames.length() - 1);
+ }
+ attributeAttributes.addAttribute(namespaceURI, "aliasName", "sdo:aliasName", "CDATA", aliasNames.toString());
+ }
+ attributeAttributes.addAttribute(namespaceURI, "readOnly", "sdo:readOnly", "CDATA", Boolean.toString(prop.isReadOnly()));
+ if (prop.getDefault() != null){
+ attributeAttributes.addAttribute(namespaceURI, "default", "default", "CDATA", prop.getDefault().toString());
+ }
+ if (prop.getType().isDataType()){
+ String xsdType = this.xsdTypeForSDOType(prop.getType().getName());
+ if (xsdType != null) {
+ attributeAttributes.addAttribute(namespaceURI, "type", "type", "CDATA", "xsd:" + xsdType);
+ } else {
+ attributeAttributes.addAttribute(namespaceURI, "instanceClass", "sdoJava:instanceClass", "CDATA", prop.getType().getName());
+ }
+ } else {
+ attributeAttributes.addAttribute(namespaceURI, "type", "type", "CDATA", "xsd:anyURI");
+ attributeAttributes.addAttribute(namespaceURI, "propertyType", "sdo:propertyType", "CDATA", uri2Namespace.get(prop.getType().getURI()) + ":" + prop.getType().getName());
+ }
+ if (prop.getOpposite() != null){
+ attributeAttributes.addAttribute(namespaceURI, "oppositeProperty", "sdo:oppositeProperty", "CDATA", prop.getOpposite().getName());
+ }
+
+ hd.startElement(namespaceURI, "attribute", "xsd:attribute", attributeAttributes);
+ hd.endElement(namespaceURI, "attribute", "xsd:attribute");
+ }
+ hd.endElement(namespaceURI, "complexType", "xsd:complexType");
+ }
+
+ public String generate(List types, Map namespaceToSchemaLocation) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ List<Type> readXsd(InputSource in) throws IOException, SAXException, ParserConfigurationException {
+ Document document = parse(in);
+ String uri = document.getDocumentElement().getAttributeNS(XML_SCHEMA_URI, "targetNamespace");
+ if (uri.length() == 0) {
+ uri = document.getDocumentElement().getAttribute("targetNamespace");
+ }
+ Map<String, String> uriPrefixMap = new HashMap<String, String>();
+ NamedNodeMap docAttributes = document.getDocumentElement().getAttributes();
+ String defaultNamespaceURI = null;
+ for (int i = 0; i < docAttributes.getLength(); i++){
+ Node attribute = docAttributes.item(i);
+ if ("http://www.w3.org/2000/xmlns/".equals(attribute.getNamespaceURI())){
+ if ("xmlns".equals(attribute.getNodeName())){
+ defaultNamespaceURI = attribute.getNodeValue();
+ } else {
+ uriPrefixMap.put(attribute.getNodeName().substring(attribute.getNodeName().lastIndexOf(':') + 1), attribute.getNodeValue());
+ }
+ }
+ }
+ NodeList types = document.getElementsByTagNameNS(XML_SCHEMA_URI, "simpleType");
+ List<Type> result = new ArrayList<Type>();
+ readTypes(uri, uriPrefixMap, defaultNamespaceURI, types, result);
+ types = document.getElementsByTagNameNS(XML_SCHEMA_URI, "complexType");
+ readTypes(uri, uriPrefixMap, defaultNamespaceURI, types, result);
+ createOppositeProperties(result);
+ resolveBaseTypes(result);
+ return result;
+ }
+
+ private void readTypes(String uri, Map<String, String> uriPrefixMap, String defaultNamespaceURI, NodeList types, List<Type> result) {
+ for (int i = 0; i < types.getLength(); i++) {
+ Element type = (Element) types.item(i);
+ result.add(readType(uri, type, defaultNamespaceURI, uriPrefixMap));
+ }
+ }
+
+ private void createOppositeProperties(List<Type> types) {
+ for (Type t : types) {
+ // no iterator to avoid ConcurrentModificationException
+ for (int i = 0; i < t.getDeclaredProperties().size(); i++) {
+ ((PropertyImplementation) t.getDeclaredProperties().get(i)).createOppositeProperty();
+ }
+ }
+ }
+
+ private void resolveBaseTypes(List<Type> types) {
+ for (Type t : types) {
+ ((TypeImplementation) t).normalizeTypeHierarchy();
+ }
+ }
+
+ private Document parse(InputSource in) throws ParserConfigurationException, SAXException, IOException {
+ Document document;
+ try {
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ document = documentBuilder.parse(in);
+ } finally {
+ if (in.getByteStream() != null) {
+ in.getByteStream().close();
+ }
+ if (in.getCharacterStream() != null) {
+ in.getCharacterStream().close();
+ }
+ }
+ return document;
+ }
+
+ Type readType(String uri, Element typeElement, String defaultNamespaceURI, Map<String, String> uriPrefixMap) {
+ if (typeElement.getNodeName().endsWith("simpleType")) {
+ return readSimpleType(typeElement, uri);
+ }
+ String name = typeElement.getAttribute("name");
+ TypeImplementation result = ((TypeHelperImpl) TypeHelper.INSTANCE).define(uri, name);
+ superType(typeElement, defaultNamespaceURI, uriPrefixMap, result);
+ NodeList nodeList = typeElement.getElementsByTagNameNS(XML_SCHEMA_URI, "attribute");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ createProperty(result, (Element) nodeList.item(i), defaultNamespaceURI, uriPrefixMap, uri);
+ }
+ nodeList = typeElement.getElementsByTagNameNS(XML_SCHEMA_URI, "element");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ createProperty(result, (Element) nodeList.item(i), defaultNamespaceURI, uriPrefixMap, uri);
+ }
+ if (typeElement.hasAttributeNS(SDO_JAVA_URI, "extendedInstanceClass")) {
+ try {
+ Class instanceClass = Class.forName(typeElement.getAttributeNS(SDO_JAVA_URI, "extendedInstanceClass"));
+ result.setInstanceClass(instanceClass);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Unknown java class ", e);
+ }
+ }
+ String id = typeElement.getAttribute(IDENTITY_PROPERTY);
+ if (id != null) {
+ result.setIdentityProperty(result.getProperty(id));
+ }
+ return result;
+ }
+
+ private void superType(Element typeElement, String defaultNamespaceURI, Map<String, String> uriPrefixMap, TypeImplementation result) {
+ if (!result.getBaseTypes().isEmpty()){
+ return; //in case the type already has a base type, leave it as it is
+ //TODO review: alternative is to overwrite the existing base type with a new one
+ }
+ NodeList nodeList = typeElement.getElementsByTagNameNS(XML_SCHEMA_URI, "extension");
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ String superTypeName = ((Element) nodeList.item(i)).getAttribute("base");
+ Type superType = resolveType(superTypeName, uriPrefixMap, defaultNamespaceURI);
+ result.setBaseType((TypeImplementation) superType);
+ }
+ }
+
+ private Type readSimpleType(Element type, String uri) {
+ String name = type.getAttribute("name");
+ try {
+ Class<?> instanceClass = null;
+ TypeConverter<?> typeConverter = null;
+ String instanceClassName = type.getAttributeNS(SDO_JAVA_URI, "instanceClass");
+ if (instanceClassName != null && instanceClassName.length() > 0) {
+ instanceClass = Class.forName(instanceClassName);
+ String typeConverterName = type.getAttributeNS(AGFA_SDO_URI, "typeConverter");
+ if (typeConverterName != null && typeConverterName.length() > 0) {
+ try {
+ typeConverter = (TypeConverter<?>) Class.forName(typeConverterName).newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Unknown TypeConverter class " + typeConverterName, e);
+ }
+ }
+ }
+ if (instanceClass == null) {
+ ClassHolder classHolder = ImplementationClassRepository.getInstance().getImplementationClass(uri, name);
+ if (classHolder == null) {
+ throw new SdoImplementationException("No implementation class registered for type " + uri + ":" + name);
+ }
+ instanceClass = classHolder.resolveClass();
+ }
+ if (typeConverter == null) {
+ typeConverter = TypeConverter.getDefaultConverter(instanceClass);
+ }
+ return ((TypeHelperImpl) TypeHelper.INSTANCE).registerBasicType(name, uri, instanceClass, typeConverter);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException("Unknown java class " , e);
+ }
+ }
+
+ private void createProperty(TypeImplementation type, Element node, String defaultNamespaceURI, Map<String, String> uriPrefixMap, String targetNameSpace) {
+ boolean isSdoRef = false;
+ String propertyName = node.getAttribute("name");
+ if (type.getProperty(propertyName) != null){
+ return; //property already exists, so don't create another one, since the property may already be referenced by other types (eg in case of an opposite property)
+ }
+ String xsdType = node.getAttribute("type");
+ com.agfa.hap.sdo.Type propertyType;
+ if (xsdType.length() > 0) {
+ int prefixIndex = xsdType.indexOf(':');
+ if (prefixIndex > 0) {
+ String namespacePrefix = xsdType.substring(0, prefixIndex);
+ String xsdTypeWithoutPrefix = xsdType.substring(prefixIndex+1);
+ String namespace = uriPrefixMap.get(namespacePrefix);
+ if (XML_SCHEMA_URI.equals(namespace)){
+ if (xsdTypeWithoutPrefix.equals(XSD_ANYURI)) {
+ String fullPropertyTypeName = node.getAttributeNS(SDO_URI, SDO_PROPERTYTYPE);
+ if (fullPropertyTypeName.length() == 0) {
+ propertyType = TypeHelper.INSTANCE.getType(URI.class);
+ } else {
+ isSdoRef = true;
+ int propIndex = fullPropertyTypeName.indexOf(':');
+ String sdoPropertyTypeNamespace = null;
+ String propertyTypeName = null;
+ if (propIndex > 0) {
+ String prefix = fullPropertyTypeName.substring(0, propIndex);
+ sdoPropertyTypeNamespace = uriPrefixMap.get(prefix);
+ propertyTypeName = fullPropertyTypeName.substring(propIndex + 1);
+ } else {
+ sdoPropertyTypeNamespace = defaultNamespaceURI;
+ }
+ if (sdoPropertyTypeNamespace == null){
+ logger.warn("no namespace for " + fullPropertyTypeName + " in " + type);
+ }
+ // define will return the existing type if it already exists, or create a new one otherwise,
+ // in the latter case, it will have 0 properties, but those will get filled in later
+ propertyType = ((TypeHelperImpl) TypeHelper.INSTANCE).define(sdoPropertyTypeNamespace, propertyTypeName);
+ }
+ } else {
+ propertyType = TypeHelper.INSTANCE.getType("commonj.sdo", this.sdoTypeForXSDType(xsdTypeWithoutPrefix));
+ }
+ } else {
+ propertyType = ((TypeHelperImpl) TypeHelper.INSTANCE).define(namespace, xsdTypeWithoutPrefix);
+ }
+ } else {
+ propertyType = ((TypeHelperImpl) TypeHelper.INSTANCE).define(type.getURI(), xsdType);
+ }
+ } else {
+ String instanceClassName = node.getAttributeNS(SDO_JAVA_URI, "instanceClass");
+ propertyType = ((TypeHelperImpl) TypeHelper.INSTANCE).defineInstanceClass(instanceClassName);
+ }
+ PropertyImplementation result = type.addProperty(propertyName, propertyType);
+ String oppositeProperty = node.getAttributeNS(SDO_URI, "oppositeProperty");
+ if (oppositeProperty != null && oppositeProperty.length() > 0) {
+ result.setOppositeName(oppositeProperty);
+ }
+ String nodePrefix = node.getPrefix();
+ if (nodePrefix != null && XML_SCHEMA_URI.equals(uriPrefixMap.get(nodePrefix))
+ && "element".equals(node.getNodeName().substring(nodePrefix.length() + 1))
+ &&!isSdoRef && !propertyType.isDataType()) {
+ result.setIsContainment(true);
+ }
+ if ("unbounded".equals(node.getAttribute("maxOccurs"))) {
+ result.setIsMany(true);
+ }
+
+ }
+
+ private Type resolveType(String xsdType, Map<String, String> uriPrefixMap, String defaultNamespaceURI) {
+ int prefixIndex = xsdType.indexOf(':');
+ if (prefixIndex > 0) {
+ String namespacePrefix = xsdType.substring(0, prefixIndex);
+ String xsdTypeWithoutPrefix = xsdType.substring(prefixIndex+1);
+ String namespace = uriPrefixMap.get(namespacePrefix);
+ if (XML_SCHEMA_URI.equals(namespace)){
+ return TypeHelper.INSTANCE.getType("commonj.sdo", this.sdoTypeForXSDType(xsdTypeWithoutPrefix));
+ }
+ return ((TypeHelperImpl) TypeHelper.INSTANCE).define(namespace, xsdTypeWithoutPrefix);
+ }
+ return ((TypeHelperImpl) TypeHelper.INSTANCE).define(defaultNamespaceURI, xsdType);
+ }
+
+ private String sdoTypeForXSDType(String actualType) {
+ return xsdType2SdoType.get(actualType);
+ }
+
+ private String xsdTypeForSDOType(String sdoTypename){
+ return sdoType2XsdTypes.get(sdoTypename);
+ }
+
+ protected void registerXsdType(String xsdSimpleType, Class javaClass) {
+ if (javaClass.getName().startsWith("java.lang.")){
+ this.registerXsdType(xsdSimpleType, javaClass, javaClass.getName().substring(javaClass.getName().lastIndexOf('.') + 1));
+ } else {
+ this.registerXsdType(xsdSimpleType, javaClass, javaClass.getName());
+ }
+ }
+
+ protected void initializeXsdTypes() {
+ //ref SDO_2_.1_DRAFT_20060726.pdf p97
+ registerXsdType("string", String.class);
+ registerXsdType("int", Integer.class);
+ registerXsdType("long", Long.class);
+ registerXsdType("double", Double.class);
+ registerXsdType("boolean", Boolean.class);
+ registerXsdType("short", Short.class);
+ registerXsdType("byte", Byte.class);
+ registerXsdType("float", Float.class);
+ registerXsdType("hexBinary", byte[].class, "Bytes");
+ registerXsdType("anyURI", URI.class);
+ }
+
+ protected void registerXsdType(String xsdSimpleType, Class javaClass, String sdoTypeName) {
+ sdoType2XsdTypes.put(sdoTypeName, xsdSimpleType);
+ xsdType2SdoType.put(xsdSimpleType, sdoTypeName);
+ }
+
+
+ private Map<String, String> sdoType2XsdTypes = new HashMap<String, String>();
+ private Map<String, String> xsdType2SdoType = new HashMap<String, String>();
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java
new file mode 100644
index 0000000000..3b27452007
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/AbstractPropertyAccessor.java
@@ -0,0 +1,35 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java
new file mode 100644
index 0000000000..71f7e8e3f5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessor.java
@@ -0,0 +1,79 @@
+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, e.getTargetException());
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Couldn't access property " + property, 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, e.getTargetException());
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Couldn't access property " + property, 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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java
new file mode 100644
index 0000000000..1ebb121177
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilder.java
@@ -0,0 +1,62 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java
new file mode 100644
index 0000000000..dea136e15c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingDataMapper.java
@@ -0,0 +1,71 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java
new file mode 100644
index 0000000000..a925a2d9db
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/DelegatingPartialDataObjectMapper.java
@@ -0,0 +1,119 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilder.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilder.java
new file mode 100644
index 0000000000..b395574c24
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilder.java
@@ -0,0 +1,75 @@
+package com.agfa.hap.sdo.mapper;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.Type;
+
+/**
+ * {@link PropertyAccessorBuilder} that allows configuration of dedicated
+ * PropertyAccessor classes for properties. Each time such properties are accessed
+ * (read and written) the configured {@link PropertyAccessor}.
+ *
+ * Configuration of a property must be done in "sdo-propertyaccessors.properties" properties file.
+ * The name of a property should be the fully qualified class name followed by '.'
+ * followed by the name of the property. The value of the property is the fully
+ * qualified name of a class that implements {@link PropertyAccessor}.
+ *
+ * @author AMOCZ
+ */
+public class ExtendablePropertyAccessorBuilder extends PropertyAccessorBuilder {
+ private static final String SDOPROPERTYACCESSORS = "sdo-propertyaccessors.properties";
+ private Properties specialPropertyAccessors = new Properties();
+ public ExtendablePropertyAccessorBuilder(PropertyAccessorBuilder next){
+ super(next);
+ initializeClassPropertyAccessorMap();
+ }
+
+ private void initializeClassPropertyAccessorMap() {
+ try {
+ Enumeration<URL> props = this.getClass().getClassLoader().getResources(SDOPROPERTYACCESSORS);
+ while (props.hasMoreElements()) {
+ specialPropertyAccessors.load(props.nextElement().openStream());
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected boolean accepts(Class cls, Type type) {
+ return true;
+ }
+
+ @Override
+ protected PropertyAccessor createPropertyAccessor(Class cls, Property prop) {
+ //TODO performance: in most cases there will be no special property accessor
+ String accessor = null;
+ Class clazz = cls;
+ while (clazz != null){
+ String qualifiedProperty = clazz.getName() + "." + prop.getName();
+ accessor = specialPropertyAccessors.getProperty(qualifiedProperty);
+ if (accessor != null){
+ try {
+ return (PropertyAccessor) Class.forName(accessor).newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("while creating property accessor for " + qualifiedProperty + " accessor=" + accessor, e);
+ }
+ }
+ clazz = clazz.getSuperclass();
+ }
+
+ //no special accessor found
+ return next.createPropertyAccessorOrDelegate(cls, prop);
+
+
+ }
+
+ public void reinitialize() {
+ this.initializeClassPropertyAccessorMap();
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java
new file mode 100644
index 0000000000..a64b69b87d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FalsePropertyAccessor.java
@@ -0,0 +1,13 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java
new file mode 100644
index 0000000000..4ccd81ca69
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/FilteringPartialDataObjectMapper.java
@@ -0,0 +1,30 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java
new file mode 100644
index 0000000000..08fe60f7de
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/JavaBeanMapper.java
@@ -0,0 +1,125 @@
+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);
+ }
+ Collection<?> value = (Collection<?>) propertyAccessor.getValue(object, property, this);
+ if (value == null){
+ return Collections.emptyList().iterator();
+ }
+ return value.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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java
new file mode 100644
index 0000000000..1f35cd26b1
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedBeanPropertyAccessor.java
@@ -0,0 +1,25 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedNullPropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedNullPropertyAccessor.java
new file mode 100644
index 0000000000..1c5b28d5e1
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/ManyValuedNullPropertyAccessor.java
@@ -0,0 +1,23 @@
+package com.agfa.hap.sdo.mapper;
+
+import java.util.Collection;
+
+import com.agfa.hap.sdo.DataMapper;
+import com.agfa.hap.sdo.Property;
+
+public class ManyValuedNullPropertyAccessor extends ManyValuedBeanPropertyAccessor{
+
+ @Override
+ public Object getValue(Object instance, Property property, DataMapper dataMapper) {
+ return null;
+ }
+
+ @Override
+ public void initialize(Object instance, Collection<Object> value) {
+ }
+
+ @Override
+ public void setValue(Object instance, Property property, Object newValue, DataMapper dataMapper) {
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java
new file mode 100644
index 0000000000..3d593fded2
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/NullPropertyAccessor.java
@@ -0,0 +1,17 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java
new file mode 100644
index 0000000000..156723b5c0
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PartialDataObjectMapper.java
@@ -0,0 +1,77 @@
+package com.agfa.hap.sdo.mapper;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java
new file mode 100644
index 0000000000..26f12c10cf
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessor.java
@@ -0,0 +1,26 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java
new file mode 100644
index 0000000000..428768ecc1
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/PropertyAccessorBuilder.java
@@ -0,0 +1,53 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java
new file mode 100644
index 0000000000..ad555078e5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TruePropertyAccessor.java
@@ -0,0 +1,13 @@
+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/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java
new file mode 100644
index 0000000000..3340fa4cb1
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/mapper/TypeMapper.java
@@ -0,0 +1,81 @@
+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;
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/CatalogIdentity.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/CatalogIdentity.java
new file mode 100644
index 0000000000..3eb9b4d2ad
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/CatalogIdentity.java
@@ -0,0 +1,51 @@
+package com.agfa.hap.sdo.model;
+
+import java.util.StringTokenizer;
+
+public class CatalogIdentity extends Identity {
+
+ private static final long serialVersionUID = -1631933616618962179L;
+ private static final String SEPARATOR = "!";
+
+ public CatalogIdentity(String databaseId, Long alid, String catalogName, Long dbUID, String lid) {
+ super(databaseId, new Object[]{alid, catalogName, dbUID, lid});
+ }
+
+ public Long getAlid(){
+ return (Long)((Object[])getPrimaryKey())[0];
+ }
+
+ public String getCatalogName(){
+ return (String)((Object[])getPrimaryKey())[1];
+ }
+
+ public Long getDbUID(){
+ return (Long)((Object[])getPrimaryKey())[2];
+ }
+
+ public String getLid(){
+ return (String)((Object[])getPrimaryKey())[3];
+ }
+
+ public static CatalogIdentity fromString(String str) {
+ StringTokenizer tokenizer = new StringTokenizer(str, SEPARATOR);
+ String databaseId = tokenizer.nextToken();
+ String alid = tokenizer.nextToken();
+ String catalogName = tokenizer.nextToken();
+ String dbUID = tokenizer.nextToken();
+ String lid = tokenizer.nextToken();
+ return new CatalogIdentity(databaseId,
+ "null".equals(alid) ? null : Long.valueOf(alid),
+ catalogName,
+ "null".equals(dbUID) ? null : Long.valueOf(dbUID), lid);
+ }
+
+ public static String toString(CatalogIdentity instance) {
+ return instance.getDatabaseId()
+ + SEPARATOR + instance.getAlid()
+ + SEPARATOR + instance.getCatalogName()
+ + SEPARATOR + instance.getDbUID()
+ + SEPARATOR + instance.getLid();
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/Identity.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/Identity.java
new file mode 100644
index 0000000000..5b1c4bd26c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/Identity.java
@@ -0,0 +1,60 @@
+package com.agfa.hap.sdo.model;
+
+import java.io.Serializable;
+
+public abstract class Identity implements Serializable {
+
+ private final Serializable primaryKey;
+ private final String databaseId;
+
+ // temporary until we finally decide on how to do the databaseId
+ public Identity(Serializable primaryKey) {
+ this(null, primaryKey);
+ }
+
+ public Identity(String databaseId, Serializable primaryKey) {
+ this.databaseId = databaseId;
+ this.primaryKey = primaryKey;
+ }
+
+ public String getDatabaseId() {
+ return databaseId;
+ }
+
+ public Serializable getPrimaryKey() {
+ return primaryKey;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ }
+ if (other.getClass() != this.getClass()) {
+ return false;
+ }
+ Identity otherIdentity = (Identity) other;
+ return isEquals(primaryKey, otherIdentity.primaryKey) && isEquals(databaseId, otherIdentity.databaseId);
+ }
+
+ @Override
+ public int hashCode() {
+ return primaryKey.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ if (databaseId == null) {
+ return primaryKey.toString();
+ }
+ return databaseId + "/" + primaryKey.toString();
+ }
+
+ private static boolean isEquals(Object one, Object two) {
+ if (one == null) {
+ return two == null;
+ }
+ return one.equals(two);
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/LongIdentity.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/LongIdentity.java
new file mode 100644
index 0000000000..0d552b7e54
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/LongIdentity.java
@@ -0,0 +1,24 @@
+package com.agfa.hap.sdo.model;
+
+
+public class LongIdentity extends Identity {
+
+ public LongIdentity(String databaseId, Long primaryKey) {
+ super(databaseId, primaryKey);
+ }
+
+ @Override
+ public Long getPrimaryKey() {
+ return (Long) super.getPrimaryKey();
+ }
+
+ public static LongIdentity fromString(String str) {
+ int lastSlashIndex = str.lastIndexOf('/');
+ String databaseId = null;
+ if (lastSlashIndex >= 0) {
+ databaseId = str.substring(0, lastSlashIndex);
+ str = str.substring(lastSlashIndex+1, str.length());
+ }
+ return new LongIdentity(databaseId, Long.parseLong(str));
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/ObjectReference.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/ObjectReference.java
new file mode 100644
index 0000000000..66eca80469
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/ObjectReference.java
@@ -0,0 +1,105 @@
+package com.agfa.hap.sdo.model;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+/**
+ * Encapsulate a reference to a server-side object. Can be converted to and from a {@link URI}.
+ *
+ * @author AMOCZ
+ */
+public class ObjectReference implements Serializable {
+
+ private static final long serialVersionUID = 8626498796265240806L;
+
+ private transient Type type;
+ private transient Identity id;
+
+ public ObjectReference(String uri) {
+ try {
+ this.initialize(new URI(uri));
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Invalid uri " + uri);
+ }
+ }
+
+ public ObjectReference(URI uri) {
+ initialize(uri);
+ }
+
+ private void initialize(URI uri) {
+ String frag = uri.getFragment();
+ this.id = LongIdentity.fromString(frag);
+ String ssp = uri.getSchemeSpecificPart();
+ int index = ssp.indexOf('/');
+ this.type = TypeHelper.INSTANCE.getType(ssp.substring(0, index), ssp.substring(index+1));
+ }
+
+ public ObjectReference(Type type, Identity id) {
+ if (id == null){
+ throw new IllegalArgumentException("objectreference should have an id");
+ }
+ this.type = type;
+ this.id = id;
+ }
+
+ public Identity getId() {
+ return id;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public URI asURI() {
+ try {
+ return new URI("ris", type.getURI() + "/" + type.getName(), id.toString());
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Couldn't create URI", e);
+ }
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+ out.writeUTF(type.getURI());
+ out.writeUTF(type.getName());
+ out.writeObject(id);
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+ String uri = in.readUTF();
+ String name = in.readUTF();
+ type = TypeHelper.INSTANCE.getType(uri, name);
+ id = (Identity) in.readObject();
+ }
+
+ public PartialDataObject createProxy() {
+ return PartialDataFactory.INSTANCE.createProxy(type, id);
+ }
+
+ public String toString() {
+ return type.getURI() + "/" + type.getName() + "#" + id;
+ }
+
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ }
+ if (other.getClass() != this.getClass()) {
+ return false;
+ }
+ ObjectReference otherRef = (ObjectReference) other;
+ return otherRef.id.equals(id) && otherRef.type.equals(type);
+ }
+
+ public int hashCode() {
+ return id.hashCode();
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/StringIdentity.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/StringIdentity.java
new file mode 100644
index 0000000000..27a5be4951
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/model/StringIdentity.java
@@ -0,0 +1,14 @@
+package com.agfa.hap.sdo.model;
+
+public class StringIdentity extends Identity {
+
+ public StringIdentity(String databaseId, String id){
+ super(databaseId, id);
+ }
+
+ @Override
+ public String getPrimaryKey() {
+ return (String) super.getPrimaryKey();
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/BundleClassHolder.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/BundleClassHolder.java
new file mode 100644
index 0000000000..7f89908b05
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/BundleClassHolder.java
@@ -0,0 +1,28 @@
+package com.agfa.hap.sdo.osgi;
+
+import org.osgi.framework.Bundle;
+
+import com.agfa.hap.sdo.util.ClassForNameClassHolder;
+
+public class BundleClassHolder extends ClassForNameClassHolder {
+
+ final Bundle bundle;
+
+ public BundleClassHolder(Bundle bundle, String name) {
+ super(name);
+ this.bundle = bundle;
+ }
+
+ @Override
+ public Class resolveClass() {
+ try {
+ return bundle.loadClass(getClassName());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Could not find class " + getClassName() + " in bundle " + bundle.getBundleId(), e);
+ }
+ }
+
+
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/OsgiBasedImplementationClassRepository.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/OsgiBasedImplementationClassRepository.java
new file mode 100644
index 0000000000..6ec6583d6d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/OsgiBasedImplementationClassRepository.java
@@ -0,0 +1,84 @@
+package com.agfa.hap.sdo.osgi;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionDelta;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IRegistryChangeEvent;
+import org.eclipse.core.runtime.IRegistryChangeListener;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+
+import com.agfa.hap.sdo.implementation.ImplementationClassRepository;
+import com.agfa.hap.sdo.util.ClassHolder;
+
+/**
+ * Registers all implementation classes for the bundles that extend the
+ * com.agfa.hap.sdo.implementationclasses extension point.
+ *
+ * @author AMOCZ
+ */
+public class OsgiBasedImplementationClassRepository extends ImplementationClassRepository {
+
+ private static final String IMPLEMENTATIONCLASSES_EXTENSION = "com.agfa.hap.sdo.implementationclasses";
+
+ @Override
+ protected void initialize() {
+ processExtensions();
+ Platform.getExtensionRegistry().addRegistryChangeListener(new IRegistryChangeListener() {
+
+ public void registryChanged(IRegistryChangeEvent event) {
+ IExtensionDelta[] deltas = event.getExtensionDeltas("com.agfa.hap.sdo", IMPLEMENTATIONCLASSES_EXTENSION);
+ for (IExtensionDelta delta : deltas) {
+ if (delta.getKind() == IExtensionDelta.ADDED) {
+ initializeImplementationClasses(delta.getExtension());
+ }
+ }
+ }
+
+ }, "com.agfa.hap.sdo");
+ }
+
+ protected void processExtensions() {
+ IExtensionPoint exp = Platform.getExtensionRegistry().getExtensionPoint(IMPLEMENTATIONCLASSES_EXTENSION);
+ for (IExtension extension : exp.getExtensions()) {
+ initializeImplementationClasses(extension);
+ }
+ }
+
+ protected void initializeImplementationClasses(IExtension extension) {
+ final Bundle bundle = Platform.getBundle(extension.getContributor().getName());
+ try {
+ URL url = bundle.getEntry(IMPLEMENTATIONCLASS_RESOURCEFILE);
+ if (url != null) {
+ // this works outside of eclipse, with a jar build by maven
+ addImplementationClasses(bundle, url);
+ return;
+ }
+ Enumeration<URL> urls = bundle.getResources(IMPLEMENTATIONCLASS_RESOURCEFILE);
+ if (urls == null) {
+ return;
+ }
+ while (urls.hasMoreElements()){
+ addImplementationClasses(bundle, urls.nextElement());
+ }
+ } catch (IOException e) {
+ getLogger().warn("Could not read implementation classes.", e);
+ }
+ }
+
+ protected void addImplementationClasses(final Bundle bundle, URL url) {
+ addImplementationClasses(url, new ClassHolderFactory() {
+
+ public ClassHolder createClassHolder(String className) {
+ return new BundleClassHolder(bundle, className);
+ }
+
+ });
+ }
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/SdoActivator.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/SdoActivator.java
new file mode 100644
index 0000000000..67440b942e
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/osgi/SdoActivator.java
@@ -0,0 +1,90 @@
+package com.agfa.hap.sdo.osgi;
+
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.Platform;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+
+import com.agfa.hap.sdo.impl.SdoImplementationFactory;
+import com.agfa.hap.sdo.implementation.ImplementationClassRepository;
+
+public class SdoActivator implements BundleActivator {
+
+ private static SdoActivator instance;
+
+ public static SdoActivator getInstance() {
+ return instance;
+ }
+
+ private BundleContext context;
+
+ public void start(BundleContext context) throws Exception {
+ instance = this;
+ this.context = context;
+ findHelperProvider();
+ initializeImplementationClassesRepository();
+ }
+
+ protected void findHelperProvider() {
+ boolean firstTime = true;
+ IExtensionPoint exp = Platform.getExtensionRegistry().getExtensionPoint("com.agfa.hap.sdo.helperprovider");
+ if (exp == null) {
+ return;
+ }
+ for (IExtension extension : exp.getExtensions()) {
+ if (!firstTime) {
+ throw new IllegalArgumentException("There should be only one extension for com.agfa.hap.sdo.helperprovider!");
+ }
+ firstTime = false;
+ Bundle bundle = Platform.getBundle(extension.getContributor().getName());
+ String impName = extension.getConfigurationElements()[0].getAttribute("class");
+ try {
+ SdoImplementationFactory.setImplementationClass(bundle.loadClass(impName));
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Can't find implementation class repository implementation: " + impName, e);
+ }
+ }
+ }
+
+ protected void initializeImplementationClassesRepository() {
+ ImplementationClassRepository.setInstance(new OsgiBasedImplementationClassRepository());
+ }
+
+ public BundleContext getContext() {
+ return context;
+ }
+
+ /**
+ * Empty default implementation
+ */
+ public void stop(BundleContext context) throws Exception {
+ }
+
+ /**
+ * returns an implementation of the given interface
+ *
+ * @param <T>
+ * @param interfaceClass
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T getService(Class<T> interfaceClass) {
+ ServiceReference sr = context.getServiceReference(interfaceClass
+ .getName());
+ if (sr == null) {
+ return null;
+ }
+
+ T service = (T) context.getService(sr);
+ return service;
+ }
+
+ public <T> ServiceRegistration registerService(Class<T> clazz, T service) {
+ ServiceRegistration sr = context.registerService(clazz.getName(), service, null);
+ return sr;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassForNameClassHolder.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassForNameClassHolder.java
new file mode 100644
index 0000000000..1048b3dc69
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassForNameClassHolder.java
@@ -0,0 +1,24 @@
+package com.agfa.hap.sdo.util;
+
+public class ClassForNameClassHolder implements ClassHolder {
+
+ private final String name;
+
+ public ClassForNameClassHolder(final String name) {
+ super();
+ this.name = name;
+ }
+
+ public Class resolveClass() {
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Could not resolve class " + name, e);
+ }
+ }
+
+ public String getClassName() {
+ return name;
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassHolder.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassHolder.java
new file mode 100644
index 0000000000..24d8a1c580
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassHolder.java
@@ -0,0 +1,14 @@
+package com.agfa.hap.sdo.util;
+
+/**
+ * Object that is able to produce a class when asked. The goal of this class is to
+ * delay classloading as long as possible.
+ * @author AMOCZ
+ */
+public interface ClassHolder {
+
+ Class resolveClass();
+
+ String getClassName();
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassLoaderBasedClassHolder.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassLoaderBasedClassHolder.java
new file mode 100644
index 0000000000..62c72f5f55
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ClassLoaderBasedClassHolder.java
@@ -0,0 +1,24 @@
+package com.agfa.hap.sdo.util;
+
+public class ClassLoaderBasedClassHolder extends ClassForNameClassHolder {
+
+ private final ClassLoader classLoader;
+
+ public ClassLoaderBasedClassHolder(final String name, final ClassLoader classLoader) {
+ super(name);
+ this.classLoader = classLoader;
+ }
+
+ @Override
+ public Class resolveClass() {
+ try {
+ return classLoader.loadClass(getClassName());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Could not resolve class " + getClassName(), e);
+ }
+ }
+
+
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ResultSet.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ResultSet.java
new file mode 100644
index 0000000000..df491c13de
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/com/agfa/hap/sdo/util/ResultSet.java
@@ -0,0 +1,133 @@
+package com.agfa.hap.sdo.util;
+
+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 com.agfa.hap.sdo.PartialDataObject;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+
+/**
+ * This class converts a list of dataobjects into a ResultSet.
+ * In case of many-valued properties, appropriate cartesian products are made.
+ *
+ * Example: Suppose for a list of serviceRequests we want a ResultSet for the
+ * properties requestedProcedures.id, patient.name. In case we have three service
+ * requests (sr?) each with a number of requested procedures (reqProc?), we get
+ * the following "result set".
+ *
+ * sr1 pat1.name reqProc1.id
+ * sr1 pat1.name reqProc2.id
+ * sr2 pat2.name reqProc3.id
+ * sr2 pat2.name reqProc4.id
+ * sr3 null reqProc5.id
+ *
+ * The order in which the rows are returned is not defined.
+ *
+ * This class is useful to use a snapshot as input for a Jasper Reports data source.
+ * @author AMOCZ
+ */
+public class ResultSet {
+
+ private final static String ROOT = "";
+
+ private final List<Map<String, Object>> data;
+
+ private final Type rootType;
+
+ public ResultSet(Collection<? extends DataObject> data, List<String> propertyPaths, Type rootType) {
+ this.data = new ArrayList<Map<String,Object>>();
+ this.rootType = rootType;
+ addData(data);
+ for (String propertyPath : propertyPaths) {
+ addProperty(propertyPath);
+ }
+ }
+
+ public ResultSet(Collection<? extends DataObject> data, String selectClause, Type rootType) {
+ this.data = new ArrayList<Map<String,Object>>();
+ this.rootType = rootType;
+ addData(data);
+ addProperties(selectClause);
+ }
+
+ protected void addProperties(String selectClause) {
+ String[] props = selectClause.split("\\s*,\\s*");
+ for (String prop : props) {
+ addProperty(prop);
+ }
+ }
+
+ public int getSize() {
+ return data.size();
+ }
+
+ public Object getValue(int row, String propertyPath) {
+ return data.get(row).get(propertyPath);
+ }
+
+ protected void addData(Collection<? extends DataObject> dos) {
+ for (DataObject d:dos) {
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put(ROOT, d);
+ data.add(map);
+ }
+ }
+
+ protected void addProperty(String propertyPath) {
+ String rootPath = ROOT;
+ Type type = rootType;
+ while (propertyPath.length() > 0) {
+ int index = propertyPath.indexOf('.');
+ String propertyName = propertyPath;
+ if (index >= 0) {
+ propertyName = propertyPath.substring(0, index);
+ propertyPath = propertyPath.substring(index+1);
+ } else {
+ propertyPath = "";
+ }
+ Property property = type.getProperty(propertyName);
+ rootPath = addProperty(rootPath, property);
+ type = property.getType();
+ }
+ }
+
+ protected String addProperty(String rootPath, Property property) {
+ String propertyPath = rootPath.length() == 0 ? property.getName() : rootPath + "." + property.getName();
+ int length = data.size();
+ for (int i = 0 ; i < length; i++) {
+ Map<String, Object> values = data.get(i);
+ if (i == 0 && values.containsKey(propertyPath)) {
+ return propertyPath;
+ }
+ PartialDataObject value = (PartialDataObject) values.get(rootPath);
+ if (value == null) {
+ continue;
+ }
+ if (property.isMany()) {
+ boolean firstTime = true;
+ Iterator<PartialDataObject> it = value.getList(property).iterator();
+ while (it.hasNext()) {
+ if (firstTime) {
+ values.put(propertyPath, it.next());
+ firstTime = false;
+ } else {
+ Map<String, Object> newValues = new HashMap<String, Object>(values);
+ newValues.put(propertyPath, it.next());
+ data.add(newValues);
+ }
+ }
+ } else {
+ values.put(propertyPath, value.get(property));
+ }
+ }
+ return propertyPath;
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/ChangeSummary.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/ChangeSummary.java
new file mode 100644
index 0000000000..1b4d667109
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/ChangeSummary.java
@@ -0,0 +1,207 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo;
+
+import java.util.List;
+
+/**
+ * A change summary is used to record changes to DataObjects,
+ * allowing applications to efficiently and incrementally update back-end storage when required.
+ */
+public interface ChangeSummary
+{
+ /**
+ * Indicates whether change logging is on (<code>true</code>) or off (<code>false</code>).
+ * @return <code>true</code> if change logging is on.
+ * @see #beginLogging
+ * @see #endLogging
+ */
+ boolean isLogging();
+
+ /**
+ * Returns the {@link DataGraph data graph} associated with this change summary or null.
+ * @return the data graph.
+ * @see DataGraph#getChangeSummary
+ */
+ DataGraph getDataGraph();
+
+ /**
+ * Returns a list consisting of all the {@link DataObject data objects} that have been changed while {@link #isLogging logging}.
+ * <p>
+ * The {@link #isCreated new} and {@link #isModified modified} objects in the List are references to objects
+ * associated with this ChangeSummary.
+ * The {@link #isDeleted deleted} objects in the List are references to objects
+ * at the time that event logging was enabled;
+ * <p> Each changed object must have exactly one of the following methods return true:
+ * {@link #isCreated isCreated},
+ * {@link #isDeleted isDeleted}, or
+ * {@link #isModified isModified}.
+ * @return a list of changed data objects.
+ * @see #isCreated(DataObject)
+ * @see #isDeleted(DataObject)
+ * @see #isModified(DataObject)
+ */
+ List /*DataObject*/ getChangedDataObjects();
+
+ /**
+ * Returns whether or not the specified data object was created while {@link #isLogging logging}.
+ * Any object that was added to the scope
+ * but was not in the scope when logging began,
+ * will be considered created.
+ * @param dataObject the data object in question.
+ * @return <code>true</code> if the specified data object was created.
+ * @see #getChangedDataObjects
+ */
+ boolean isCreated(DataObject dataObject);
+
+ /**
+ * Returns whether or not the specified data object was deleted while {@link #isLogging logging}.
+ * Any object that is not in scope but was in scope when logging began
+ * will be considered deleted.
+ * @param dataObject the data object in question.
+ * @return <code>true</code> if the specified data object was deleted.
+ * @see #getChangedDataObjects
+ */
+ boolean isDeleted(DataObject dataObject);
+
+ /**
+ * A setting encapsulates a {@link Property property} and a corresponding single value of the property's {@link Property#getType type}.
+ */
+ public interface Setting
+ {
+ /**
+ * Returns the property of the setting.
+ * @return the setting property.
+ */
+ Property getProperty();
+
+ /**
+ * Returns the value of the setting.
+ * @return the setting value.
+ */
+ Object getValue();
+
+ /**
+ * Returns whether or not the property is set.
+ * @return <code>true</code> if the property is set.
+ */
+ boolean isSet();
+ }
+
+ /**
+ * Returns a list of {@link ChangeSummary.Setting settings}
+ * that represent the property values of the given <code>dataObject</code>
+ * at the point when logging {@link #beginLogging() began}.
+ * <p>In the case of a {@link #isDeleted(DataObject) deleted} object,
+ * the List will include settings for all the Properties.
+ * <p> An old value setting indicates the value at the
+ * point logging begins. A setting is only produced for
+ * {@link #isModified modified} objects if
+ * either the old value differs from the current value or
+ * if the isSet differs from the current value.
+ * <p> No settings are produced for {@link #isCreated created} objects.
+ * @param dataObject the object in question.
+ * @return a list of settings.
+ * @see #getChangedDataObjects
+ */
+ List /*ChangeSummary.Setting*/ getOldValues(DataObject dataObject);
+
+ /**
+ * Clears the List of {@link #getChangedDataObjects changes} and turns change logging on.
+ * No operation occurs if logging is already on.
+ * @see #endLogging
+ * @see #isLogging
+ */
+ void beginLogging();
+
+ /**
+ * An implementation that requires logging may throw an UnsupportedOperationException.
+ * Turns change logging off. No operation occurs if logging is already off.
+ * @see #beginLogging
+ * @see #isLogging
+ */
+ void endLogging();
+
+
+ /**
+ * Returns whether or not the specified data object was updated while {@link #isLogging logging}.
+ * An object that was contained in the scope when logging began
+ * and remains in the scope when logging ends will be considered potentially modified.
+ * <p> An object considered modified must have at least one old value setting.
+ * @param dataObject the data object in question.
+ * @return <code>true</code> if the specified data object was modified.
+ * @see #getChangedDataObjects
+ */
+ boolean isModified(DataObject dataObject);
+
+ /**
+ * Returns the ChangeSummary root DataObject - the object from which
+ * changes are tracked.
+ * When a DataGraph is used, this is the same as getDataGraph().getRootObject().
+ * @return the ChangeSummary root DataObject
+ */
+ DataObject getRootObject();
+
+ /**
+ * Returns a {@link ChangeSummary.Setting setting} for the specified property
+ * representing the property value of the given <code>dataObject</code>
+ * at the point when logging {@link #beginLogging() began}.
+ * <p>Returns null if the property was not modified and
+ * has not been {@link #isDeleted(DataObject) deleted}.
+ * @param dataObject the object in question.
+ * @param property the property of the object.
+ * @return the Setting for the specified property.
+ * @see #getChangedDataObjects
+ */
+ Setting getOldValue(DataObject dataObject, Property property);
+
+ /**
+ * Returns the value of the {@link DataObject#getContainer container} data object
+ * at the point when logging {@link #beginLogging() began}.
+ * @param dataObject the object in question.
+ * @return the old container data object.
+ */
+ DataObject getOldContainer(DataObject dataObject);
+
+ /**
+ * Returns the value of the {@link DataObject#getContainmentProperty containment property} data object property
+ * at the point when logging {@link #beginLogging() began}.
+ * @param dataObject the object in question.
+ * @return the old containment property.
+ */
+ Property getOldContainmentProperty(DataObject dataObject);
+
+ /**
+ * Returns the value of the {@link DataObject#getSequence sequence} for the data object
+ * at the point when logging {@link #beginLogging() began}.
+ * @param dataObject the object in question.
+ * @return the old containment property.
+ */
+ Sequence getOldSequence(DataObject dataObject);
+
+ /**
+ * This method is intended for use by service implementations only.
+ * Undoes all changes in the log to restore the tree of
+ * DataObjects to its original state when logging began.
+ * isLogging() is unchanged. The log is cleared.
+ * @see #beginLogging
+ * @see #endLogging
+ * @see #isLogging
+ */
+ void undoChanges();
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataGraph.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataGraph.java
new file mode 100644
index 0000000000..2ffd2c6120
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataGraph.java
@@ -0,0 +1,76 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo;
+
+import java.io.Serializable;
+
+/**
+ * A data graph is used to package a graph of {@link DataObject data objects} along with their
+ * metadata, that is, data describing the data.
+ * A data graph also contains a {@link #getChangeSummary change summary}
+ * which is used to record changes made to the objects in the graph.
+ */
+
+public interface DataGraph extends Serializable
+{
+ /**
+ * Returns the root {@link DataObject data object} of this data graph.
+ * @return the root data object.
+ * @see DataObject#getDataGraph
+ */
+ DataObject getRootObject();
+
+ /**
+ * Returns the {@link ChangeSummary change summary} associated with this data graph.
+ * @return the change summary.
+ * @see ChangeSummary#getDataGraph
+ */
+ ChangeSummary getChangeSummary();
+
+ /**
+ * Returns the {@link Type type} with the given the {@link Type#getURI() URI},
+ * or contained by the resource at the given URI,
+ * and with the given {@link Type#getName name}.
+ * @param uri the namespace URI of a type or the location URI of a resource containing a type.
+ * @param typeName name of a type.
+ * @return the type with the corresponding namespace and name.
+ */
+ Type getType(String uri, String typeName);
+
+ /**
+ * Creates a new root data object of the {@link #getType specified type}.
+ * An exception is thrown if a root object exists.
+ * @param namespaceURI namespace of the type.
+ * @param typeName name of the type.
+ * @return the new root.
+ * @throws IllegalStateException if the root object already exists.
+ * @see #createRootObject(Type)
+ * @see #getType(String, String)
+ */
+ DataObject createRootObject(String namespaceURI, String typeName);
+
+ /**
+ * Creates a new root data object of the specified type.
+ * An exception is thrown if a root object exists.
+ * @param type the type of the new root.
+ * @return the new root.
+ * @throws IllegalStateException if the root object already exists.
+ * @see #createRootObject(String, String)
+ */
+ DataObject createRootObject(Type type);
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataObject.java
new file mode 100644
index 0000000000..7e1b5950bc
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/DataObject.java
@@ -0,0 +1,1121 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * A data object is a representation of some structured data.
+ * It is the fundamental component in the SDO (Service Data Objects) package.
+ * Data objects support reflection, path-based accesss, convenience creation and deletion methods,
+ * and the ability to be part of a {@link DataGraph data graph}.
+ * <p>
+ * Each data object holds its data as a series of {@link Property Properties}.
+ * Properties can be accessed by name, property index, or using the property meta object itself.
+ * A data object can also contain references to other data objects, through reference-type Properties.
+ * <p>
+ * A data object has a series of convenience accessors for its Properties.
+ * These methods either use a path (String),
+ * a property index,
+ * or the {@link Property property's meta object} itself, to identify the property.
+ * Some examples of the path-based accessors are as follows:
+ *<pre>
+ * DataObject company = ...;
+ * company.get("name"); is the same as company.get(company.getType().getProperty("name"))
+ * company.set("name", "acme");
+ * company.get("department.0/name") is the same as ((DataObject)((List)company.get("department")).get(0)).get("name")
+ * .n indexes from 0 ... implies the name property of the first department
+ * company.get("department[1]/name") [] indexes from 1 ... implies the name property of the first department
+ * company.get("department[number=123]") returns the first department where number=123
+ * company.get("..") returns the containing data object
+ * company.get("/") returns the root containing data object
+ *</pre>
+ * <p> There are general accessors for Properties, i.e., {@link #get(Property) get} and {@link #set(Property, Object) set},
+ * as well as specific accessors for the primitive types and commonly used data types like
+ * String, Date, List, BigInteger, and BigDecimal.
+ */
+public interface DataObject extends Serializable
+{
+ /**
+ * Returns the value of a property of either this object or an object reachable from it, as identified by the
+ * specified path.
+ * @param path the path to a valid object and property.
+ * @return the value of the specified property.
+ * @see #get(Property)
+ */
+ Object get(String path);
+
+ /**
+ * Sets a property of either this object or an object reachable from it, as identified by the specified path,
+ * to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void set(String path, Object value);
+
+ /**
+ * Returns whether a property of either this object or an object reachable from it, as identified by the specified path,
+ * is considered to be set.
+ * @param path the path to a valid object and property.
+ * @see #isSet(Property)
+ */
+ boolean isSet(String path);
+
+ /**
+ * Unsets a property of either this object or an object reachable from it, as identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @see #unset(Property)
+ */
+ void unset(String path);
+
+ /**
+ * Returns the value of a <code>boolean</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>boolean</code> value of the specified property.
+ * @see #get(String)
+ */
+ boolean getBoolean(String path);
+
+ /**
+ * Returns the value of a <code>byte</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>byte</code> value of the specified property.
+ * @see #get(String)
+ */
+ byte getByte(String path);
+
+ /**
+ * Returns the value of a <code>char</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>char</code> value of the specified property.
+ * @see #get(String)
+ */
+ char getChar(String path);
+
+ /**
+ * Returns the value of a <code>double</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>double</code> value of the specified property.
+ * @see #get(String)
+ */
+ double getDouble(String path);
+
+ /**
+ * Returns the value of a <code>float</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>float</code> value of the specified property.
+ * @see #get(String)
+ */
+ float getFloat(String path);
+
+ /**
+ * Returns the value of a <code>int</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>int</code> value of the specified property.
+ * @see #get(String)
+ */
+ int getInt(String path);
+
+ /**
+ * Returns the value of a <code>long</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>long</code> value of the specified property.
+ * @see #get(String)
+ */
+ long getLong(String path);
+
+ /**
+ * Returns the value of a <code>short</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>short</code> value of the specified property.
+ * @see #get(String)
+ */
+ short getShort(String path);
+
+ /**
+ * Returns the value of a <code>byte[]</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>byte[]</code> value of the specified property.
+ * @see #get(String)
+ */
+ byte[] getBytes(String path);
+
+ /**
+ * Returns the value of a <code>BigDecimal</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>BigDecimal</code> value of the specified property.
+ * @see #get(String)
+ */
+ BigDecimal getBigDecimal(String path);
+
+ /**
+ * Returns the value of a <code>BigInteger</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>BigInteger</code> value of the specified property.
+ * @see #get(String)
+ */
+ BigInteger getBigInteger(String path);
+
+ /**
+ * Returns the value of a <code>DataObject</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>DataObject</code> value of the specified property.
+ * @see #get(String)
+ */
+ DataObject getDataObject(String path);
+
+ /**
+ * Returns the value of a <code>Date</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>Date</code> value of the specified property.
+ * @see #get(String)
+ */
+ Date getDate(String path);
+
+ /**
+ * Returns the value of a <code>String</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>String</code> value of the specified property.
+ * @see #get(String)
+ */
+ String getString(String path);
+
+ /**
+ * Returns the value of a <code>List</code> property identified by the specified path.
+ * @param path the path to a valid object and property.
+ * @return the <code>List</code> value of the specified property.
+ * @see #get(String)
+ */
+ List getList(String path);
+
+ /**
+ * @see #getSequence()
+ * Returns the value of a <code>Sequence</code> property identified by the specified path.
+ * An implementation may throw an UnsupportedOperationException.
+ * @param path the path to a valid object and property.
+ * @return the <code>Sequence</code> value of the specified property.
+ * @see #get(String)
+ * @deprecated in 2.1.0.
+ */
+ Sequence getSequence(String path);
+
+ /**
+ * Sets the value of a <code>boolean</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setBoolean(String path, boolean value);
+
+ /**
+ * Sets the value of a <code>byte</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setByte(String path, byte value);
+
+ /**
+ * Sets the value of a <code>char</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setChar(String path, char value);
+
+ /**
+ * Sets the value of a <code>double</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setDouble(String path, double value);
+
+ /**
+ * Sets the value of a <code>float</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setFloat(String path, float value);
+
+ /**
+ * Sets the value of a <code>int</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setInt(String path, int value);
+
+ /**
+ * Sets the value of a <code>long</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setLong(String path, long value);
+
+ /**
+ * Sets the value of a <code>short</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setShort(String path, short value);
+
+ /**
+ * Sets the value of a <code>byte[]</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setBytes(String path, byte[] value);
+
+ /**
+ * Sets the value of a <code>BigDecimal</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setBigDecimal(String path, BigDecimal value);
+
+ /**
+ * Sets the value of a <code>BigInteger</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setBigInteger(String path, BigInteger value);
+
+ /**
+ * Sets the value of a <code>DataObject</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setDataObject(String path, DataObject value);
+
+ /**
+ * Sets the value of a <code>Date</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setDate(String path, Date value);
+
+ /**
+ * Sets the value of a <code>String</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ */
+ void setString(String path, String value);
+
+ /**
+ * Sets the value of a <code>List</code> property identified by the specified path, to the specified value.
+ * @param path the path to a valid object and property.
+ * @param value the new value for the property.
+ * @see #set(String, Object)
+ * @see #setList(Property, List)
+ */
+ void setList(String path, List value);
+
+ /**
+ * Returns the value of the property at the specified index in {@link Type#getProperties property list}
+ * of this object's {@link Type type}.
+ * @param propertyIndex the index of the property.
+ * @return the value of the specified property.
+ * @see #get(Property)
+ */
+ Object get(int propertyIndex);
+
+ /**
+ * Sets the property at the specified index in {@link Type#getProperties property list} of this object's
+ * {@link Type type}, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void set(int propertyIndex, Object value);
+
+ /**
+ * Returns whether the the property at the specified index in {@link Type#getProperties property list} of this object's
+ * {@link Type type}, is considered to be set.
+ * @param propertyIndex the index of the property.
+ * @return whether the specified property is set.
+ * @see #isSet(Property)
+ */
+ boolean isSet(int propertyIndex);
+
+ /**
+ * Unsets the property at the specified index in {@link Type#getProperties property list} of this object's {@link Type type}.
+ * @param propertyIndex the index of the property.
+ * @see #unset(Property)
+ */
+ void unset(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>boolean</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>boolean</code> value of the specified property.
+ * @see #get(int)
+ */
+ boolean getBoolean(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>byte</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>byte</code> value of the specified property.
+ * @see #get(int)
+ */
+ byte getByte(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>char</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>char</code> value of the specified property.
+ * @see #get(int)
+ */
+ char getChar(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>double</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>double</code> value of the specified property.
+ * @see #get(int)
+ */
+ double getDouble(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>float</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>float</code> value of the specified property.
+ * @see #get(int)
+ */
+ float getFloat(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>int</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>int</code> value of the specified property.
+ * @see #get(int)
+ */
+ int getInt(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>long</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>long</code> value of the specified property.
+ * @see #get(int)
+ */
+ long getLong(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>short</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>short</code> value of the specified property.
+ * @see #get(int)
+ */
+ short getShort(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>byte[]</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>byte[]</code> value of the specified property.
+ * @see #get(int)
+ */
+ byte[] getBytes(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>BigDecimal</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>BigDecimal</code> value of the specified property.
+ * @see #get(int)
+ */
+ BigDecimal getBigDecimal(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>BigInteger</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>BigInteger</code> value of the specified property.
+ * @see #get(int)
+ */
+ BigInteger getBigInteger(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>DataObject</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>DataObject</code> value of the specified property.
+ * @see #get(int)
+ */
+ DataObject getDataObject(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>Date</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>Date</code> value of the specified property.
+ * @see #get(int)
+ */
+ Date getDate(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>String</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>String</code> value of the specified property.
+ * @see #get(int)
+ */
+ String getString(int propertyIndex);
+
+ /**
+ * Returns the value of a <code>List</code> property identified by the specified property index.
+ * @param propertyIndex the index of the property.
+ * @return the <code>List</code> value of the specified property.
+ * @see #get(int)
+ */
+ List getList(int propertyIndex);
+
+ /**
+ * @see #getSequence()
+ * Returns the value of a <code>Sequence</code> property identified by the specified property index.
+ * An implementation may throw an UnsupportedOperationException.
+ * @param propertyIndex the index of the property.
+ * @return the <code>Sequence</code> value of the specified property.
+ * @see #get(int)
+ * @deprecated in 2.1.0.
+ */
+ Sequence getSequence(int propertyIndex);
+
+ /**
+ * Sets the value of a <code>boolean</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setBoolean(int propertyIndex, boolean value);
+
+ /**
+ * Sets the value of a <code>byte</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setByte(int propertyIndex, byte value);
+
+ /**
+ * Sets the value of a <code>char</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setChar(int propertyIndex, char value);
+
+ /**
+ * Sets the value of a <code>double</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setDouble(int propertyIndex, double value);
+
+ /**
+ * Sets the value of a <code>float</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setFloat(int propertyIndex, float value);
+
+ /**
+ * Sets the value of a <code>int</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setInt(int propertyIndex, int value);
+
+ /**
+ * Sets the value of a <code>long</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setLong(int propertyIndex, long value);
+
+ /**
+ * Sets the value of a <code>short</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setShort(int propertyIndex, short value);
+
+ /**
+ * Sets the value of a <code>byte[]</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setBytes(int propertyIndex, byte[] value);
+
+ /**
+ * Sets the value of a <code>BigDecimal</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setBigDecimal(int propertyIndex, BigDecimal value);
+
+ /**
+ * Sets the value of a <code>BigInteger</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setBigInteger(int propertyIndex, BigInteger value);
+
+ /**
+ * Sets the value of a <code>DataObject</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setDataObject(int propertyIndex, DataObject value);
+
+ /**
+ * Sets the value of a <code>Date</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setDate(int propertyIndex, Date value);
+
+ /**
+ * Sets the value of a <code>String</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ */
+ void setString(int propertyIndex, String value);
+
+ /**
+ * Sets the value of a <code>List</code> property identified by the specified property index, to the specified value.
+ * @param propertyIndex the index of the property.
+ * @param value the new value for the property.
+ * @see #set(int, Object)
+ * @see #setList(Property, List)
+ */
+ void setList(int propertyIndex, List value);
+
+ /**
+ * Returns the value of the given property of this object.
+ * <p>
+ * If the property is {@link Property#isMany many-valued},
+ * the result will be a {@link java.util.List}
+ * and each object in the List will be {@link Type#isInstance an instance of}
+ * the property's {@link Property#getType type}.
+ * Otherwise the result will directly be an instance of the property's type.
+ * @param property the property of the value to fetch.
+ * @return the value of the given property of the object.
+ * @see #set(Property, Object)
+ * @see #unset(Property)
+ * @see #isSet(Property)
+ */
+ Object get(Property property);
+
+ /**
+ * Sets the value of the given property of the object to the new value.
+ * <p>
+ * If the property is {@link Property#isMany many-valued},
+ * the new value must be a {@link java.util.List}
+ * and each object in that list must be {@link Type#isInstance an instance of}
+ * the property's {@link Property#getType type};
+ * the existing contents are cleared and the contents of the new value are added.
+ * Otherwise the new value directly must be an instance of the property's type
+ * and it becomes the new value of the property of the object.
+ * @param property the property of the value to set.
+ * @param value the new value for the property.
+ * @see #unset(Property)
+ * @see #isSet(Property)
+ * @see #get(Property)
+ */
+ void set(Property property, Object value);
+
+ /**
+ * Returns whether the property of the object is considered to be set.
+ * <p>
+ * isSet() for many-valued Properties returns true if the List is not empty and
+ * false if the List is empty. For single-valued Properties it returns true if the Property
+ * has been set() and not unset(), and false otherwise.
+ * Any call to set() without a call to unset() will cause isSet() to return true, regardless of
+ * the value being set. For example, after calling set(property, property.getDefault()) on a
+ * previously unset property, isSet(property) will return true, even though the value of
+ * get(property) will be unchanged.
+ * @param property the property in question.
+ * @return whether the property of the object is set.
+ * @see #set(Property, Object)
+ * @see #unset(Property)
+ * @see #get(Property)
+ */
+ boolean isSet(Property property);
+
+ /**
+ * Unsets the property of the object.
+ * <p>
+ * If the property is {@link Property#isMany many-valued},
+ * the value must be an {@link java.util.List}
+ * and that list is cleared.
+ * Otherwise,
+ * the value of the property of the object
+ * is set to the property's {@link Property#getDefault default value}.
+ * The property will no longer be considered {@link #isSet set}.
+ * @param property the property in question.
+ * @see #isSet(Property)
+ * @see #set(Property, Object)
+ * @see #get(Property)
+ */
+ void unset(Property property);
+
+ /**
+ * Returns the value of the specified <code>boolean</code> property.
+ * @param property the property to get.
+ * @return the <code>boolean</code> value of the specified property.
+ * @see #get(Property)
+ */
+ boolean getBoolean(Property property);
+
+ /**
+ * Returns the value of the specified <code>byte</code> property.
+ * @param property the property to get.
+ * @return the <code>byte</code> value of the specified property.
+ * @see #get(Property)
+ */
+ byte getByte(Property property);
+
+ /**
+ * Returns the value of the specified <code>char</code> property.
+ * @param property the property to get.
+ * @return the <code>char</code> value of the specified property.
+ * @see #get(Property)
+ */
+ char getChar(Property property);
+
+ /**
+ * Returns the value of the specified <code>double</code> property.
+ * @param property the property to get.
+ * @return the <code>double</code> value of the specified property.
+ * @see #get(Property)
+ */
+ double getDouble(Property property);
+
+ /**
+ * Returns the value of the specified <code>float</code> property.
+ * @param property the property to get.
+ * @return the <code>float</code> value of the specified property.
+ * @see #get(Property)
+ */
+ float getFloat(Property property);
+
+ /**
+ * Returns the value of the specified <code>int</code> property.
+ * @param property the property to get.
+ * @return the <code>int</code> value of the specified property.
+ * @see #get(Property)
+ */
+ int getInt(Property property);
+
+ /**
+ * Returns the value of the specified <code>long</code> property.
+ * @param property the property to get.
+ * @return the <code>long</code> value of the specified property.
+ * @see #get(Property)
+ */
+ long getLong(Property property);
+
+ /**
+ * Returns the value of the specified <code>short</code> property.
+ * @param property the property to get.
+ * @return the <code>short</code> value of the specified property.
+ * @see #get(Property)
+ */
+ short getShort(Property property);
+
+ /**
+ * Returns the value of the specified <code>byte[]</code> property.
+ * @param property the property to get.
+ * @return the <code>byte[]</code> value of the specified property.
+ * @see #get(Property)
+ */
+ byte[] getBytes(Property property);
+
+ /**
+ * Returns the value of the specified <code>BigDecimal</code> property.
+ * @param property the property to get.
+ * @return the <code>BigDecimal</code> value of the specified property.
+ * @see #get(Property)
+ */
+ BigDecimal getBigDecimal(Property property);
+
+ /**
+ * Returns the value of the specified <code>BigInteger</code> property.
+ * @param property the property to get.
+ * @return the <code>BigInteger</code> value of the specified property.
+ * @see #get(Property)
+ */
+ BigInteger getBigInteger(Property property);
+
+ /**
+ * Returns the value of the specified <code>DataObject</code> property.
+ * @param property the property to get.
+ * @return the <code>DataObject</code> value of the specified property.
+ * @see #get(Property)
+ */
+ DataObject getDataObject(Property property);
+
+ /**
+ * Returns the value of the specified <code>Date</code> property.
+ * @param property the property to get.
+ * @return the <code>Date</code> value of the specified property.
+ * @see #get(Property)
+ */
+ Date getDate(Property property);
+
+ /**
+ * Returns the value of the specified <code>String</code> property.
+ * @param property the property to get.
+ * @return the <code>String</code> value of the specified property.
+ * @see #get(Property)
+ */
+ String getString(Property property);
+
+ /**
+ * Returns the value of the specified <code>List</code> property.
+ * The List returned contains the current values.
+ * Updates through the List interface operate on the current values of the DataObject.
+ * Each access returns the same List object.
+ * @param property the property to get.
+ * @return the <code>List</code> value of the specified property.
+ * @see #get(Property)
+ */
+ List getList(Property property);
+
+ /**
+ * @see #getSequence()
+ * Returns the value of the specified <code>Sequence</code> property.
+ * An implementation may throw an UnsupportedOperationException.
+ * @param property the property to get.
+ * @return the <code>Sequence</code> value of the specified property.
+ * @see #get(Property)
+ * @deprecated in 2.1.0.
+ */
+ Sequence getSequence(Property property);
+
+ /**
+ * Sets the value of the specified <code>boolean</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setBoolean(Property property, boolean value);
+
+ /**
+ * Sets the value of the specified <code>byte</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setByte(Property property, byte value);
+
+ /**
+ * Sets the value of the specified <code>char</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setChar(Property property, char value);
+
+ /**
+ * Sets the value of the specified <code>double</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setDouble(Property property, double value);
+
+ /**
+ * Sets the value of the specified <code>float</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setFloat(Property property, float value);
+
+ /**
+ * Sets the value of the specified <code>int</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setInt(Property property, int value);
+
+ /**
+ * Sets the value of the specified <code>long</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setLong(Property property, long value);
+
+ /**
+ * Sets the value of the specified <code>short</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setShort(Property property, short value);
+
+ /**
+ * Sets the value of the specified <code>byte[]</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setBytes(Property property, byte[] value);
+
+ /**
+ * Sets the value of the specified <code>BigDecimal</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setBigDecimal(Property property, BigDecimal value);
+
+ /**
+ * Sets the value of the specified <code>BigInteger</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setBigInteger(Property property, BigInteger value);
+
+ /**
+ * Sets the value of the specified <code>DataObject</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setDataObject(Property property, DataObject value);
+
+ /**
+ * Sets the value of the specified <code>Date</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setDate(Property property, Date value);
+
+ /**
+ * Sets the value of the specified <code>String</code> property, to the specified value.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setString(Property property, String value);
+
+ /**
+ * Sets the value of the specified <code>List</code> property, to the specified value.
+ * <p> The new value must be a {@link java.util.List}
+ * and each object in that list must be {@link Type#isInstance an instance of}
+ * the property's {@link Property#getType type};
+ * the existing contents are cleared and the contents of the new value are added.
+ * @param property the property to set.
+ * @param value the new value for the property.
+ * @see #set(Property, Object)
+ */
+ void setList(Property property, List value);
+
+ /**
+ * Returns a new {@link DataObject data object} contained by this object using the specified property,
+ * which must be a {@link Property#isContainment containment property}.
+ * The type of the created object is the {@link Property#getType declared type} of the specified property.
+ * @param propertyName the name of the specified containment property.
+ * @return the created data object.
+ * @see #createDataObject(String, String, String)
+ */
+ DataObject createDataObject(String propertyName);
+
+ /**
+ * Returns a new {@link DataObject data object} contained by this object using the specified property,
+ * which must be a {@link Property#isContainment containment property}.
+ * The type of the created object is the {@link Property#getType declared type} of the specified property.
+ * @param propertyIndex the index of the specified containment property.
+ * @return the created data object.
+ * @see #createDataObject(int, String, String)
+ */
+ DataObject createDataObject(int propertyIndex);
+
+ /**
+ * Returns a new {@link DataObject data object} contained by this object using the specified property,
+ * which must be a {@link Property#isContainment containment property}.
+ * The type of the created object is the {@link Property#getType declared type} of the specified property.
+ * @param property the specified containment property.
+ * @return the created data object.
+ * @see #createDataObject(Property, Type)
+ */
+ DataObject createDataObject(Property property);
+
+ /**
+ * Returns a new {@link DataObject data object} contained by this object using the specified property,
+ * which must be a {@link Property#isContainment containment property}.
+ * The type of the created object is specified by the packageURI and typeName arguments.
+ * The specified type must be a compatible target for the property identified by propertyName.
+ * @param propertyName the name of the specified containment property.
+ * @param namespaceURI the namespace URI of the package containing the type of object to be created.
+ * @param typeName the name of a type in the specified package.
+ * @return the created data object.
+ * @see #createDataObject(String)
+ * @see DataGraph#getType
+ */
+ DataObject createDataObject(String propertyName, String namespaceURI, String typeName);
+
+ /**
+ * Returns a new {@link DataObject data object} contained by this object using the specified property,
+ * which must be a {@link Property#isContainment containment property}.
+ * The type of the created object is specified by the packageURI and typeName arguments.
+ * The specified type must be a compatible target for the property identified by propertyIndex.
+ * @param propertyIndex the index of the specified containment property.
+ * @param namespaceURI the namespace URI of the package containing the type of object to be created.
+ * @param typeName the name of a type in the specified package.
+ * @return the created data object.
+ * @see #createDataObject(int)
+ * @see DataGraph#getType
+ */
+ DataObject createDataObject(int propertyIndex, String namespaceURI, String typeName);
+
+ /**
+ * Returns a new {@link DataObject data object} contained by this object using the specified property,
+ * which must be of {@link Property#isContainment containment type}.
+ * The type of the created object is specified by the type argument,
+ * which must be a compatible target for the speicifed property.
+ * @param property a containment property of this object.
+ * @param type the type of object to be created.
+ * @return the created data object.
+ * @see #createDataObject(int)
+ */
+ DataObject createDataObject(Property property, Type type);
+
+ /**
+ * Remove this object from its container and then unset all its non-{@link Property#isReadOnly readOnly} Properties.
+ * If this object is contained by a {@link Property#isReadOnly readOnly} {@link Property#isContainment containment property}, its non-{@link Property#isReadOnly readOnly} Properties will be unset but the object will not be removed from its container.
+ * All DataObjects recursively contained by {@link Property#isContainment containment Properties} will also be deleted.
+ */
+ void delete();
+
+ /**
+ * Returns the containing {@link DataObject data object}
+ * or <code>null</code> if there is no container.
+ * @return the containing data object or <code>null</code>.
+ */
+ DataObject getContainer();
+
+ /**
+ * Return the Property of the {@link DataObject data object} containing this data object
+ * or <code>null</code> if there is no container.
+ * @return the property containing this data object.
+ */
+ Property getContainmentProperty();
+
+ /**
+ * Returns the {@link DataGraph data graph} for this object or <code>null</code> if there isn't one.
+ * @return the containing data graph or <code>null</code>.
+ */
+ DataGraph getDataGraph();
+
+ /**
+ * Returns the data object's type.
+ * <p>
+ * The type defines the Properties available for reflective access.
+ * @return the type.
+ */
+ Type getType();
+
+ /**
+ * Returns the <code>Sequence</code> for this DataObject.
+ * When getType().isSequencedType() == true,
+ * the Sequence of a DataObject corresponds to the
+ * XML elements representing the values of its Properties.
+ * Updates through DataObject and the Lists or Sequences returned
+ * from DataObject operate on the same data.
+ * When getType().isSequencedType() == false, null is returned.
+ * @return the <code>Sequence</code> or null.
+ */
+ Sequence getSequence();
+
+ /**
+ * Returns a read-only List of the Properties currently used in this DataObject.
+ * This list will contain all of the Properties in getType().getProperties()
+ * and any Properties where isSet(property) is true.
+ * For example, Properties resulting from the use of
+ * open or mixed XML content are present if allowed by the Type.
+ * the List does not contain duplicates.
+ * The order of the Properties in the List begins with getType().getProperties()
+ * and the order of the remaining Properties is determined by the implementation.
+ * The same list will be returned unless the DataObject is updated so that
+ * the contents of the List change.
+ * @return the List of Properties currently used in this DataObject.
+ */
+ List /* Property */ getInstanceProperties();
+
+ /**
+ * Returns the named Property from the current instance properties,
+ * or null if not found. The instance properties are getInstanceProperties().
+ * @param propertyName the name of the Property
+ * @return the named Property from the DataObject's current instance properties, or null.
+ */
+ Property getInstanceProperty(String propertyName);
+
+ /**
+ * @deprecated replaced by {@link #getInstanceProperty(String)} in 2.1.0
+ */
+ Property getProperty(String propertyName);
+
+ /**
+ * Returns the root {@link DataObject data object}.
+ * @return the root data object.
+ */
+ DataObject getRootObject();
+
+ /**
+ * Returns the ChangeSummary with scope covering this dataObject, or null
+ * if there is no ChangeSummary.
+ * @return the ChangeSummary with scope covering this dataObject, or null.
+ */
+ ChangeSummary getChangeSummary();
+
+ /**
+ * Removes this DataObject from its container, if any.
+ * Same as
+ * getContainer().getList(getContainmentProperty()).remove(this) or
+ * getContainer().unset(getContainmentProperty())
+ * depending on getContainmentProperty().isMany() respectively.
+ */
+ void detach();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Property.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Property.java
new file mode 100644
index 0000000000..06c7423a6c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Property.java
@@ -0,0 +1,121 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo;
+
+import java.util.List;
+
+/**
+ * A representation of a Property in the {@link Type type} of a {@link DataObject data object}.
+ */
+public interface Property
+{
+ /**
+ * Returns the name of the Property.
+ * @return the Property name.
+ */
+ String getName();
+
+ /**
+ * Returns the type of the Property.
+ * @return the Property type.
+ */
+ Type getType();
+
+ /**
+ * Returns whether the Property is many-valued.
+ * @return <code>true</code> if the Property is many-valued.
+ */
+ boolean isMany();
+
+ /**
+ * Returns whether the Property is containment, i.e., whether it represents by-value composition.
+ * @return <code>true</code> if the Property is containment.
+ */
+ boolean isContainment();
+
+ /**
+ * Returns the containing type of this Property.
+ * @return the Property's containing type.
+ * @see Type#getProperties()
+ */
+ Type getContainingType();
+
+ /**
+ * Returns the default value this Property will have in a {@link DataObject data object} where the Property hasn't been set.
+ * @return the default value.
+ */
+ Object getDefault();
+
+ /**
+ * Returns true if values for this Property cannot be modified using the SDO APIs.
+ * When true, DataObject.set(Property property, Object value) throws an exception.
+ * Values may change due to other factors, such as services operating on DataObjects.
+ * @return true if values for this Property cannot be modified.
+ */
+ boolean isReadOnly();
+
+ /**
+ * Returns the opposite Property if the Property is bi-directional or null otherwise.
+ * @return the opposite Property if the Property is bi-directional or null
+ */
+ Property getOpposite();
+
+ /**
+ * Returns a list of alias names for this Property.
+ * @return a list of alias names for this Property.
+ */
+ List /*String*/ getAliasNames();
+
+ /**
+ * Returns whether or not instances of this property can be set to null. The effect of calling set(null) on a non-nullable
+ * property is not specified by SDO.
+ * @return true if this property is nullable.
+ */
+ boolean isNullable();
+
+ /**
+ * Returns whether or not this is an open content Property.
+ * @return true if this property is an open content Property.
+ */
+ boolean isOpenContent();
+
+ /**
+ * Returns a read-only List of instance Properties available on this Property.
+ * <p>
+ * This list includes, at a minimum, any open content properties (extensions) added to
+ * the object before {@link commonj.sdo.helper.TypeHelper#define(DataObject) defining
+ * the Property's Type}. Implementations may, but are not required to in the 2.1 version
+ * of SDO, provide additional instance properties.
+ * @return the List of instance Properties on this Property.
+ */
+ List /*Property*/ getInstanceProperties();
+
+ /**
+ * Returns the value of the specified instance property of this Property.
+ * @param property one of the properties returned by {@link #getInstanceProperties()}.
+ * @return the value of the specified property.
+ * @see DataObject#get(Property)
+ */
+ Object get(Property property);
+
+ /**
+ * Returns the index of this property in the list of properties of its containing type.
+ * This is the only modification we did to the sdo spec.
+ * @see Type#getProperties()
+ */
+ int getIndex();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Sequence.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Sequence.java
new file mode 100644
index 0000000000..99fbcaf413
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Sequence.java
@@ -0,0 +1,140 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo;
+
+/**
+ * A sequence is a heterogeneous list of {@link Property properties} and corresponding values.
+ * It represents an ordered arbitrary mixture of data values from more than one property of a {@link DataObject data object}.
+ */
+public interface Sequence
+{
+ /**
+ * Returns the number of entries in the sequence.
+ * @return the number of entries.
+ */
+ int size();
+
+ /**
+ * Returns the property for the given entry index.
+ * Returns <code>null</code> for mixed text entries.
+ * @param index the index of the entry.
+ * @return the property or <code>null</code> for the given entry index.
+ */
+ Property getProperty(int index);
+
+ /**
+ * Returns the property value for the given entry index.
+ * @param index the index of the entry.
+ * @return the value for the given entry index.
+ */
+ Object getValue(int index);
+
+ /**
+ * Sets the entry at a specified index to the new value.
+ * @param index the index of the entry.
+ * @param value the new value for the entry.
+ */
+ Object setValue(int index, Object value);
+
+ /**
+ * Adds a new entry with the specified property name and value
+ * to the end of the entries.
+ * @param propertyName the name of the entry's property.
+ * @param value the value for the entry.
+ */
+ boolean add(String propertyName, Object value);
+
+ /**
+ * Adds a new entry with the specified property index and value
+ * to the end of the entries.
+ * @param propertyIndex the index of the entry's property.
+ * @param value the value for the entry.
+ */
+ boolean add(int propertyIndex, Object value);
+
+ /**
+ * Adds a new entry with the specified property and value
+ * to the end of the entries.
+ * @param property the property of the entry.
+ * @param value the value for the entry.
+ */
+ boolean add(Property property, Object value);
+
+ /**
+ * Adds a new entry with the specified property name and value
+ * at the specified entry index.
+ * @param index the index at which to add the entry.
+ * @param propertyName the name of the entry's property.
+ * @param value the value for the entry.
+ */
+ void add(int index, String propertyName, Object value);
+
+ /**
+ * Adds a new entry with the specified property index and value
+ * at the specified entry index.
+ * @param index the index at which to add the entry.
+ * @param propertyIndex the index of the entry's property.
+ * @param value the value for the entry.
+ */
+ void add(int index, int propertyIndex, Object value);
+
+ /**
+ * Adds a new entry with the specified property and value
+ * at the specified entry index.
+ * @param index the index at which to add the entry.
+ * @param property the property of the entry.
+ * @param value the value for the entry.
+ */
+ void add(int index, Property property, Object value);
+
+ /**
+ * Removes the entry at the given entry index.
+ * @param index the index of the entry.
+ */
+ void remove(int index);
+
+ /**
+ * Moves the entry at <code>fromIndex</code> to <code>toIndex</code>.
+ * @param toIndex the index of the entry destination.
+ * @param fromIndex the index of the entry to move.
+ */
+ void move(int toIndex, int fromIndex);
+
+ /**
+ * @deprecated replaced by {@link #addText(String)} in 2.1.0
+ */
+ void add(String text);
+
+ /**
+ * @deprecated replaced by {@link #addText(int, String)} in 2.1.0
+ */
+ void add(int index, String text);
+
+ /**
+ * Adds a new text entry to the end of the Sequence.
+ * @param text value of the entry.
+ */
+ void addText(String text);
+
+ /**
+ * Adds a new text entry at the given index.
+ * @param index the index at which to add the entry.
+ * @param text value of the entry.
+ */
+ void addText(int index, String text);
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Type.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Type.java
new file mode 100644
index 0000000000..1c21e2c7d1
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/Type.java
@@ -0,0 +1,166 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo;
+
+import java.util.List;
+
+/**
+ * A representation of the type of a {@link Property property} of a {@link DataObject data object}.
+ */
+public interface Type
+{
+ /**
+ * Returns the name of the type.
+ * @return the type name.
+ */
+ String getName();
+
+ /**
+ * Returns the namespace URI of the type.
+ * @return the namespace URI.
+ */
+ String getURI();
+
+ /**
+ * Returns the Java class that this type represents.
+ * @return the Java class.
+ */
+ Class getInstanceClass();
+
+ /**
+ * Returns whether the specified object is an instance of this type.
+ * @param object the object in question.
+ * @return <code>true</code> if the object is an instance.
+ * @see Class#isInstance
+ */
+ boolean isInstance(Object object);
+
+ /**
+ * Returns the List of the {@link Property Properties} of this type.
+ * <p>
+ * The expression
+ *<pre>
+ * type.getProperties().indexOf(property)
+ *</pre>
+ * yields the property's index relative to this type.
+ * As such, these expressions are equivalent:
+ *<pre>
+ * dataObject.{@link DataObject#get(int) get}(i)
+ * dataObject.{@link DataObject#get(Property) get}((Property)dataObject.getType().getProperties().get(i));
+ *</pre>
+ * </p>
+ * @return the Properties of the type.
+ * @see Property#getContainingType
+ */
+ List /*Property*/ getProperties();
+
+ /**
+ * Returns from {@link #getProperties all the Properties} of this type, the one with the specified name.
+ * As such, these expressions are equivalent:
+ *<pre>
+ * dataObject.{@link DataObject#get(String) get}("name")
+ * dataObject.{@link DataObject#get(Property) get}(dataObject.getType().getProperty("name"))
+ *</pre>
+ * </p>
+ * @return the Property with the specified name.
+ * @see #getProperties
+ */
+ Property getProperty(String propertyName);
+
+ /**
+ * Indicates if this Type specifies DataTypes (true) or DataObjects (false).
+ * When false, any object that is an instance of this type
+ * also implements the DataObject interface.
+ * True for simple types such as Strings and numbers.
+ * For any object:
+ * <pre>
+ * isInstance(object) && !isDataType() implies
+ * DataObject.class.isInstance(object) returns true.
+ * </pre>
+ * @return true if Type specifies DataTypes, false for DataObjects.
+ */
+ boolean isDataType();
+
+ /**
+ * Indicates if this Type allows any form of open content. If false,
+ * dataObject.getInstanceProperties() must be the same as
+ * dataObject.getType().getProperties() for any DataObject dataObject of this Type.
+ * @return true if this Type allows open content.
+ */
+ boolean isOpen();
+
+ /**
+ * Indicates if this Type specifies Sequenced DataObjects.
+ * Sequenced DataObjects are used when the order of values
+ * between Properties must be preserved.
+ * When true, a DataObject will return a Sequence. For example,
+ * <pre>
+ * Sequence elements = dataObject.{@link DataObject#getSequence() getSequence}();
+ * </pre>
+ * @return true if this Type specifies Sequenced DataObjects.
+ */
+ boolean isSequenced();
+
+ /**
+ * Indicates if this Type is abstract. If true, this Type cannot be
+ * instantiated. Abstract types cannot be used in DataObject or
+ * DataFactory create methods.
+ * @return true if this Type is abstract.
+ */
+ boolean isAbstract();
+
+ /**
+ * Returns the List of base Types for this Type. The List is empty
+ * if there are no base Types. XSD <extension>, <restriction>, and
+ * Java extends keyword are mapped to this list.
+ * @return the List of base Types for this Type.
+ */
+ List /*Type*/ getBaseTypes();
+
+ /**
+ * Returns the Properties declared in this Type as opposed to
+ * those declared in base Types.
+ * @return the Properties declared in this Type.
+ */
+ List /*Property*/ getDeclaredProperties();
+
+ /**
+ * Return a list of alias names for this Type.
+ * @return a list of alias names for this Type.
+ */
+ List /*String*/ getAliasNames();
+
+ /**
+ * Returns a read-only List of instance Properties available on this Type.
+ * <p>
+ * This list includes, at a minimum, any open content properties (extensions) added to
+ * the object before {@link commonj.sdo.helper.TypeHelper#define(DataObject) defining
+ * the Type's Type}. Implementations may, but are not required to in the 2.1 version
+ * of SDO, provide additional instance properties.
+ * @return the List of instance Properties on this Type.
+ */
+ List /*Property*/ getInstanceProperties();
+
+ /**
+ * Returns the value of the specified instance property of this Type.
+ * @param property one of the properties returned by {@link #getInstanceProperties()}.
+ * @return the value of the specified property.
+ * @see DataObject#get(Property)
+ */
+ Object get(Property property);
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/CopyHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/CopyHelper.java
new file mode 100644
index 0000000000..045b5214bb
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/CopyHelper.java
@@ -0,0 +1,85 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * A helper for copying DataObjects.
+ */
+public interface CopyHelper
+{
+ /**
+ * Create a shallow copy of the DataObject dataObject:
+ * Creates a new DataObject copiedDataObject with the same values
+ * as the source dataObject for each property where
+ * property.getType().isDataType() is true.
+ * The value of such a Property property in copiedDataObject is:
+ * dataObject.get(property) for single-valued Properties
+ * (copiedDataObject.get(property) equals() dataObject.get(property)), or
+ * a List where each member is equal to the member at the
+ * same index in dataObject for multi-valued Properties
+ * copiedDataObject.getList(property).get(i) equals() dataObject.getList(property).get(i)
+ * The copied Object is unset for each Property where
+ * property.getType().isDataType() is false
+ * since they are not copied.
+ * Read-only properties are copied.
+ * A copied object shares metadata with the source object
+ * sourceDO.getType() == copiedDO.getType()
+ * If a ChangeSummary is part of the source DataObject
+ * the copy has a new, empty ChangeSummary.
+ * Logging state is the same as the source ChangeSummary.
+ *
+ * @param dataObject to be copied
+ * @return copy of dataObject
+ */
+ DataObject copyShallow(DataObject dataObject);
+
+ /**
+ * Create a deep copy of the DataObject tree:
+ * Copies the dataObject and all its {@link commonj.sdo.Property#isContainment() contained}
+ * DataObjects recursively.
+ * Values of Properties are copied as in shallow copy,
+ * and values of Properties where
+ * property.getType().isDataType() is false
+ * are copied where each value copied must be a
+ * DataObject contained by the source dataObject.
+ * If a DataObject is outside the DataObject tree and the
+ * property is bidirectional, then the DataObject is skipped.
+ * If a DataObject is outside the DataObject tree and the
+ * property is unidirectional, then the same DataObject is referenced.
+ * Read-only properties are copied.
+ * If any DataObject referenced is not in the containment
+ * tree an IllegalArgumentException is thrown.
+ * If a ChangeSummary is part of the copy tree the new
+ * ChangeSummary refers to objects in the new DataObject tree.
+ * Logging state is the same as the source ChangeSummary.
+ *
+ * @param dataObject to be copied.
+ * @return copy of dataObject
+ * @throws IllegalArgumentException if any referenced DataObject
+ * is not part of the containment tree.
+ */
+ DataObject copy(DataObject dataObject);
+
+ /**
+ * The default CopyHelper.
+ */
+ CopyHelper INSTANCE = HelperProvider.getCopyHelper();
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataFactory.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataFactory.java
new file mode 100644
index 0000000000..bb41b64373
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataFactory.java
@@ -0,0 +1,64 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * A Factory for creating DataObjects.
+ * The created DataObjects are not connected to any other DataObjects.
+ */
+public interface DataFactory
+{
+ /**
+ * Create a DataObject of the Type specified by typeName with the given package uri.
+ * @param uri The uri of the Type.
+ * @param typeName The name of the Type.
+ * @return the created DataObject.
+ * @throws IllegalArgumentException if the uri and typeName does
+ * not correspond to a Type this factory can instantiate.
+ */
+ DataObject create(String uri, String typeName);
+
+ /**
+ * Create a DataObject supporting the given interface.
+ * InterfaceClass is the interface for the DataObject's Type.
+ * The DataObject created is an instance of the interfaceClass.
+ * @param interfaceClass is the interface for the DataObject's Type.
+ * @return the created DataObject.
+ * @throws IllegalArgumentException if the instanceClass does
+ * not correspond to a Type this factory can instantiate.
+ */
+ DataObject create(Class interfaceClass);
+
+ /**
+ * Create a DataObject of the Type specified.
+ * @param type The Type.
+ * @return the created DataObject.
+ * @throws IllegalArgumentException if the Type
+ * cannot be instantiaed by this factory.
+ */
+ DataObject create(Type type);
+
+ /**
+ * The default DataFactory.
+ */
+ DataFactory INSTANCE = HelperProvider.getDataFactory();
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataHelper.java
new file mode 100644
index 0000000000..b09b7bde2e
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/DataHelper.java
@@ -0,0 +1,214 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * Data helper methods.
+ */
+public interface DataHelper
+{
+ /**
+ * Convert from a String representation of an SDO date type to a Date.
+ * @param dateString the String representation of an SDO date type
+ * @return a Date representation of an SDO date type.
+ * @throws IllegalArgumentException for invalid formats.
+ */
+ Date toDate(String dateString);
+
+ /**
+ * Convert from a String representation of an SDO date type to a Calendar using the
+ * default locale. Same as toCalendar(dateString, null).
+ * @param dateString the String representation of an SDO date type
+ * @return a Calendar representation of an SDO date type.
+ * @throws IllegalArgumentException for invalid formats.
+ */
+ Calendar toCalendar(String dateString);
+
+ /**
+ * Convert from a String representation of an SDO date type to a Calendar using the
+ * specified locale, or the default locale if the locale is null.
+ * @param dateString the String representation of an SDO date type
+ * @param locale the locale or null for default locale.
+ * @return a Calendar representation of an SDO date type.
+ * @throws IllegalArgumentException for invalid formats.
+ */
+ Calendar toCalendar(String dateString, Locale locale);
+
+ /**
+ * Convert from a Date to a String representation of the DateTime type.
+ * @param date the date
+ * @return a Date to a String representation of the DateTime type.
+ */
+ String toDateTime(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the Duration type.
+ * @param date the date
+ * @return a Date to a String representation of the Duration type.
+ */
+ String toDuration(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the Time type.
+ * @param date the date
+ * @return a Date to a String representation of the Time type.
+ */
+ String toTime(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the Day type.
+ * @param date the date
+ * @return a Date to a String representation of the Day type.
+ */
+ String toDay(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the Month type.
+ * @param date the date
+ * @return a Date to a String representation of the Month type.
+ */
+ String toMonth(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the MonthDay type.
+ * @param date the date
+ * @return a Date to a String representation of the MonthDay type.
+ */
+ String toMonthDay(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the Year type.
+ * @param date the date
+ * @return a Date to a String representation of the Year type.
+ */
+ String toYear(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the YearMonth type.
+ * @param date the date
+ * @return a Date to a String representation of the YearMonth type.
+ */
+ String toYearMonth(Date date);
+
+ /**
+ * Convert from a Date to a String representation of the YearMonthDay type.
+ * @param date the date
+ * @return a Date to a String representation of the YearMonthDay type.
+ */
+ String toYearMonthDay(Date date);
+
+ /**
+ * Convert from a Calendar to a String representation of the DateTime type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the DateTime type.
+ */
+ String toDateTime(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the Duration type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the Duration type.
+ */
+ String toDuration(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the Time type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the Time type.
+ */
+ String toTime(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the Day type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the Day type.
+ */
+ String toDay(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the Month type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the Month type.
+ */
+ String toMonth(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the MonthDay type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the MonthDay type.
+ */
+ String toMonthDay(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the Year type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the Year type.
+ */
+ String toYear(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the YearMonth type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the YearMonth type.
+ */
+ String toYearMonth(Calendar calendar);
+
+ /**
+ * Convert from a Calendar to a String representation of the YearMonthDay type.
+ * @param calendar the calendar to convert
+ * @return a Calendar to a String representation of the YearMonthDay type.
+ */
+ String toYearMonthDay(Calendar calendar);
+
+ /**
+ * Convert the specified value to an {@link Type#getInstanceClass() instance}
+ * of the specified type.
+ * Supported conversions are listed in Section 16 of the SDO specification.
+ * @param type the target {@link Type#isDataType() data type}.
+ * @param value the value to convert
+ * @return a value of the specified type's instance class
+ * @throws IllegalArgumentException if the value could not be converted
+ * @see #convert(Property, Object)
+ */
+ Object convert(Type type, Object value);
+
+ /**
+ * Convert the specified value to an {@link Type#getInstanceClass() instance}
+ * of the specified property's {@link Property#getType() type}.
+ * The specified value must be a List if the property is {@link Property#isMany()
+ * many valued}. In this case, all the values in the List are converted.
+ * @param property the target {@link Type#isDataType() data type} property.
+ * @param value the value or List of values to convert
+ * @return a converted value or list of converted values
+ * @throws IllegalArgumentException if the value could not be converted
+ * @see #convert(Type, Object)
+ */
+ Object convert(Property property, Object value);
+
+ /**
+ * The default DataHelper.
+ */
+ DataHelper INSTANCE = HelperProvider.getDataHelper();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/EqualityHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/EqualityHelper.java
new file mode 100644
index 0000000000..eb9077e15b
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/EqualityHelper.java
@@ -0,0 +1,92 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * A helper for comparing DataObjects.
+ */
+public interface EqualityHelper
+{
+ /**
+ * <p>Two DataObjects are equalShallow if
+ * they have the same {@link DataObject#getType Type}
+ * and all their compared Properties are equal.
+ * The set of Properties compared are the
+ * {@link DataObject#getInstanceProperties() instance properties}
+ * where property.getType().isDataType() is true
+ * and property.getType() is not ChangeSummaryType.
+ * <br/>Two of these Property values are equal if they are both not
+ * {@link DataObject#isSet(Property) set}, or set to an equal value
+ * dataObject1.get(property).equals(dataObject2.get(property))
+ * <br/>If the type is a sequenced type, the sequence entries must be the same.
+ * For each entry x in the sequence where the property is used in the comparison,
+ * dataObject1.getSequence().getValue(x).equals(
+ * dataObject2.getSequence().getValue(x)) and
+ * dataObject1.getSequence().getProperty(x) ==
+ * dataObject2.getSequence().getProperty(x)
+ * must be true.
+ * </p>
+ * Returns true the objects have the same Type and all values of all compared Properties are equal.
+ * @param dataObject1 DataObject to be compared
+ * @param dataObject2 DataObject to be compared
+ * @return true the objects have the same Type and all values of all compared Properties are equal.
+ */
+ boolean equalShallow(DataObject dataObject1, DataObject dataObject2);
+
+ /**
+ * <p>Two DataObjects are equal(Deep) if they are equalShallow,
+ * all their compared Properties are equal, and all reachable DataObjects in their
+ * graphs excluding containers are equal.
+ * The set of Properties compared are the
+ * {@link DataObject#getInstanceProperties() instance properties}
+ * where property.getType().isDataType() is false,
+ * and is not a container property, ie !property.getOpposite().isContainment()
+ * <br/>Two of these Property values are equal if they are both not
+ * {@link DataObject#isSet(Property) set}, or all the DataObjects
+ * they refer to are {@link #equal(DataObject, DataObject) equal} in the
+ * context of dataObject1 and dataObject2.
+ * <br/>Note that properties to a containing DataObject are not compared
+ * which means two DataObject trees can be equal even if their containers are not equal.
+ * <br/>If the type is a sequenced type, the sequence entries must be the same.
+ * For each entry x in the sequence where the property is used in the comparison,
+ * equal(dataObject1.getSequence().getValue(x),
+ * dataObject2.getSequence().getValue(x)) and
+ * dataObject1.getSequence().getProperty(x) ==
+ * dataObject2.getSequence().getProperty(x)
+ * must be true.
+ * </p><p>
+ * A DataObject directly or indirectly referenced by dataObject1 or dataObject2
+ * can only be equal to exactly one DataObject directly or indirectly referenced
+ * by dataObject1 or dataObject2, respectively.
+ * This ensures that dataObject1 and dataObject2 are equal if the graph formed by
+ * all their referenced DataObjects have the same shape.
+ * </p>
+ * Returns true if the trees of DataObjects are equal(Deep).
+ * @param dataObject1 DataObject to be compared
+ * @param dataObject2 DataObject to be compared
+ * @return true if the trees of DataObjects are equal(Deep).
+ */
+ boolean equal(DataObject dataObject1, DataObject dataObject2);
+
+ /**
+ * The default EqualityHelper.
+ */
+ EqualityHelper INSTANCE = HelperProvider.getEqualityHelper();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/HelperContext.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/HelperContext.java
new file mode 100644
index 0000000000..058393f727
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/HelperContext.java
@@ -0,0 +1,67 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+/**
+ * This interface represents a helper execution context.
+ * The set of helpers returned by the methods in this interface have visibility
+ * to the same SDO metadata, that is, they execute in the same "scope".
+ */
+public interface HelperContext
+{
+ /**
+ * Gets the CopyHelper to use in this context.
+ * @return a CopyHelper object
+ */
+ CopyHelper getCopyHelper();
+
+ /**
+ * Gets the DataFactory to use in this context.
+ * @return a DataFactory object
+ */
+ DataFactory getDataFactory();
+
+ /**
+ * Gets the DataHelper to use in this context.
+ * @return a DataHelper object
+ */
+ DataHelper getDataHelper();
+
+ /**
+ * Gets the EqualityHelper to use in this context.
+ * @return an EqualityHelper object
+ */
+ EqualityHelper getEqualityHelper();
+
+ /**
+ * Gets the TypeHelper to use in this context.
+ * @return a TypeHelper object
+ */
+ TypeHelper getTypeHelper();
+
+ /**
+ * Gets the XMLHelper to use in this context.
+ * @return an XMLHelper object
+ */
+ XMLHelper getXMLHelper();
+
+ /**
+ * Gets the XSDHelper to use in this context.
+ * @return an XSDHelper object
+ */
+ XSDHelper getXSDHelper();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/TypeHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/TypeHelper.java
new file mode 100644
index 0000000000..13e4c1b30b
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/TypeHelper.java
@@ -0,0 +1,96 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import java.util.List;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * Look up a Type given the uri and typeName or interfaceClass.
+ * SDO Types are available through the
+ * getType("commonj.sdo", typeName) method.
+ * Defines Types from DataObjects.
+ */
+public interface TypeHelper
+{
+ /**
+ * Return the Type specified by typeName with the given uri,
+ * or null if not found.
+ * @param uri The uri of the Type - type.getURI();
+ * @param typeName The name of the Type - type.getName();
+ * @return the Type specified by typeName with the given uri,
+ * or null if not found.
+ */
+ Type getType(String uri, String typeName);
+
+ /**
+ * Return the Type for this interfaceClass or null if not found.
+ * @param interfaceClass is the interface for the DataObject's Type -
+ * type.getInstanceClass();
+ * @return the Type for this interfaceClass or null if not found.
+ */
+ Type getType(Class interfaceClass);
+
+ /**
+ * Get the open content (global) Property with the specified uri and name, or null
+ * if not found.
+ * @param uri the namespace URI of the open content Property.
+ * @param propertyName the name of the open content Property.
+ * @return the global Property.
+ */
+ Property getOpenContentProperty(String uri, String propertyName);
+
+ /**
+ * Define the DataObject as a Type.
+ * The Type is available through TypeHelper and DataGraph getType() methods.
+ * @param type the DataObject representing the Type.
+ * @return the defined Type.
+ * @throws IllegalArgumentException if the Type could not be defined.
+ */
+ Type define(DataObject type);
+
+ /**
+ * Define the list of DataObjects as Types.
+ * The Types are available through TypeHelper and DataGraph getType() methods.
+ * @param types a List of DataObjects representing the Types.
+ * @return the defined Types.
+ * @throws IllegalArgumentException if the Types could not be defined.
+ */
+ List /*Type*/ define(List /*DataObject*/ types);
+
+ /**
+ * Define the DataObject as a Property for setting open content.
+ * The containing Type of the open content property is not specified by SDO.
+ * If the specified uri is not null the defined property is accessible through
+ * TypeHelper.getOpenContentProperty(uri, propertyName).
+ * If a null uri is specified, the location and management of the open content property
+ * is not specified by SDO.
+ * @param uri the namespace URI of the open content Property or null.
+ * @return the defined open content Property.
+ * @throws IllegalArgumentException if the Property could not be defined.
+ */
+ Property defineOpenContentProperty(String uri, DataObject property);
+
+ /**
+ * The default TypeHelper.
+ */
+ TypeHelper INSTANCE = HelperProvider.getTypeHelper();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLDocument.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLDocument.java
new file mode 100644
index 0000000000..1c6754f87c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLDocument.java
@@ -0,0 +1,155 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import commonj.sdo.DataObject;
+
+/**
+ * Represents an XML Document containing a tree of DataObjects.
+ *
+ * An example XMLDocument fragment is:
+ * <?xml version="1.0"?>
+ * <purchaseOrder orderDate="1999-10-20">
+ *
+ * created from this XML Schema fragment:
+ * <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ * <xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
+ * <xsd:complexType name="PurchaseOrderType">
+ *
+ * Upon loading this XMLDocument:
+ * DataObject is an instance of Type PurchaseOrderType.
+ * RootElementURI is null because the XSD has no targetNamespace URI.
+ * RootElementName is purchaseOrder.
+ * Encoding is null because the document did not specify an encoding.
+ * XMLDeclaration is true because the document contained an XML declaration.
+ * XMLVersion is 1.0
+ * SchemaLocation and noNamespaceSchemaLocation are null because they are
+ * not specified in the document.
+ *
+ * When saving the root element, if the type of the root dataObject is not the
+ * type of global element specified by rootElementURI and rootElementName,
+ * or if a global element does not exist for rootElementURI and rootElementName,
+ * then an xsi:type declaration is written to record the root DataObject's Type.
+ *
+ * When loading the root element and an xsi:type declaration is found
+ * it is used as the type of the root DataObject. In this case,
+ * if validation is not being performed, it is not an error if the
+ * rootElementName is not a global element.
+ */
+public interface XMLDocument
+{
+ /**
+ * Return the root DataObject for the XMLDocument.
+ * @return root DataObject for the XMLDocument.
+ */
+ DataObject getRootObject();
+
+ /**
+ * Return the targetNamespace URI for the root element.
+ * If there is no targetNamespace URI, the value is null.
+ * The root element is a global element of the XML Schema
+ * with a type compatible to the DataObject.
+ * @return the targetNamespace URI for the root element.
+ */
+ String getRootElementURI();
+
+ /**
+ * Return the name of the root element.
+ * The root element is a global element of the XML Schema
+ * with a type compatible to the DataObject.
+ * @return the name of the root element.
+ */
+ String getRootElementName();
+
+ /**
+ * Return the XML encoding of the document, or null if not specified.
+ * The default value is "UTF-8".
+ * Specification of other values is implementation-dependent.
+ * @return the XML encoding of the document, or null if not specified.
+ */
+ String getEncoding();
+
+ /**
+ * Set the XML encoding of the document, or null if not specified.
+ * @param encoding
+ */
+ void setEncoding(String encoding);
+
+ /**
+ * Return the XML declaration of the document. If true,
+ * XMLHelper save() will produce a declaration of the form:
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * Encoding will be suppressed if getEncoding() is null.
+ * The default value is true.
+ * @return the XML declaration of the document.
+ */
+ boolean isXMLDeclaration();
+
+ /**
+ * Set the XML declaration version of the document.
+ * @param xmlDeclaration the XML declaration version of the document.
+ */
+ void setXMLDeclaration(boolean xmlDeclaration);
+
+ /**
+ * Return the XML version of the document, or null if not specified.
+ * The default value is "1.0".
+ * Specification of other values is implementation-dependent.
+ * @return the XML version of the document, or null if not specified.
+ */
+ String getXMLVersion();
+
+ /**
+ * Set the XML version of the document, or null if not specified.
+ * @param xmlVersion the XML version of the document, or null if not specified.
+ */
+ void setXMLVersion(String xmlVersion);
+
+ /**
+ * Return the value of the schemaLocation declaration
+ * for the http://www.w3.org/2001/XMLSchema-instance namespace in the
+ * root element, or null if not present.
+ * @return the value of the schemaLocation declaration,
+ * or null if not present.
+ */
+ String getSchemaLocation();
+
+ /**
+ * Sets the value of the schemaLocation declaration
+ * for the http://www.w3.org/2001/XMLSchema-instance namespace in the
+ * root element, or null if it should not be present.
+ * @param schemaLocation the value of the schemaLocation declaration, or null.
+ */
+ void setSchemaLocation(String schemaLocation);
+
+ /**
+ * Return the value of the noNamespaceSchemaLocation declaration
+ * for the http://www.w3.org/2001/XMLSchema-instance namespace in the
+ * root element, or null if not present.
+ * @return the value of the noNamespaceSchemaLocation declaration,
+ * or null if not present.
+ */
+ String getNoNamespaceSchemaLocation();
+
+ /**
+ * Sets the value of the noNamespaceSchemaLocation declaration
+ * for the http://www.w3.org/2001/XMLSchema-instance namespace in the
+ * root element, or null if it should not be present.
+ * @param schemaLocation the value of the noNamespaceSchemaLocation declaration, or null.
+ */
+ void setNoNamespaceSchemaLocation(String schemaLocation);
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLHelper.java
new file mode 100644
index 0000000000..ac67143570
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XMLHelper.java
@@ -0,0 +1,202 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * A helper to convert XML documents into DataObects and
+ * DataObjects into XML documnets.
+ */
+public interface XMLHelper
+{
+ /**
+ * Creates and returns an XMLDocument from the input String.
+ * By default does not perform XSD validation.
+ * Same as
+ * load(new StringReader(inputString), null, null);
+ *
+ * @param inputString specifies the String to read from
+ * @return the new XMLDocument loaded
+ * @throws RuntimeException for errors in XML parsing or
+ * implementation-specific validation.
+ */
+ XMLDocument load(String inputString);
+
+ /**
+ * Creates and returns an XMLDocument from the inputStream.
+ * The InputStream will be closed after reading.
+ * By default does not perform XSD validation.
+ * Same as
+ * load(inputStream, null, null);
+ *
+ * @param inputStream specifies the InputStream to read from
+ * @return the new XMLDocument loaded
+ * @throws IOException for stream exceptions.
+ * @throws RuntimeException for errors in XML parsing or
+ * implementation-specific validation.
+ */
+ XMLDocument load(InputStream inputStream) throws IOException;
+
+ /**
+ * Creates and returns an XMLDocument from the inputStream.
+ * The InputStream will be closed after reading.
+ * By default does not perform XSD validation.
+ * @param inputStream specifies the InputStream to read from
+ * @param locationURI specifies the URI of the document for relative schema locations
+ * @param options implementation-specific options.
+ * @return the new XMLDocument loaded
+ * @throws IOException for stream exceptions.
+ * @throws RuntimeException for errors in XML parsing or
+ * implementation-specific validation.
+ */
+ XMLDocument load(InputStream inputStream, String locationURI, Object options) throws IOException;
+
+ /**
+ * Creates and returns an XMLDocument from the inputReader.
+ * The InputStream will be closed after reading.
+ * By default does not perform XSD validation.
+ * @param inputReader specifies the Reader to read from
+ * @param locationURI specifies the URI of the document for relative schema locations
+ * @param options implementation-specific options.
+ * @return the new XMLDocument loaded
+ * @throws IOException for stream exceptions.
+ * @throws RuntimeException for errors in XML parsing or
+ * implementation-specific validation.
+ */
+ XMLDocument load(Reader inputReader, String locationURI, Object options) throws IOException;
+
+ /**
+ * Creates and returns an XMLDocument from the inputSource.
+ * The InputSource will be closed after reading.
+ * By default does not perform XSD validation.
+ * @param inputSource specifies the Source to read from
+ * @param locationURI specifies the URI of the document for relative schema locations
+ * @param options implementation-specific options.
+ * @return the new XMLDocument loaded
+ * @throws IOException for stream exceptions.
+ * @throws RuntimeException for errors in XML parsing or
+ * implementation-specific validation.
+ */
+ XMLDocument load(Source inputSource, String locationURI, Object options) throws IOException;
+
+ /**
+ * Returns the DataObject saved as an XML document with the specified root element.
+ * Same as
+ * StringWriter stringWriter = new StringWriter();
+ * save(createDocument(dataObject, rootElementURI, rootElementName),
+ * stringWriter, null);
+ * stringWriter.toString();
+ *
+ * @param dataObject specifies DataObject to be saved
+ * @param rootElementURI the Target Namespace URI of the root XML element
+ * @param rootElementName the Name of the root XML element
+ * @return the saved XML document as a string
+ * @throws IllegalArgumentException if the dataObject tree
+ * is not closed or has no container.
+ */
+ String save(DataObject dataObject, String rootElementURI, String rootElementName);
+
+ /**
+ * Saves the DataObject as an XML document with the specified root element.
+ * Same as
+ * save(createDocument(dataObject, rootElementURI, rootElementName),
+ * outputStream, null);
+ *
+ * @param dataObject specifies DataObject to be saved
+ * @param rootElementURI the Target Namespace URI of the root XML element
+ * @param rootElementName the Name of the root XML element
+ * @param outputStream specifies the OutputStream to write to.
+ * @throws IOException for stream exceptions.
+ * @throws IllegalArgumentException if the dataObject tree
+ * is not closed or has no container.
+ */
+ void save(DataObject dataObject, String rootElementURI, String rootElementName, OutputStream outputStream) throws IOException;
+
+ /**
+ * Serializes an XMLDocument as an XML document into the outputStream.
+ * If the DataObject's Type was defined by an XSD, the serialization
+ * will follow the XSD.
+ * Otherwise the serialization will follow the format as if an XSD
+ * were generated as defined by the SDO specification.
+ * The OutputStream will be flushed after writing.
+ * Does not perform validation to ensure compliance with an XSD.
+ * @param xmlDocument specifies XMLDocument to be saved
+ * @param outputStream specifies the OutputStream to write to.
+ * @param options implementation-specific options.
+ * @throws IOException for stream exceptions.
+ * @throws IllegalArgumentException if the dataObject tree
+ * is not closed or has no container.
+ */
+ void save(XMLDocument xmlDocument, OutputStream outputStream, Object options) throws IOException;
+
+ /**
+ * Serializes an XMLDocument as an XML document into the outputWriter.
+ * If the DataObject's Type was defined by an XSD, the serialization
+ * will follow the XSD.
+ * Otherwise the serialization will follow the format as if an XSD
+ * were generated as defined by the SDO specification.
+ * The OutputStream will be flushed after writing.
+ * Does not perform validation to ensure compliance with an XSD.
+ * @param xmlDocument specifies XMLDocument to be saved
+ * @param outputWriter specifies the Writer to write to.
+ * @param options implementation-specific options.
+ * @throws IOException for stream exceptions.
+ * @throws IllegalArgumentException if the dataObject tree
+ * is not closed or has no container.
+ */
+ void save(XMLDocument xmlDocument, Writer outputWriter, Object options) throws IOException;
+
+ /**
+ * Serializes an XMLDocument as an XML document into the outputResult in a
+ * serialization technology independent format (as specified in
+ * javax.xml.transform).
+ * The OutputResult will be flushed after writing.
+ * Does not perform validation to ensure compliance with an XSD.
+ * @param xmlDocument specifies XMLDocument to be saved
+ * @param outputResult specifies Result to be saved
+ * @param options implementation-specific options.
+ * @throws IOException for stream exceptions.
+ * @throws IllegalArgumentException if the dataObject tree
+ * is not closed or has no container.
+ */
+ void save(XMLDocument xmlDocument, Result outputResult, Object options) throws IOException;
+
+ /**
+ * Creates an XMLDocument with the specified XML rootElement for the DataObject.
+ * @param dataObject specifies DataObject to be saved
+ * @param rootElementURI the Target Namespace URI of the root XML element
+ * @param rootElementName the Name of the root XML element
+ * @return XMLDocument a new XMLDocument set with the specified parameters.
+ */
+ XMLDocument createDocument(DataObject dataObject, String rootElementURI, String rootElementName);
+
+ /**
+ * The default XMLHelper.
+ */
+ XMLHelper INSTANCE = HelperProvider.getXMLHelper();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XSDHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XSDHelper.java
new file mode 100644
index 0000000000..37e6927dc8
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/helper/XSDHelper.java
@@ -0,0 +1,196 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.helper;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.List;
+import java.util.Map;
+
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.impl.HelperProvider;
+
+/**
+ * Provides access to additional information when the
+ * Type or Property is defined by an XML Schema (XSD).
+ * Methods return null/false otherwise or if the information is unavailable.
+ * Defines Types from an XSD.
+*/
+public interface XSDHelper
+{
+ /**
+ * Returns the local name as declared in the XSD.
+ * @param type to return local name for.
+ * @return the local name as declared in the XSD.
+ */
+ String getLocalName(Type type);
+
+ /**
+ * Returns the local name as declared in the XSD.
+ * @param property to return local name for.
+ * @return the local name as declared in the XSD.
+ */
+ String getLocalName(Property property);
+
+ /**
+ * Returns the namespace URI as declared in the XSD.
+ * @param property to return namespace URI for.
+ * @return the namespace URI as declared in the XSD.
+ */
+ String getNamespaceURI(Property property);
+
+ /**
+ * Returns true if the property is declared as an attribute in the XSD.
+ * Returns false if not known or for advanced cases.
+ * It is possible for both isAttribute and isElement to return false
+ * but they will not both return true.
+ * @param property to identify if an attribute.
+ * @return true if the property is declared as an attribute in the XSD.
+ */
+ boolean isAttribute(Property property);
+
+ /**
+ * Returns true if the property is declared as an element in the XSD.
+ * Returns false if not known or for advanced cases.
+ * It is possible for both isAttribute and isElement to return false
+ * but they will not both return true.
+ * @param property to identify if an element.
+ * @return true if the property is declared as an element in the XSD.
+ */
+ boolean isElement(Property property);
+
+ /**
+ * Returns true if the Type is declared to contain mixed content.
+ * A DataObject's mixed content values are typically accessed via a Sequence.
+ * @param type to identify if mixed content.
+ * @return true if the Type is declared to contain mixed content.
+ */
+ boolean isMixed(Type type);
+
+ /**
+ * Indicates if this helper contains XSD information for the specified type.
+ * @param type the type.
+ * @return true if this helper contains XSD information for the specified type.
+ */
+ boolean isXSD(Type type);
+
+ /**
+ * Returns the Property defined by the named global element or attribute
+ * in the targetNamespace uri, or null if not found.
+ * @param uri The uri of the targetNamespace.
+ * @param propertyName The name of the global property.
+ * @param isElement is true for global elements, false for global attributes.
+ * @return the Property defined by the named global element or attribute
+ * in the targetNamespace uri, or null if not found.
+ */
+ Property getGlobalProperty(String uri, String propertyName, boolean isElement);
+
+ /**
+ * Return the appinfo declared for this Type and source.
+ * The appinfo start and end tags and content are returned.
+ * The xml namespace context is preserved in the appinfo element.
+ * If more than one appinfo with the same source is declared on the same
+ * Type their contents are concatenated.
+ * @param type the type with the appinfo declaration
+ * @param source the source of the appinfo declaration.
+ * @return the appinfo declared for this Type and source.
+ */
+ String getAppinfo(Type type, String source);
+
+ /**
+ * Return the content of the appinfo declared for this Property and source.
+ * If the property is defined by ref= the appinfo of the referenced
+ * element or attribute is included.
+ * The appinfo start and end tags and content are returned.
+ * The xml namespace context is preserved in the appinfo element.
+ * If more than one appinfo with the same source is declared on the same
+ * Type their contents are concatenated.
+ * @param property the Property with the appinfo declaration
+ * @param source the source of the appinfo declaration.
+ * @return the appinfo declared for this Property and source.
+ */
+ String getAppinfo(Property property, String source);
+
+ /**
+ * Define the XML Schema as Types.
+ * The Types are available through TypeHelper and DataGraph getType() methods.
+ * Same as define(new StringReader(xsd), null)
+ * @param xsd the XML Schema.
+ * @return the defined Types.
+ * @throws IllegalArgumentException if the Types could not be defined.
+ */
+ List /*Type*/ define(String xsd);
+
+ /**
+ * Define XML Schema as Types.
+ * The Types are available through TypeHelper and DataGraph getType() methods.
+ * @param xsdReader reader to an XML Schema.
+ * @param schemaLocation the URI of the location of the schema, used
+ * for processing relative imports and includes. May be null if not used.
+ * @return the defined Types.
+ * @throws IllegalArgumentException if the Types could not be defined.
+ */
+ List /*Type*/ define(Reader xsdReader, String schemaLocation);
+
+ /**
+ * Define XML Schema as Types.
+ * The Types are available through TypeHelper and DataGraph getType() methods.
+ * @param xsdInputStream input stream to an XML Schema.
+ * @param schemaLocation the URI of the location of the schema, used
+ * for processing relative imports and includes. May be null if not used.
+ * @return the defined Types.
+ * @throws IllegalArgumentException if the Types could not be defined.
+ */
+ List /*Type*/ define(InputStream xsdInputStream, String schemaLocation);
+
+ /**
+ * Generate an XML Schema Declaration (XSD) from Types.
+ * Same as generate(types, null);
+ * @param types a List containing the Types
+ * @return a String containing the generated XSD.
+ * @throws IllegalArgumentException if the XSD could not be generated.
+ */
+ String generate(List /*Type*/ types);
+
+ /**
+ * Generate an XML Schema Declaration (XSD) from Types.
+ * Round trip from SDO to XSD to SDO is supported.
+ * Round trip from XSD to SDO to XSD is not supported.
+ * Use the original schema if one exists instead of generating a new one, as
+ * the generated XSD validates a different set of documents than the original XSD.
+ * Generating an XSD does not affect the XSDHelper or the Types.
+ * The Types must all have the same URI.
+ * The result is a String containing the generated XSD.
+ * All Types referenced with the same URI will be generated in the XSD
+ * and the list will be expanded to include all types generated.
+ * Any Types referenced with other URIs will cause
+ * imports to be produced as appropriate.
+ * Imports will include a schemaLocation if a Map is provided with an entry
+ * of the form key=import target namespace, value=schemaLocation
+ * @param types a List containing the Types
+ * @param namespaceToSchemaLocation map of target namespace to schema locations or null
+ * @return a String containing the generated XSD.
+ * @throws IllegalArgumentException if the XSD could not be generated.
+ */
+ String generate(List /*Type*/ types, Map /*String, String*/ namespaceToSchemaLocation);
+
+ /**
+ * The default XSDHelper.
+ */
+ XSDHelper INSTANCE = HelperProvider.getXSDHelper();
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/ExternalizableDelegator.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/ExternalizableDelegator.java
new file mode 100644
index 0000000000..8ca4eb07a0
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/ExternalizableDelegator.java
@@ -0,0 +1,90 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+package commonj.sdo.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.ObjectStreamException;
+
+/**
+ * Delegates DataObject serialization while ensuring implementation independent
+ * java.io.Serialization. An implementation of DataObject
+ * returns an ExternalizableDelegator from its writeReplace() method.
+ *
+ * The root DataObject is the object returned from do.getRootObject() where
+ * do is the DataObject being serialized in a java.io.ObjectOutputStream.
+ * When do.getContainer() == null then do is a root object.
+ *
+ * The byte format for each DataObject in the stream is:
+ * [0] [path] [root] // when do is not a root object
+ * [1] [rootXML] // when do is a root object
+ *
+ * where:
+ * [0] is the byte 0, serialized using writeByte(0).
+ * [1] is the byte 1, serialized using writeByte(1).
+ *
+ * [path] is an SDO path expression from the root DataObject to the serialized
+ * DataObject such that root.getDataObject(path) == do.
+ * Serialized using writeUTF(path).
+ *
+ * [root] is the root object serialized using writeObject(root).
+ *
+ * [rootXML] is the GZip of the XML serialization of the root DataObject.
+ * The XML serialization is the same as
+ * XMLHelper.INSTANCE.save(root, "commonj.sdo", "dataObject", stream);
+ * where stream is a GZIPOutputStream, length is the number of bytes
+ * in the stream, and bytes are the contents of the stream.
+ * Serialized using writeInt(length), write(bytes).
+ *
+ */
+public class ExternalizableDelegator implements Externalizable
+{
+ public interface Resolvable extends Externalizable
+ {
+ Object readResolve() throws ObjectStreamException;
+ }
+
+ static final long serialVersionUID = 1;
+ transient Resolvable delegate;
+
+ public ExternalizableDelegator()
+ {
+ delegate = HelperProvider.createResolvable();
+ }
+
+ public ExternalizableDelegator(Object target)
+ {
+ delegate = HelperProvider.createResolvable(target);
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException
+ {
+ delegate.writeExternal(out);
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ delegate.readExternal(in);
+ }
+
+ public Object readResolve() throws ObjectStreamException
+ {
+ return delegate.readResolve();
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/HelperProvider.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/HelperProvider.java
new file mode 100644
index 0000000000..1918a453f5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/commonj/sdo/impl/HelperProvider.java
@@ -0,0 +1,175 @@
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+
+package commonj.sdo.impl;
+
+
+import com.agfa.hap.sdo.impl.SdoImplementationFactory;
+import commonj.sdo.helper.CopyHelper;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.DataHelper;
+import commonj.sdo.helper.EqualityHelper;
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XMLHelper;
+import commonj.sdo.helper.XSDHelper;
+import commonj.sdo.impl.ExternalizableDelegator.Resolvable;
+
+/**
+ * This class instantiates a HelperProviderImpl that returns concrete helpers.
+ * This class may be replaced by another implementation.
+ */
+public abstract class HelperProvider {
+
+ static HelperProvider INSTANCE = getHelperProviderImpl();
+
+ static HelperProvider getHelperProviderImpl()
+ {
+ // HAP-specific
+ return SdoImplementationFactory.getHelperProviderImplementation();
+ }
+
+ protected HelperProvider()
+ {
+ }
+
+ /**
+ * Gets a CopyHelper
+ * @return a CopyHelper object
+ */
+ public static CopyHelper getCopyHelper()
+ {
+ return INSTANCE.copyHelper();
+ }
+
+ /**
+ * Gets a DataFactory
+ * @return a DataFactory object
+ */
+ public static DataFactory getDataFactory()
+ {
+ return INSTANCE.dataFactory();
+ }
+
+ /**
+ * Gets a DataHelper
+ * @return a DataHelper object
+ */
+ public static DataHelper getDataHelper()
+ {
+ return INSTANCE.dataHelper();
+ }
+
+ /**
+ * Gets an EqualityHelper
+ * @return an EqualityHelper object
+ */
+ public static EqualityHelper getEqualityHelper()
+ {
+ return INSTANCE.equalityHelper();
+ }
+
+ /**
+ * Gets a TypeHelper
+ * @return a TypeHelper object
+ */
+ public static TypeHelper getTypeHelper()
+ {
+ return INSTANCE.typeHelper();
+ }
+
+ /**
+ * Gets an XMLHelper
+ * @return an XMLHelper object
+ */
+ public static XMLHelper getXMLHelper()
+ {
+ return INSTANCE.xmlHelper();
+ }
+
+ /**
+ * Gets an XSDHelper
+ * @return an XSDHelper object
+ */
+ public static XSDHelper getXSDHelper()
+ {
+ return INSTANCE.xsdHelper();
+ }
+
+ /**
+ * Gets a Resolvable
+ * @return a Resolvable object
+ * @see ExternalizableDelegator
+ */
+ public static Resolvable createResolvable()
+ {
+ return INSTANCE.resolvable();
+ }
+
+ /**
+ * Gets a Resolvable
+ * @param target the target object for the Resolvable
+ * @return a Resolvable object
+ * @see ExternalizableDelegator
+ */
+ public static Resolvable createResolvable(Object target)
+ {
+ return INSTANCE.resolvable(target);
+ }
+
+ protected abstract CopyHelper copyHelper();
+ protected abstract DataFactory dataFactory();
+ protected abstract DataHelper dataHelper();
+ protected abstract EqualityHelper equalityHelper();
+ protected abstract TypeHelper typeHelper();
+ protected abstract XMLHelper xmlHelper();
+ protected abstract XSDHelper xsdHelper();
+ protected abstract Resolvable resolvable();
+ protected abstract Resolvable resolvable(Object target);
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
+ // New in SDO 2.1
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Gets the default HelperContext
+ * @return a HelperContext object
+ */
+ public static HelperContext getDefaultContext()
+ {
+ return INSTANCE.helperContext();
+ }
+
+ HelperContext helperContext()
+ {
+ return defaultContext;
+ }
+
+ static HelperContext defaultContext = new DefaultHelperContext();
+
+ static class DefaultHelperContext implements HelperContext
+ {
+ public CopyHelper getCopyHelper() { return INSTANCE.copyHelper(); }
+ public DataFactory getDataFactory() { return INSTANCE.dataFactory(); }
+ public DataHelper getDataHelper() { return INSTANCE.dataHelper(); }
+ public EqualityHelper getEqualityHelper() { return INSTANCE.equalityHelper(); }
+ public TypeHelper getTypeHelper() { return INSTANCE.typeHelper(); }
+ public XMLHelper getXMLHelper() { return INSTANCE.xmlHelper(); }
+ public XSDHelper getXSDHelper() { return INSTANCE.xsdHelper(); }
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/license.txt b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/license.txt
new file mode 100644
index 0000000000..413f33b5e2
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/license.txt
@@ -0,0 +1,33 @@
+License for the Service Data Objects JavaDoc and Interface Definition files.
+
+The Service Data Objects Specification is being provided by the copyright holders under the following
+license. By using and/or copying this work, you agree that you have read, understood and will comply with
+the following terms and conditions:
+
+Permission to copy, display and distribute the Service Data Objects Specification and/or portions thereof, without
+modification, in any medium without fee or royalty is hereby granted, provided that you include the
+following on ALL copies of the Service Data Objects Specification, or portions thereof, that you make:
+
+1. A link or URL to the Service Data Objects Specification at this location:
+http://www.osoa.org/display/Main/Service+Data+Objects+Specifications
+
+2. The full text of this copyright notice as shown in the Service Data Objects Specification.
+
+BEA, IBM, Oracle, Primeton Technologies, Rogue Wave Software, SAP, Software AG, Sun Microsystems, Xcalia,
+Zend Technologies (collectively, the “Authors”) agree to grant you a royalty-free license, under reasonable,
+non-discriminatory terms and conditions to patents that they deem necessary to implement the Service Data
+Objects Specification.
+
+THE Service Data Objects SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO REPRESENTATIONS OR
+WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SPECIFICATION AND THE IMPLEMENTATION OF ITS CONTENTS,
+INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+NON-INFRINGEMENT OR TITLE. THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL
+OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY USE OR DISTRIBUTION OF THE SERVICE DATA OBJECTS
+SPECIFICATION.
+
+The name and trademarks of the Authors may NOT be used in any manner, including advertising or publicity
+pertaining to the Service Data Objects Specification or its contents without specific, written prior
+permission. Title to copyright in the Service Data Objects Specification will at all times remain with the
+Authors.
+
+No other rights are granted by implication, estoppel or otherwise.
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/datagraph.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/datagraph.xsd
new file mode 100644
index 0000000000..2a7f76fe1c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/datagraph.xsd
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+-->
+
+<xsd:schema
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo"
+ targetNamespace="commonj.sdo">
+
+ <xsd:element name="datagraph" type="sdo:DataGraphType"/>
+
+ <xsd:complexType name="DataGraphType">
+ <xsd:complexContent>
+ <xsd:extension base="sdo:BaseDataGraphType">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="1" namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="BaseDataGraphType" abstract="true">
+ <xsd:sequence>
+ <xsd:element name="models" type="sdo:ModelsType" minOccurs="0"/>
+ <xsd:element name="xsd" type="sdo:XSDType" minOccurs="0"/>
+ <xsd:element name="changeSummary" type="sdo:ChangeSummaryType" minOccurs="0"/>
+ </xsd:sequence>
+ <xsd:anyAttribute namespace="##other" processContents="lax"/>
+ </xsd:complexType>
+
+ <xsd:complexType name="ModelsType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Expected type is emof:Package.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="XSDType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Expected type is xsd:schema.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="unbounded" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="ChangeSummaryType">
+ <xsd:sequence>
+ <xsd:any minOccurs="0" maxOccurs="unbounded" namespace="##any" processContents="lax"/>
+ </xsd:sequence>
+ <xsd:attribute name="create" type="xsd:string"/>
+ <xsd:attribute name="delete" type="xsd:string"/>
+ <xsd:attribute name="logging" type="xsd:boolean"/>
+ </xsd:complexType>
+
+ <xsd:attribute name="ref" type="xsd:string"/>
+ <xsd:attribute name="unset" type="xsd:string"/>
+
+</xsd:schema>
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xml b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xml
new file mode 100644
index 0000000000..3fb1507947
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+-->
+
+<types xmlns="commonj.sdo"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:sdoJava="commonj.sdo/java"
+ xsi:schemaLocation="commonj.sdo sdoModel.xsd commonj.sdo/java sdoJava.xsd commonj.sdo/xml sdoXML.xsd">
+
+<!--
+ Global properties used in open content for
+ the Java binding of SDO Types and Properties.
+-->
+
+ <type uri="commonj.sdo/java">
+ <property name="javaClass" type="commonj.sdo#String"/>
+ </type>
+
+ <!-- JavaInfo deprecated in 2.1.0 -->
+ <type name="JavaInfo" uri="commonj.sdo/java">
+ <property name="javaClass" type="commonj.sdo#String"/>
+ </type>
+
+<!--
+ The Java object data types.
+-->
+
+ <type name="BooleanObject" dataType="true" sdoJava:instanceClass="java.lang.Boolean" uri="commonj.sdo/java"/>
+ <type name="ByteObject" dataType="true" sdoJava:instanceClass="java.lang.Byte" uri="commonj.sdo/java"/>
+ <type name="CharacterObject" dataType="true" sdoJava:instanceClass="java.lang.Character" uri="commonj.sdo/java"/>
+ <type name="DoubleObject" dataType="true" sdoJava:instanceClass="java.lang.Double" uri="commonj.sdo/java"/>
+ <type name="FloatObject" dataType="true" sdoJava:instanceClass="java.lang.Float" uri="commonj.sdo/java"/>
+ <type name="IntObject" dataType="true" sdoJava:instanceClass="java.lang.Int" uri="commonj.sdo/java"/>
+ <type name="LongObject" dataType="true" sdoJava:instanceClass="java.lang.Long" uri="commonj.sdo/java"/>
+ <type name="ShortObject" dataType="true" sdoJava:instanceClass="java.lang.Short" uri="commonj.sdo/java"/>
+
+</types>
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xsd
new file mode 100644
index 0000000000..700e91c5a5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoJava.xsd
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+-->
+
+<xsd:schema
+ targetNamespace="commonj.sdo/java"
+ xmlns:sdoJava="commonj.sdo/java"
+ xmlns:sdo="commonj.sdo"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+<xsd:import namespace="commonj.sdo" schemaLocation="sdoModel.xsd"/>
+
+<!--
+ These attributes are used to customize the Java mapping of
+ XSD to SDO Types and Properties.
+-->
+
+<xsd:attribute name="package" type="xsd:string" />
+<xsd:attribute name="instanceClass" type="xsd:string" />
+<xsd:attribute name="extendedInstanceClass" type="xsd:string" />
+<xsd:attribute name="nestedInterfaces" type="xsd:boolean" />
+
+<!--
+ Global properties used in open content for
+ the Java binding of SDO Types and Properties.
+-->
+
+<xsd:attribute name="javaClass" type="sdo:String"/>
+
+<!-- JavaInfo deprecated in 2.1.0 -->
+<xsd:complexType name="JavaInfo">
+ <xsd:attribute name="javaClass" type="sdo:String"/>
+</xsd:complexType>
+
+<!--
+ The Java object data types.
+-->
+
+<xsd:simpleType name="BooleanObject" sdoJava:instanceClass="java.lang.Boolean">
+ <xsd:restriction base="xsd:boolean"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="ByteObject" sdoJava:instanceClass="java.lang.Byte">
+ <xsd:restriction base="xsd:byte"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="CharacterObject" sdoJava:instanceClass="java.lang.Character">
+ <xsd:restriction base="xsd:string"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="DoubleObject" sdoJava:instanceClass="java.lang.Double">
+ <xsd:restriction base="xsd:double"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="FloatObject" sdoJava:instanceClass="java.lang.Float">
+ <xsd:restriction base="xsd:float"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="IntObject" sdoJava:instanceClass="java.lang.Integer">
+ <xsd:restriction base="xsd:int"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="LongObject" sdoJava:instanceClass="java.lang.Long">
+ <xsd:restriction base="xsd:long"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="ShortObject" sdoJava:instanceClass="java.lang.Short">
+ <xsd:restriction base="xsd:short"/>
+</xsd:simpleType>
+
+</xsd:schema>
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xml b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xml
new file mode 100644
index 0000000000..ce490c467d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+-->
+
+<types xmlns="commonj.sdo"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:sdoJava="commonj.sdo/java"
+ xsi:schemaLocation="commonj.sdo sdoModel.xsd commonj.sdo/java sdoJava.xsd commonj.sdo/xml sdoXML.xsd">
+
+<!-- Model Types
+ SDO Type and Property are defined in terms of themselves.
+-->
+
+ <type name="Type" open="true" uri="commonj.sdo">
+ <property name="baseType" type="#Type" many="true"/>
+ <property name="property" type="#Property" containment="true" many="true"/>
+ <property name="aliasName" type="#String" many="true"/>
+ <property name="name" type="#String"/>
+ <property name="uri" type="#String"/>
+ <property name="dataType" type="#Boolean"/>
+ <property name="open" type="#Boolean"/>
+ <property name="sequenced" type="#Boolean"/>
+ <property name="abstract" type="#Boolean"/>
+ </type>
+
+ <type name="Property" open="true" uri="commonj.sdo">
+ <property name="aliasName" type="#String" many="true"/>
+ <property name="name" type="#String"/>
+ <property name="many" type="#Boolean"/>
+ <property name="containment" type="#Boolean"/>
+ <property name="type" type="#Type" />
+ <property name="default" type="#String"/>
+ <property name="readOnly" type="#Boolean"/>
+ <property name="opposite" type="#Property"/>
+ <property name="nullable" type="#Boolean"/>
+ </type>
+
+<!-- SDO special types -->
+
+ <type name="DataObject" abstract="true" sdoJava:instanceClass="commonj.sdo.DataObject" uri="commonj.sdo"/>
+ <type name="Object" abstract="true" datatype="true" sdoJava:instanceClass="java.lang.Object" uri="commonj.sdo"/>
+ <type name="ChangeSummaryType" abstract="true" datatype="true" sdoJava:instanceClass="commonj.sdo.ChangeSummary" uri="commonj.sdo"/>
+
+ <!-- TextType deprecated in 2.1.0 -->
+ <type name="TextType" abstract="true">
+ <property name="text" type="#String" many="true"/>
+ </type>
+
+<!-- SDO data types -->
+
+ <type name="Boolean" datatype="true" sdoJava:instanceClass="boolean" uri="commonj.sdo"/>
+ <type name="Byte" datatype="true" sdoJava:instanceClass="byte" uri="commonj.sdo"/>
+ <type name="Bytes" datatype="true" sdoJava:instanceClass="byte[]" uri="commonj.sdo"/>
+ <type name="Character" datatype="true" sdoJava:instanceClass="char" uri="commonj.sdo"/>
+ <type name="Date" datatype="true" sdoJava:instanceClass="java.util.Date" uri="commonj.sdo"/>
+ <type name="DateTime" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="Day" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="Decimal" datatype="true" sdoJava:instanceClass="java.math.BigDecimal" uri="commonj.sdo"/>
+ <type name="Duration" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="Double" datatype="true" sdoJava:instanceClass="double" uri="commonj.sdo"/>
+ <type name="Float" datatype="true" sdoJava:instanceClass="float" uri="commonj.sdo"/>
+ <type name="Int" datatype="true" sdoJava:instanceClass="int" uri="commonj.sdo"/>
+ <type name="Integer" datatype="true" sdoJava:instanceClass="java.math.BigInteger" uri="commonj.sdo"/>
+ <type name="Long" datatype="true" sdoJava:instanceClass="long" uri="commonj.sdo"/>
+ <type name="MonthDay" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="Month" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="Short" datatype="true" sdoJava:instanceClass="short" uri="commonj.sdo"/>
+ <type name="String" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="Strings" datatype="true" sdoJava:instanceClass="java.util.List" uri="commonj.sdo"/>
+ <type name="Time" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="Year" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="YearMonth" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="YearMonthDay" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+ <type name="URI" datatype="true" sdoJava:instanceClass="java.lang.String" uri="commonj.sdo"/>
+
+</types>
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xsd
new file mode 100644
index 0000000000..170c651df6
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoModel.xsd
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+
+-->
+
+<xsd:schema
+ targetNamespace="commonj.sdo"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:sdo="commonj.sdo"
+ xmlns:sdoXML="commonj.sdo/xml"
+ xmlns:sdoJava="commonj.sdo/java"
+ elementFormDefault="qualified"
+ xsi:schemaLocation="commonj.sdo/xml sdoXML.xsd
+ commonj.sdo/java sdoJava.xsd">
+
+<xsd:include schemaLocation="datagraph.xsd"/>
+
+<!-- Root element for defining several Types in one document.
+ Is not part of the model.
+-->
+<xsd:element name="types" type="sdo:Types"/>
+<xsd:complexType name="Types">
+ <xsd:sequence>
+ <xsd:element name="type" type="sdo:Type" minOccurs="0" maxOccurs="unbounded"/>
+ </xsd:sequence>
+</xsd:complexType>
+
+<!-- Any data object may be serialized with this element,
+ with xsi:type to declare the
+ actual type of the DataObject serialized.
+-->
+<xsd:element name="dataObject" type="xsd:anyType"/>
+
+<!-- Model Types
+ SDO Type and Property are defined in terms of themselves.
+-->
+<xsd:element name="type" type="sdo:Type"/>
+<xsd:complexType name="Type">
+ <xsd:sequence>
+ <xsd:element name="baseType" type="sdo:URI"
+ minOccurs="0" maxOccurs="unbounded"
+ sdoXML:propertyType="sdo:Type" />
+ <xsd:element name="property" type="sdo:Property"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="aliasName" type="sdo:String"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:ID" sdoXML:dataType="sdo:String"/>
+ <xsd:attribute name="uri" type="sdo:URI"/>
+ <xsd:attribute name="dataType" type="sdo:Boolean"/>
+ <xsd:attribute name="open" type="sdo:Boolean"/>
+ <xsd:attribute name="sequenced" type="sdo:Boolean"/>
+ <xsd:attribute name="abstract" type="sdo:Boolean"/>
+ <xsd:anyAttribute namespace="##any" processContents="lax"/>
+</xsd:complexType>
+
+<xsd:complexType name="Property">
+ <xsd:sequence>
+ <xsd:element name="aliasName" type="sdo:String"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:any namespace="##other" processContents="lax"
+ minOccurs="0" maxOccurs="unbounded" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="sdo:String"/>
+ <xsd:attribute name="many" type="sdo:Boolean"/>
+ <xsd:attribute name="containment" type="sdo:Boolean"/>
+ <xsd:attribute name="default" type="sdo:String"/>
+ <xsd:attribute name="readOnly" type="sdo:Boolean"/>
+ <xsd:attribute name="type" type="sdo:URI" sdoXML:propertyType="sdo:Type"/>
+ <xsd:attribute name="opposite" type="sdo:URI" sdoXML:propertyType="sdo:Property"/>
+ <xsd:attribute name="nullable" type="sdo:Boolean"/>
+ <xsd:anyAttribute namespace="##any" processContents="lax"/>
+</xsd:complexType>
+
+<!-- Special Types -->
+<xsd:complexType name="DataObject" abstract="true"/>
+
+<!-- TextType deprecated in 2.1.0 -->
+ <xsd:complexType name="TextType" abstract="true">
+ <xsd:sequence>
+ <xsd:element name="text" minOccurs="0" maxOccurs="unbounded" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+
+<!-- ChangeSummaryType is defined in datagraph.xsd.
+ Although declared there as a ComplexType,
+ at the model level it is treated as a SimpleType
+ with a special XML serialization.
+-->
+
+<!-- Data Types -->
+<xsd:simpleType name="Boolean" sdoJava:instanceClass="boolean">
+ <xsd:restriction base="xsd:boolean"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Byte" sdoJava:instanceClass="byte">
+ <xsd:restriction base="xsd:byte"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Bytes" sdoJava:instanceClass="byte[]">
+ <xsd:restriction base="xsd:hexBinary"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Character" sdoJava:instanceClass="char">
+ <xsd:restriction base="xsd:string"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Date" sdoJava:instanceClass="java.util.Date">
+ <xsd:restriction base="xsd:dateTime"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="DateTime" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:dateTime"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Day" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:gDay"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Decimal" sdoJava:instanceClass="java.math.BigDecimal">
+ <xsd:restriction base="xsd:decimal"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Double" sdoJava:instanceClass="double">
+ <xsd:restriction base="xsd:double"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Duration" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:duration"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Float" sdoJava:instanceClass="float">
+ <xsd:restriction base="xsd:float"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Int" sdoJava:instanceClass="int">
+ <xsd:restriction base="xsd:int"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Integer" sdoJava:instanceClass="java.math.BigInteger">
+ <xsd:restriction base="xsd:integer"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Long" sdoJava:instanceClass="long">
+ <xsd:restriction base="xsd:long"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Month" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:gMonth"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="MonthDay" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:gMonthDay"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Object" sdoJava:instanceClass="java.lang.Object">
+ <!-- Only the schema for schemas is allowed to restrict anySimpleType.
+ <xsd:restriction base="xsd:anySimpleType"/>
+ The equivalent declaration is a union of the predefined XSD data types.
+ -->
+ <xsd:union memberTypes="xsd:anyURI xsd:base64Binary xsd:boolean xsd:byte
+ xsd:date xsd:dateTime xsd:decimal xsd:double xsd:duration xsd:ENTITIES xsd:ENTITY xsd:float
+ xsd:gDay xsd:gMonth xsd:gMonthDay xsd:gYear xsd:gYearMonth xsd:hexBinary xsd:ID xsd:IDREF xsd:IDREFS
+ xsd:int xsd:integer xsd:language xsd:long xsd:Name xsd:NCName xsd:negativeInteger
+ xsd:NMTOKEN xsd:NMTOKENS xsd:nonNegativeInteger xsd:nonPositiveInteger
+ xsd:normalizedString xsd:NOTATION xsd:positiveInteger xsd:QName xsd:short xsd:string
+ xsd:time xsd:token xsd:unsignedByte xsd:unsignedInt xsd:unsignedLong xsd:unsignedShort"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Short" sdoJava:instanceClass="short">
+ <xsd:restriction base="xsd:short"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="String" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:string"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Strings" sdoJava:instanceClass="java.util.List">
+ <xsd:restriction base="xsd:string"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Time" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:time"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="Year" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:gYear"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="YearMonth" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:gYearMonth"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="YearMonthDay" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:date"/>
+</xsd:simpleType>
+
+<xsd:simpleType name="URI" sdoJava:instanceClass="java.lang.String">
+ <xsd:restriction base="xsd:anyURI"/>
+</xsd:simpleType>
+
+</xsd:schema>
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xml b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xml
new file mode 100644
index 0000000000..3ed0840854
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+-->
+
+<types xmlns="commonj.sdo"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:sdoXML="commonj.sdo/xml"
+ xsi:schemaLocation="commonj.sdo sdoModel.xsd commonj.sdo/java sdoJava.xsd commonj.sdo/xml sdoXML.xsd">
+
+<!--
+ Global properties used in open content for
+ the XML binding of SDO Types and Properties.
+-->
+
+ <type uri="commonj.sdo/xml">
+ <property name="xmlElement" type="commonj.sdo#Boolean"/>
+ </type>
+
+ <!-- XMLInfo deprecated in 2.1.0 -->
+ <type name="XMLInfo" uri="commonj.sdo/xml">
+ <property name="xmlElement" type="commonj.sdo#Boolean"/>
+ </type>
+
+</types>
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xsd
new file mode 100644
index 0000000000..c300874fb8
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/main/java/xml/sdoXML.xsd
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+/**
+ * <copyright>
+ *
+ * Service Data Objects
+ * Version 2.1.0
+ * Licensed Materials
+ *
+ * (c) Copyright BEA Systems, Inc., International Business Machines Corporation,
+ * Oracle Corporation, Primeton Technologies Ltd., Rogue Wave Software, SAP AG.,
+ * Software AG., Sun Microsystems, Sybase Inc., Xcalia, Zend Technologies,
+ * 2005, 2006. All rights reserved.
+ *
+ * </copyright>
+ *
+ */
+-->
+
+<xsd:schema
+ targetNamespace="commonj.sdo/xml"
+ xmlns:sdo="commonj.sdo"
+ xmlns:sdoXML="commonj.sdo/xml"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+<xsd:import namespace="commonj.sdo" schemaLocation="sdoModel.xsd"/>
+
+
+<!--
+ These attributes are used to customize the XSD mapping of SDO Types and Properties.
+-->
+
+<xsd:attribute name="name" type="xsd:string" />
+<xsd:attribute name="propertyType" type="xsd:QName" />
+<xsd:attribute name="oppositeProperty" type="xsd:string" />
+<xsd:attribute name="sequence" type="xsd:boolean" />
+<xsd:attribute name="string" type="xsd:boolean" />
+<xsd:attribute name="dataType" type="xsd:QName" />
+<xsd:attribute name="aliasName" type="xsd:string" />
+<xsd:attribute name="readOnly" type="xsd:boolean" />
+<xsd:attribute name="many" type="xsd:boolean" />
+
+<!--
+ Global properties used in open content for
+ the XML binding of SDO Types and Properties.
+-->
+
+<xsd:attribute name="xmlElement" type="sdo:Boolean"/>
+
+<!-- XMLInfo deprecated in 2.1.0 -->
+<xsd:complexType name="XMLInfo">
+ <xsd:attribute name="xmlElement" type="sdo:Boolean"/>
+</xsd:complexType>
+
+</xsd:schema>
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/configuration/config.ini b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/configuration/config.ini
new file mode 100644
index 0000000000..3b8be1b173
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/configuration/config.ini
@@ -0,0 +1,6 @@
+#Product Runtime Configuration File
+
+osgi.bundles=\
+ org.eclipse.equinox.common@2\:start,\
+ org.eclipse.update.configurator@3:start,\
+ org.eclipse.core.runtime@4:start
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/BytesTypeConverterTest.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/BytesTypeConverterTest.java
new file mode 100644
index 0000000000..b86f6ed42d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/BytesTypeConverterTest.java
@@ -0,0 +1,24 @@
+package com.agfa.hap.sdo.implementation;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.impl.BytesTypeConverter;
+
+public class BytesTypeConverterTest {
+ @Test
+ public void convert(){
+ BytesTypeConverter converter = new BytesTypeConverter();
+ byte[] input = new byte[256];
+ int i = 0;
+ for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++, i++){
+ input[i] = b;
+ }
+ byte[] output = converter.parse(converter.toString(input));
+ for (int j = 0; j < output.length; j++){
+ Assert.assertEquals(input[j], output[j]);
+ }
+ }
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/TestLongUTFSerialization.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/TestLongUTFSerialization.java
new file mode 100644
index 0000000000..e3c56c3f46
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/implementation/TestLongUTFSerialization.java
@@ -0,0 +1,56 @@
+package com.agfa.hap.sdo.implementation;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.implementation.SnapshotImplementation.SnapshotSerializer;
+
+public class TestLongUTFSerialization {
+
+ private SnapshotSerializer serializer;
+
+ @Before
+ public void setup(){
+ serializer = new SnapshotImplementation.SnapshotSerializer(null);
+ }
+
+ @Test
+ public void testShort() throws IOException{
+ testUTFRoundtrip("test123");
+ }
+ @Test
+ public void testMaxUTF() throws IOException{
+ StringBuilder maxUTFString = new StringBuilder();
+ for (int i = 0; i < SnapshotSerializer.MAX_UTF_LENGTH; i++){
+ maxUTFString.append(i % 9);
+ }
+ testUTFRoundtrip(maxUTFString.toString());
+ }
+
+ @Test
+ public void testLongUTF() throws IOException {
+ StringBuilder maxUTFString = new StringBuilder();
+ for (int i = 0; i < 2*SnapshotSerializer.MAX_UTF_LENGTH; i++){
+ maxUTFString.append(i % 9);
+ }
+ maxUTFString.append("somemorecharacters");
+ testUTFRoundtrip(maxUTFString.toString());
+
+ }
+
+ private void testUTFRoundtrip(String inputString) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ serializer.writePotentiallyLongStringUTF(inputString, new DataOutputStream(bos));
+ String outputString = serializer.readPotentiallyLongUTF(new DataInputStream(new ByteArrayInputStream(bos.toByteArray())));
+ Assert.assertEquals(inputString, outputString);
+ }
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilderTest.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilderTest.java
new file mode 100644
index 0000000000..11335f290c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/BeanPropertyAccessorBuilderTest.java
@@ -0,0 +1,30 @@
+package com.agfa.hap.sdo.mapper;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.implementation.PropertyImplementation;
+import com.agfa.hap.sdo.mapper.BeanPropertyAccessor;
+import com.agfa.hap.sdo.mapper.BeanPropertyAccessorBuilder;
+
+public class BeanPropertyAccessorBuilderTest {
+ @Test
+ public void booleanProperties(){
+ BeanPropertyAccessorBuilder builder = new BeanPropertyAccessorBuilder();
+ Property isCancelledProp = new PropertyImplementation("isCancelled", TypeHelper.INSTANCE.getType(Boolean.class), null, 0);
+ Assert.assertNotNull((BeanPropertyAccessor) builder.createPropertyAccessor(SomePojo.class, isCancelledProp));
+ Property someBooleanProp = new PropertyImplementation("someBoolean", TypeHelper.INSTANCE.getType(Boolean.class), null, 0);
+ Assert.assertNotNull((BeanPropertyAccessor) builder.createPropertyAccessor(SomePojo.class, someBooleanProp));
+ }
+
+ @Test
+ public void someRegularProp(){
+ BeanPropertyAccessorBuilder builder = new BeanPropertyAccessorBuilder();
+ Property someProp = new PropertyImplementation("someProperty", TypeHelper.INSTANCE.getType(String.class), null, 0);
+ BeanPropertyAccessor propAccessor = (BeanPropertyAccessor) builder.createPropertyAccessor(SomePojo.class, someProp );
+ Assert.assertNotNull(propAccessor);
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/DummyPropertyAccessor.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/DummyPropertyAccessor.java
new file mode 100644
index 0000000000..5a0e945b59
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/DummyPropertyAccessor.java
@@ -0,0 +1,14 @@
+package com.agfa.hap.sdo.mapper;
+
+import com.agfa.hap.sdo.DataMapper;
+import com.agfa.hap.sdo.Property;
+
+public class DummyPropertyAccessor extends AbstractPropertyAccessor {
+
+ public Object getValue(Object instance, Property property, DataMapper dataMapper) {
+ return null;
+ }
+
+ public void setValue(Object instance, Property property, Object value, DataMapper dataMapper) {
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilderTest.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilderTest.java
new file mode 100644
index 0000000000..6a83adbc83
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/ExtendablePropertyAccessorBuilderTest.java
@@ -0,0 +1,20 @@
+package com.agfa.hap.sdo.mapper;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.implementation.PropertyImplementation;
+import com.agfa.hap.sdo.mapper.ExtendablePropertyAccessorBuilder;
+import com.agfa.hap.sdo.mapper.PropertyAccessor;
+
+public class ExtendablePropertyAccessorBuilderTest {
+ @Test
+ public void extendedPropertyIsInSuperClass(){
+ ExtendablePropertyAccessorBuilder builder = new ExtendablePropertyAccessorBuilder(null);
+ Property superPropProperty = new PropertyImplementation("superProperty", null, null, 1);
+ PropertyAccessor accessor = builder.createPropertyAccessor(Sub.class, superPropProperty );
+ Assert.assertTrue(accessor instanceof DummyPropertyAccessor);
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/SomePojo.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/SomePojo.java
new file mode 100644
index 0000000000..812ab4618d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/SomePojo.java
@@ -0,0 +1,26 @@
+package com.agfa.hap.sdo.mapper;
+
+public class SomePojo {
+ private boolean isCancelled;
+ private String someProperty;
+ private boolean someBoolean;
+ public boolean isSomeBoolean() {
+ return someBoolean;
+ }
+ public void setSomeBoolean(boolean someBoolean) {
+ this.someBoolean = someBoolean;
+ }
+ public boolean isCancelled() {
+ return isCancelled;
+ }
+ public void setCancelled(boolean isCancelled) {
+ this.isCancelled = isCancelled;
+ }
+ public String getSomeProperty() {
+ return someProperty;
+ }
+ public void setSomeProperty(String someProperty) {
+ this.someProperty = someProperty;
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Sub.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Sub.java
new file mode 100644
index 0000000000..88aba1eeb2
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Sub.java
@@ -0,0 +1,13 @@
+package com.agfa.hap.sdo.mapper;
+
+public class Sub extends Super {
+ private String subProperty;
+
+ public String getSubProperty() {
+ return subProperty;
+ }
+
+ public void setSubProperty(String subProperty) {
+ this.subProperty = subProperty;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Super.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Super.java
new file mode 100644
index 0000000000..e2fdd24bc1
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/mapper/Super.java
@@ -0,0 +1,13 @@
+package com.agfa.hap.sdo.mapper;
+
+public class Super {
+ private String superProperty;
+
+ public String getSuperProperty() {
+ return superProperty;
+ }
+
+ public void setSuperProperty(String superProp) {
+ this.superProperty = superProp;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/A.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/A.java
new file mode 100644
index 0000000000..ebb02b3b08
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/A.java
@@ -0,0 +1,91 @@
+package com.agfa.hap.sdo.test;
+
+import java.net.URI;
+
+public class A {
+ private byte[] bytearrayProp;
+ private String stringProp;
+ private int intProp;
+ private B b;
+ private B containedB;
+ private long longProp;
+ private short shortProp;
+ private boolean booleanProp;
+ private double doubleProp;
+ private byte byteProp;
+ private float floatProp;
+ private URI uriProp;
+
+ public B getB() {
+ return b;
+ }
+ public void setB(B b) {
+ this.b = b;
+ }
+ public B getContainedB() {
+ return containedB;
+ }
+ public void setContainedB(B b) {
+ this.containedB = b;
+ }
+ public boolean isBooleanProp() {
+ return booleanProp;
+ }
+ public void setBooleanProp(boolean booleanProp) {
+ this.booleanProp = booleanProp;
+ }
+ public byte getByteProp() {
+ return byteProp;
+ }
+ public void setByteProp(byte byteProp) {
+ this.byteProp = byteProp;
+ }
+ public double getDoubleProp() {
+ return doubleProp;
+ }
+ public void setDoubleProp(double doubleProp) {
+ this.doubleProp = doubleProp;
+ }
+ public float getFloatProp() {
+ return floatProp;
+ }
+ public void setFloatProp(float floatProp) {
+ this.floatProp = floatProp;
+ }
+ public int getIntProp() {
+ return intProp;
+ }
+ public void setIntProp(int intProp) {
+ this.intProp = intProp;
+ }
+ public long getLongProp() {
+ return longProp;
+ }
+ public void setLongProp(long longProp) {
+ this.longProp = longProp;
+ }
+ public short getShortProp() {
+ return shortProp;
+ }
+ public void setShortProp(short shortProp) {
+ this.shortProp = shortProp;
+ }
+ public String getStringProp() {
+ return stringProp;
+ }
+ public void setStringProp(String stringProp) {
+ this.stringProp = stringProp;
+ }
+ public URI getUriProp() {
+ return uriProp;
+ }
+ public void setUriProp(URI uriProp) {
+ this.uriProp = uriProp;
+ }
+ public byte[] getBytearrayProp() {
+ return bytearrayProp;
+ }
+ public void setBytearrayProp(byte[] bytearrayProp) {
+ this.bytearrayProp = bytearrayProp;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/B.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/B.java
new file mode 100644
index 0000000000..e6c04d9913
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/B.java
@@ -0,0 +1,41 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class B {
+
+ private String name;
+ private List<B> children;
+ private B parent;
+ private B favouriteChild;
+
+ public B() {
+ children = new ArrayList<B>();
+ }
+
+ public List<B> getChildren() {
+ return children;
+ }
+ public void setChildren(List<B> children) {
+ this.children = children;
+ }
+ public B getFavouriteChild() {
+ return favouriteChild;
+ }
+ public void setFavouriteChild(B favouriteChild) {
+ this.favouriteChild = favouriteChild;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public B getParent() {
+ return parent;
+ }
+ public void setParent(B parent) {
+ this.parent = parent;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/C.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/C.java
new file mode 100644
index 0000000000..1b9313deaf
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/C.java
@@ -0,0 +1,42 @@
+package com.agfa.hap.sdo.test;
+
+import java.net.URI;
+
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.implementation.DataObjectImplementation;
+import com.agfa.hap.sdo.implementation.TypeImplementation;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XSDHelper;
+
+public class C extends DataObjectImplementation {
+
+ private static final long serialVersionUID = -5008889354555116408L;
+
+ public C() {
+ super(TypeHolder.type);
+ }
+
+ public C(Type type) {
+ super(type);
+ }
+
+ public String getName() {
+ return (String) super.get("name");
+ }
+
+ public void setName(String name) {
+ super.set("name", name);
+ }
+
+ public URI getUri() {
+ return (URI) super.getIdentity();
+ }
+
+ private static class TypeHolder {
+ public final static TypeImplementation type;
+ static {
+ XSDHelper.INSTANCE.define(C.class.getResourceAsStream("/sdo/test-sdo-types.xsd"), "test");
+ type = (TypeImplementation) TypeHelper.INSTANCE.getType("test", "C");
+ }
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/DataObjectCreator.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/DataObjectCreator.java
new file mode 100644
index 0000000000..3b6775196e
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/DataObjectCreator.java
@@ -0,0 +1,26 @@
+package com.agfa.hap.sdo.test;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.DataFactory;
+
+public class DataObjectCreator {
+
+ static DataObject createSimpleDataObject() {
+ DataObject result = DataFactory.INSTANCE.create("commonj.sdo", "Type");
+ result.set("name", "TestType");
+ result.set("dataType", Boolean.FALSE);
+ return result;
+ }
+
+ static DataObject createDataObjectWithManyValuedProperty() {
+ DataObject dataObject = createSimpleDataObject();
+ DataObject prop = dataObject.createDataObject("property");
+ prop.set("name", "prop1");
+ prop = dataObject.createDataObject("property");
+ prop.set("name", "prop2");
+ return dataObject;
+ }
+
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ExampleEnum.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ExampleEnum.java
new file mode 100644
index 0000000000..362d06eef5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ExampleEnum.java
@@ -0,0 +1,7 @@
+package com.agfa.hap.sdo.test;
+
+public enum ExampleEnum {
+
+ ONE, TWO, THREE
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/FilteringPartialDataObjectMapperTest.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/FilteringPartialDataObjectMapperTest.java
new file mode 100644
index 0000000000..8ae9dfce32
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/FilteringPartialDataObjectMapperTest.java
@@ -0,0 +1,78 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.ReachableDefinition;
+import com.agfa.hap.sdo.Snapshot;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.implementation.TypeImplementation;
+import com.agfa.hap.sdo.mapper.FilteringPartialDataObjectMapper;
+import com.agfa.hap.sdo.mapper.PartialDataObjectMapper;
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.DataFactory;
+
+public class FilteringPartialDataObjectMapperTest {
+
+ @Test
+ public void test(){
+ Type typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ DataObject stringType = DataFactory.INSTANCE.create(typeType);
+ stringType.set("name", "String");
+ stringType.set("uri", "commonj");
+
+ DataObject fTypeDO = DataFactory.INSTANCE.create(typeType);
+ fTypeDO.set("name", "TestTypeF");
+ fTypeDO.set("uri", "unittest");
+ DataObject someProp = fTypeDO.createDataObject("property");
+ someProp.set("name", "propF1");
+ someProp.set("type", stringType);
+ DataObject idProp = fTypeDO.createDataObject("property");
+ idProp.set("name", "idProp");
+ idProp.set("type", stringType);
+
+ DataObject rTypeDO = DataFactory.INSTANCE.create(typeType);
+ rTypeDO.set("name", "TestTypeR");
+ rTypeDO.set("uri", "unittest");
+ DataObject prop = rTypeDO.createDataObject("property");
+ prop.set("name", "prop1");
+ prop.set("type", fTypeDO);
+ prop = rTypeDO.createDataObject("property");
+ prop.set("name", "prop2");
+ prop.set("type", stringType);
+ List<DataObject> types = new ArrayList<DataObject>();
+ types.add(stringType);
+ types.add(fTypeDO);
+ types.add(rTypeDO);
+ TypeHelper.INSTANCE.define(types);
+ Type fType = TypeHelper.INSTANCE.getType("unittest", "TestTypeF");
+ ((TypeImplementation) fType).setIdentityProperty(fType.getProperty("idProp"));
+
+
+ List<Type> typesToBeFiltered = new ArrayList<Type>();
+
+ typesToBeFiltered.add(fType);
+
+ DataObject someF = DataFactory.INSTANCE.create("unittest", "TestTypeF");
+ someF.set("propF1", "dit is een test");
+ someF.set("idProp", "123123");
+ DataObject someR = DataFactory.INSTANCE.create("unittest", "TestTypeR");
+ someR.set("prop1", someF);
+ someR.set("prop2", "test123");
+
+ List<PartialDataObject> roots = new ArrayList<PartialDataObject>();
+ roots.add((PartialDataObject) someR);
+ Snapshot snapshot = DataAccessService.createMultiSnapShot(new FilteringPartialDataObjectMapper(typesToBeFiltered), new ReachableDefinition(), roots);
+ List<PartialDataObject> extracted = snapshot.extract(new PartialDataObjectMapper());
+ Assert.assertEquals(1, extracted.size());
+ PartialDataObject extractedR = extracted.get(0);
+ Assert.assertTrue(((PartialDataObject) extractedR.get("prop1")).isProxy());
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/InheritedB.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/InheritedB.java
new file mode 100644
index 0000000000..5789e24427
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/InheritedB.java
@@ -0,0 +1,14 @@
+package com.agfa.hap.sdo.test;
+
+public class InheritedB extends B {
+
+ private String nickname;
+
+ public String getNickname() {
+ return nickname;
+ }
+
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObject.java
new file mode 100644
index 0000000000..8ae1ce68ec
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObject.java
@@ -0,0 +1,14 @@
+package com.agfa.hap.sdo.test;
+
+public class MyBasicObject {
+
+ public static MyBasicObject ONE = new MyBasicObject(1);
+ public static MyBasicObject TWO = new MyBasicObject(2);
+ public static MyBasicObject THREE = new MyBasicObject(3);
+
+ public MyBasicObject(int i) {
+ this.i = i;
+ }
+
+ public int i;
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObjectTypeConverter.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObjectTypeConverter.java
new file mode 100644
index 0000000000..f7a7d7fb19
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/MyBasicObjectTypeConverter.java
@@ -0,0 +1,26 @@
+package com.agfa.hap.sdo.test;
+
+import com.agfa.hap.sdo.impl.TypeConverter;
+
+public class MyBasicObjectTypeConverter extends TypeConverter<MyBasicObject> {
+
+ @Override
+ public MyBasicObject parse(String str) {
+ int i = Integer.parseInt(str);
+ switch(i) {
+ case 1:
+ return MyBasicObject.ONE;
+ case 2:
+ return MyBasicObject.TWO;
+ case 3:
+ return MyBasicObject.THREE;
+ }
+ return new MyBasicObject(i);
+ }
+
+ @Override
+ public String toString(MyBasicObject instance) {
+ return Integer.toString(instance.i);
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ResultSetTest.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ResultSetTest.java
new file mode 100644
index 0000000000..30a03ee7ba
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/ResultSetTest.java
@@ -0,0 +1,101 @@
+package com.agfa.hap.sdo.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.util.ResultSet;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.TypeHelper;
+
+public class ResultSetTest {
+
+ protected Type typeType;
+
+ @Before
+ public void initializeTypes() {
+ typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ }
+
+ @Test
+ public void simpleResultSet() throws Exception {
+ List<DataObject> data = createSimpleData("t1");
+ ResultSet rs = new ResultSet(data, "name, property.name", typeType);
+ assertEquals(5, rs.getSize());
+ for (int i = 0; i < 5; i++) {
+ assertEquals("t1", rs.getValue(i, "name"));
+ Assert.assertTrue(((String) rs.getValue(i, "property.name")).startsWith("t1prop"));
+ }
+ }
+
+ protected List<DataObject> createSimpleData(String name) {
+ List<DataObject> result = new ArrayList<DataObject>();
+ DataObject t1 = DataFactory.INSTANCE.create(typeType);
+ t1.set("name", name);
+ for (int i = 0; i < 5; i++) {
+ DataObject prop = t1.createDataObject("property");
+ prop.set("name", name + "prop" + i);
+ prop.set("aliasName", name + "alias" + i);
+ }
+ result.add(t1);
+ return result;
+ }
+
+ @Test
+ public void multiResultSet() throws Exception {
+ List<DataObject> data = createSimpleData("1");
+ data.addAll(createSimpleData("2"));
+ ResultSet rs = new ResultSet(data, "name, property.name", typeType);
+ assertEquals(10, rs.getSize());
+ int one = 0;
+ int two = 0;
+ for (int i = 0; i < rs.getSize(); i++) {
+ if (rs.getValue(i, "name").equals("1")) {
+ one++;
+ }
+ if (rs.getValue(i, "name").equals("2")) {
+ two++;
+ }
+ Assert.assertTrue(((String) rs.getValue(i, "property.name")).startsWith(rs.getValue(i,"name").toString()));
+ }
+ Assert.assertEquals(5, one);
+ Assert.assertEquals(5, two);
+ }
+
+
+ @Test
+ public void twoManyValuedProperties() {
+ List<DataObject> data = createSimpleData("t1");
+ ResultSet rs = new ResultSet(data, "name, property.name, property.aliasName", typeType);
+ assertEquals(5, rs.getSize());
+ for (int i = 0; i < 5; i++) {
+ assertEquals("t1", rs.getValue(i, "name"));
+ Assert.assertEquals("t1prop"+i, rs.getValue(i, "property.name"));
+ Assert.assertEquals("t1alias"+i, rs.getValue(i, "property.aliasName"));
+ }
+ }
+
+ @Test
+ public void nullProperties() {
+ List<DataObject> data = createSimpleData("t1");
+ data.add(DataFactory.INSTANCE.create(typeType));
+ ResultSet rs = new ResultSet(data, "name, property.name", typeType);
+ assertEquals(6, rs.getSize());
+ for (int i = 0; i < rs.getSize() - 1; i++) {
+ if ("t1".equals(rs.getValue(i, "name"))) {
+ Assert.assertTrue(((String) rs.getValue(i, "property.name")).startsWith("t1prop"));
+ } else {
+ Assert.assertEquals(null, rs.getValue(i, "name"));
+ Assert.assertEquals(null, rs.getValue(i, "property.name"));
+ }
+ }
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SdoTestUtil.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SdoTestUtil.java
new file mode 100644
index 0000000000..83c69a5635
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SdoTestUtil.java
@@ -0,0 +1,30 @@
+package com.agfa.hap.sdo.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.junit.Assert;
+
+public class SdoTestUtil {
+
+ @SuppressWarnings("unchecked")
+ public static <T> T marshallUnmarshal(T object) {
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(object);
+ ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
+ return (T) is.readObject();
+ } catch (ClassNotFoundException e) {
+ Assert.fail("Exception during serialization: " + e.getMessage());
+ } catch (IOException e) {
+ Assert.fail("Exception during serialization: " + e.getMessage());
+ }
+ return null;
+ }
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SerializableBasicObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SerializableBasicObject.java
new file mode 100644
index 0000000000..be0039d1a7
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SerializableBasicObject.java
@@ -0,0 +1,23 @@
+package com.agfa.hap.sdo.test;
+
+import java.io.Serializable;
+
+public class SerializableBasicObject implements Serializable {
+
+ private static final long serialVersionUID = -207081518262599555L;
+
+ public SerializableBasicObject() {}
+
+ public SerializableBasicObject(int i) { this.i = i; }
+
+ public int i;
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof SerializableBasicObject)) {
+ return false;
+ }
+ SerializableBasicObject sbo = (SerializableBasicObject) other;
+ return sbo.i == i;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SomeType.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SomeType.java
new file mode 100644
index 0000000000..39ac7dc50c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/SomeType.java
@@ -0,0 +1,192 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class SomeType {
+ private String nullStringProp = null;
+ private String nonNullStringProp = "notnull";
+ private List<String> nonNullStringPropMany = Arrays.asList(new String[]{"test1", "test2"});
+ private List<String> nullStringPropMany = null;
+ private List<String> emptyStringPropMany = Collections.<String>emptyList();
+ private TypeWithoutId nullComplexNoIdNotInSelectClauseSingle = null;
+ private TypeWithoutId nonNullComplexNoIdNotInSelectClauseSingle = new TypeWithoutId();
+ private TypeWithoutId nullComplexNoIdInSelectClauseSingle = null;
+ private TypeWithoutId nonNullComplexNoIdInSelectClauseSingle = new TypeWithoutId();
+ private TypeWithId nullComplexIdNotInSelectClauseSingle = null;
+ private TypeWithId nonNullComplexIdNotInSelectClauseSingle = new TypeWithId(13235L);
+ private TypeWithId nullComplexIdInSelectClauseSingle = null;
+ private TypeWithId nonNullComplexIdInSelectClauseSingle = new TypeWithId(123123L);
+ private TypeWithId nonNullComplexIdInSelectClauseSingleIdIsNull = new TypeWithId(null);
+ private TypeWithId nonNullComplexIdNotInSelectClauseSingleIdIsNull = new TypeWithId(null);
+ private List<TypeWithoutId> nullComplexNoIdNotInSelectClauseMany = null;
+ private List<TypeWithoutId> nonNullComplexNoIdNotInSelectClauseMany = Arrays.asList(new TypeWithoutId[]{new TypeWithoutId(), new TypeWithoutId()});
+ private List<TypeWithoutId> nullComplexNoIdInSelectClauseMany = null;
+ private List<TypeWithoutId> nonNullComplexNoIdInSelectClauseMany = Arrays.asList(new TypeWithoutId[]{new TypeWithoutId(), new TypeWithoutId()});
+ private List<TypeWithId> nullComplexIdNotInSelectClauseMany = null;
+ private List<TypeWithId> nonNullComplexIdNotInSelectClauseMany = Arrays.asList(new TypeWithId[]{new TypeWithId(1L), new TypeWithId(2L)});
+ private List<TypeWithId> nullComplexIdInSelectClauseMany = null;
+ private List<TypeWithId> nonNullComplexIdInSelectClauseMany = Arrays.asList(new TypeWithId[]{new TypeWithId(3L), new TypeWithId(4L)});
+
+
+ private List<TypeWithoutId> emptyComplexNoIdNotInSelectClauseMany = Collections.<TypeWithoutId>emptyList();
+ private List<TypeWithoutId> emptyComplexNoIdInSelectClauseMany = Collections.<TypeWithoutId>emptyList();
+ private List<TypeWithId> emptyComplexIdNotInSelectClauseMany = Collections.<TypeWithId>emptyList();
+ private List<TypeWithId> emptyComplexIdInSelectClauseMany = Collections.<TypeWithId>emptyList();
+ public String getNullStringProp() {
+ return nullStringProp;
+ }
+ public void setNullStringProp(String nullStringProp) {
+ this.nullStringProp = nullStringProp;
+ }
+ public String getNonNullStringProp() {
+ return nonNullStringProp;
+ }
+ public void setNonNullStringProp(String nonNullStringProp) {
+ this.nonNullStringProp = nonNullStringProp;
+ }
+ public TypeWithoutId getNullComplexNoIdNotInSelectClauseSingle() {
+ return nullComplexNoIdNotInSelectClauseSingle;
+ }
+ public void setNullComplexNoIdNotInSelectClauseSingle(
+ TypeWithoutId nullComplexNoIdNotInSelectClauseSingle) {
+ this.nullComplexNoIdNotInSelectClauseSingle = nullComplexNoIdNotInSelectClauseSingle;
+ }
+ public TypeWithoutId getNonNullComplexNoIdNotInSelectClauseSingle() {
+ return nonNullComplexNoIdNotInSelectClauseSingle;
+ }
+ public void setNonNullComplexNoIdNotInSelectClauseSingle(
+ TypeWithoutId nonNullComplexNoIdNotInSelectClauseSingle) {
+ this.nonNullComplexNoIdNotInSelectClauseSingle = nonNullComplexNoIdNotInSelectClauseSingle;
+ }
+ public TypeWithoutId getNullComplexNoIdInSelectClauseSingle() {
+ return nullComplexNoIdInSelectClauseSingle;
+ }
+ public void setNullComplexNoIdInSelectClauseSingle(
+ TypeWithoutId nullComplexNoIdInSelectClauseSingle) {
+ this.nullComplexNoIdInSelectClauseSingle = nullComplexNoIdInSelectClauseSingle;
+ }
+ public TypeWithoutId getNonNullComplexNoIdInSelectClauseSingle() {
+ return nonNullComplexNoIdInSelectClauseSingle;
+ }
+ public void setNonNullComplexNoIdInSelectClauseSingle(
+ TypeWithoutId nonNullComplexNoIdInSelectClauseSingle) {
+ this.nonNullComplexNoIdInSelectClauseSingle = nonNullComplexNoIdInSelectClauseSingle;
+ }
+ public TypeWithId getNullComplexIdNotInSelectClauseSingle() {
+ return nullComplexIdNotInSelectClauseSingle;
+ }
+ public void setNullComplexIdNotInSelectClauseSingle(
+ TypeWithId nullComplexIdNotInSelectClauseSingle) {
+ this.nullComplexIdNotInSelectClauseSingle = nullComplexIdNotInSelectClauseSingle;
+ }
+ public TypeWithId getNonNullComplexIdNotInSelectClauseSingle() {
+ return nonNullComplexIdNotInSelectClauseSingle;
+ }
+ public void setNonNullComplexIdNotInSelectClauseSingle(
+ TypeWithId nonNullComplexIdNotInSelectClauseSingle) {
+ this.nonNullComplexIdNotInSelectClauseSingle = nonNullComplexIdNotInSelectClauseSingle;
+ }
+ public TypeWithId getNullComplexIdInSelectClauseSingle() {
+ return nullComplexIdInSelectClauseSingle;
+ }
+ public void setNullComplexIdInSelectClauseSingle(
+ TypeWithId nullComplexIdInSelectClauseSingle) {
+ this.nullComplexIdInSelectClauseSingle = nullComplexIdInSelectClauseSingle;
+ }
+ public TypeWithId getNonNullComplexIdInSelectClauseSingle() {
+ return nonNullComplexIdInSelectClauseSingle;
+ }
+ public void setNonNullComplexIdInSelectClauseSingle(
+ TypeWithId nonNullComplexIdInSelectClauseSingle) {
+ this.nonNullComplexIdInSelectClauseSingle = nonNullComplexIdInSelectClauseSingle;
+ }
+ public List<TypeWithoutId> getNullComplexNoIdNotInSelectClauseMany() {
+ return nullComplexNoIdNotInSelectClauseMany;
+ }
+ public void setNullComplexNoIdNotInSelectClauseMany(
+ List<TypeWithoutId> nullComplexNoIdNotInSelectClauseMany) {
+ this.nullComplexNoIdNotInSelectClauseMany = nullComplexNoIdNotInSelectClauseMany;
+ }
+ public List<TypeWithoutId> getNonNullComplexNoIdNotInSelectClauseMany() {
+ return nonNullComplexNoIdNotInSelectClauseMany;
+ }
+ public void setNonNullComplexNoIdNotInSelectClauseMany(
+ List<TypeWithoutId> nonNullComplexNoIdNotInSelectClauseMany) {
+ this.nonNullComplexNoIdNotInSelectClauseMany = nonNullComplexNoIdNotInSelectClauseMany;
+ }
+ public List<TypeWithoutId> getNullComplexNoIdInSelectClauseMany() {
+ return nullComplexNoIdInSelectClauseMany;
+ }
+ public void setNullComplexNoIdInSelectClauseMany(
+ List<TypeWithoutId> nullComplexNoIdInSelectClauseMany) {
+ this.nullComplexNoIdInSelectClauseMany = nullComplexNoIdInSelectClauseMany;
+ }
+ public List<TypeWithoutId> getNonNullComplexNoIdInSelectClauseMany() {
+ return nonNullComplexNoIdInSelectClauseMany;
+ }
+ public void setNonNullComplexNoIdInSelectClauseMany(
+ List<TypeWithoutId> nonNullComplexNoIdInSelectClauseMany) {
+ this.nonNullComplexNoIdInSelectClauseMany = nonNullComplexNoIdInSelectClauseMany;
+ }
+ public List<TypeWithId> getNullComplexIdNotInSelectClauseMany() {
+ return nullComplexIdNotInSelectClauseMany;
+ }
+ public void setNullComplexIdNotInSelectClauseMany(
+ List<TypeWithId> nullComplexIdNotInSelectClauseMany) {
+ this.nullComplexIdNotInSelectClauseMany = nullComplexIdNotInSelectClauseMany;
+ }
+ public List<TypeWithId> getNonNullComplexIdNotInSelectClauseMany() {
+ return nonNullComplexIdNotInSelectClauseMany;
+ }
+ public void setNonNullComplexIdNotInSelectClauseMany(
+ List<TypeWithId> nonNullComplexIdNotInSelectClauseMany) {
+ this.nonNullComplexIdNotInSelectClauseMany = nonNullComplexIdNotInSelectClauseMany;
+ }
+ public List<TypeWithId> getNullComplexIdInSelectClauseMany() {
+ return nullComplexIdInSelectClauseMany;
+ }
+ public void setNullComplexIdInSelectClauseMany(
+ List<TypeWithId> nullComplexIdInSelectClauseMany) {
+ this.nullComplexIdInSelectClauseMany = nullComplexIdInSelectClauseMany;
+ }
+ public List<TypeWithId> getNonNullComplexIdInSelectClauseMany() {
+ return nonNullComplexIdInSelectClauseMany;
+ }
+ public void setNonNullComplexIdInSelectClauseMany(
+ List<TypeWithId> nonNullComplexIdInSelectClauseMany) {
+ this.nonNullComplexIdInSelectClauseMany = nonNullComplexIdInSelectClauseMany;
+ }
+ public List<TypeWithoutId> getEmptyComplexNoIdNotInSelectClauseMany() {
+ return emptyComplexNoIdNotInSelectClauseMany;
+ }
+ public List<TypeWithoutId> getEmptyComplexNoIdInSelectClauseMany() {
+ return emptyComplexNoIdInSelectClauseMany;
+ }
+ public List<TypeWithId> getEmptyComplexIdNotInSelectClauseMany() {
+ return emptyComplexIdNotInSelectClauseMany;
+ }
+ public List<TypeWithId> getEmptyComplexIdInSelectClauseMany() {
+ return emptyComplexIdInSelectClauseMany;
+ }
+ public TypeWithId getNonNullComplexIdInSelectClauseSingleIdIsNull() {
+ return nonNullComplexIdInSelectClauseSingleIdIsNull;
+ }
+ public List<String> getNonNullStringPropMany() {
+ return nonNullStringPropMany;
+ }
+ public List<String> getNullStringPropMany() {
+ return nullStringPropMany;
+ }
+ public List<String> getEmptyStringPropMany() {
+ return emptyStringPropMany;
+ }
+ public TypeWithId getNonNullComplexIdNotInSelectClauseSingleIdIsNull() {
+ return nonNullComplexIdNotInSelectClauseSingleIdIsNull;
+ }
+ public void setNonNullComplexIdNotInSelectClauseSingleIdIsNull(
+ TypeWithId nonNullComplexIdNotInSelectClauseSingleIdIsNull) {
+ this.nonNullComplexIdNotInSelectClauseSingleIdIsNull = nonNullComplexIdNotInSelectClauseSingleIdIsNull;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestBulkProperties.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestBulkProperties.java
new file mode 100644
index 0000000000..87a7fd6445
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestBulkProperties.java
@@ -0,0 +1,292 @@
+package com.agfa.hap.sdo.test;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.DataMapper;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.ReachableDefinition;
+import com.agfa.hap.sdo.SelectClause;
+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.mapper.BeanPropertyAccessorBuilder;
+import com.agfa.hap.sdo.mapper.JavaBeanMapper;
+import com.agfa.hap.sdo.mapper.PartialDataObjectMapper;
+import com.agfa.hap.sdo.mapper.PropertyAccessor;
+import com.agfa.hap.sdo.mapper.TypeMapper;
+import commonj.sdo.DataObject;
+
+public class TestBulkProperties {
+
+ private Type typeA;
+ private Type typeB;
+ private JavaBeanMapper mapper;
+
+ private Collection<Object> bulkObjects;
+ private Collection<Property> bulkProperties;
+
+ @Before
+ public void defineTypes() {
+ TestXSDHelper.defineTestTypes();
+ typeA = TypeHelper.INSTANCE.getType(TestObjectSnapShot.class.getName(), "A");
+ typeB = TypeHelper.INSTANCE.getType(TestObjectSnapShot.class.getName(), "B");
+ TypeMapper typeMapper = new TypeMapper(new BeanPropertyAccessorBuilder() {
+ @Override
+ protected PropertyAccessor createPropertyAccessor(Class cls, Property prop) {
+ PropertyAccessor result = super.createPropertyAccessor(cls, prop);
+ return new TestBulkPropertyAccessor(prop, result);
+ }
+ });
+ typeMapper.register(A.class, typeA.getURI(), typeA.getName());
+ typeMapper.register(B.class, typeB.getURI(), typeB.getName());
+ mapper = new JavaBeanMapper(typeMapper);
+ }
+
+ @Before
+ public void clearBulkObjects() {
+ bulkObjects = new ArrayList<Object>();
+ bulkProperties = new ArrayList<Property>();
+ }
+
+ @Test
+ public void simpleBulkProperty() {
+ this.bulkProperties.add(typeA.getProperty("containedB"));
+ A a = new A();
+ a.setStringProp("test");
+ B b = new B();
+ a.setContainedB(b);
+ b.setName("b1");
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeA, "containedB"), a);
+ A copyA = (A) DataAccessService.getRootObject(mapper, s);
+ Assert.assertEquals(a.getStringProp(), copyA.getStringProp());
+ Assert.assertEquals(a.getContainedB().getName(), copyA.getContainedB().getName());
+ Assert.assertEquals(1, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(a));
+ }
+
+ @Test
+ @Ignore
+ public void simpleBulkPropertyReachableDefinition() throws URISyntaxException {
+ this.bulkProperties.add(typeA.getProperty("containedB"));
+ A a = new A();
+ a.setStringProp("test");
+ a.setLongProp(1L);
+ a.setShortProp((short)2);
+ a.setBooleanProp(true);
+ a.setDoubleProp(2.0d);
+ a.setByteProp((byte) 3);
+ a.setFloatProp(5.0f);
+ a.setUriProp(new URI(""));
+ a.setBytearrayProp(new byte[]{1,2,3});
+ a.setIntProp(7);
+ B b = new B();
+ a.setContainedB(b);
+ b.setName("b1");
+ Snapshot s = DataAccessService.createSnapShot(mapper, new ReachableDefinition(), a);
+ A copyA = (A) DataAccessService.getRootObject(mapper, s);
+ Assert.assertEquals(a.getStringProp(), copyA.getStringProp());
+ Assert.assertEquals(a.getContainedB().getName(), copyA.getContainedB().getName());
+ Assert.assertEquals(1, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(a));
+ }
+
+ @Test
+ public void subselectBulkSnapshot() {
+ this.bulkProperties.add(typeA.getProperty("containedB"));
+ A a = new A();
+ B b = new B();
+ a.setContainedB(b);
+ b.setParent(new B());
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeA, "containedB.parent"), a);
+ A copyA = (A) DataAccessService.getRootObject(mapper, s);
+ Assert.assertNotNull(copyA.getContainedB().getParent());
+ Assert.assertEquals(1, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(a));
+ }
+
+ @Test
+ public void multiBulkSnapshot() {
+ this.bulkProperties.add(typeB.getProperty("parent"));
+ B b = new B();
+ B child1 = new B();
+ b.getChildren().add(child1);
+ child1.setParent(b);
+ B child2 = new B();
+ b.getChildren().add(child2);
+ child2.setParent(b);
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeB, "children.parent"), b);
+ B copyB = (B) DataAccessService.getRootObject(mapper, s);
+ Assert.assertEquals(2, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(child1));
+ Assert.assertTrue(bulkObjects.contains(child2));
+ Assert.assertEquals(2, copyB.getChildren().size());
+ for (B copyChild : copyB.getChildren()) {
+ Assert.assertEquals(copyB, copyChild.getParent());
+ }
+ }
+
+ @Test
+ public void manyValuedBulkProperty() {
+ this.bulkProperties.add(typeB.getProperty("children"));
+ B b = new B();
+ B child = new B();
+ b.getChildren().add(child);
+ child.setParent(b);
+ child = new B();
+ b.getChildren().add(child);
+ child.setParent(b);
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeB, "children.parent"), b);
+ B copyB = (B) DataAccessService.getRootObject(mapper, s);
+ Assert.assertEquals(1, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(b));
+ Assert.assertEquals(2, copyB.getChildren().size());
+ for (B copyChild : copyB.getChildren()) {
+ Assert.assertEquals(copyB, copyChild.getParent());
+ }
+ }
+
+ @Test
+ public void manyValuedDataObjectBulkProperty() {
+ this.bulkProperties.add(typeB.getProperty("children"));
+ B b = new B();
+ B child = new B();
+ b.getChildren().add(child);
+ child.setParent(b);
+ child = new B();
+ b.getChildren().add(child);
+ child.setParent(b);
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeB, "children.parent"), b);
+ Assert.assertEquals(1, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(b));
+ DataObject copyB = DataAccessService.getRootObject(new PartialDataObjectMapper() {
+
+ @Override
+ public boolean isBulkProperty(Class clazz, Property property) {
+ return bulkProperties.contains(property);
+ }
+
+ }, s);
+ Assert.assertEquals(2, copyB.getList("children").size());
+ for (Object copyChild : copyB.getList("children")) {
+ Assert.assertEquals(copyB, ((DataObject) copyChild).get("parent"));
+ }
+ }
+
+ @Test
+ public void manyValuedEmptyDataObjectBulkProperty() {
+ this.bulkProperties.add(typeB.getProperty("children"));
+ B b = new B();
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeB, "children.parent"), b);
+ Assert.assertEquals(1, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(b));
+ DataObject copyB = DataAccessService.getRootObject(new PartialDataObjectMapper() {
+
+ @Override
+ public boolean isBulkProperty(Class clazz, Property property) {
+ return bulkProperties.contains(property);
+ }
+
+ }, s);
+ Assert.assertEquals(0, copyB.getList("children").size());
+ }
+
+ @Test
+ public void dataTypeBulkProperty(){
+ this.bulkProperties.add(typeA.getProperty("stringProp"));
+ A a = new A();
+ a.setStringProp("stringpropvalue");
+ A anotherA = new A();
+ anotherA.setStringProp("somevalue");
+ List<A> as = new ArrayList<A>();
+ as.add(a);
+ as.add(anotherA);
+ Snapshot s = DataAccessService.createMultiSnapShot(mapper, new SelectClause(typeA, ""), as);
+ A copyA = (A) DataAccessService.getRootObjects(mapper, s).get(0);
+ Assert.assertEquals(a.getStringProp(), copyA.getStringProp());
+ Assert.assertEquals(2, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(a));
+ }
+
+ private class TestBulkPropertyAccessor implements PropertyAccessor {
+ private PropertyAccessor delegate;
+ private Property property;
+
+ public TestBulkPropertyAccessor(Property property, PropertyAccessor delegate) {
+ this.delegate = delegate;
+ this.property = property;
+ }
+
+ public Object getValue(Object instance, Property property, DataMapper dataMapper) {
+ Assert.assertFalse(isBulkAccessor());
+ return delegate.getValue(instance, property, dataMapper);
+ }
+
+ public Collection<?> getValues(Collection<?> instances, Property property, SnapshotDefinition def, DataMapper dataMapper) {
+ Assert.assertTrue(isBulkAccessor());
+ List<Object> result = new ArrayList<Object>();
+ for (Object a : instances) {
+ result.add(delegate.getValue(a, property, dataMapper));
+ }
+ bulkObjects.addAll(instances);
+ return result;
+ }
+
+ public boolean isBulkAccessor() {
+ return bulkProperties.contains(property);
+ }
+
+ public void setValue(Object instance, Property property, Object value, DataMapper dataMapper) {
+ delegate.setValue(instance, property, value, dataMapper);
+ }
+
+ public String fetchJoinPropertyPath(Property property) {
+ return property.getName();
+ }
+
+ }
+
+ @Test
+ public void nestedBulkProperties(){
+ this.bulkProperties.add(typeA.getProperty("b"));
+ this.bulkProperties.add(typeB.getProperty("favouriteChild"));
+ A a = new A();
+ a.setStringProp("test");
+ B b = new B();
+ a.setB(b);
+ b.setName("b1");
+ B favB = new B();
+ favB.setName("favBName");
+ b.setFavouriteChild(favB);
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeA, "b.favouriteChild"), a);
+ A copyA = (A) DataAccessService.getRootObject(mapper, s);
+ Assert.assertEquals(a.getStringProp(), copyA.getStringProp());
+ Assert.assertEquals(a.getB().getName(), copyA.getB().getName());
+ Assert.assertEquals(a.getB().getFavouriteChild().getName(), copyA.getB().getFavouriteChild().getName());
+ Assert.assertEquals(2, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(a));
+ }
+
+ @Test
+ public void nulls(){
+ this.bulkProperties.add(typeA.getProperty("containedB"));
+ A a = new A();
+ B b = new B();
+ a.setContainedB(null);
+ Snapshot s = DataAccessService.createSnapShot(mapper, new SelectClause(typeA, "containedB"), a);
+ A copyA = (A) DataAccessService.getRootObject(mapper, s);
+ Assert.assertEquals(a.getContainedB(), copyA.getContainedB());
+ Assert.assertEquals(1, bulkObjects.size());
+ Assert.assertTrue(bulkObjects.contains(a));
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDataObjectImpl.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDataObjectImpl.java
new file mode 100644
index 0000000000..dfe8003c06
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDataObjectImpl.java
@@ -0,0 +1,173 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.TypeHelper;
+
+
+public class TestDataObjectImpl {
+
+ private Type propertyType;
+ private Type typeType;
+
+
+ @Before
+ public void setUp() throws Exception {
+ propertyType = TypeHelper.INSTANCE.getType("commonj.sdo", "Property");
+ typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ }
+
+ @Test
+ public void testDataFactory() {
+ DataObject property = DataFactory.INSTANCE.create(propertyType);
+ property.createDataObject(propertyType.getProperty("type").getIndex());
+ Assert.assertNotNull(property.get("type"));
+ }
+
+ @Test
+ public void testRootObject() {
+ DataObject property = DataFactory.INSTANCE.create(propertyType);
+ Assert.assertEquals(property, property.getRootObject());
+ Assert.assertNull(property.getContainer());
+ DataObject typeProperty = property.createDataObject(propertyType.getProperty("type").getIndex());
+ Assert.assertNull(typeProperty.getContainer());
+ Assert.assertEquals(typeProperty, typeProperty.getRootObject());
+ DataObject childProperty = typeProperty.createDataObject("property", "commonj.sdo", "Property");
+ Assert.assertEquals(typeProperty, childProperty.getRootObject());
+ Assert.assertEquals(typeProperty, childProperty.getContainer());
+ }
+
+ @Test
+ public void testGetSetValue() {
+ DataObject property = DataFactory.INSTANCE.create(propertyType);
+ Assert.assertFalse(property.isSet("name"));
+ property.set("name", "test");
+ Assert.assertTrue(property.isSet("name"));
+ Assert.assertEquals("test", property.get("name"));
+ property.unset("name");
+ Assert.assertNull(property.get("name"));
+ Assert.assertFalse(property.isSet("name"));
+ }
+
+ @Test
+ public void testGetSetDataObjectValue() {
+ DataObject property = DataFactory.INSTANCE.create(propertyType);
+ DataObject type = property.createDataObject("type");
+ Assert.assertEquals(typeType, type.getType());
+ Assert.assertEquals(type, property.get("type"));
+ Assert.assertEquals(type, property.getDataObject("type"));
+ }
+
+ @Test
+ public void testGetSetListValue() {
+ TestXSDHelper.defineTestTypes();
+ PartialDataObject b = PartialDataFactory.INSTANCE.create(null, "B");
+ Assert.assertTrue(b.getList("children").isEmpty());
+ for (int i = 0; i < 5; i++) {
+ DataObject child = b.createDataObject("children");
+ child.set("name", Integer.toString(i));
+ DataObject odo = (DataObject) b.getList("children").get(i);
+ Assert.assertEquals(child, odo);
+ Assert.assertEquals(Integer.toString(i), odo.get("name"));
+ Assert.assertEquals(b, child.getContainer());
+ Assert.assertEquals(b.getType().getProperty("children"), child.getContainmentProperty());
+ }
+ }
+
+ @Test
+ public void changeList() {
+ TestXSDHelper.defineTestTypes();
+ PartialDataObject b = PartialDataFactory.INSTANCE.create(null, "B");
+ List<Object> children = b.getList("children");
+ PartialDataObject child = PartialDataFactory.INSTANCE.create(b.getType().getProperty("children").getType());
+ children.add(child);
+ Assert.assertEquals(b, child.get("parent"));
+ PartialDataObject child2 = b.createDataObject("children");
+ Assert.assertEquals(2, children.size());
+ Assert.assertTrue(children.remove(child2));
+ Assert.assertEquals(1, children.size());
+ children.set(0, child2);
+ Assert.assertEquals(b, child2.get("parent"));
+ Assert.assertNull(child.get("parent"));
+ Assert.assertEquals(1, children.size());
+ }
+
+ @Test
+ public void setList() {
+ TestXSDHelper.defineTestTypes();
+ PartialDataObject b = PartialDataFactory.INSTANCE.create(null, "B");
+ PartialDataObject child = b.createDataObject("children");
+ PartialDataObject child2 = PartialDataFactory.INSTANCE.create(child.getType());
+ List<Object> properties = new ArrayList<Object>();
+ properties.add(child2);
+ b.setList("children", properties);
+ Assert.assertEquals(b, child2.get("parent"));
+ Assert.assertEquals(1, properties.size());
+ Assert.assertNull(child.get("parent"));
+ }
+
+
+ @Test
+ public void testGetSetOpposite() {
+ TestXSDHelper.defineTestTypes();
+ PartialDataObject b = PartialDataFactory.INSTANCE.create(null, "B");
+ DataObject child = b.createDataObject("children");
+ Assert.assertEquals(b, child.get("parent"));
+ Iterator<PartialDataObject> it = b.getList("children").iterator();
+ Assert.assertTrue(it.hasNext());
+ Assert.assertEquals(child, it.next());
+ Assert.assertFalse(it.hasNext());
+ PartialDataObject b2 = PartialDataFactory.INSTANCE.create(null, "B");
+ Assert.assertTrue(b2.getList("children").isEmpty());
+ child.set("parent", b2);
+ Assert.assertEquals(b2, child.get("parent"));
+ it = b2.getList("children").iterator();
+ Assert.assertTrue(it.hasNext());
+ Assert.assertEquals(child, it.next());
+ Assert.assertFalse(it.hasNext());
+ Assert.assertTrue(b.getList("children").isEmpty());
+ }
+
+ @Test
+ public void testBasicDataTypes() {
+ TestXSDHelper.defineTestTypes();
+ Type typeA = TypeHelper.INSTANCE.getType(null, "A");
+ DataObject a = DataFactory.INSTANCE.create(typeA);
+ verifyGetSetValue(a, "intProp", 5);
+ verifyGetSetValue(a, "doubleProp", 1.5);
+ verifyGetSetValue(a, "stringProp", "Test");
+ verifyGetSetValue(a, "stringProp", null);
+ verifyGetSetValue(a, "shortProp", (short) 5);
+ verifyGetSetValue(a, "longProp", 5l);
+ verifyGetSetValue(a, "byteProp", (byte) 5l);
+ verifyGetSetValue(a, "floatProp", (float) 5.23);
+ }
+
+
+ private void verifyGetSetValue(DataObject a, String prop, Object value) {
+ a.set(prop, value);
+ Assert.assertEquals(value, a.get(prop));
+ }
+
+ @Test
+ public void testSpecializedClass() {
+ TestXSDHelper.defineTestTypes();
+ C c = (C) DataFactory.INSTANCE.create(null, "C");
+ c.setName("testje");
+ Assert.assertEquals("testje", c.getName());
+ Assert.assertEquals(c.getName(), c.get("name"));
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDefineTypeWithDataObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDefineTypeWithDataObject.java
new file mode 100644
index 0000000000..427ecae7bd
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestDefineTypeWithDataObject.java
@@ -0,0 +1,54 @@
+package com.agfa.hap.sdo.test;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.impl.TypeProvider;
+import com.agfa.hap.sdo.model.LongIdentity;
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.TypeHelper;
+
+public class TestDefineTypeWithDataObject {
+
+ @Test
+ public void define(){
+ Type typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ DataObject testType = DataFactory.INSTANCE.create(typeType);
+ testType.set("name", "test77");
+ testType.set("uri", "unittest-7");
+ DataObject prop = testType.createDataObject("property");
+ prop.set("name", "test");
+ prop.set("type", testType);
+ prop = testType.createDataObject("property");
+ prop.set("name", "primaryKey");
+ DataObject longIdentityType = DataFactory.INSTANCE.create(typeType);
+ longIdentityType.set("name", LongIdentity.class.getName());
+ prop.set("type", longIdentityType);
+ testType.set("identityProperty", "primaryKey");
+ Type newType = TypeHelper.INSTANCE.define(testType);
+ Assert.assertNotNull(newType);
+ Assert.assertEquals("test77", newType.getName());
+ Assert.assertEquals("unittest-7", newType.getURI());
+ Type lookupType = TypeHelper.INSTANCE.getType("unittest-7", "test77");
+ Assert.assertNotNull(lookupType);
+ Assert.assertEquals(newType, lookupType);
+ }
+
+ @Before
+ public void setup() {
+ TypeProvider.setInstance(new TypeProvider(){
+ public String getTypes(String uri) {
+ return null;
+ }});
+ }
+
+ @After
+ public void teardown(){
+ TypeProvider.setInstance(null);
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEmptySnapshot.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEmptySnapshot.java
new file mode 100644
index 0000000000..85e950e9ee
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEmptySnapshot.java
@@ -0,0 +1,18 @@
+package com.agfa.hap.sdo.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.Snapshot;
+import com.agfa.hap.sdo.implementation.SnapshotImplementation;
+
+public class TestEmptySnapshot {
+ @Test
+ public void empty(){
+ Snapshot emptySnapshot = SnapshotImplementation.emptySnapshot();
+ Assert.assertNotNull(emptySnapshot);
+ Assert.assertTrue(DataAccessService.getRootObjects(emptySnapshot).isEmpty());
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEqualityHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEqualityHelper.java
new file mode 100644
index 0000000000..b8a84b8cfd
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestEqualityHelper.java
@@ -0,0 +1,76 @@
+package com.agfa.hap.sdo.test;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.EqualityHelper;
+import commonj.sdo.helper.TypeHelper;
+
+public class TestEqualityHelper{
+
+ private Type typeType;
+
+ @Before
+ public void setUp() throws Exception {
+ typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ }
+
+ @Test
+ public void testNullEquality() {
+ Assert.assertTrue(EqualityHelper.INSTANCE.equalShallow(null, null));
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(null, null));
+ DataObject instance = DataFactory.INSTANCE.create(typeType);
+ instance.set("name", "a");
+ instance.createDataObject("property");
+ Assert.assertFalse(EqualityHelper.INSTANCE.equalShallow(instance, null));
+ Assert.assertFalse(EqualityHelper.INSTANCE.equal(instance, null));
+ Assert.assertFalse(EqualityHelper.INSTANCE.equalShallow(null, instance));
+ Assert.assertFalse(EqualityHelper.INSTANCE.equal(null, instance));
+ }
+
+ @Test
+ public void testShallowEquality() {
+ DataObject a = DataFactory.INSTANCE.create(typeType);
+ a.set("name", "a");
+ DataObject b = DataFactory.INSTANCE.create(typeType);
+ b.set("name", "a");
+ Assert.assertTrue(EqualityHelper.INSTANCE.equalShallow(a,b));
+ b.set("name", "b");
+ Assert.assertFalse(EqualityHelper.INSTANCE.equalShallow(a,b));
+ b.set("name", "a");
+ Assert.assertTrue(EqualityHelper.INSTANCE.equalShallow(a,b));
+ b.set("dataType", true);
+ Assert.assertFalse(EqualityHelper.INSTANCE.equalShallow(a,b));
+ a.set("dataType", true);
+ Assert.assertTrue(EqualityHelper.INSTANCE.equalShallow(a,b));
+ b.createDataObject("property");
+ Assert.assertTrue(EqualityHelper.INSTANCE.equalShallow(a,b));
+ }
+
+ @Test
+ public void testEquality() {
+ DataObject a = DataFactory.INSTANCE.create(typeType);
+ a.set("name", "a");
+ DataObject b = DataFactory.INSTANCE.create(typeType);
+ b.set("name", "a");
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(a,b));
+ b.set("name", "b");
+ Assert.assertFalse(EqualityHelper.INSTANCE.equal(a,b));
+ b.set("name", "a");
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(a,b));
+ DataObject propB = b.createDataObject("property");
+ Assert.assertFalse(EqualityHelper.INSTANCE.equal(a,b));
+ DataObject propA = a.createDataObject("property");
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(a,b));
+ propB.set("name", "propB");
+ Assert.assertFalse(EqualityHelper.INSTANCE.equal(a,b));
+ propA.set("name", "propB");
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(a,b));
+ propA.set("name", "propA");
+ Assert.assertFalse(EqualityHelper.INSTANCE.equal(a,b));
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestObjectSnapShot.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestObjectSnapShot.java
new file mode 100644
index 0000000000..e0a568d8f5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestObjectSnapShot.java
@@ -0,0 +1,148 @@
+package com.agfa.hap.sdo.test;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.ReachableDefinition;
+import com.agfa.hap.sdo.SelectClause;
+import com.agfa.hap.sdo.Snapshot;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.mapper.JavaBeanMapper;
+import com.agfa.hap.sdo.mapper.TypeMapper;
+import commonj.sdo.DataObject;
+
+public class TestObjectSnapShot{
+
+ private Type typeA;
+ private Type typeB;
+ private JavaBeanMapper mapper;
+
+
+ @Before
+ public void setUp() throws Exception {
+ TestXSDHelper.defineTestTypes();
+ typeA = TypeHelper.INSTANCE.getType(TestObjectSnapShot.class.getName(), "A");
+ typeB = TypeHelper.INSTANCE.getType(TestObjectSnapShot.class.getName(), "B");
+ TypeMapper typeMapper = new TypeMapper();
+ typeMapper.register(A.class, typeA.getURI(), typeA.getName());
+ typeMapper.register(B.class, typeB.getURI(), typeB.getName());
+ mapper = new JavaBeanMapper(typeMapper);
+ }
+
+ @Test
+ public void testObjectToDataObject() throws Exception {
+ A a = new A();
+ a.setStringProp("acc");
+ Snapshot s = DataAccessService.createSnapShot(mapper, new ReachableDefinition(), a);
+ Assert.assertNotNull(s);
+ DataObject dao = DataAccessService.getRootObject(s);
+ Assert.assertEquals(typeA, dao.getType());
+ Assert.assertEquals(a.getStringProp(), dao.get("stringProp"));
+ }
+
+ @Test
+ public void testComplexerObjectToDataObject() throws Exception {
+ A a = new A();
+ a.setStringProp("acc");
+ B b = new B();
+ a.setB(b);
+ B child = new B();
+ child.setName("ch1");
+ child.setParent(b);
+ b.getChildren().add(child);
+ child = new B();
+ child.setName("ch2");
+ child.setParent(b);
+ b.getChildren().add(child);
+ Snapshot s = DataAccessService.createSnapShot(mapper, new ReachableDefinition(), a);
+ Assert.assertNotNull(s);
+ DataObject dao = DataAccessService.getRootObject(s);
+ Assert.assertEquals(a.getStringProp(), dao.get("stringProp"));
+ dao = dao.getDataObject("b");
+ Assert.assertNotNull(dao);
+ Assert.assertEquals(b.getName(), dao.get("name"));
+ Assert.assertEquals(b.getChildren().size(), dao.getList("children").size());
+ for (int i = 0; i < b.getChildren().size(); i++) {
+ child = b.getChildren().get(i);
+ DataObject daoChild = (DataObject) dao.getList("children").get(i);
+ Assert.assertEquals(child.getName(), daoChild.get("name"));
+ Assert.assertTrue(dao == daoChild.get("parent"));
+ }
+ }
+
+ @Test
+ public void testDataObjectMap() {
+ B b = new B();
+ b.setName("test");
+ for (Property property : typeB.getProperties()) {
+ mapper.getProperty(b, property);
+ }
+ Assert.assertEquals(b.getName(), mapper.getProperty(b, typeB.getProperty("name")));
+ }
+
+ @Test
+ public void testInheritanceInDataObjectMap() {
+ Type typeInheritedB = TypeHelper.INSTANCE.getType(TestObjectSnapShot.class.getName(), "InheritedB");
+ mapper.getTypeMapper().register(InheritedB.class, typeInheritedB.getURI(), typeInheritedB.getName());
+ InheritedB b = new InheritedB();
+ b.setName("test");
+ b.setNickname("nick");
+ Assert.assertEquals(b.getName(), mapper.getProperty(b, typeB.getProperty("name")));
+ Assert.assertEquals(b.getNickname(), mapper.getProperty(b, typeInheritedB.getProperty("nickname")));
+ }
+
+ @Test
+ public void testObjectToObject() throws Exception {
+ B b = new B();
+ b.setName("child");
+ B parent = new B();
+ parent.setName("parent");
+ b.setParent(parent);
+ Snapshot s = DataAccessService.createSnapShot(mapper, new ReachableDefinition(), b);
+ Assert.assertNotNull(s);
+ B copy = (B) DataAccessService.getRootObject(mapper, s);
+ Assert.assertEquals(b.getName(), copy.getName());
+ Assert.assertEquals(b.getParent().getName(), copy.getParent().getName());
+ }
+
+ @Test
+ public void testRoundTrip() throws Exception {
+ B b = new B();
+ b.setName("parent");
+ B child = new B();
+ child.setName("child");
+ b.getChildren().add(child);
+ child.setParent(b);
+ Snapshot snapshot = DataAccessService.createSnapShot(mapper, new ReachableDefinition(), b);
+ B copy = (B) DataAccessService.getRootObject(mapper, snapshot);
+ Assert.assertFalse(b == copy);
+ Assert.assertEquals(b.getName(), copy.getName());
+ Assert.assertEquals(b.getChildren().size(), copy.getChildren().size());
+ Assert.assertEquals(b.getChildren().get(0).getName(), copy.getChildren().get(0).getName());
+ snapshot = DataAccessService.createSnapShot(mapper, new ReachableDefinition(), b);
+ PartialDataObject bAsDataObject = DataAccessService.getRootObject(snapshot);
+ Assert.assertEquals(b.getName(), bAsDataObject.get("name"));
+ snapshot = DataAccessService.createSnapShot(new ReachableDefinition(), bAsDataObject);
+ copy = (B) DataAccessService.getRootObject(mapper, snapshot);
+ Assert.assertFalse(b == copy);
+ Assert.assertEquals(b.getName(), copy.getName());
+ Assert.assertEquals(b.getChildren().size(), copy.getChildren().size());
+ Assert.assertEquals(b.getChildren().get(0).getName(), copy.getChildren().get(0).getName());
+ }
+
+ @Test
+ public void testOppositeProperty() {
+ B b = new B();
+ B child = new B();
+ b.getChildren().add(child);
+ child.setParent(b);
+ Snapshot snapshot = DataAccessService.createSnapShot(mapper, new SelectClause(typeB, "children"), b);
+ B copy = (B) DataAccessService.getRootObject(mapper, snapshot);
+ Assert.assertEquals(copy, copy.getChildren().get(0).getParent());
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestPartialDataObject.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestPartialDataObject.java
new file mode 100644
index 0000000000..ab0ada436f
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestPartialDataObject.java
@@ -0,0 +1,131 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.PropertyNotAvailableException;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.implementation.TypeImplementation;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XSDHelper;
+
+public class TestPartialDataObject{
+
+ private Type propertyType;
+ private commonj.sdo.Type typeType;
+ private Type bType;
+
+ @Before
+ public void setUp() throws Exception {
+ propertyType = (Type) TypeHelper.INSTANCE.getType("commonj.sdo", "Property");
+ typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ XSDHelper.INSTANCE.define(this.getClass().getResourceAsStream("/sdo/test-sdo-types.xsd"), "com.agfa.hap.rcp.sdo.test");
+ bType = (TypeImplementation) TypeHelper.INSTANCE.getType("com.agfa.hap.rcp.sdo.test", "B");
+ }
+
+ @Test
+ public void testPartialDataObject() {
+ PartialDataObject property = PartialDataFactory.INSTANCE.create(propertyType);
+ Assert.assertEquals(propertyType, property.getType());
+ Assert.assertTrue(propertyType.getProperties().size() > 0);
+ for (Property p : propertyType.getProperties()) {
+ Assert.assertTrue(property.isAvailable(p));
+ property.setUnavailable(p);
+ Assert.assertFalse(property.isAvailable(p));
+ try {
+ property.get(p);
+ Assert.fail("Should not be able to access partial properties");
+ } catch (PropertyNotAvailableException e) {
+ // ok;
+ }
+ property.set(p, null);
+ Assert.assertTrue(property.isAvailable(p));
+ Assert.assertNull(property.get(p));
+ }
+ }
+
+ @Test
+ public void testGetSetPartialListValue() {
+ PartialDataObject type = PartialDataFactory.INSTANCE.create(typeType);
+ type.setUnavailable(type.getType().getProperty("property"));
+ try {
+ type.getList("property");
+ Assert.fail("Should not be able to access partial prop");
+ } catch (PropertyNotAvailableException e) {
+ // ok
+ }
+ for (int i = 0; i < 5; i++) {
+ DataObject property = type.createDataObject("property");
+ property.set("name", Integer.toString(i));
+ DataObject odo = (DataObject) type.getList("property").get(i);
+ Assert.assertEquals(property, odo);
+ Assert.assertEquals(Integer.toString(i), odo.get("name"));
+ Assert.assertEquals(type, property.getContainer());
+ Assert.assertEquals(type.getType().getProperty("property"), property.getContainmentProperty());
+ }
+ }
+
+ @Test
+ public void testSetUnavailableList() {
+ PartialDataObject type = PartialDataFactory.INSTANCE.create(typeType);
+ type.setUnavailable(type.getType().getProperty("property"));
+ type.setList("property", Collections.emptyList());
+ Assert.assertTrue(type.isAvailable(type.getType().getProperty("property")));
+ Assert.assertEquals(0, type.getList("property").size());
+ }
+
+ @Test
+ public void linkWithUnavailableOpposite() {
+ PartialDataObject parent = PartialDataFactory.INSTANCE.create(bType);
+ parent.set("name", "parent");
+ parent.setUnavailable(bType.getProperty("children"));
+ PartialDataObject child = PartialDataFactory.INSTANCE.create(bType);
+ child.set("name", "child");
+ child.set("parent", parent);
+ Assert.assertEquals(parent, child.get("parent"));
+ Assert.assertFalse(parent.isAvailable(bType.getProperty("children")));
+ Assert.assertNull(child.getContainer());
+ child.set("parent", null);
+ Assert.assertNull(child.get("parent"));
+ Assert.assertFalse(parent.isAvailable(bType.getProperty("children")));
+ }
+
+ @Test
+ public void setListWhichWasUnavailable() {
+ PartialDataObject parent = PartialDataFactory.INSTANCE.create(bType);
+ parent.set("name", "parent");
+ Property childrenProperty = bType.getProperty("children");
+ parent.setUnavailable(childrenProperty);
+ PartialDataObject child = PartialDataFactory.INSTANCE.create(bType);
+ child.set("name", "child");
+ child.set("parent", parent);
+ List<Object> children = new ArrayList<Object>();
+ children.add(child);
+ parent.setList(childrenProperty, children);
+ Assert.assertTrue(parent.isAvailable(childrenProperty));
+ Assert.assertEquals(1, parent.getList(childrenProperty).size());
+ }
+
+ @Test
+ public void testProxy() {
+ TestXSDHelper.defineTestTypes();
+ PartialDataObject proxy = PartialDataFactory.INSTANCE.createProxy(null, "C", 5);
+ Assert.assertNotNull(proxy);
+ Assert.assertTrue(proxy.isProxy());
+ Assert.assertEquals(proxy.getIdentity(), 5);
+ for (Property p : proxy.getType().getProperties()) {
+ Assert.assertEquals(p == proxy.getType().getIdentityProperty(), proxy.isAvailable(p));
+ }
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestScanner.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestScanner.java
new file mode 100644
index 0000000000..021d176800
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestScanner.java
@@ -0,0 +1,23 @@
+package com.agfa.hap.sdo.test;
+
+import java.io.IOException;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.helper.XsdScanner;
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+
+public class TestScanner {
+
+ @Test
+ @Ignore("Doesn't work yet with OSGI bundles")
+ public void scanner() throws IOException {
+ XsdScanner scanner = new XsdScanner(this.getClass().getClassLoader());
+ scanner.scanClassPath("sdo/scanner");
+ Type type = TypeHelper.INSTANCE.getType("com.agfa.hap.sdo.test.scanning", "Scanner");
+ Assert.assertNotNull(type);
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClause.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClause.java
new file mode 100644
index 0000000000..d5990720ce
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClause.java
@@ -0,0 +1,147 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.ObjectPropertyVisitor;
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.SelectClause;
+import com.agfa.hap.sdo.Snapshot;
+import com.agfa.hap.sdo.SnapshotDefinition;
+import com.agfa.hap.sdo.mapper.PartialDataObjectMapper;
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.TypeHelper;
+
+public class TestSelectClause {
+
+ private Type typeType;
+
+
+ @Before
+ public void setUp() throws Exception {
+ typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ }
+
+ @Test
+ public void testPropertyTree() throws Exception {
+ SelectClause s = new SelectClause(typeType, "baseType");
+ TestVisitor visitor = new TestVisitor();
+ DataObject dataObject = DataFactory.INSTANCE.create(typeType);
+ dataObject.set("name", "test");
+ dataObject.getList("baseType").add(dataObject);
+ s.visit(new PartialDataObjectMapper(), visitor, (PartialDataObject) dataObject);
+ Assert.assertEquals(10, visitor.getResults().size());
+ Assert.assertEquals(dataObject, visitor.getResults().get(0));
+ Assert.assertEquals(dataObject.getType().getProperty("baseType"), visitor.getResults().get(1));
+ Assert.assertEquals(dataObject, visitor.getResults().get(2));
+ Assert.assertEquals(dataObject.getType().getProperty("baseType").getType().getProperty("baseType"), visitor.getResults().get(3));
+ Assert.assertEquals(dataObject.getType().getProperty("baseType").getType().getProperty("property"), visitor.getResults().get(4));
+ Assert.assertEquals(dataObject.get("name"), visitor.getResults().get(5));
+ Assert.assertEquals(dataObject, visitor.getResults().get(6));
+ Assert.assertEquals(dataObject.getType().getProperty("property"), visitor.getResults().get(7));
+ Assert.assertEquals(dataObject.get("name"), visitor.getResults().get(8));
+ Assert.assertEquals(dataObject, visitor.getResults().get(9));
+ }
+
+ @Test
+ public void asCommmaSeparatedString(){
+ SelectClause selectClause = new SelectClause(typeType, "baseType, property.opposite");
+ List<String> paths = Arrays.asList(selectClause.asCommaSeparatedString().split(","));
+ Assert.assertEquals(2,paths.size());
+ Assert.assertTrue(paths.contains("baseType"));
+ Assert.assertTrue(paths.contains("property.opposite"));
+ }
+
+ @Test
+ public void asCommmaSeparatedStringEmpty(){
+ SelectClause selectClause = new SelectClause(typeType, "");
+ Assert.assertEquals("",selectClause.asCommaSeparatedString());
+ }
+
+ @Test
+ public void testStarStar() throws Exception {
+ PartialDataObject dataObject = PartialDataFactory.INSTANCE.create(typeType);
+ dataObject.set("name", "X");
+ DataObject superDO = dataObject;
+ for (int i = 0; i < 5; i++) {
+ String name = (String) superDO.get("name");
+ superDO = superDO.createDataObject("baseType");
+ superDO.set("name", "super of " + name);
+ }
+ Snapshot s = DataAccessService.createSnapShot(new SelectClause(typeType, "baseType.**"), dataObject);
+ PartialDataObject copy = DataAccessService.getRootObject(s);
+ for (int i = 0; i < 5; i++) {
+ dataObject = (PartialDataObject) dataObject.getList("baseType").get(0);
+ copy = (PartialDataObject) copy.getList("baseType").get(0);
+ Assert.assertEquals(dataObject.get("name"), copy.get("name"));
+ }
+ }
+
+ @Test
+ public void testStar() throws Exception {
+ PartialDataObject dataObject = PartialDataFactory.INSTANCE.create(typeType);
+ dataObject.set("name", "X");
+ DataObject superDO = dataObject;
+ for (int i = 0; i < 5; i++) {
+ String name = (String) superDO.get("name");
+ superDO = superDO.createDataObject("baseType");
+ superDO.set("name", "super of " + name);
+ }
+ Snapshot s = DataAccessService.createSnapShot(new SelectClause(typeType, "baseType.baseType.*"), dataObject);
+ PartialDataObject copy = DataAccessService.getRootObject(s);
+ for (int i = 0; i < 3; i++) {
+ dataObject = (PartialDataObject) dataObject.getList("baseType").get(0);
+ copy = (PartialDataObject) copy.getList("baseType").get(0);
+ Assert.assertEquals(dataObject.get("name"), copy.get("name"));
+ }
+ Assert.assertFalse(copy.isAvailable(copy.getType().getProperty("baseType")));
+ }
+
+ private static class TestVisitor implements ObjectPropertyVisitor {
+
+ private List<Object> results = new ArrayList<Object>();
+ private List<Object> bulkProperties = new ArrayList<Object>();
+
+ public List<Object> getResults() {
+ return results;
+ }
+
+ public void endDataObject(Object instance, com.agfa.hap.sdo.Type type) throws Exception {
+ results.add(instance);
+ }
+
+ public void startDataObject(Object instance, com.agfa.hap.sdo.Type type) throws Exception {
+ results.add(instance);
+ }
+
+ public void visitProxyProperty(Object instance, com.agfa.hap.sdo.Property property, Object identity) throws Exception {
+ results.add(property);
+ }
+
+ public boolean visitProperty(Object instance, com.agfa.hap.sdo.Property property, Object value) throws Exception {
+ if (property.getType().isDataType()) {
+ results.add(value);
+ return false;
+ }
+ results.add(property);
+ return true;
+ }
+
+ public void visitBulkProperty(Object instance, Property property, SnapshotDefinition subselect) {
+ this.bulkProperties.add(instance);
+ }
+
+
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClauseSnapshotSerialization.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClauseSnapshotSerialization.java
new file mode 100644
index 0000000000..e27fa72180
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSelectClauseSnapshotSerialization.java
@@ -0,0 +1,129 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.SelectClause;
+import com.agfa.hap.sdo.Snapshot;
+import com.agfa.hap.sdo.mapper.JavaBeanMapper;
+import com.agfa.hap.sdo.mapper.TypeMapper;
+import commonj.sdo.Type;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XSDHelper;
+
+public class TestSelectClauseSnapshotSerialization {
+ @Before
+ public void setup(){
+ XSDHelper.INSTANCE.define(TestSelectClauseSnapshotSerialization.class.getResourceAsStream("/sdo/test-sdo-selectclause.xsd"), null);
+ }
+
+ @Test
+ public void test(){
+ Type someType = TypeHelper.INSTANCE.getType("com.agfa.hap.sdo.test.selectclause", "SomeType");
+ SomeType sourceObject = new SomeType();
+
+ SelectClause selectClause = new SelectClause(someType, "nullComplexNoIdInSelectClauseSingle,nullComplexIdNotInSelectClauseSingle," +
+ "nullComplexIdInSelectClauseSingle,nonNullComplexNoIdInSelectClauseSingle,nonNullComplexIdInSelectClauseSingle,nullComplexNoIdInSelectClauseMany," +
+ "nonNullComplexNoIdInSelectClauseMany,nullComplexIdInSelectClauseMany,nonNullComplexIdInSelectClauseMany," +
+ "nonNullComplexIdInSelectClauseSingleIdIsNull, emptyComplexNoIdInSelectClauseMany, " +
+ "emptyComplexIdInSelectClauseMany");
+
+
+ TypeMapper typeMapper = new TypeMapper();
+ typeMapper.register(SomeType.class, "com.agfa.hap.sdo.test.selectclause", "SomeType");
+ typeMapper.register(TypeWithId.class, "com.agfa.hap.sdo.test.selectclause", "TypeWithId");
+ typeMapper.register(TypeWithoutId.class, "com.agfa.hap.sdo.test.selectclause", "TypeWithoutId");
+ Snapshot snapshot = DataAccessService.createSnapShot(new JavaBeanMapper(typeMapper), selectClause, sourceObject);
+ PartialDataObject target = DataAccessService.getRootObject(snapshot);
+ Assert.assertNotNull(target);
+
+ Assert.assertNull(target.get("nullStringProp"));
+
+ Assert.assertNotNull(target.get("nonNullStringProp"));
+
+ Assert.assertNotNull(target.get("nonNullStringPropMany"));
+ Assert.assertEquals("test2", target.getList("nonNullStringPropMany").get(1));
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nullStringPropMany")));
+ Assert.assertTrue(target.getList("nullStringPropMany").isEmpty());
+
+ Assert.assertNotNull(target.get("emptyStringPropMany"));
+ Assert.assertTrue(target.isAvailable(someType.getProperty("emptyStringPropMany")));
+ Assert.assertTrue(target.getList("emptyStringPropMany").isEmpty());
+
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("nullComplexNoIdNotInSelectClauseSingle")));
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("nonNullComplexNoIdNotInSelectClauseSingle")));
+
+ Assert.assertNull(target.get("nullComplexNoIdInSelectClauseSingle"));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nonNullComplexNoIdInSelectClauseSingle")));
+ Assert.assertNotNull(target.get("nonNullComplexNoIdInSelectClauseSingle"));
+
+ Assert.assertNull(target.get("nullComplexIdNotInSelectClauseSingle"));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nonNullComplexIdNotInSelectClauseSingle")));
+ Assert.assertNotNull(target.get("nonNullComplexIdNotInSelectClauseSingle"));
+ Assert.assertTrue(((PartialDataObject) target.get("nonNullComplexIdNotInSelectClauseSingle")).isProxy());
+
+ Assert.assertNull(target.get("nullComplexIdInSelectClauseSingle"));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nonNullComplexIdInSelectClauseSingle")));
+ Assert.assertNotNull(target.get("nonNullComplexIdInSelectClauseSingle"));
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("nullComplexNoIdNotInSelectClauseMany")));
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("nonNullComplexNoIdNotInSelectClauseMany")));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nullComplexNoIdInSelectClauseMany")));
+ Assert.assertNotNull("many valued props in sdo are never null SDO_2.1_DRAFT_20060726.pdf p18 par 2",
+ target.get("nullComplexNoIdInSelectClauseMany"));
+ Assert.assertTrue(((List) target.get("nullComplexNoIdInSelectClauseMany")).isEmpty());
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nonNullComplexNoIdInSelectClauseMany")));
+ Assert.assertNotNull(target.get("nonNullComplexNoIdInSelectClauseMany"));
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("nullComplexIdNotInSelectClauseMany")));
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("nonNullComplexIdNotInSelectClauseMany")));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nullComplexIdInSelectClauseMany")));
+ Assert.assertNotNull(target.get("nullComplexIdInSelectClauseMany"));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("nonNullComplexIdInSelectClauseMany")));
+ Assert.assertNotNull("many valued props in sdo are never null SDO_2.1_DRAFT_20060726.pdf p18 par 2",
+ target.get("nullComplexIdInSelectClauseMany"));
+ Assert.assertTrue(((List) target.get("nullComplexIdInSelectClauseMany")).isEmpty());
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("emptyComplexNoIdNotInSelectClauseMany")));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("emptyComplexNoIdInSelectClauseMany")));
+ Assert.assertNotNull("many valued props in sdo are never null SDO_2.1_DRAFT_20060726.pdf p18 par 2",
+ target.get("emptyComplexNoIdInSelectClauseMany"));
+ Assert.assertTrue(((List) target.get("emptyComplexNoIdInSelectClauseMany")).isEmpty());
+
+ Assert.assertFalse(target.isAvailable(someType.getProperty("emptyComplexIdNotInSelectClauseMany")));
+
+ Assert.assertTrue(target.isAvailable(someType.getProperty("emptyComplexIdInSelectClauseMany")));
+ Assert.assertNotNull("many valued props in sdo are never null SDO_2.1_DRAFT_20060726.pdf p18 par 2",
+ target.get("emptyComplexIdInSelectClauseMany"));
+ Assert.assertTrue(((List) target.get("emptyComplexIdInSelectClauseMany")).isEmpty());
+
+ Assert.assertNotNull("you could argue that since the id is null it doesn't actually exists, but that " +
+ "is not the way it currently works, so we expect it to be in the snapshot",
+ target.get("nonNullComplexIdInSelectClauseSingleIdIsNull"));
+
+ Assert.assertFalse("you could argue that since the id is null it doesn't actually exists and so" +
+ " it should be null in the snapshot, " +
+ "but that is not the way it currently works, so we expect it to be unavailable in the snapshot." +
+ " (in agility ris otherwise problems with ProcedureDefinitionType of qdoc requestedprocedures)",
+ target.isAvailable(someType.getProperty("nonNullComplexIdNotInSelectClauseSingleIdIsNull")));
+
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSerialization.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSerialization.java
new file mode 100644
index 0000000000..7d44d439a0
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSerialization.java
@@ -0,0 +1,76 @@
+package com.agfa.hap.sdo.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.URI;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import commonj.sdo.DataObject;
+import commonj.sdo.Type;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.EqualityHelper;
+import commonj.sdo.helper.TypeHelper;
+
+public class TestSerialization{
+ @Test
+ public void testBasicSerialization() {
+ validate(DataObjectCreator.createSimpleDataObject());
+ }
+
+ @Test
+ public void testListSerialization() {
+ validate(DataObjectCreator.createDataObjectWithManyValuedProperty());
+ }
+
+ void validate(DataObject original) {
+ DataObject copy = copy(original);
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(copy, original));
+ }
+
+ @Test
+ public void testBasicDataTypes() throws Exception {
+ TestXSDHelper.defineTestTypes();
+ Type typeA = TypeHelper.INSTANCE.getType("null", "A");
+ DataObject a = DataFactory.INSTANCE.create(typeA);
+ a.set("intProp", 5);
+ a.set("doubleProp", 1.5);
+ a.set("shortProp", (short) 5);
+ a.set("longProp", 5l);
+ a.set("stringProp", "Test");
+ a.set("uriProp", new URI("http://www.google.be/"));
+ a.set("bytearrayProp", new byte[]{-1,2,3,4,5});
+ validate(a);
+ }
+
+ @Test
+ public void testSdoRef() {
+ DataObject dataObject = DataObjectCreator.createSimpleDataObject();
+ DataObject prop1 = dataObject.createDataObject("property");
+ prop1.set("name", "prop1");
+ prop1.set("type", dataObject);
+ DataObject prop2 = dataObject.createDataObject("property");
+ prop2.set("name", "prop2");
+ prop2.set("opposite", prop1);
+ validate(dataObject);
+ }
+
+ DataObject copy(DataObject original) {
+ try {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(os);
+ oos.writeObject(original);
+ oos.close();
+ ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(os.toByteArray()));
+ return (DataObject) ois.readObject();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshot.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshot.java
new file mode 100644
index 0000000000..aa609b9e34
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshot.java
@@ -0,0 +1,194 @@
+package com.agfa.hap.sdo.test;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.PropertyNotAvailableException;
+import com.agfa.hap.sdo.ReachableDefinition;
+import com.agfa.hap.sdo.SelectClause;
+import com.agfa.hap.sdo.Snapshot;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.implementation.SdoImplementationException;
+import com.agfa.hap.sdo.implementation.TypeImplementation;
+import com.agfa.hap.sdo.mapper.PartialDataObjectMapper;
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.EqualityHelper;
+import commonj.sdo.helper.XSDHelper;
+
+public class TestSnapshot{
+
+ private Type typeType;
+ private Type bType;
+
+ @Before
+ public void setUp() throws Exception {
+ typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ XSDHelper.INSTANCE.define(this.getClass().getResourceAsStream("/sdo/test-sdo-types.xsd"), "com.agfa.hap.rcp.sdo.test");
+ bType = (TypeImplementation) TypeHelper.INSTANCE.getType("com.agfa.hap.rcp.sdo.test", "B");
+ }
+
+ @Test
+ public void testSnapshot() {
+ PartialDataObject type = PartialDataFactory.INSTANCE.create(typeType);
+ type.set("name", "test");
+ type.getList("baseType").add(type);
+ type.createDataObject("property");
+ Snapshot snapshot = DataAccessService.createSnapShot(new SelectClause(typeType, "baseType"), type);
+ snapshot = SdoTestUtil.marshallUnmarshal(snapshot);
+ PartialDataObject copy = DataAccessService.getRootObject(snapshot);
+ Assert.assertTrue(copy.isAvailable(typeType.getProperty("baseType")));
+ Assert.assertTrue(copy.isAvailable(typeType.getProperty("name")));
+ Assert.assertTrue(copy.isAvailable(typeType.getProperty("dataType")));
+ Assert.assertFalse(copy.isAvailable(typeType.getProperty("property")));
+ try {
+ copy.get("property");
+ Assert.fail("Should not be able to access property");
+ } catch (PropertyNotAvailableException e) {
+ // ok;
+ }
+ Assert.assertEquals(copy.getList("baseType").get(0), copy);
+ Assert.assertEquals(copy.get("name"), type.get("name"));
+ }
+
+ @Test
+ public void testManyInSnapshot() {
+ PartialDataObject type = PartialDataFactory.INSTANCE.create(typeType);
+ type.set("name", "test");
+ type.createDataObject("property").set("name", "prop1");
+ type.createDataObject("property").set("name", "prop2");
+ Snapshot snapshot = DataAccessService.createSnapShot(new SelectClause(typeType, "property"), type);
+ snapshot = SdoTestUtil.marshallUnmarshal(snapshot);
+ PartialDataObject copy = DataAccessService.getRootObject(snapshot);
+ Assert.assertEquals(type.get("name"), copy.get("name"));
+ Assert.assertEquals(2, copy.getList("property").size());
+ for (int i = 0; i < 2; i++) {
+ Assert.assertEquals(((DataObject) type.getList("property").get(i)).get("name"), ((DataObject) copy.getList("property").get(i)).get("name"));
+ }
+ }
+
+ @Test
+ public void testMultiSnapshot(){
+ PartialDataObject testType1 = PartialDataFactory.INSTANCE.create(typeType);
+ testType1.set("name", "test1");
+ testType1.getList("baseType").add(testType1);
+ PartialDataObject testType2 = PartialDataFactory.INSTANCE.create(typeType);
+ testType2.set("name", "test2");
+ testType2.getList("baseType").add(testType2);
+ Collection<PartialDataObject> dataObjects = new ArrayList<PartialDataObject>();
+ dataObjects.add(testType1);
+ dataObjects.add(testType2);
+ Snapshot snapshot = DataAccessService.createMultiSnapShot(new PartialDataObjectMapper(), new SelectClause(typeType, "name, baseType"), dataObjects);
+ Snapshot marshalledSnapshot = SdoTestUtil.marshallUnmarshal(snapshot);
+ List<PartialDataObject> rootObjects = DataAccessService.getRootObjects(marshalledSnapshot);
+ Assert.assertNotNull(rootObjects);
+ Assert.assertFalse(rootObjects == DataAccessService.getRootObjects(marshalledSnapshot));
+ Assert.assertEquals("test1", rootObjects.get(0).get("name"));
+ Assert.assertEquals("test2", rootObjects.get(1).get("name"));
+ try {
+ DataAccessService.getRootObject(marshalledSnapshot);
+ } catch (RuntimeException e){
+ return;
+ }
+ Assert.fail("calling getRootObject() on a snapshot with more than 1 rootobject should throw an exception");
+ }
+
+ @Test
+ public void testCompleteSnapshot() throws Exception {
+ PartialDataObject dataObject = PartialDataFactory.INSTANCE.create(typeType);
+ dataObject.set("name", "test");
+ SelectClause s = new SelectClause(typeType, "*");
+ Snapshot snapshot = DataAccessService.createSnapShot(s, dataObject);
+ PartialDataObject copy = DataAccessService.getRootObject(snapshot);
+ for (Property p : dataObject.getType().getProperties()) {
+ Assert.assertTrue(copy.isAvailable(p));
+ Assert.assertEquals(dataObject.get(p), copy.get(p));
+ }
+ }
+
+ @Test
+ public void testPartialSnapshot() throws Exception {
+ C c = new C();
+ c.setName("test");
+ C peer = new C();
+ peer.setName("peer");
+ peer.setIdentity(new URI("test"));
+ c.set("peer", peer);
+ Snapshot snapshot = DataAccessService.createSnapShot(new SelectClause(c.getType()), c);
+ PartialDataObject copy = DataAccessService.getRootObject(snapshot);
+ Assert.assertEquals(c.getName(), copy.get("name"));
+ Assert.assertTrue(((PartialDataObject) copy.get("peer")).isProxy());
+ Assert.assertEquals(peer.getIdentity(), copy.getDataObject("peer").getIdentity());
+ }
+
+ @Test
+ public void testPartialProxySnapshot() throws Exception {
+ C c = new C();
+ c.setName("test");
+ C peer = new C();
+ peer.setName("peer");
+ c.set("peer", peer);
+ Snapshot snapshot = DataAccessService.createSnapShot(new SelectClause(c.getType()), c);
+ PartialDataObject copy = DataAccessService.getRootObject(snapshot);
+ Assert.assertEquals(c.getName(), copy.get("name"));
+ Assert.assertFalse(copy.isAvailable(copy.getType().getProperty("peer")));
+ }
+
+ @Test
+ public void testProxySnapshot() throws Exception {
+ C c = new C();
+ c.setName("test");
+ c.set("peer", PartialDataFactory.INSTANCE.createProxy(c.getType(), new URI("test")));
+ try {
+ DataAccessService.createSnapShot(new SelectClause(c.getType(), "peer"), c);
+ } catch (SdoImplementationException e) {
+ // ok
+ }
+ Snapshot snapshot = DataAccessService.createSnapShot(new ReachableDefinition(), c);
+ PartialDataObject copy = DataAccessService.getRootObject(snapshot);
+ Assert.assertTrue(((PartialDataObject) copy.get("peer")).isProxy());
+ }
+
+ @Test
+ public void bidirectionalParentLinkInSnapshot() throws Exception {
+ PartialDataObject main = PartialDataFactory.INSTANCE.create(bType);
+ main.set("name", "parent");
+ PartialDataObject child1 = main.createDataObject("children");
+ child1.set("name", "child1");
+ PartialDataObject child2 = main.createDataObject("children");
+ child2.set("name", "child2");
+ List<PartialDataObject> children = new ArrayList<PartialDataObject>();
+ children.add(child1);
+ children.add(child2);
+ Snapshot snapshot = DataAccessService.createMultiSnapShot(new SelectClause(bType, "parent"), children);
+ children = DataAccessService.getRootObjects(snapshot);
+ Assert.assertEquals(2, children.size());
+ Assert.assertEquals(child1.get("name"), children.get(0).get("name"));
+ Assert.assertEquals(child2.get("name"), children.get(1).get("name"));
+ Assert.assertTrue(children.get(0).get("parent") == children.get(1).get("parent"));
+ Assert.assertEquals(main.get("name"), children.get(0).getDataObject("parent").getString("name"));
+ }
+
+ @Test
+ public void testCustomConverters() {
+ TestXSDHelper.defineBasicTestTypes();
+ Type typeBO = TypeHelper.INSTANCE.getType("com.agfa.ris.common.test.basic", "BasicObject");
+ PartialDataObject bo = PartialDataFactory.INSTANCE.create(typeBO);
+ bo.set("enum", ExampleEnum.TWO);
+ bo.set("serializable", new SerializableBasicObject(5));
+ bo.set("custom", MyBasicObject.THREE);
+ Snapshot s = DataAccessService.createSnapShot(new ReachableDefinition(), bo);
+ PartialDataObject copy = DataAccessService.getRootObject(s);
+ org.junit.Assert.assertTrue(EqualityHelper.INSTANCE.equal(bo, copy));
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshotUnion.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshotUnion.java
new file mode 100644
index 0000000000..31e8c34039
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestSnapshotUnion.java
@@ -0,0 +1,54 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.DataAccessService;
+import com.agfa.hap.sdo.PartialDataFactory;
+import com.agfa.hap.sdo.PartialDataObject;
+import com.agfa.hap.sdo.SelectClause;
+import com.agfa.hap.sdo.Snapshot;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.implementation.SnapshotUnion;
+
+public class TestSnapshotUnion{
+
+ private Type typeType;
+
+ @Before
+ public void setUp() throws Exception {
+ typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ }
+
+ @Test
+ public void testUnion(){
+ PartialDataObject typeInFirstSnapshot = PartialDataFactory.INSTANCE.create(typeType);
+ typeInFirstSnapshot.set("name", "test1");
+ typeInFirstSnapshot.getList("baseType").add(typeInFirstSnapshot);
+ typeInFirstSnapshot.createDataObject("property");
+ Snapshot firstSnapshot = DataAccessService.createSnapShot(new SelectClause(typeType, "baseType"), typeInFirstSnapshot);
+ PartialDataObject typeInSecondSnapshot = PartialDataFactory.INSTANCE.create(typeType);
+ typeInSecondSnapshot.set("name", "test2");
+ typeInSecondSnapshot.getList("baseType").add(typeInSecondSnapshot);
+ typeInSecondSnapshot.createDataObject("property");
+ Snapshot secondSnapshot = DataAccessService.createSnapShot(new SelectClause(typeType, "baseType"), typeInSecondSnapshot);
+ Snapshot union = new SnapshotUnion(firstSnapshot, secondSnapshot);
+
+ Snapshot receivedSnapshot = SdoTestUtil.marshallUnmarshal(union);
+ List<PartialDataObject> receivedObjects= DataAccessService.getRootObjects(receivedSnapshot);
+ Assert.assertEquals(2, receivedObjects.size());
+ PartialDataObject firstObj = receivedObjects.get(0);
+ Assert.assertEquals("Type", firstObj.getType().getName());
+ Assert.assertEquals("test1", firstObj.get(typeType.getProperty("name")));
+
+ PartialDataObject secondObj = receivedObjects.get(1);
+ Assert.assertEquals("Type", secondObj.getType().getName());
+ Assert.assertEquals("test2", secondObj.get(typeType.getProperty("name")));
+ }
+
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestTypeHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestTypeHelper.java
new file mode 100644
index 0000000000..ed3dbdd93a
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestTypeHelper.java
@@ -0,0 +1,124 @@
+package com.agfa.hap.sdo.test;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.DataFactory;
+
+public class TestTypeHelper{
+ @Test
+ public void testBasicTypes() {
+ Type type = TypeHelper.INSTANCE.getType("commonj", "String");
+ Assert.assertEquals("String", type.getName());
+ Assert.assertTrue(type.isDataType());
+ Assert.assertEquals(String.class, type.getInstanceClass());
+ }
+
+ @Test
+ public void testObjectType() {
+ Type type = TypeHelper.INSTANCE.getType("commonj", "Object");
+ Assert.assertEquals("Object", type.getName());
+ Assert.assertTrue(type.isDataType());
+ Assert.assertEquals(Object.class, type.getInstanceClass());
+ }
+
+ @Test
+ public void testMetaTypes() {
+ Type propertyType = TypeHelper.INSTANCE.getType("commonj.sdo", "Property");
+ Assert.assertNotNull(propertyType);
+ Type typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ Assert.assertNotNull(typeType);
+ Assert.assertEquals("Property", propertyType.getName());
+ Assert.assertEquals("commonj.sdo", propertyType.getURI());
+ Assert.assertFalse(propertyType.isDataType());
+ List<Property> properties = propertyType.getProperties();
+ Assert.assertEquals(8, properties.size());
+ for (int i = 0; i < properties.size(); i++) {
+ Assert.assertEquals(propertyType.getProperty(i), properties.get(i));
+ Assert.assertEquals(propertyType.getProperty(properties.get(i).getName()), properties.get(i));
+ Assert.assertEquals(propertyType, propertyType.getProperty(i).getContainingType());
+ }
+ Property nameProp = propertyType.getProperty("name");
+ Assert.assertEquals("name", nameProp.getName());
+ Assert.assertFalse(nameProp.isContainment());
+ Assert.assertFalse(nameProp.isMany());
+ Assert.assertTrue(nameProp.getType().isDataType());
+ Assert.assertFalse(propertyType.getProperty("type").getType().isDataType());
+ }
+
+ @Test
+ public void testImplementationClass() {
+ C c = new C();
+ Type typeC = TypeHelper.INSTANCE.getType(C.class);
+ Assert.assertEquals(typeC, c.getType());
+ }
+
+ @Test
+ public void testContainment() {
+ Type propertyType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ Assert.assertTrue(propertyType.getProperty("property").isContainment());
+ }
+
+// public void testOpposite() {
+// Type propertyType = TypeHelper.INSTANCE.getType("commonj.sdo", "Property");
+// Property propertyTypeProp = propertyType.getProperty("type");
+// Type typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+// Property typePropertiesProp = typeType.getProperty("property");
+// Assert.assertEquals(propertyTypeProp, typePropertiesProp.getOpposite());
+// Assert.assertEquals(typePropertiesProp, propertyTypeProp.getOpposite());
+// }
+
+ @SuppressWarnings("unchecked")
+ public void testDefineType() {
+ Type typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ DataObject stringType = DataFactory.INSTANCE.create(typeType);
+ stringType.set("name", "String");
+ stringType.set("uri", "commonj");
+ DataObject xType = DataFactory.INSTANCE.create(typeType);
+ xType.set("name", "X");
+ xType.set("uri", "test");
+ DataObject prop = xType.createDataObject("property");
+ prop.set("name", "prop1");
+ prop.set("type", xType);
+ prop = xType.createDataObject("property");
+ prop.set("name", "prop2");
+ prop.set("type", stringType);
+ List<DataObject> types = new ArrayList<DataObject>();
+ types.add(stringType);
+ types.add(xType);
+ List<Type> result = TypeHelper.INSTANCE.define(types);
+ Assert.assertEquals(2, result.size());
+ Assert.assertEquals(TypeHelper.INSTANCE.getType(String.class), result.get(0));
+ Assert.assertEquals(TypeHelper.INSTANCE.getType("test", "X"), result.get(1));
+ DataObject x = DataFactory.INSTANCE.create("test", "X");
+ x.set("prop2", "blabla");
+ Assert.assertEquals("X", x.createDataObject("prop1").getType().getName());
+ }
+
+ public void testIdentifierProperty() {
+ Type typeType = TypeHelper.INSTANCE.getType("commonj.sdo", "Type");
+ DataObject uriType = DataFactory.INSTANCE.create(typeType);
+ uriType.set("name", URI.class.getName());
+ DataObject testType = DataFactory.INSTANCE.create(typeType);
+ testType.set("name", "test");
+ testType.set("uri", "test");
+ DataObject prop = testType.createDataObject("property");
+ prop.set("name", "test");
+ prop.set("type", testType);
+ prop = testType.createDataObject("property");
+ prop.set("name", "uri");
+ prop.set("type", uriType);
+ testType.set("identityProperty", "uri");
+ Type sdoTestType = (Type) TypeHelper.INSTANCE.define(testType);
+ Assert.assertNotNull(sdoTestType.getIdentityProperty());
+ Assert.assertEquals(sdoTestType.getProperty("uri"), sdoTestType.getIdentityProperty());
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXMLHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXMLHelper.java
new file mode 100644
index 0000000000..27c98213f2
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXMLHelper.java
@@ -0,0 +1,144 @@
+package com.agfa.hap.sdo.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import commonj.sdo.DataObject;
+import commonj.sdo.helper.DataFactory;
+import commonj.sdo.helper.EqualityHelper;
+import commonj.sdo.helper.XMLDocument;
+import commonj.sdo.helper.XMLHelper;
+
+public class TestXMLHelper{
+
+ @Test
+ public void testToXml() {
+ String xml = XMLHelper.INSTANCE.save(DataObjectCreator.createSimpleDataObject(), "com.agfa.ris/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ Assert.assertTrue(xml.indexOf("<test") > 0);
+ Assert.assertTrue(xml.indexOf("<name>") > 0);
+ Assert.assertTrue(xml.indexOf("<dataType>") > 0);
+ }
+
+ @Test
+ public void testManyValuedToXml() {
+ DataObject root = DataObjectCreator.createDataObjectWithManyValuedProperty();
+ String xml = XMLHelper.INSTANCE.save(root, "com.agfa.ris/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ Assert.assertTrue(xml.indexOf("<test") > 0);
+ int index = xml.indexOf("<property>");
+ Assert.assertTrue(index > 0);
+ Assert.assertTrue(xml.indexOf("<property>", index) > 0);
+ }
+
+ @Test
+ public void testFromXml() {
+ DataObject original = DataObjectCreator.createDataObjectWithManyValuedProperty();
+ String xml = XMLHelper.INSTANCE.save(original, original.getType().getURI(), "test");
+ Assert.assertNotNull(xml);
+ XMLDocument doc = XMLHelper.INSTANCE.load(xml);
+ Assert.assertEquals(original.getType().getURI(), doc.getRootElementURI());
+ Assert.assertEquals("test", doc.getRootElementName());
+ DataObject copy = doc.getRootObject();
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(original, copy));
+ }
+
+ @Test
+ public void testSdoRef() {
+ DataObject dataObject = DataObjectCreator.createSimpleDataObject();
+ DataObject prop1 = dataObject.createDataObject("property");
+ prop1.set("name", "prop1");
+ prop1.set("type", dataObject);
+ DataObject prop2 = dataObject.createDataObject("property");
+ prop2.set("name", "prop2");
+ prop2.set("opposite", prop1);
+ String xml = XMLHelper.INSTANCE.save(dataObject, "com.agfa.ris/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ Assert.assertTrue(xml.indexOf("sdo:ref") > 0);
+ XMLDocument doc = XMLHelper.INSTANCE.load(xml);
+ DataObject copy = doc.getRootObject();
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(dataObject, copy));
+ }
+
+ @Test
+ public void testSubobjectFromXml() {
+ DataObject original = DataObjectCreator.createSimpleDataObject();
+ String xml = XMLHelper.INSTANCE.save(original, "com.agfa.ris.common/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ XMLDocument doc = XMLHelper.INSTANCE.load(xml);
+ Assert.assertEquals("com.agfa.ris.common/sdo/test", doc.getRootElementURI());
+ Assert.assertEquals("test", doc.getRootElementName());
+ DataObject copy = doc.getRootObject();
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(original, copy));
+ }
+
+ @Test
+ public void testNullValue() {
+ DataObject original = DataObjectCreator.createSimpleDataObject();
+ Assert.assertTrue(original.isSet("name"));
+ original.set("name", null);
+ // Assert.assertTrue(original.isSet("name"));
+ Assert.assertNull(original.get("name"));
+ String xml = XMLHelper.INSTANCE.save(original, "com.agfa.ris.common/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ XMLDocument doc = XMLHelper.INSTANCE.load(xml);
+ DataObject copy = doc.getRootObject();
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(original, copy));
+ }
+
+ @Test
+ public void testBasicDataTypes() {
+ TestXSDHelper.defineTestTypes();
+ Type typeA = TypeHelper.INSTANCE.getType("null", "A");
+ DataObject original = DataFactory.INSTANCE.create(typeA);
+ original.set("intProp", 5);
+ original.set("doubleProp", 1.5);
+ original.set("stringProp", "Test");
+ original.set("shortProp", (short) 5);
+ original.set("longProp", 5l);
+ original.set("byteProp", (byte) 5l);
+ original.set("floatProp", (float) 3.143);
+ String xml = XMLHelper.INSTANCE.save(original, "com.agfa.ris.common/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ XMLDocument doc = XMLHelper.INSTANCE.load(xml);
+ DataObject copy = doc.getRootObject();
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(original, copy));
+ }
+
+ @Test
+ public void testCustomConverters() {
+ TestXSDHelper.defineBasicTestTypes();
+ Type typeBO = TypeHelper.INSTANCE.getType("com.agfa.ris.common.test.basic", "BasicObject");
+ DataObject bo = DataFactory.INSTANCE.create(typeBO);
+ bo.set("enum", ExampleEnum.TWO);
+ bo.set("serializable", new SerializableBasicObject(5));
+ bo.set("custom", MyBasicObject.THREE);
+ String xml = XMLHelper.INSTANCE.save(bo, "com.agfa.ris.common/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ XMLDocument doc = XMLHelper.INSTANCE.load(xml);
+ DataObject copy = doc.getRootObject();
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(bo, copy));
+ }
+
+ @Test
+ public void polymorphLink() {
+ TestXSDHelper.defineBasicTestTypes();
+ Type typeA = TypeHelper.INSTANCE.getType("com.agfa.ris.common.test.basic", "A");
+ DataObject bo = DataFactory.INSTANCE.create(typeA);
+ DataObject b = bo.createDataObject("containedB", "com.agfa.ris.common.test.basic", "InheritedB");
+ b.set("nickname", "ikke");
+ String xml = XMLHelper.INSTANCE.save(bo, "com.agfa.ris.common/sdo/test", "test");
+ Assert.assertNotNull(xml);
+ XMLDocument doc = XMLHelper.INSTANCE.load(xml);
+ DataObject copy = doc.getRootObject();
+ Assert.assertTrue(EqualityHelper.INSTANCE.equal(bo, copy));
+ }
+
+ @Test
+ public void correctNamespaceFirstType() {
+ String xml = XMLHelper.INSTANCE.save(DataObjectCreator.createSimpleDataObject(), "bla", "test");
+ Assert.assertTrue(xml.contains("sdo:Type"));
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXSDHelper.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXSDHelper.java
new file mode 100644
index 0000000000..e9dab24620
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXSDHelper.java
@@ -0,0 +1,179 @@
+package com.agfa.hap.sdo.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.Property;
+import com.agfa.hap.sdo.Type;
+import com.agfa.hap.sdo.helper.TypeHelper;
+import com.agfa.hap.sdo.impl.EnumTypeConverter;
+import com.agfa.hap.sdo.impl.SerializableTypeConverter;
+import com.agfa.hap.sdo.impl.TypeConverter;
+import com.agfa.hap.sdo.implementation.PropertyImplementation;
+import com.agfa.hap.sdo.implementation.TypeImplementation;
+import commonj.sdo.helper.XSDHelper;
+
+public class TestXSDHelper{
+
+ private static final String TESTURI = "com.agfa.hap.sdo.test";
+
+ public static void defineTestTypes() {
+ XSDHelper.INSTANCE.define(TestXSDHelper.class.getResourceAsStream("/sdo/test-sdo-types.xsd"), null);
+ }
+
+ public static void defineBasicTestTypes() {
+ XSDHelper.INSTANCE.define(TestXSDHelper.class.getClassLoader().getResourceAsStream("sdo/test-sdo-basictypes.xsd"), null);
+ }
+
+
+ @Before
+ public void setUp() throws Exception {
+ defineTestTypes();
+ }
+
+ @Test
+ public void testMultipleDefinition() {
+ Type typeA = TypeHelper.INSTANCE.getType(TESTURI, "A");
+ int count = typeA.getProperties().size();
+ defineTestTypes();
+ Assert.assertEquals(count, typeA.getProperties().size());
+ }
+
+ @Test
+ public void testRead() {
+ Type typeA = TypeHelper.INSTANCE.getType(TESTURI, "A");
+ Assert.assertNotNull(typeA);
+ Assert.assertEquals("String", typeA.getProperty("stringProp").getType().getName());
+ Assert.assertFalse(typeA.getProperty("stringProp").isMany());
+ Assert.assertFalse(typeA.getProperty("b").isContainment());
+ Assert.assertTrue(typeA.getProperty("containedB").isContainment());
+ Type typeB = typeA.getProperty("b").getType();
+ Assert.assertEquals("B", typeB.getName());
+ Assert.assertEquals(4, typeB.getProperties().size());
+ Assert.assertTrue(typeB.getProperty("children").isMany());
+ Assert.assertEquals(typeB, typeB.getProperty("children").getType());
+ Type typeD = TypeHelper.INSTANCE.getType(TESTURI, "E");
+ Assert.assertEquals("B", typeD.getProperty(0).getType().getName());
+
+ Type typeF = TypeHelper.INSTANCE.getType(TESTURI, "F");
+ Assert.assertNotNull(typeF);
+ Property manyStringsProp = typeF.getProperty("manyStringsProp");
+ Assert.assertTrue(manyStringsProp.isMany());
+ Assert.assertEquals("String", manyStringsProp.getType().getName());
+ Assert.assertEquals("commonj.sdo", manyStringsProp.getType().getURI());
+ }
+
+ @Test
+ public void testOppositeProperty() {
+ Type typeB = TypeHelper.INSTANCE.getType(TESTURI, "B");
+ Assert.assertNotNull(typeB.getProperty("parent"));
+ Assert.assertEquals(typeB.getProperty("parent"), typeB.getProperty("children").getOpposite());
+ Assert.assertEquals(typeB.getProperty("children"), typeB.getProperty("parent").getOpposite());
+ }
+
+ @Test
+ public void testSdoRef() {
+ Type typeB = TypeHelper.INSTANCE.getType(TESTURI, "B");
+ Property property = typeB.getProperty("favouriteChild");
+ Assert.assertNotNull(property);
+ Assert.assertEquals(typeB, property.getType());
+ Assert.assertFalse(property.isContainment());
+ }
+
+ @Test
+ public void testGenerate(){
+ List<Type> types = new ArrayList<Type>();
+ Type stringType = TypeHelper.INSTANCE.getType(String.class);
+ TypeImplementation typeF = new TypeImplementation("someotheruri", "testtypeF");
+ typeF.addProperty("someprop", stringType);
+ TypeImplementation typeE = new TypeImplementation("testuri", "testtypeE");
+ typeE.addProperty("yetanotherprop", stringType);
+ typeE.addProperty("fProp", typeF);
+ TypeImplementation typeD = new TypeImplementation("testuri", "testtypeD");
+ typeD.setBaseType(typeF);
+ typeD.normalizeTypeHierarchy();
+ typeD.addProperty("stringProp", stringType);
+ Type intType = new TypeImplementation(java.lang.Integer.class);
+ typeD.addProperty("intProp", intType);
+ PropertyImplementation manyProp = typeD.addProperty("manyprop", intType);
+ manyProp.setIsMany(true);
+ typeD.addProperty("eProp", typeE);
+ types.add(typeD);
+ String xsd = XSDHelper.INSTANCE.generate(types);
+ Assert.assertNotNull(xsd);
+ Assert.assertTrue(xsd.startsWith("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" +
+ "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"testuri\" xmlns:sdo=\"commonj.sdo/xml\" " +
+ "xmlns:sdoJava=\"commonj.sdo/java\" xmlns:agfaSdo=\"com.agfa.ris/sdo\" " +
+ "xmlns:tns=\"testuri\" xmlns:ns1=\"someotheruri\""));
+ Assert.assertTrue(xsd.contains("<xsd:complexType name=\"testtypeE\">\r\n" +
+ "<xsd:attribute name=\"yetanotherprop\" sdo:readOnly=\"false\" type=\"xsd:string\"/>\r\n" +
+ "<xsd:attribute name=\"fProp\" sdo:readOnly=\"false\" type=\"xsd:anyURI\" sdo:propertyType=\"ns1:testtypeF\"/>\r\n" +
+ "</xsd:complexType>"));
+ Assert.assertTrue(xsd.contains("<xsd:complexType name=\"testtypeD\">\r\n" +
+ "<xsd:complexContent>\r\n" +
+ "<xsd:extension base=\"ns1:testtypeF\"/>\r\n" +
+ "</xsd:complexContent>\r\n" +
+ "<xsd:choice maxOccurs=\"unbounded\">\r\n" +
+ "<xsd:element name=\"manyprop\" sdo:readOnly=\"false\" maxOccurs=\"unbounded\" type=\"xsd:int\"/>\r\n" +
+ "</xsd:choice>\r\n" +
+ "<xsd:attribute name=\"stringProp\" sdo:readOnly=\"false\" type=\"xsd:string\"/>\r\n" +
+ "<xsd:attribute name=\"intProp\" sdo:readOnly=\"false\" type=\"xsd:int\"/>\r\n" +
+ "<xsd:attribute name=\"eProp\" sdo:readOnly=\"false\" type=\"xsd:anyURI\" sdo:propertyType=\"tns:testtypeE\"/>\r\n" +
+ "</xsd:complexType>"));
+ Assert.assertEquals("the list will be expanded to include all types generated", 2, types.size());
+ }
+
+ @Test
+ public void testIdProperty() {
+ Type typeC = TypeHelper.INSTANCE.getType(TESTURI, "C");
+ Assert.assertNotNull(typeC.getIdentityProperty());
+ Assert.assertEquals(typeC.getProperty("uri"), typeC.getIdentityProperty());
+ }
+
+ @Test
+ public void testOppositePropertyDefinedAsAttribute() {
+ Type typeC = TypeHelper.INSTANCE.getType(TESTURI, "C");
+ Property p = typeC.getProperty("peer");
+ Assert.assertNotNull(p);
+ Assert.assertEquals(p, p.getOpposite());
+ }
+
+ @Test
+ public void testInheritance() {
+ Type typeInheritedB = TypeHelper.INSTANCE.getType(TESTURI, "InheritedB");
+ Type typeB = TypeHelper.INSTANCE.getType(TESTURI, "B");
+ Assert.assertEquals(1, typeInheritedB.getBaseTypes().size());
+ Assert.assertEquals(typeB, typeInheritedB.getBaseTypes().get(0));
+ Assert.assertEquals(typeB.getProperty("name"), typeInheritedB.getProperty("name"));
+ Assert.assertNotNull(typeInheritedB.getProperty("nickname"));
+ Assert.assertNull(typeB.getProperty("nickname"));
+ for (int i = 0; i < typeB.getProperties().size(); i++) {
+ Assert.assertEquals(typeB.getProperty(i), typeInheritedB.getProperty(i));
+ }
+ Assert.assertEquals(1, typeInheritedB.getDeclaredProperties().size());
+ Assert.assertEquals(1 + typeB.getProperties().size(), typeInheritedB.getProperties().size());
+ }
+
+ @Test
+ public void testBasicTypes() {
+ defineBasicTestTypes();
+ checkBasicType(MyBasicObject.class, MyBasicObjectTypeConverter.class);
+ checkBasicType(ExampleEnum.class, EnumTypeConverter.class);
+ checkBasicType(SerializableBasicObject.class, SerializableTypeConverter.class);
+ }
+
+ private void checkBasicType(Class clazz, Class converterClass) {
+ Type type = TypeHelper.INSTANCE.getType(clazz);
+ Assert.assertNotNull(type);
+ Assert.assertEquals("com.agfa.sdo.common.test.basic", type.getURI());
+ int index = clazz.getName().lastIndexOf('.');
+ Assert.assertEquals(clazz.getName().substring(index+1), type.getName());
+ Assert.assertTrue(type.isDataType());
+ Assert.assertEquals(clazz, type.getInstanceClass());
+ Assert.assertEquals(converterClass, TypeConverter.get(type).getClass());
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXsdHelperMultipleURI.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXsdHelperMultipleURI.java
new file mode 100644
index 0000000000..cac868bf50
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TestXsdHelperMultipleURI.java
@@ -0,0 +1,33 @@
+package com.agfa.hap.sdo.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.agfa.hap.sdo.Type;
+
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XSDHelper;
+
+
+public class TestXsdHelperMultipleURI {
+
+ @Test
+ public void multipleXsdsReferencingEatchOther(){
+ XSDHelper.INSTANCE.define(TestXSDHelper.class.getResourceAsStream("/sdo/test-sdo-types1.xsd"), null);
+ XSDHelper.INSTANCE.define(TestXSDHelper.class.getResourceAsStream("/sdo/test-sdo-types2.xsd"), null);
+ Type a1Type = (Type) TypeHelper.INSTANCE.getType("com.agfa.hap.sdo.test1", "A1");
+ Assert.assertEquals(2, a1Type.getProperties().size());
+ Type b2Type = (Type) TypeHelper.INSTANCE.getType("com.agfa.hap.sdo.test2", "B2");
+ Assert.assertEquals(2, b2Type.getProperties().size());
+ }
+
+ @Test
+ public void forwardReference(){
+ XSDHelper.INSTANCE.define(TestXSDHelper.class.getResourceAsStream("/sdo/test-sdo-types-forward.xsd"), null);
+ Type aType = (Type) TypeHelper.INSTANCE.getType("com.agfa.hap.sdo.test.forward", "Af");
+ Assert.assertEquals(2, aType.getProperties().size());
+ Type bType = (Type) TypeHelper.INSTANCE.getType("com.agfa.hap.sdo.forward", "Bf");
+ Assert.assertEquals(2, bType.getProperties().size());
+ }
+
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithId.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithId.java
new file mode 100644
index 0000000000..cbccf0fe1f
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithId.java
@@ -0,0 +1,26 @@
+package com.agfa.hap.sdo.test;
+
+public class TypeWithId {
+ public TypeWithId(Long id){
+ this.id = id;
+ }
+
+ private Long id;
+ private String stringProp;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getStringProp() {
+ return stringProp;
+ }
+
+ public void setStringProp(String stringProp) {
+ this.stringProp = stringProp;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithoutId.java b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithoutId.java
new file mode 100644
index 0000000000..e2ca7b6a2c
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/java/com/agfa/hap/sdo/test/TypeWithoutId.java
@@ -0,0 +1,13 @@
+package com.agfa.hap.sdo.test;
+
+public class TypeWithoutId {
+ private String stringProp;
+
+ public String getStringProp() {
+ return stringProp;
+ }
+
+ public void setStringProp(String stringProp) {
+ this.stringProp = stringProp;
+ }
+}
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo-propertyaccessors.properties b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo-propertyaccessors.properties
new file mode 100644
index 0000000000..8308679698
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo-propertyaccessors.properties
@@ -0,0 +1 @@
+com.agfa.hap.sdo.mapper.Super.superProperty=com.agfa.hap.sdo.mapper.DummyPropertyAccessor \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/implementationclasses.properties b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/implementationclasses.properties
new file mode 100644
index 0000000000..f1aa15b116
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/implementationclasses.properties
@@ -0,0 +1 @@
+com.agfa.hap.sdo.test.C=com.agfa.hap.sdo.test$C \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/scanner/scan-types.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/scanner/scan-types.xsd
new file mode 100644
index 0000000000..27dd4afd79
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/scanner/scan-types.xsd
@@ -0,0 +1,12 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.hap.sdo.test.scanning" xmlns:tns="com.agfa.hap.sdo.test.scanning">
+
+<xsd:element name="scanner" type="tns:Scanner"/>
+<xsd:complexType name="Scanner">
+ <xsd:sequence>
+ <xsd:element name="stringProp" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+</xsd:complexType>
+
+</xsd:schema> \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-basictypes.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-basictypes.xsd
new file mode 100644
index 0000000000..acf12da5fb
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-basictypes.xsd
@@ -0,0 +1,25 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.sdo.common.test.basic" xmlns:tns="com.agfa.sdo.common.test.basic" xmlns:agfaSdoJava="com.agfa.ris/sdo">
+
+<xsd:element name="a" type="tns:BasicObject"/>
+<xsd:complexType name="BasicObject">
+ <xsd:attribute name="enum" type="tns:ExampleEnum" />
+ <xsd:attribute name="serializable" type="tns:SerializableBasicObject" />
+ <xsd:attribute name="custom" type="tns:MyBasicObject" />
+</xsd:complexType>
+
+<xsd:simpleType name="ExampleEnum" sdoJava:instanceClass="com.agfa.hap.sdo.test.ExampleEnum">
+ <xsd:restriction base="xsd:string" />
+</xsd:simpleType>
+
+<xsd:simpleType name="SerializableBasicObject" sdoJava:instanceClass="com.agfa.hap.sdo.test.SerializableBasicObject">
+ <xsd:restriction base="xsd:string" />
+</xsd:simpleType>
+
+<xsd:simpleType name="MyBasicObject" sdoJava:instanceClass="com.agfa.hap.sdo.test.MyBasicObject" agfaSdoJava:typeConverter="com.agfa.hap.sdo.test.MyBasicObjectTypeConverter">
+ <xsd:restriction base="xsd:string" />
+</xsd:simpleType>
+
+
+</xsd:schema> \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-selectclause.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-selectclause.xsd
new file mode 100644
index 0000000000..f1c0b1c305
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-selectclause.xsd
@@ -0,0 +1,45 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.hap.sdo.test.selectclause" xmlns:tns="com.agfa.hap.sdo.test.selectclause">
+
+<xsd:complexType name="SomeType">
+ <xsd:attribute name="nullStringProp" type="xsd:string"/>
+ <xsd:attribute name="nonNullStringProp" type="xsd:string"/>
+ <xsd:attribute name="nonNullStringPropMany" type="xsd:string" maxOccurs="unbounded"/>
+ <xsd:attribute name="nullStringPropMany" type="xsd:string" maxOccurs="unbounded"/>
+ <xsd:attribute name="emptyStringPropMany" type="xsd:string" maxOccurs="unbounded"/>
+ <xsd:attribute name="nullComplexNoIdNotInSelectClauseSingle" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nonNullComplexNoIdNotInSelectClauseSingle" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nullComplexNoIdInSelectClauseSingle" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nonNullComplexNoIdInSelectClauseSingle" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nullComplexIdNotInSelectClauseSingle" type="tns:TypeWithId"/>
+ <xsd:attribute name="nonNullComplexIdNotInSelectClauseSingle" type="tns:TypeWithId"/>
+ <xsd:attribute name="nullComplexIdInSelectClauseSingle" type="tns:TypeWithId"/>
+ <xsd:attribute name="nonNullComplexIdInSelectClauseSingle" type="tns:TypeWithId"/>
+ <xsd:attribute name="nonNullComplexIdInSelectClauseSingleIdIsNull" type="tns:TypeWithId"/>
+ <xsd:attribute name="nonNullComplexIdNotInSelectClauseSingleIdIsNull" type="tns:TypeWithId"/>
+ <xsd:attribute name="nullComplexNoIdNotInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nonNullComplexNoIdNotInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nullComplexNoIdInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nonNullComplexNoIdInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="nullComplexIdNotInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithId"/>
+ <xsd:attribute name="nonNullComplexIdNotInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithId"/>
+ <xsd:attribute name="nullComplexIdInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithId"/>
+ <xsd:attribute name="nonNullComplexIdInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithId"/>
+
+ <xsd:attribute name="emptyComplexNoIdNotInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="emptyComplexNoIdInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithoutId"/>
+ <xsd:attribute name="emptyComplexIdNotInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithId"/>
+ <xsd:attribute name="emptyComplexIdInSelectClauseMany" maxOccurs="unbounded" type="tns:TypeWithId"/>
+</xsd:complexType>
+
+<xsd:complexType name="TypeWithId" identityProperty="id">
+ <xsd:attribute name="id" type="xsd:long"/>
+ <xsd:attribute name="stringProp" type="xsd:string"/>
+</xsd:complexType>
+
+<xsd:complexType name="TypeWithoutId">
+ <xsd:attribute name="stringProp" type="xsd:string"/>
+</xsd:complexType>
+
+</xsd:schema> \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types-forward.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types-forward.xsd
new file mode 100644
index 0000000000..3ac75352a5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types-forward.xsd
@@ -0,0 +1,18 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.hap.sdo.test.forward" xmlns:tns="com.agfa.hap.sdo.test.forward">
+
+<xsd:complexType name="Af">
+ <xsd:sequence>
+ <xsd:element name="bs" type="tns:Bf" sdo:readOlny="false" maxOccurs="unbounded" sdo:oppositeProperty="a"/>
+ </xsd:sequence>
+ <xsd:attribute name="anotherProperty" type="xsd:int"/>
+</xsd:complexType>
+
+<xsd:complexType name="Bf">
+ <xsd:attribute name="a" type="xsd:anyURI" sdo:propertyType="tns:Af"/>
+ <xsd:attribute name="someProperty" type="xsd:int"/>
+</xsd:complexType>
+
+
+</xsd:schema> \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types.xsd
new file mode 100644
index 0000000000..b277996d04
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types.xsd
@@ -0,0 +1,64 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.hap.sdo.test" xmlns:tns="com.agfa.hap.sdo.test">
+
+<xsd:element name="a" type="tns:A"/>
+<xsd:complexType name="A">
+ <xsd:sequence>
+ <xsd:element name="stringProp" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="intProp" type="xsd:int" minOccurs="0"/>
+ <xsd:element name="b" type="xsd:anyURI" sdo:propertyType="tns:B"/>
+ <xsd:element name="containedB" type="tns:B"/>
+ </xsd:sequence>
+ <xsd:attribute name="longProp" type="xsd:long" />
+ <xsd:attribute name="shortProp" type="xsd:short" />
+ <xsd:attribute name="booleanProp" type="xsd:boolean" />
+ <xsd:attribute name="doubleProp" type="xsd:double" />
+ <xsd:attribute name="byteProp" type="xsd:byte" />
+ <xsd:attribute name="floatProp" type="xsd:float" />
+ <xsd:attribute name="uriProp" sdoJava:instanceClass="java.net.URI" />
+ <xsd:attribute name="bytearrayProp" type="xsd:hexBinary"/>
+</xsd:complexType>
+
+<xsd:complexType name="B">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ <xsd:element name="children" type="tns:B" minOccurs="0" maxOccurs="unbounded" sdo:oppositeProperty="parent"/>
+ <xsd:element name="favouriteChild" type="xsd:anyURI" sdo:propertyType="tns:B" minOccurs="0" />
+ </xsd:sequence>
+</xsd:complexType>
+
+<xsd:complexType name="InheritedB">
+ <xsd:complexContent>
+ <xsd:extension base="tns:B">
+ <xsd:sequence>
+ <xsd:element name="nickname" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ </xsd:extension>
+ </xsd:complexContent>
+</xsd:complexType>
+
+<xsd:complexType name="C" identityProperty="uri">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+ <xsd:attribute name="uri" type="xsd:anyURI" />
+ <xsd:attribute name="peer" sdo:readOnly="false" type="xsd:anyURI" sdo:propertyType="tns:C" sdo:oppositeProperty="peer"/>
+</xsd:complexType>
+
+<xsd:complexType name="D">
+ <xsd:attribute name="forwardRef" sdo:readOnly="false" type="xsd:anyURI" sdo:propertyType="tns:E"/>
+</xsd:complexType>
+
+<xsd:complexType name="E">
+ <xsd:attribute name="bRef" sdo:readOnly="false" type="xsd:anyURI" sdo:propertyType="tns:B"/>
+</xsd:complexType>
+
+<xsd:complexType name="F">
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="manyStringsProp" sdo:readOnly="false" maxOccurs="unbounded" type="xsd:string"/>
+ </xsd:choice>
+</xsd:complexType>
+
+
+</xsd:schema> \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types1.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types1.xsd
new file mode 100644
index 0000000000..2539d4d7d5
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types1.xsd
@@ -0,0 +1,13 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.hap.sdo.test1" xmlns:tns="com.agfa.hap.sdo.test1" xmlns:test2="com.agfa.hap.sdo.test2">
+
+<xsd:complexType name="A1">
+ <xsd:sequence>
+ <xsd:element name="b2s" type="test2:B2" sdo:readOlny="false" maxOccurs="unbounded" sdo:oppositeProperty="a1"/>
+ </xsd:sequence>
+ <xsd:attribute name="anotherProperty" type="xsd:int"/>
+</xsd:complexType>
+
+
+</xsd:schema> \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types2.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types2.xsd
new file mode 100644
index 0000000000..02a3b0a48d
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-sdo-types2.xsd
@@ -0,0 +1,11 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.hap.sdo.test2" xmlns:tns="com.agfa.hap.sdo.test2" xmlns:test1="com.agfa.hap.sdo.test1">
+
+
+<xsd:complexType name="B2">
+ <xsd:attribute name="a1" type="xsd:anyURI" sdo:propertyType="test1:A1"/>
+ <xsd:attribute name="someProperty" type="xsd:int"/>
+</xsd:complexType>
+
+</xsd:schema> \ No newline at end of file
diff --git a/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-userrole-types.xsd b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-userrole-types.xsd
new file mode 100644
index 0000000000..b659216088
--- /dev/null
+++ b/sandbox/kgoodson/agfasdo/com.agfa.hap.sdo/src/test/resources/sdo/test-userrole-types.xsd
@@ -0,0 +1,18 @@
+<xsd:schema xmlns="http://defaultnamespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdo="commonj.sdo/xml" xmlns:sdoJava="commonj.sdo/java"
+ targetNamespace="com.agfa.hap.sdo.test" xmlns:tns="com.agfa.hap.sdo.test.workflow">
+
+<xsd:element name="user" type="agfa.User"/>
+<xsd:complexType name="agfa.User">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+</xsd:complexType>
+
+<xsd:complexType name="agfa.Role">
+ <xsd:sequence>
+ <xsd:element name="name" type="xsd:string" minOccurs="0"/>
+ </xsd:sequence>
+</xsd:complexType>
+
+</xsd:schema> \ No newline at end of file