Browse Source

* Initial implementation of FCL-SDO

git-svn-id: trunk@22399 -
michael 13 years ago
parent
commit
9058529a44
70 changed files with 91012 additions and 0 deletions
  1. 69 0
      .gitattributes
  2. 76 0
      packages/fcl-sdo/Makefile.fpc
  3. 15 0
      packages/fcl-sdo/README
  4. 142 0
      packages/fcl-sdo/examples/changes-summary/project.pas
  5. 23 0
      packages/fcl-sdo/examples/changes-summary2/out.xsd
  6. BIN
      packages/fcl-sdo/examples/changes-summary2/project
  7. 142 0
      packages/fcl-sdo/examples/changes-summary2/project.pas
  8. BIN
      packages/fcl-sdo/examples/load-embedded-schema/project
  9. 133 0
      packages/fcl-sdo/examples/load-embedded-schema/project.pas
  10. 136 0
      packages/fcl-sdo/examples/simple/simple.pas
  11. 72 0
      packages/fcl-sdo/examples/xsd2pas/xsd2pas.lpi
  12. 61 0
      packages/fcl-sdo/examples/xsd2pas/xsd2pas.pas
  13. 609 0
      packages/fcl-sdo/src/base/pas_generator.pas
  14. 3287 0
      packages/fcl-sdo/src/base/sdo.pas
  15. 699 0
      packages/fcl-sdo/src/base/sdo_binary_streamer.pas
  16. 2535 0
      packages/fcl-sdo/src/base/sdo_changesummary.pas
  17. 138 0
      packages/fcl-sdo/src/base/sdo_consts.pas
  18. 226 0
      packages/fcl-sdo/src/base/sdo_cursor_intf.pas
  19. 612 0
      packages/fcl-sdo/src/base/sdo_datafactory.pas
  20. 4199 0
      packages/fcl-sdo/src/base/sdo_dataobject.pas
  21. 790 0
      packages/fcl-sdo/src/base/sdo_date_utils.pas
  22. 377 0
      packages/fcl-sdo/src/base/sdo_dom_cursors.pas
  23. 3647 0
      packages/fcl-sdo/src/base/sdo_field_imp.pas
  24. 188 0
      packages/fcl-sdo/src/base/sdo_fpc_xml.pas
  25. 63 0
      packages/fcl-sdo/src/base/sdo_global.inc
  26. 358 0
      packages/fcl-sdo/src/base/sdo_imp_utils.pas
  27. 593 0
      packages/fcl-sdo/src/base/sdo_linked_list.pas
  28. 73 0
      packages/fcl-sdo/src/base/sdo_locators.pas
  29. 98 0
      packages/fcl-sdo/src/base/sdo_logger_intf.pas
  30. 543 0
      packages/fcl-sdo/src/base/sdo_parserutils.pas
  31. 920 0
      packages/fcl-sdo/src/base/sdo_rtti_filters.pas
  32. 2955 0
      packages/fcl-sdo/src/base/sdo_serialization.pas
  33. 1997 0
      packages/fcl-sdo/src/base/sdo_serialization_binary.pas
  34. 155 0
      packages/fcl-sdo/src/base/sdo_serialization_utils.pas
  35. 1806 0
      packages/fcl-sdo/src/base/sdo_serialization_xml.pas
  36. 2287 0
      packages/fcl-sdo/src/base/sdo_type.pas
  37. 58 0
      packages/fcl-sdo/src/base/sdo_types.pas
  38. 315 0
      packages/fcl-sdo/src/base/sdo_utils.pas
  39. 1401 0
      packages/fcl-sdo/src/base/sdo_xpath_helper.pas
  40. 888 0
      packages/fcl-sdo/src/base/sdo_xsd_helper.pas
  41. 508 0
      packages/fcl-sdo/src/base/sdo_xsdintf.pas
  42. 2178 0
      packages/fcl-sdo/src/base/sdo_xsdparser.pas
  43. 112 0
      packages/fcl-sdo/src/base/xsd_consts.pas
  44. 550 0
      packages/fcl-sdo/src/base/xsd_generator.pas
  45. 137 0
      packages/fcl-sdo/src/das/data_acces_intf.pas
  46. 99 0
      packages/fcl-sdo/src/das/sdo_das.pas
  47. 437 0
      packages/fcl-sdo/src/das/sdo_das_imp.pas
  48. 326 0
      packages/fcl-sdo/src/das/sdo_das_utils.pas
  49. 63 0
      packages/fcl-sdo/src/das/sdo_global.inc
  50. 53 0
      packages/fcl-sdo/tests/test_suite/projects/dunit_tests.pas
  51. 253 0
      packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite.lpi
  52. 33 0
      packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite.lpr
  53. 169 0
      packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite_gui.lpi
  54. 19 0
      packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite_gui.lpr
  55. 137 0
      packages/fcl-sdo/tests/test_suite/projects/testrunner.pp
  56. 12466 0
      packages/fcl-sdo/tests/test_suite/test_changesummary.pas
  57. 611 0
      packages/fcl-sdo/tests/test_suite/test_convert_helper.pas
  58. 779 0
      packages/fcl-sdo/tests/test_suite/test_copyhelper.pas
  59. 6626 0
      packages/fcl-sdo/tests/test_suite/test_dataobject.pas
  60. 7898 0
      packages/fcl-sdo/tests/test_suite/test_dataobjectlist.pas
  61. 1031 0
      packages/fcl-sdo/tests/test_suite/test_equalityhelper.pas
  62. 10272 0
      packages/fcl-sdo/tests/test_suite/test_field_imp.pas
  63. 1035 0
      packages/fcl-sdo/tests/test_suite/test_property.pas
  64. 5118 0
      packages/fcl-sdo/tests/test_suite/test_serializer.pas
  65. 206 0
      packages/fcl-sdo/tests/test_suite/test_suite_utils.pas
  66. 2120 0
      packages/fcl-sdo/tests/test_suite/test_type.pas
  67. 805 0
      packages/fcl-sdo/tests/test_suite/test_utils.pas
  68. 2163 0
      packages/fcl-sdo/tests/test_suite/test_xpathhelper.pas
  69. 808 0
      packages/fcl-sdo/tests/test_suite/test_xsdhelper.pas
  70. 1314 0
      packages/fcl-sdo/tests/test_suite/test_xsdparser.pas

+ 69 - 0
.gitattributes

@@ -2466,6 +2466,75 @@ packages/fcl-res/xml/versionconsts.xml svneol=native#text/plain
 packages/fcl-res/xml/versionresource.xml svneol=native#text/plain
 packages/fcl-res/xml/versiontypes.xml svneol=native#text/plain
 packages/fcl-res/xml/winpeimagereader.xml svneol=native#text/plain
+packages/fcl-sdo/Makefile.fpc svneol=native#text/plain
+packages/fcl-sdo/README svneol=native#text/plain
+packages/fcl-sdo/examples/changes-summary/project.pas svneol=native#text/plain
+packages/fcl-sdo/examples/changes-summary2/out.xsd svneol=native#text/plain
+packages/fcl-sdo/examples/changes-summary2/project -text
+packages/fcl-sdo/examples/changes-summary2/project.pas svneol=native#text/plain
+packages/fcl-sdo/examples/load-embedded-schema/project -text
+packages/fcl-sdo/examples/load-embedded-schema/project.pas svneol=native#text/plain
+packages/fcl-sdo/examples/simple/simple.pas svneol=native#text/plain
+packages/fcl-sdo/examples/xsd2pas/xsd2pas.lpi svneol=native#text/plain
+packages/fcl-sdo/examples/xsd2pas/xsd2pas.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/pas_generator.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_binary_streamer.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_changesummary.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_consts.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_cursor_intf.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_datafactory.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_dataobject.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_date_utils.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_dom_cursors.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_field_imp.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_fpc_xml.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_global.inc svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_imp_utils.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_linked_list.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_locators.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_logger_intf.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_parserutils.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_rtti_filters.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_serialization.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_serialization_binary.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_serialization_utils.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_serialization_xml.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_type.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_types.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_utils.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_xpath_helper.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_xsd_helper.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_xsdintf.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/sdo_xsdparser.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/xsd_consts.pas svneol=native#text/plain
+packages/fcl-sdo/src/base/xsd_generator.pas svneol=native#text/plain
+packages/fcl-sdo/src/das/data_acces_intf.pas svneol=native#text/plain
+packages/fcl-sdo/src/das/sdo_das.pas svneol=native#text/plain
+packages/fcl-sdo/src/das/sdo_das_imp.pas svneol=native#text/plain
+packages/fcl-sdo/src/das/sdo_das_utils.pas svneol=native#text/plain
+packages/fcl-sdo/src/das/sdo_global.inc svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/projects/dunit_tests.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite.lpi svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite.lpr svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite_gui.lpi svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite_gui.lpr svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/projects/testrunner.pp svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_changesummary.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_convert_helper.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_copyhelper.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_dataobject.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_dataobjectlist.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_equalityhelper.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_field_imp.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_property.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_serializer.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_suite_utils.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_type.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_utils.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_xpathhelper.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_xsdhelper.pas svneol=native#text/plain
+packages/fcl-sdo/tests/test_suite/test_xsdparser.pas svneol=native#text/plain
 packages/fcl-stl/Makefile svneol=native#text/plain
 packages/fcl-stl/Makefile.fpc svneol=native#text/plain
 packages/fcl-stl/Makefile.fpc.fpcmake svneol=native#text/plain

+ 76 - 0
packages/fcl-sdo/Makefile.fpc

@@ -0,0 +1,76 @@
+#
+#   Makefile.fpc for running fpmake
+#
+
+[package]
+name=fcl-sdo
+version=2.7.1
+
+[require]
+packages=rtl fpmkunit fcl-base fcl-xml fcl-db
+
+[install]
+fpcpackage=y
+
+[default]
+fpcdir=../..
+
+[prerules]
+FPMAKE_BIN_CLEAN=$(wildcard .$(PATHSEP)fpmake$(SRCEXEEXT))
+ifdef OS_TARGET
+FPC_TARGETOPT+=--os=$(OS_TARGET)
+endif
+ifdef CPU_TARGET
+FPC_TARGETOPT+=--cpu=$(CPU_TARGET)
+endif
+LOCALFPMAKE=.$(PATHSEP)fpmake$(SRCEXEEXT)
+
+[rules]
+.NOTPARALLEL:
+
+fpmake: fpmake.pp
+	$(FPCFPMAKE) fpmake.pp $(FPMAKE_SKIP_CONFIG) $(addprefix -Fu,$(COMPILER_FPMAKE_UNITDIR)) $(FPCMAKEOPT)
+all:	fpmake
+	$(LOCALFPMAKE) compile --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) -bu
+smart:	fpmake
+	$(LOCALFPMAKE) compile --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) -bu -o -XX -o -CX
+release:	fpmake
+	$(LOCALFPMAKE) compile --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) -bu -o -dRELEASE
+debug:	fpmake
+	$(LOCALFPMAKE) compile --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) -bu -o -dDEBUG
+# If no fpmake exists and (dist)clean is called, do not try to build fpmake, it will
+# most often fail because the dependencies are cleared.
+# In case of a clean, simply do nothing
+ifeq ($(FPMAKE_BIN_CLEAN),)
+clean:	
+else
+clean:	
+	$(FPMAKE_BIN_CLEAN) clean --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC)
+endif
+# In case of a distclean, perform an 'old'-style distclean. This to avoid problems
+# when the package is compiled using fpcmake prior to running this clean using fpmake
+ifeq ($(FPMAKE_BIN_CLEAN),)
+distclean:	$(addsuffix _distclean,$(TARGET_DIRS)) fpc_cleanall
+else
+distclean:	
+ifdef inUnix
+        { $(FPMAKE_BIN_CLEAN) distclean --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC); if [ $$? != "0" ]; then { echo Something wrong with fpmake exectable. Remove the executable and call make recursively to recover.; $(DEL) $(FPMAKE_BIN_CLEAN); $(MAKE) fpc_cleanall; }; fi;  }
+else
+        $(FPMAKE_BIN_CLEAN) distclean --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC)
+endif
+	-$(DEL) $(LOCALFPMAKE)
+endif
+install:	fpmake
+ifdef UNIXHier
+	$(LOCALFPMAKE) install --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR)
+else
+	$(LOCALFPMAKE) install --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) --prefix=$(INSTALL_BASEDIR) --unitinstalldir=$(INSTALL_UNITDIR)
+endif
+# distinstall also installs the example-sources
+distinstall:	fpmake
+ifdef UNIXHier
+	$(LOCALFPMAKE) install --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) --prefix=$(INSTALL_PREFIX) --baseinstalldir=$(INSTALL_LIBDIR)/fpc/$(FPC_VERSION) --unitinstalldir=$(INSTALL_UNITDIR) -ie
+else
+	$(LOCALFPMAKE) install --localunitdir=../.. --globalunitdir=.. $(FPC_TARGETOPT) $(addprefix -o ,$(FPCOPT)) --compiler=$(FPC) --prefix=$(INSTALL_BASEDIR)  --unitinstalldir=$(INSTALL_UNITDIR) -ie
+endif
+

+ 15 - 0
packages/fcl-sdo/README

@@ -0,0 +1,15 @@
+
+fcl-sdo is an implementation in Object Pascal of the SDO standard.
+(Service Data Objects) by Inoussa Ouedraogo
+
+Service Data Objects are a way of keeping arbitrary data in memory and
+provides standardised means to query and modify this data. Its reference
+implementation is in Java and it is used mainly in web applications in
+combination with XML/XSD data.
+
+For more information, see
+http://www.ibm.com/developerworks/java/library/j-sdo/
+http://en.wikipedia.org/wiki/Service_Data_Objects
+
+The simple examples provided here will get you started in no time.
+

+ 142 - 0
packages/fcl-sdo/examples/changes-summary/project.pas

@@ -0,0 +1,142 @@
+program sample;
+
+{$mode objfpc}{$H+}
+
+uses
+  SysUtils,
+  sdo, sdo_consts, sdo_datafactory, sdo_serialization,
+  sdo_serialization_xml, sdo_xsd_helper;
+
+const
+  s_manager = 'Manager';
+  s_is_manager = 'IsManager';
+  s_member = 'Member';
+  s_name = 'Name';
+  s_person_type = 'Person';
+  s_project_leader = 'ProjectLeader';
+  s_project_list_type = 'ProjectList';
+  s_project_name = 'ProjectName';
+  s_project = 'Project';
+  s_project_type = 'ProjectType';
+  s_uri = 'uri:sample';
+
+  procedure PopulateFactoryByCode(AFactory : ISDODataFactory);
+  begin
+    // add the types
+    AFactory.AddType(s_uri,s_project_list_type,[]);
+    AFactory.AddType(s_uri,s_project_type,[]);
+    AFactory.AddType(s_uri,s_person_type,[]);
+
+    // Fill the informations of the project list type
+    AFactory.addProperty(s_uri,s_project_list_type,s_project,s_uri,s_project_type,[pfIsMany,pfIsContainment]);
+    AFactory.addProperty(s_uri,s_project_list_type,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+    // Fill the informations of the project type
+    AFactory.addProperty(s_uri,s_project_type,s_project_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    AFactory.addProperty(s_uri,s_project_type,s_member,s_uri,s_person_type,[pfIsMany,pfIsContainment]);
+    AFactory.addProperty(s_uri,s_project_type,s_project_leader,s_uri,s_person_type,[]);
+
+    // Fill the informations of the person type
+    AFactory.addProperty(s_uri,s_person_type,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    AFactory.addProperty(s_uri,s_person_type,s_is_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+    AFactory.addProperty(s_uri,s_person_type,s_manager,s_uri,s_person_type,[]);
+  end;
+
+  procedure GenerateSchemaFileFromFactory(AFactory : ISDODataFactory; AFileName : string);
+  var
+    xsdHelper : IXSDHelper;     
+  begin
+    xsdHelper := TXSDHelper.Create(AFactory); 
+    xsdHelper.Generate(AFactory.getTypes(),s_uri,AFileName);
+  end;
+
+procedure MainProc();
+var
+  fact : ISDODataFactory;
+  projList, proj, pers,b : ISDODataObject;
+  serializer : ISDOSerializer;
+  locSchemaFileName : string;
+begin
+  fact := TSDODataFactory.Create();
+  locSchemaFileName := ExpandFileName('.' + PathDelim + 'schema.xsd');
+  PopulateFactoryByCode(fact);
+  GenerateSchemaFileFromFactory(fact,locSchemaFileName);
+  WriteLn('Schema file generated !');
+
+  projList := fact.createNew(s_uri,s_project_list_type); 
+  // stop changes tracking
+  projList.getChangeSummary().endLogging();
+  //Add some data
+  proj := projList.createDataObject(s_project);
+    //add the project object to the list
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'WST');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Inoussa O.');
+      pers.setBoolean(s_is_manager,True);
+
+  //Add some data
+  proj := projList.createDataObject(s_project);
+    //add the project object to the list
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'sample project');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Inoussa O.');
+      pers.setBoolean(s_is_manager,True);
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'David KIS');
+      // this demonstrates object finding by sdo xpath expression
+      pers.setDataObject(s_manager,proj.getDataObject('Member[Name="Inoussa O."]'));
+
+  // start changes trackink now
+  projList.getChangeSummary.beginLogging();
+    proj.setString(s_project_name,'Object Pascal Project');
+    pers.setString(s_name,'D.K.');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Kis');
+      pers.setBoolean(s_is_manager,False);
+      // this demonstrates object finding by sdo xpath expression
+      pers.setDataObject(s_manager,projList.getDataObject('Project[0]/Member[Name="Inoussa O."]'));
+   projList.setDataObject('Project[0]/ProjectLeader',projList.getDataObject('Project[0]/Member[Name="Inoussa O."]'));
+
+  proj := projList.createDataObject(s_project);
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'SDO');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev manager');
+      pers.setBoolean(s_is_manager,True);
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev 1');
+      pers.setDataObject(s_manager,projList.getDataObject('Project[2]/Member[Name="SDO dev manager"]'));
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev 2');
+      pers.setDataObject(s_manager,projList.getDataObject('Project[2]/Member[Name="SDO dev manager"]'));
+    proj.setDataObject('ProjectLeader',proj.getDataObject('Member[Name="SDO dev manager"]'));
+  
+  projList.getList(s_project).delete(0);
+  
+  //save it now to file
+  serializer := TSDOSerializer.Create(fact,TSDOSerializerStreamXML.Create());   
+  serializer.save(s_project_list_type,projList,'data.xml');
+  WriteLn('Data file created.');
+
+  
+  //revert changes
+  projList.getChangeSummary.undoChanges();
+  serializer := TSDOSerializer.Create(fact,TSDOSerializerStreamXML.Create());   
+  serializer.save(s_project_list_type,projList,'data-original.xml');
+  WriteLn('Original Data file created.');
+
+end;
+
+begin
+  MainProc();
+end.
+

+ 23 - 0
packages/fcl-sdo/examples/changes-summary2/out.xsd

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<schema xmlns:sdo="commonj.sdo" xmlns:tns="uri:sample" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="uri:sample">
+  <xsd:complexType name="ProjectList">
+    <xsd:sequence>
+      <xsd:element name="Project" type="tns:ProjectType" maxOccurs="unbounded" minOccurs="0"/>
+      <xsd:element name="changeSummary" type="sdo:ChangeSummary"/>
+    </xsd:sequence>
+  </xsd:complexType>
+  <xsd:complexType name="ProjectType">
+    <xsd:sequence>
+      <xsd:element name="ProjectName" type="xsd:string" minOccurs="0"/>
+      <xsd:element name="Member" type="tns:Person" maxOccurs="unbounded" minOccurs="0"/>
+      <xsd:element name="ProjectLeader" type="xsd:anyURI" minOccurs="0" sdo:propertyType="tns:Person"/>
+    </xsd:sequence>
+  </xsd:complexType>
+  <xsd:complexType name="Person">
+    <xsd:sequence>
+      <xsd:element name="Name" type="xsd:string" minOccurs="0"/>
+      <xsd:element name="Manager" type="xsd:anyURI" minOccurs="0" sdo:propertyType="tns:Person"/>
+    </xsd:sequence>
+    <xsd:attribute name="IsManager" type="xsd:boolean"/>
+  </xsd:complexType>
+</schema>

BIN
packages/fcl-sdo/examples/changes-summary2/project


+ 142 - 0
packages/fcl-sdo/examples/changes-summary2/project.pas

@@ -0,0 +1,142 @@
+program sample;
+
+{$mode objfpc}{$H+}
+
+uses
+  SysUtils,
+  sdo, sdo_consts, sdo_datafactory, sdo_xsd_helper, sdo_xpath_helper;
+
+const
+  s_manager = 'Manager';
+  s_is_manager = 'IsManager';
+  s_member = 'Member';
+  s_name = 'Name';
+  s_person_type = 'Person';
+  s_project_leader = 'ProjectLeader';
+  s_project_list_type = 'ProjectList';
+  s_project_name = 'ProjectName';
+  s_project = 'Project';
+  s_project_type = 'ProjectType';
+  s_uri = 'uri:sample';
+
+  procedure PopulateFactoryByCode(AFactory : ISDODataFactory);
+  begin
+    // add the types
+    AFactory.AddType(s_uri,s_project_list_type,[]);
+    AFactory.AddType(s_uri,s_project_type,[]);
+    AFactory.AddType(s_uri,s_person_type,[]);
+
+    // Fill the informations of the project list type
+    AFactory.addProperty(s_uri,s_project_list_type,s_project,s_uri,s_project_type,[pfIsMany,pfIsContainment]);
+    AFactory.addProperty(s_uri,s_project_list_type,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+    // Fill the informations of the project type
+    AFactory.addProperty(s_uri,s_project_type,s_project_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    AFactory.addProperty(s_uri,s_project_type,s_member,s_uri,s_person_type,[pfIsMany,pfIsContainment]);
+    AFactory.addProperty(s_uri,s_project_type,s_project_leader,s_uri,s_person_type,[]);
+
+    // Fill the informations of the person type
+    AFactory.addProperty(s_uri,s_person_type,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    AFactory.addProperty(s_uri,s_person_type,s_is_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+    AFactory.addProperty(s_uri,s_person_type,s_manager,s_uri,s_person_type,[]);
+  end;
+
+  procedure GenerateSchemaFileFromFactory(AFactory : ISDODataFactory; AFileName : string);
+  var
+    xsdHelper : IXSDHelper;     
+  begin
+    xsdHelper := TXSDHelper.Create(AFactory); 
+    xsdHelper.Generate(AFactory.getTypes(),s_uri,AFileName);
+  end;
+
+procedure MainProc();
+var
+  fact : ISDODataFactory;
+  projList, proj, pers,b : ISDODataObject;
+  serializer : ISDOSerializer;
+  changeLS : ISDOChangedDataObjectList;
+  i : Integer;
+  x : ISDODataObject;
+begin
+  fact := TSDODataFactory.Create();
+  PopulateFactoryByCode(fact);
+  generateschemafilefromfactory(fact,'out.xsd');
+  projList := fact.createNew(s_uri,s_project_list_type); 
+  // stop changes tracking
+  projList.getChangeSummary().endLogging();
+  //Add some data
+  proj := projList.createDataObject(s_project);
+    //add the project object to the list
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'WST');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Inoussa O.');
+      pers.setBoolean(s_is_manager,True);
+
+  //Add some data
+  proj := projList.createDataObject(s_project);
+    //add the project object to the list
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'sample project');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Inoussa O.');
+      pers.setBoolean(s_is_manager,True);
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'David KIS');
+      // this demonstrates object finding by sdo xpath expression
+      pers.setDataObject(s_manager,proj.getDataObject('Member[Name="Inoussa O."]'));
+
+  // start changes trackink now
+  projList.getChangeSummary.beginLogging();
+    proj.setString(s_project_name,'Object Pascal Project');
+    pers.setString(s_name,'D.K.');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Kis');
+      pers.setBoolean(s_is_manager,False);
+      // this demonstrates object finding by sdo xpath expression
+      pers.setDataObject(s_manager,projList.getDataObject('Project[0]/Member[Name="Inoussa O."]'));
+   projList.setDataObject('Project[0]/ProjectLeader',projList.getDataObject('Project[0]/Member[Name="Inoussa O."]'));
+
+  proj := projList.createDataObject(s_project);
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'SDO');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev manager');
+      pers.setBoolean(s_is_manager,True);
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev 1');
+      pers.setDataObject(s_manager,projList.getDataObject('Project[2]/Member[Name="SDO dev manager"]'));
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev 2');
+      pers.setDataObject(s_manager,projList.getDataObject('Project[2]/Member[Name="SDO dev manager"]'));
+    proj.setDataObject('ProjectLeader',proj.getDataObject('Member[Name="SDO dev manager"]'));
+  
+  projList.getList(s_project).delete(0);
+  
+  //save it now to file
+  changeLS := projList.getChangeSummary.getChangedDataObjects();
+  WriteLn('There are ',changeLS.size(), ' changed objects :');
+  for i := 0 to changeLS.size() - 1 do begin
+    WriteLn('    ChangeType = ',changeLS.getType(i));
+    x := changeLS.getDataObject(i);
+    WriteLn('    Object Path = ',getXpath(changeLS.getDataObject(i)));
+  end;
+
+  
+  //revert changes
+  projList.getChangeSummary.undoChanges();
+  WriteLn('There are ',changeLS.size(), ' changed objects after changes undo.');
+
+end;
+
+begin
+  MainProc();
+end.
+

BIN
packages/fcl-sdo/examples/load-embedded-schema/project


+ 133 - 0
packages/fcl-sdo/examples/load-embedded-schema/project.pas

@@ -0,0 +1,133 @@
+program project;
+
+{$mode objfpc}{$H+}
+
+uses
+  SysUtils,
+  sdo, sdo_datafactory, sdo_serialization,
+  sdo_serialization_xml, sdo_xsd_helper;
+
+const
+  s_manager = 'Manager';
+  s_is_manager = 'IsManager';
+  s_member = 'Member';
+  s_name = 'Name';
+  s_person_type = 'Person';
+  s_project_leader = 'ProjectLeader';
+  s_project_list_type = 'ProjectList';
+  s_project_name = 'ProjectName';
+  s_project = 'Project';
+  s_project_type = 'ProjectType';
+  s_uri = 'uri:sample';
+
+  function IndentStr(const AIndent : Integer) : string;
+  begin
+    Result := StringOfChar(' ',3*AIndent);
+  end;
+  
+  function ToString(const AObj : ISDODataObject; const AIndent : Integer) : string;overload;forward;
+  function ToString(const AObj : ISDODataObjectList; const AItemType : ISDOType; const AIndent : Integer) : string;overload;
+  var
+    crs : ISDOCursor;
+    oldPos : ISDOCursorBookmark;
+  begin
+    crs := AObj.getCursor();
+    oldPos := crs.GetBookmark();
+    try
+      crs.Reset();
+      if AItemType.isDataType() then begin
+        while crs.MoveNext() do begin
+          Result := Format('%s, %s',[Result,AObj.getString()]);
+        end;
+      end else begin
+        while crs.MoveNext() do begin
+          Result := Result + sLinebreak + IndentStr(AIndent+1) + '(' +// sLineBreak + 
+                      Copy(IndentStr(1),2,1024) + TrimLeft(ToSTring(AObj.getDataObject(),AIndent+1)) + sLineBreak + 
+                    IndentStr(AIndent+1) + ')';
+        end;
+        Result := Copy(IndentStr(1),2,1024) + TrimLeft(Result);
+      end;
+      if ( Length(Result) > 0 ) and ( Result[1] = ',' ) then
+        Delete(Result,1,1);
+    finally
+      crs.GotoBookmark(oldPos);
+    end;
+    Result := sLineBreak + IndentStr(AIndent) + '[' + //sLineBreak +
+                Result +
+              sLineBreak + IndentStr(AIndent) + ']';
+  end;
+
+  function ToString(const AObj : ISDODataObject; const AIndent : Integer) : string;overload;
+  var
+    pls : ISDOPropertyList;
+    p : ISDOProperty;
+    i, c : PtrInt;
+  begin
+    Result := '';
+    if ( AObj = nil ) then begin
+      Result := sLineBreak + IndentStr(AIndent + 1) +'<nil>';
+    end else begin
+      pls := AObj.getInstanceProperties();
+      c := pls.getCount();
+      if ( c > 0 ) then begin
+        for i := 0 to Pred(c) do begin
+          p := pls.getItem(i);
+          if ( p.getTypeEnum() = ChangeSummaryType ) then
+            Continue;
+          if not p.isMany() then begin
+            if p.getType().isDataType() then begin
+              Result := Result + sLineBreak +
+                        IndentStr(AIndent + 1) + p.getName() + ' : ' + AObj.getString(p);
+            end else begin
+              Result := Result + sLineBreak +
+                        IndentStr(AIndent + 1) + p.getName() + ' :' + //sLineBreak +
+                        ToString(AObj.getDataObject(p),AIndent+1);
+            end;
+          end else begin
+              Result := Result + sLineBreak +
+                        IndentStr(AIndent + 1) + p.getName() + ' :' + //sLineBreak +
+                        ToString(AObj.getList(p),p.getType(),AIndent+2);
+          end;
+        end;
+        if ( Length(Result) > 0 ) and ( Result[1] = ',' ) then
+          Delete(Result,1,1);
+      end;
+    end;
+    Result := IndentStr(AIndent) + Result;
+  end;
+
+  procedure GenerateSchemaFileFromFactory(AFactory : ISDODataFactory; AFileName : string);
+  var
+    xsdHelper : IXSDHelper;     
+  begin
+    xsdHelper := TXSDHelper.Create(AFactory); 
+    xsdHelper.Generate(AFactory.getTypes(),s_uri,AFileName);
+  end;
+
+procedure MainProc();
+var
+  fact : ISDODataFactory;
+  projList, proj, pers,b : ISDODataObject;
+  serializer : ISDOSerializer;
+  locDataFileName, locSchemaFileName : string;
+begin
+  fact := TSDODataFactory.Create();
+  locDataFileName := ExpandFileName('.' + PathDelim + 'data-with-schema.xml');
+  
+  //Load data from the file
+  serializer := TSDOSerializer.Create(fact,TSDOSerializerStreamXML.Create());
+  projList := serializer.load(locDataFileName);
+  
+  locSchemaFileName := ExpandFileName('.' + PathDelim + 'schema.xsd');
+  GenerateSchemaFileFromFactory(fact,locSchemaFileName);
+  WriteLn('Schema file generated !');
+  
+  Writeln;
+  WriteLn('Data :');
+  WriteLn(ToString(projList,0));
+end;
+
+begin
+  MainProc();
+end.
+

+ 136 - 0
packages/fcl-sdo/examples/simple/simple.pas

@@ -0,0 +1,136 @@
+program simple;
+
+{$mode objfpc}{$H+}
+
+uses
+  SysUtils,
+  sdo, sdo_datafactory, sdo_serialization,
+  sdo_serialization_xml, sdo_xsd_helper;
+
+const
+  s_manager = 'Manager';
+  s_is_manager = 'IsManager';
+  s_member = 'Member';
+  s_name = 'Name';
+  s_person_type = 'Person';
+  s_project_leader = 'ProjectLeader';
+  s_project_list_type = 'ProjectList';
+  s_project_name = 'ProjectName';
+  s_project = 'Project';
+  s_project_type = 'ProjectType';
+  s_uri = 'uri:sample';
+
+  procedure PopulateFactoryByCode(AFactory : ISDODataFactory);
+  begin
+    // add the types
+    AFactory.AddType(s_uri,s_project_list_type,[]);
+    AFactory.AddType(s_uri,s_project_type,[]);
+    AFactory.AddType(s_uri,s_person_type,[]);
+
+    // Fill the informations of the project list type
+    AFactory.addProperty(s_uri,s_project_list_type,s_project,s_uri,s_project_type,[pfIsMany,pfIsContainment]);
+
+    // Fill the informations of the project type
+    AFactory.addProperty(s_uri,s_project_type,s_project_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    AFactory.addProperty(s_uri,s_project_type,s_member,s_uri,s_person_type,[pfIsMany,pfIsContainment]);
+    AFactory.addProperty(s_uri,s_project_type,s_project_leader,s_uri,s_person_type,[]);
+
+    // Fill the informations of the person type
+    AFactory.addProperty(s_uri,s_person_type,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    AFactory.addProperty(s_uri,s_person_type,s_is_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+    AFactory.addProperty(s_uri,s_person_type,s_manager,s_uri,s_person_type,[]);
+  end;
+
+  procedure GenerateSchemaFileFromFactory(AFactory : ISDODataFactory; AFileName : string);
+  var
+    xsdHelper : IXSDHelper;     
+  begin
+    xsdHelper := TXSDHelper.Create(AFactory); 
+    xsdHelper.Generate(AFactory.getTypes(),s_uri,AFileName);
+  end;
+
+  procedure PopulateFactoryBySchemaFile(AFactory : ISDODataFactory; AFileName : string);
+  var
+    xsdHelper : IXSDHelper;     
+  begin
+    xsdHelper := TXSDHelper.Create(AFactory); 
+    xsdHelper.LoadFromFile(AFileName);
+  end;   
+
+procedure MainProc();
+var
+  fact : ISDODataFactory;
+  projList, proj, pers,b : ISDODataObject;
+  serializer : ISDOSerializer;
+  locSchemaFileName : string;
+begin
+  fact := TSDODataFactory.Create();
+  locSchemaFileName := ExpandFileName('.' + PathDelim + 'schema.xsd');
+  PopulateFactoryByCode(fact);
+  GenerateSchemaFileFromFactory(fact,locSchemaFileName);
+  WriteLn('Schema file generated !');
+
+  projList := fact.createNew(s_uri,s_project_list_type); 
+  //Add some data
+  proj := projList.createDataObject(s_project);
+    //add the project object to the list
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'WST');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Inoussa O.');
+      pers.setBoolean(s_is_manager,True);
+
+  //Add some data
+  proj := projList.createDataObject(s_project);
+    //add the project object to the list
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'sample project');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Inoussa O.');
+      pers.setBoolean(s_is_manager,True);
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'David KIS');
+      // this demonstrates object finding by sdo xpath expression
+      pers.setDataObject(s_manager,proj.getDataObject('Member[Name="Inoussa O."]'));
+
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'Kis');
+      pers.setBoolean(s_is_manager,False);
+      // this demonstrates object finding by sdo xpath expression
+      pers.setDataObject(s_manager,projList.getDataObject('Project[0]/Member[Name="Inoussa O."]'));
+   projList.setDataObject('Project[0]/ProjectLeader',projList.getDataObject('Project[0]/Member[Name="Inoussa O."]'));
+
+  proj := projList.createDataObject(s_project);
+    projList.getList(s_project).append(proj);
+    proj.setString(s_project_name,'SDO');
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev manager');
+      pers.setBoolean(s_is_manager,True);
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev 1');
+      pers.setDataObject(s_manager,projList.getDataObject('Project[ProjectName="SDO"]/Member[Name="SDO dev manager"]'));
+    pers := proj.createDataObject(s_member);
+      proj.getList(s_member).append(pers);
+      pers.setString(s_name,'SDO dev 2');
+      pers.setDataObject(s_manager,projList.getDataObject('Project[2]/Member[Name="SDO dev manager"]'));
+    proj.setDataObject('ProjectLeader',proj.getDataObject('Member[Name="SDO dev manager"]'));
+
+  //save it now to file
+  serializer := TSDOSerializer.Create(fact,TSDOSerializerStreamXML.Create()); 
+  serializer.setOptions([]);
+  serializer.save(s_project_list_type,projList,'data-with-schema.xml'); 
+  serializer.setOptions([soExcludeSchema]);
+  serializer.save(s_project_list_type,projList,'data-without-schema.xml');
+  WriteLn('Data files created.');
+end;
+
+begin
+  MainProc();
+end.
+

+ 72 - 0
packages/fcl-sdo/examples/xsd2pas/xsd2pas.lpi

@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <Title Value="xsd2pas"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="/usr/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <Units Count="1">
+      <Unit0>
+        <Filename Value="xsd2pas.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="xsd2pas"/>
+      </Unit0>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="project1"/>
+    </Target>
+    <SearchPaths>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Other>
+      <CompilerMessages>
+        <MsgFileName Value=""/>
+      </CompilerMessages>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 61 - 0
packages/fcl-sdo/examples/xsd2pas/xsd2pas.pas

@@ -0,0 +1,61 @@
+program xsd2pas;
+
+{$mode objfpc}{$H+}
+
+uses
+  cwstring, Classes, SysUtils, sdo, sdo_datafactory, sdo_xsdintf,
+  sdo_xsd_helper, xsd_generator, pas_generator;
+
+  procedure LoadSchemaFile(AFactory : ISDODataFactory; AFileName : string);
+  var
+    xsdHelper : IXSDHelper;
+  begin
+    try
+      xsdHelper := TXSDHelper.Create(AFactory);
+      xsdHelper.LoadFromFile(AFileName);
+    except
+      On E : exception do
+        begin
+          E.Message:='Load failed'+E.Message;
+         raise;
+
+        end;
+    end;
+  end;
+
+  procedure CreatePascalCode(AFactory : ISDODataFactory; AFileName : string);
+
+  var
+    xsdHelper : IXSDHelper;
+  begin
+    xsdHelper := TXSDHelper.Create(AFactory);
+    try
+    xsdHelper.GenerateCode(AFactory.getTypes(),'urn:wst-test',AFileName);
+    except
+      On E : exception do
+        begin
+          E.Message:='Generate failed'+E.Message;
+         raise;
+
+        end;
+    end;
+  end;
+
+
+procedure MainProc;
+
+var
+  fact : ISDODataFactory;
+
+begin
+  Fact:=TSDODataFactory.Create();
+  Writeln('Handling ',ParamStr(1));
+  LoadSchemaFile(Fact,ParamStr(1));
+  CreatePascalCode(Fact,'myunit');
+end;
+
+
+begin
+  MainProc;
+end.
+

+ 609 - 0
packages/fcl-sdo/src/base/pas_generator.pas

@@ -0,0 +1,609 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements creating a XSD file from SDO metadata
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$mode objfpc}
+{$h+}
+unit pas_generator;
+
+interface
+
+uses
+  Classes, SysUtils, TypInfo, sdo, contnrs;
+
+type
+
+  { TPasIdentifier }
+
+  TPasIdentifier = Class(TPersistent)
+  private
+    FName: String;
+    FNameSpace: String;
+    FOutputName: String;
+    function GetOutputName: String;
+  Public
+    Constructor create; virtual;
+    Constructor CreateNamed(Const AName,ANameSpace : String);
+  Published
+    Property OutputName : String Read GetOutputName Write FOutputName;
+    Property Name : String Read FName Write Fname;
+    Property NameSpace : String Read FNameSpace Write FNameSpace;
+  end;
+
+  { TPasIdentifierList }
+
+  TPasIdentifierList = Class(TObjectList)
+  private
+    function GetI(AIndex : Integer): TPasIdentifier;
+    procedure SetI(AIndex : Integer; AValue: TPasIdentifier);
+  Public
+    Property Identifier[AIndex : Integer] : TPasIdentifier Read GetI Write SetI; default;
+  end;
+
+  { TPasEnumeration }
+
+  TPasEnumeration = Class(TPasIdentifier)
+  private
+    FValues: Tstrings;
+    procedure SetValues(AValue: Tstrings);
+  Public
+    Constructor Create; override;
+    Destructor Destroy; override;
+  Published
+    Property Values : Tstrings Read FValues Write SetValues;
+  end;
+
+  { TPasArray }
+
+  TPasArray = CLass(TPasIdentifier)
+  private
+    FElement: TPasidentifier;
+    FTypeName: String;
+  Public
+    Property Elemtent : TPasidentifier Read FElement Write FElement;
+  Published
+    Property ElementName : String Read FTypeName Write FTypeName;
+  end;
+
+  { TPasProperty }
+
+  TPasProperty = Class(TPasIdentifier)
+  private
+    FDefaultValue: String;
+    FIsRequired: Boolean;
+    FMaxOccurs: Integer;
+    FMinOccurs: Integer;
+    FTypeName: String;
+    FTypeNameSpace: String;
+  Published
+    Property TypeName : String Read FTypeName Write FTypeName;
+    Property TypeNameSpace : String Read FTypeNameSpace Write FTypeNameSpace;
+    Property DefaultValue : String Read FDefaultValue Write FDefaultValue;
+    Property IsRequired : Boolean Read FIsRequired write FIsRequired;
+    Property MinOccurs : Integer read FMinOccurs Write FMinOccurs;
+    Property MaxOccurs : Integer Read FMaxOccurs Write FMaxOccurs;
+  end;
+
+  { TPasPropertyList }
+
+  TPasPropertyList = Class(TPasIdentifierList)
+  private
+    function GetI(AIndex : Integer): TPasProperty;
+    procedure SetI(AIndex : Integer; AValue: TPasProperty);
+  Public
+    Property Properties[AIndex : Integer] : TPasProperty Read GetI Write SetI;default;
+  end;
+
+  { TPasClass }
+
+  TPasClass = Class(TPasIdentifier)
+  private
+    FMembers: TPasPropertyList;
+    FParentName: String;
+    FParentNameSpace: String;
+  Public
+    Constructor Create; override;
+    Destructor Destroy; override;
+    Property Members : TPasPropertyList Read FMembers Write FMembers;
+  Published
+    Property ParentName : String Read FParentName Write FParentName;
+    Property ParentNameSpace : String Read FParentNameSpace Write FParentNameSpace;
+  end;
+
+
+
+  TPasGeneratorOption = ( xgoIgnorembeddedArray );
+  TPasGeneratorOptions = set of TPasGeneratorOption;
+
+  EPasGeneratorException = class(Exception) end;
+
+  IGenerator = interface
+    ['{F69523B3-A6FF-4BFB-9ACB-D4B9F32DBCA9}']
+    procedure Execute(
+      ASymTable   : ISDODataObject;
+      AModuleName : string
+    );
+  end;
+
+  IPasGenerator = interface(IGenerator)
+    ['{FBFF92BC-B72B-4B85-8D16-379F9E548DDB}']
+    procedure SetPreferedShortNames(const ALongName, AShortName : string);
+    function GetPreferedShortNames() : TStrings;
+    Function GetUnitName : String;
+    Procedure SetUnitname(Const AValue : String);
+    Property UnitName : String Read GetUnitName Write setUnitName;
+  end;
+
+  { TCustomPasGenerator }
+  TTypeCategory = ( tcComplexContent, tcSimpleContent );
+
+
+  TCustomPasGenerator = class(
+    TInterfacedObject,
+    IInterface,
+    IGenerator,
+    IPasGenerator
+  )
+  private
+    FStream : TStream;
+    FOptions: TPasGeneratorOptions;
+    FUnitName: String;
+    FShortNames : TStrings;
+    FIndent : Integer;
+    FIdentifiers : TPasIdentifierList;
+    procedure ProcessProperty(AContainer : ISDODataObject; Const AClass : TPasClass; const AProp: ISDODataObject);
+{    procedure ProcessXsdAny(const Prop : TPasProperty; const AXsdInfo: string);
+    procedure ProcessXsdAnyAttribute(const Prop : TPasProperty;
+      const AXsdInfo: string);
+}    function TypeHasSequence(const AClassType: ISDODataObject;
+      const ACategory: TTypeCategory): Boolean;
+  protected
+    Procedure Error(Const AMsg : String);
+    Procedure Error(Const Fmt : String; Args : Array of const);
+    Procedure Line(Const ALine : String);
+    Procedure Line(Const Fmt : String; Args : Array of const);
+    Procedure Indent;
+    Procedure Undent;
+    procedure SetPreferedShortNames(const ALongName, AShortName : string);
+    function GetPreferedShortNames() : TStrings;
+    procedure GenerateEnum(AContainer, ASymbol : ISDODataObject);
+    procedure GenerateComplex(AContainer, ASymbol : ISDODataObject);
+    Function GetUnitName : String;
+    Procedure SetUnitname(Const AValue : String);
+    Procedure StartInterface; virtual;
+    procedure Execute(
+      ASymTable   : ISDODataObject;
+      AModuleName : string
+    );
+
+    procedure Prepare(
+      ASymTable,
+      AModule   : ISDODataObject
+    );virtual;
+    property Options : TPasGeneratorOptions read FOptions;
+  public
+    constructor Create(const AStream : TStream);overload;
+    constructor Create(
+      const AStream : TStream;
+      const AOptions : TPasGeneratorOptions
+    );overload;
+    destructor Destroy();override;
+  end;
+
+  { TPasGenerator }
+
+  TPasGenerator = class(TCustomPasGenerator)
+  private
+  protected
+    procedure Prepare(ASymTable, AModule : ISDODataObject);override;
+  end;
+
+
+implementation
+
+uses
+  sdo_xsdintf, xsd_consts,  StrUtils, sdo_types, sdo_parserutils;
+
+{ TPasClass }
+
+constructor TPasClass.Create;
+begin
+  inherited Create;
+  FMembers:=TPasPropertyList.Create(True);
+end;
+
+destructor TPasClass.Destroy;
+begin
+  FreeAndNil(FMembers);
+  inherited Destroy;
+end;
+
+{ TPasPropertyList }
+
+function TPasPropertyList.GetI(AIndex: Integer): TPasProperty;
+begin
+  Result:=Items[AIndex] as TPasProperty
+end;
+
+procedure TPasPropertyList.SetI(AIndex: Integer; AValue: TPasProperty);
+begin
+  Items[AIndex]:=AValue;
+end;
+
+function TPasIdentifier.GetOutputName: String;
+begin
+  Result:=FoutputName;
+  If Result='' then
+    Result:=FName;
+end;
+
+constructor TPasIdentifier.create;
+begin
+  // Do nothing
+end;
+
+constructor TPasIdentifier.CreateNamed(Const AName, ANameSpace : string);
+begin
+  FName:=AName;
+  FNameSpace:=ANameSpace;
+  Create;
+end;
+
+{ TPasIdentifierList }
+
+function TPasIdentifierList.GetI(AIndex : Integer): TPasIdentifier;
+begin
+  Result:=Items[AIndex] as TPasIdentifier;
+end;
+
+procedure TPasIdentifierList.SetI(AIndex : Integer; AValue: TPasIdentifier);
+begin
+  Items[AIndex]:=AValue;
+end;
+
+{ TPasEnumeration }
+
+procedure TPasEnumeration.SetValues(AValue: Tstrings);
+begin
+  if FValues=AValue then Exit;
+  FValues.Assign(AValue);
+end;
+
+constructor TPasEnumeration.Create;
+begin
+  inherited Create;
+  FValues:=TStringList.Create;
+end;
+
+destructor TPasEnumeration.Destroy;
+begin
+  FreeAndNil(FValues);
+  inherited Destroy;
+end;
+
+
+{ TCustomPasGenerator }
+
+procedure TCustomPasGenerator.Execute(
+  ASymTable   : ISDODataObject;
+  AModuleName : string
+);
+var
+  i : Integer;
+  locModule : ISDODataObject;
+begin
+  if ( ASymTable = nil ) then
+    Error('Invalid symbol table.');
+  locModule := FindModule(ASymTable,AModuleName);
+  if ( locModule = nil ) then
+    Error('Unable to find module : "%s".',[AModuleName]);
+  If (FUnitName='') then
+    FUnitName:=AModuleName;
+  Prepare(ASymTable,locModule);
+  StartInterface;
+  For I:=0 to FIDentifiers.Count-1 do
+    Writeln(FIdentifiers[i].Name, ' in ',FIdentifiers[i].NameSpace);
+end;
+
+procedure TCustomPasGenerator.Prepare(
+  ASymTable,
+  AModule   : ISDODataObject
+);
+Var
+  i : Integer;
+  locList : ISDODataObjectList;
+  locElement : ISDODataObject;
+begin
+  locList := AModule.getList(s_Type);
+  for i := 0 to locList.size() - 1 do
+    begin
+    locElement := locList.getDataObject(i);
+    if locElement.getBoolean(s_IsComplex) then
+      GenerateComplex(ASymTable,locElement)
+    else if (locElement.getList(s_EnumValue).size() > 0) then
+      GenerateEnum(ASymTable,locElement);
+    end
+end;
+
+constructor TCustomPasGenerator.Create(const AStream: TStream);
+begin
+  Create(AStream,[]);
+end;
+
+constructor TCustomPasGenerator.Create(const AStream: TStream;
+  const AOptions: TPasGeneratorOptions);
+var
+  sl : TStringList;
+begin
+  if ( AStream = nil ) then
+    raise EPasGeneratorException.Create('Invalid document.');
+  FStream := AStream;
+  FOptions := AOptions;
+  sl := TStringList.Create();
+  //sl.Sorted := True;
+  sl.Duplicates := dupIgnore;
+  FShortNames:=Sl;
+  FIdentifiers:=TPasIdentifierList.Create;
+end;
+
+procedure TCustomPasGenerator.Error(const AMsg: String);
+begin
+  raise EPasGeneratorException.Create(AMsg);
+end;
+
+procedure TCustomPasGenerator.Error(const Fmt: String; Args: array of const);
+begin
+  raise EPasGeneratorException.CreateFmt(Fmt,Args);
+end;
+
+procedure TCustomPasGenerator.Line(const ALine: String);
+
+Var
+  S : String;
+begin
+  if (ALine<>'') then
+    S:=StringOfChar(' ',FIndent)+ALine;
+  S:=S+sLineBreak;
+  FStream.WriteBuffer(S[1],Length(s)*SizeOf(Char));
+end;
+
+procedure TCustomPasGenerator.Line(const Fmt: String; Args: array of const);
+begin
+  Line(Format(Fmt,Args));
+end;
+
+procedure TCustomPasGenerator.Indent;
+begin
+  Inc(FIndent,2);
+end;
+
+procedure TCustomPasGenerator.Undent;
+begin
+  If (FIndent>0) then
+    Dec(FIndent,2);
+end;
+
+procedure TCustomPasGenerator.SetPreferedShortNames(const ALongName, AShortName: string);
+begin
+  FShortNames.Values[ALongName] := AShortName;
+end;
+
+function TCustomPasGenerator.GetPreferedShortNames() : TStrings;
+begin
+  Result := FShortNames;
+end;
+
+destructor TCustomPasGenerator.Destroy();
+begin
+  FreeAndNil(FShortNames);
+  inherited;
+end;
+
+procedure TCustomPasGenerator.GenerateEnum(AContainer, ASymbol : ISDODataObject);
+var
+  typItm : ISDODataObject;
+  valueList : ISDODataObjectList;
+  s : string;
+  i : Integer;
+{$IFDEF SDO_HANDLE_DOC}
+  ls : TStrings;
+{$ENDIF SDO_HANDLE_DOC}
+  ET : TPasEnumeration;
+
+begin
+  if (ASymbol = nil) then
+    Exit;
+  typItm := ASymbol;
+  {$IFDEF SDO_HANDLE_DOC}
+    ls := AContainer.Properties.FindList(typItm);
+    if ( ls <> nil ) then begin
+      i := ls.IndexOfName(s_documentation);
+      if ( i >= 0 ) then
+        GenerateDocumentation(resNode,DecodeLineBreak(ls.ValueFromIndex[i]),ADocument);
+    end;
+  {$ENDIF SDO_HANDLE_DOC}
+  S:=typItm.getString(sdo_xsdintf.s_Name)+' = (';
+  ET:=TPasEnumeration.CreateNamed(S,'');
+  Self.FIdentifiers.Add(Et);
+  valueList := typItm.getList(s_EnumValue);
+  for i := 0 to (valueList.size() - 1) do
+    ET.Values.Add(valueList.getString(i));
+end;
+
+function TCustomPasGenerator.TypeHasSequence(const AClassType : ISDODataObject; const ACategory : TTypeCategory) : Boolean;
+var
+  kc, k : PtrInt;
+  pl : ISDODataObjectList;
+  p : ISDODataObject;
+begin
+  Result := False;
+  pl := AClassType.getList(s_Property);
+  kc := pl.size();
+  if (kc > 0) then begin
+    for k := 0 to kc - 1 do begin
+      p := pl.getDataObject(k);
+      if not p.getBoolean(s_IsAttribute) then begin
+        if ( ACategory = tcSimpleContent ) then begin
+          Error(  'Invalid type definition, a simple type cannot have "not attribute" properties : "%s"',
+                  [AClassType.getString(sdo_xsdintf.s_Name)]
+                );
+        end;
+        Result := True;
+      end;
+    end;
+  end;
+end;
+
+
+procedure TCustomPasGenerator.ProcessProperty(AContainer : ISDODataObject; Const AClass : TPasClass; const AProp : ISDODataObject);
+var
+  p : ISDODataObject;
+  s : string;
+  pt, propItmUltimeType : ISDODataObject;
+  prop_ns_shortName : string;
+  PP : TPasProperty;
+
+begin
+  p := AProp;
+  PP:=TPasProperty.CreateNamed(p.getString(sdo_xsdintf.s_Name),'');
+  AClass.Members.Add(pp);
+  if p.getBoolean(sdo_xsdintf.s_IsAttribute) then
+    begin
+{    s := Format('%s:%s',[s_xs_short,s_attribute]);
+    if Assigned(derivationNode) then
+      propNode := CreateElement(s,derivationNode,Document)
+    else
+      propNode := CreateElement(s,cplxNode,Document);}
+    end;
+
+  pt := p.getDataObject(s_DataType);
+  if Assigned(pt) then
+    begin
+    if pt.getBoolean(sdo_xsdintf.s_Unresolved) then
+      pt := Find( AContainer,pt.getString(sdo_xsdintf.s_NameSpace),pt.getString(sdo_xsdintf.s_Name));
+    propItmUltimeType := GetUltimeType(pt);
+    PP.TypeName:=pt.getString(sdo_xsdintf.s_Name);
+    PP.TypeNamespace := GetTypeNameSpace(pt);
+    PP.DefaultValue:=p.getString(s_DefaultValue);
+    if p.getBoolean(s_IsAttribute) then
+      begin
+      PP.IsRequired:=(p.getInteger(s_PropertyMinOccurs)>0);
+      end
+    else
+      begin
+      PP.MinOccurs:=p.getInteger(s_PropertyMinOccurs);
+      PP.MaxOccurs:=p.getInteger(s_PropertyMaxOccurs);
+      end;
+    end;
+//  ProcessPropertyExtendedMetadata(p,propNode);
+end;
+
+procedure TCustomPasGenerator.GenerateComplex(AContainer, ASymbol: ISDODataObject);
+
+var
+  typItm : ISDODataObject;
+  s : string;
+  i : Integer;
+  typeCategory : TTypeCategory;
+  hasSequence : Boolean;
+  trueParent : ISDODataObject;
+  hasXsdAny, hasXsdAnyAtt : Boolean;
+  xsdAnyString, xsdAnyAttString : TSDOString;
+  pl : ISDODataObjectList;
+  PC : TpasClass;
+  CN,CNS : String;
+begin
+  if (ASymbol = nil) then
+    Exit;
+  typItm := ASymbol;
+  PC:=TPasClass.CreateNamed(typItm.getString(sdo_xsdintf.s_Name),AContainer.getDataObject(s_CurrentModule).getString(sdo_xsdintf.s_NameSpace));
+  Self.FIdentifiers.Add(PC);
+{$IFDEF SDO_HANDLE_DOC}
+  ls := AContainer.Properties.FindList(typItm);
+  if ( ls <> nil ) then begin
+    i := ls.IndexOfName(s_documentation);
+    if ( i >= 0 ) then
+      GenerateDocumentation(cplxNode,DecodeLineBreak(ls.ValueFromIndex[i]),ADocument);
+  end;
+{$ENDIF SDO_HANDLE_DOC}
+
+  typeCategory := tcComplexContent;
+  hasSequence := True;
+  trueParent := typItm.getDataObject(sdo_xsdintf.s_BaseType);
+  if (trueParent <> nil) then
+    begin
+    if trueParent.getBoolean(s_Unresolved) then
+      trueParent := Find(AContainer,trueParent.getString(sdo_xsdintf.s_NameSpace), trueParent.getString(sdo_xsdintf.s_Name));
+    if (trueParent <> nil) then
+      begin
+      if (trueParent.getByte(s_ElementKind) = sdo_xsdintf.ELEMENT_KIND_VARIABLE) then
+        trueParent := GetUltimeType(trueParent);
+      if not trueParent.getBoolean(s_IsComplex) then
+        typeCategory := tcSimpleContent;
+      PC.ParentNameSpace:=GetTypeNameSpace(trueParent);
+      PC.ParentName:=trueParent.getString(sdo_xsdintf.s_Name);
+      hasSequence := False;
+      end;
+    end;
+  pl := typItm.getList(s_Property);
+  if (pl.size() > 0) then
+    hasSequence := TypeHasSequence(typItm,typeCategory);
+  hasXsdAny := False;
+  hasXsdAnyAtt := False;
+  if (typeCategory = tcComplexContent) then
+    begin
+    hasXsdAny := FindTag(typItm,Format('%s#%s',[s_xs,s_any]),xsdAnyString);
+    if hasXsdAny then
+      begin
+      if not hasSequence then
+        hasSequence := True;
+      end;
+    hasXsdAnyAtt := FindTag(typItm,Format('%s#%s',[s_xs,s_anyAttribute]),xsdAnyAttString);
+    end;
+
+  for i := 0 to pl.size() -1 do
+    ProcessProperty(typItm,PC,pl.getDataObject(i));
+{
+if hasXsdAny then
+    ProcessXsdAny(sqcNode,xsdAnyString);
+  if hasXsdAnyAtt then
+    ProcessXsdAnyAttribute(cplxNode,xsdAnyAttString);
+}end;
+
+function TCustomPasGenerator.GetUnitName: String;
+begin
+  Result:=FUnitName;
+end;
+
+procedure TCustomPasGenerator.SetUnitname(const AValue: String);
+begin
+  FUnitName:=AValue;
+end;
+
+procedure TCustomPasGenerator.StartInterface;
+begin
+end;
+
+{ TPasGenerator }
+
+
+procedure TPasGenerator.Prepare(ASymTable, AModule : ISDODataObject);
+begin
+  inherited Prepare(ASymTable, AModule);
+//  unitExternalName := AModule.getString(s_namespace);
+end;
+
+
+  
+end.

+ 3287 - 0
packages/fcl-sdo/src/base/sdo.pas

@@ -0,0 +1,3287 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements basic SDO definitions
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo;
+
+interface
+uses
+  SysUtils, Classes, Types,
+  sdo_types, sdo_linked_list, sdo_date_utils;
+
+const
+  sdo_namespace = 'commonj.sdo';
+
+type
+
+  TSDOTypeKind = (
+    //OtherTypes , // for 'unknown type; - all data objects'
+    BooleanType,
+    ByteType,
+{$IFDEF HAS_SDO_BYTES}
+    BytesType,
+{$ENDIF HAS_SDO_BYTES}
+    ChangeSummaryType,
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType,
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType,
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType,
+    //DayType,
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType,
+{$ENDIF HAS_SDO_DOUBLE}
+    //DurationType,
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType,
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType,
+{$IFDEF HAS_SDO_LONG}
+    LongType,
+{$ENDIF HAS_SDO_LONG}
+    //MonthType,
+    //MonthDayType,
+    ObjectType,
+{$IFDEF HAS_SDO_SHORT}
+    ShortType,
+{$ENDIF HAS_SDO_SHORT}
+    StringType
+    //TimeType,
+    //UriType,
+    //YearType,
+    //YearMonthType,
+    //YearMonthDayType
+  );
+
+const
+  DateType = DateTimeType;
+  IntType = IntegerType;
+  StringsType = StringType;
+  
+  SDOTypeDefaultTypeNames : array[TSDOTypeKind] of string = (
+    //OtherTypes , // for 'unknown type; - all data objects'
+    'Boolean',
+    'Byte',
+{$IFDEF HAS_SDO_BYTES}
+    'Bytes',
+{$ENDIF HAS_SDO_BYTES}
+    'ChangeSummary',
+{$IFDEF HAS_SDO_CHAR}
+    'Character',
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    'Currency',
+{$ENDIF HAS_SDO_CURRENCY}
+    'DateTime',
+{$IFDEF HAS_SDO_DOUBLE}
+    'Double',
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    'Float',
+{$ENDIF HAS_SDO_FLOAT}
+    'Integer',
+{$IFDEF HAS_SDO_LONG}
+    'Long',
+{$ENDIF HAS_SDO_LONG}
+    'Object',
+{$IFDEF HAS_SDO_SHORT}
+    'Short',
+{$ENDIF HAS_SDO_SHORT}
+    'String'
+  );
+  SDODataTypeKinds = [Low(TSDOTypeKind)..High(TSDOTypeKind)] - [ ChangeSummaryType, ObjectType ];
+
+type
+
+  PSDOBoolean = ^TSDOBoolean;
+{$IFDEF HAS_SDO_BYTES}
+  PSDOBytes = ^TSDOBytes;
+  PPSDOBytes = ^PSDOBytes;
+{$ENDIF HAS_SDO_BYTES}
+  PPSDOChangeSummary = ^PSDOChangeSummary;
+  PSDOChangeSummary = ^ISDOChangeSummary;
+{$IFDEF HAS_SDO_CHAR}
+  PSDOChar = ^TSDOChar;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  PSDOCurrency = ^TSDOCurrency;
+{$ENDIF HAS_SDO_CURRENCY}
+  PSDODate = ^TSDODate;
+  PSDODateTime = ^TSDODateTime;
+{$IFDEF HAS_SDO_DOUBLE}
+  PSDODouble = ^TSDODouble;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  PSDOFloat = ^TSDOFloat;
+{$ENDIF HAS_SDO_FLOAT}
+  PSDOInteger = ^TSDOInteger;
+{$IFDEF HAS_SDO_LONG}
+  PSDOLong = ^TSDOLong;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  PSDOShort = ^TSDOShort;
+{$ENDIF HAS_SDO_SHORT}
+  PPSDOString = ^PSDOString;
+  PSDOString = ^TSDOString;
+  PSDODataObject = ^ISDODataObject;
+  PPSDODataObject = ^PSDODataObject;
+  PPSDODataObjectList = ^PSDODataObjectList;
+  PSDODataObjectList = ^ISDODataObjectList;
+
+  TSDOFieldBuffer = Pointer;
+  TSDOBoolean = Boolean;
+  TSDOByte = Byte;
+  TSDOBytes = TByteDynArray;
+{$IFDEF HAS_SDO_CHAR}
+  {$IFDEF USE_UNICODE}
+    TSDOChar = WideChar;
+  {$ELSE USE_UNICODE}
+    TSDOChar = Char;
+  {$ENDIF USE_UNICODE}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  TSDOCurrency = Currency;
+{$ENDIF HAS_SDO_CURRENCY}
+  TSDODateTime = TDateTimeRec;
+  TSDODate = TSDODateTime;
+{$IFDEF HAS_SDO_DOUBLE}
+  TSDODouble = Double;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  TSDOFloat = Single;
+{$ENDIF HAS_SDO_FLOAT}  
+  TSDOInteger = Integer;
+{$IFDEF HAS_SDO_LONG}  
+  TSDOLong = Int64;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  TSDOShort = SmallInt;
+{$ENDIF HAS_SDO_SHORT}
+{$IFDEF USE_UNICODE}
+  TSDOString = UnicodeString;
+{$ELSE USE_UNICODE}
+  TSDOString = AnsiString;
+{$ENDIF USE_UNICODE}
+  TSDOVariant = Variant;
+
+  TChangeType = ( ctUndefined, ctCreate, ctChange, ctDelete );
+  TTypeFlag = ( tfIsSequenced, tfIsOpen, tfIsAbstract, tfIsDataType );
+  TTypeFlags = set of TTypeFlag;
+  TPropertyFlag = (
+    pfIsMany, pfIsReadOnly, pfIsContainment, pfIsNotNullable,
+    //This is an extension
+    pfIsAttribute
+  );
+  TPropertyFlags = set of TPropertyFlag;
+  TSerializerOption = (soExcludeSchema);
+  TSerializerOptions = set of TSerializerOption;
+
+  ESDOException = class(Exception)
+  end;
+
+  ESDONotImplementedException = class(ESDOException)
+  end;
+
+  ESDOUnsupportedOperationException = class(ESDOException)
+  private
+    FOperation: string;
+  public
+    constructor Create(const AOperation : string);
+    property Operation : string read FOperation write FOperation;
+  end;
+    ESDOInvalidStateOperationException = class(ESDOUnsupportedOperationException) end;
+
+  ESDOPropertyNotFoundException = class(ESDOException)
+  private
+    FPropertyName: string;
+  public
+    constructor Create(const APropName : string);
+    property PropertyName : string read FPropertyName write FPropertyName;
+  end;
+
+  ESDOIllegalArgumentException = class(ESDOException)
+  private
+    FArgumentName: string;
+  public
+    constructor Create(const AArgumentName : string);
+    property ArgumentName : string read FArgumentName write FArgumentName;
+  end;
+    ESDOCycleContainmentException = class(ESDOIllegalArgumentException) end;
+    //ESDOPropertyNotBelongToObjectException = class(ESDOIllegalArgumentException) end;
+
+  ESDOIndexOutOfRangeException = class(ESDOException)
+  private
+    FValue: Integer;
+  public
+    constructor Create(const AValue : Integer);
+    property Value : Integer read FValue write FValue;
+  end;
+
+  ESDOTypeNotFoundException = class(ESDOException)
+  private
+    FName: string;
+  public
+    constructor Create(const AName : string);
+    property Name : string read FName write FName;
+  end;
+
+  ESDOCircularDependencyTypeException = class(ESDOIllegalArgumentException)
+  private
+    FTypeName: string;
+    FPropertyType: string;
+    FPropertyName: string;
+  public
+    constructor Create(
+      const ATypeName,
+            APropertyName,
+            APropertyType : string
+    );
+    property TypeName : string read FTypeName write FTypeName;
+    property PropertyName : string read FPropertyName write FPropertyName;
+    property PropertyType : string read FPropertyType write FPropertyType;
+  end;
+
+  ESDOIncompleteTypeException = class(ESDOException)
+  private
+    FTypeName: string;
+  public
+    constructor Create(const ATypeName : string);
+    property TypeName : string read FTypeName write FTypeName;
+  end;
+    ESDOAbstractTypeException = class(ESDOIncompleteTypeException) end;
+
+  ESDODuplicatedItemException = class(ESDOException)
+  private
+    FName: string;
+  public
+    constructor Create(const AName : string);
+    property Name : string read FName write FName;
+  end;
+
+  ESDOInvalidConversionException = class(ESDOException)
+  private
+    FName: string;
+  public
+    constructor Create(const AName : string);
+    property Name : string read FName write FName;
+  end;
+
+  ESDOInvalidPathException = class(ESDOException)
+  private
+    FPath: string;
+  public
+    constructor Create(const APath : string);
+    property Path : string read FPath write FPath;
+  end;
+
+  ISDOType = interface;
+  ISDOProperty = interface;
+  ISDOPropertyList = interface;
+  ISDODataObject = interface;
+  ISDODataObjectList = interface;
+  ISDOChangeSummary = interface;
+  ISDODataFactory = interface;
+
+  ISDOType = interface
+    ['{76F00A3A-A6F8-4D78-8514-570207853453}']
+	{  getName returns the name of the type
+     *
+	 * This method returns a const char* name of the type.
+	 }
+    function getName() : string;
+
+	{  getAlias returns the n'th alias
+     *
+	 * This method returns a const char* corresponding to the
+	 * alias at index n of the list of aliases. Use getAliasCount to
+	 * discover the size of the list.
+	 }
+	  function getAlias(const AIndex : PtrInt) : string;
+
+	{  getAliasCount  returns the number of aliases
+     *
+	 * This method returns the number of aliases for this type
+	 }
+	  function getAliasCount() : PtrInt;
+
+	{  getBaseType returns the base if there is one
+	 *
+	 * This method returns a const Type* corresponding to the
+	 * base Type for this type. The base type is the one which
+	 * this type inherits from.
+	 }
+	  function getBaseType() : ISDOType;
+
+	{  getURI  returns the URI for this type
+	 *
+	 * This method returns the URI for this type. The URI may be
+	 * null.
+	 }
+	  function getURI() : string;
+
+
+	{  getProperties returns a list of properties for this type
+	 *
+	 * This method returns the list of properties for this type.
+	 * Instances of open types may have more properties than appear
+	 * in this list.
+	 * See the propertylist API.
+	 }
+    function getProperties() : ISDOPropertyList;
+
+	{  getProperty returns a property for this type
+	 *
+	 * This method returns a property, by index or by name
+	 }
+   function getProperty(const APropertyName : string) : ISDOProperty;overload;
+   function getProperty(const APropertyIndex : Integer) : ISDOProperty;overload;
+
+	{  getPropertyIndex returns an index
+	 *
+	 * This method returns a property index for a named property
+	 }
+	  function getPropertyIndex(const APropertyName : string) : Integer;
+
+	{  isDataObjectType true if not a DataType
+	 *
+	 * This method returns true if the type is not a DataType, and is therefore
+	 * a DataObjectType with properties.
+	 }
+	  function isDataObjectType() : Boolean;
+
+
+	{  isSequencedType true if the type is sequenced
+	 *
+	 * This method returns true if the type is sequenced, and is therefore
+	 * objects of this type can be manipulate via their sequence interface.
+	 }
+	  function isSequencedType() : Boolean;
+
+
+	{  isOpenType true if the type is open
+	 *
+	 * Normal types have a predefined list of properties. Trying to set
+	 * properties which do not exist will cause an exception to be thrown.
+	 * Open types, on the other hand, may have properties added to their
+	 * instances runtime. These properties get added silently when setting a
+	 * property value for a property which does not exist.
+	 * Different instances of these objects may have different lists of
+	 * open properties.
+	 }
+	  function isOpenType() : Boolean;
+
+	{  isAbstractType true if the type is not instantiable.
+	 *
+	 * An abstract type may not be instantiated. It is useful only as
+	 * a base type to some other non-abstract type.
+	 }
+	  function isAbstractType() : Boolean;
+
+	{  isDataType true if the type is not an object.
+	 *
+	 * A DataType is anything which is not a DataObjectType. This method
+	 * is the opposite of isDataObjectType().
+	 }
+    function isDataType() : Boolean;
+
+	{  isChangeSummaryType true if the type is a change summary.
+	 *
+	 * There is only one type called ChangeSummary. This method serves
+	 * no purpose in the C++ implementation.
+	 }
+    function isChangeSummaryType() : Boolean;
+
+	{  getTypeEnum gets the enum for this type.
+	 *
+	 * Each DataType has a defined value in the list of Types.
+	 }
+    function getTypeEnum() : TSDOTypeKind;
+
+	{  equals compares uri and name.
+	 *
+	 * The types are equal if the URI and Name are equal.
+	 }
+    function equals(const AOther : ISDOType) : Boolean;
+
+    function getFlags() : TTypeFlags;
+
+    //Implementation extension
+    function getOwner() : ISDODataFactory;
+  end;
+
+
+  ISDOProperty = interface
+    ['{F4649B56-366D-42CC-B818-46E2577E87FD}']
+	{  getName gets the name of the property
+	 *
+	 * Returns the name of the property.
+	 }
+ 	  function getName() : string;
+  
+	{  getAlias returns the n'th alias
+     *
+	 * This method returns a const char* corresponding to the
+	 * alias at index n of the list of aliases. Use getAliasCount to 
+	 * discover the size of the list.
+	 }
+    function getAlias(const AIndex : Integer) : string;
+
+	{  getAliasCount  returns the number of aliases
+     *
+	 * This method returns the number of aliases for this type
+	 }
+    function getAliasCount() : Integer;
+
+	{  getType returns the type of this property
+	 *
+	 * This method returns the type, which may be a DataType or a
+	 * DataObjectType
+	 }
+    function getType() : ISDOType;
+
+	{  getTypeEnum gets the enum for this type. 
+	 *
+	 * Each DataType has a defined value in the list of Types.
+	 }
+    function getTypeEnum() : TSDOTypeKind;
+
+ 	{  isMany is true if the property is a list
+	 *
+	 * IsMany returns true if this property represents a list of
+	 * values, and should be accessed via the getList DataObjectAPI.
+	 }
+    function isMany() : Boolean;
+
+ 	{  isContainment is true if the property value is contained
+	 *
+	 * IsContainment returns true if this property represents a DataObjectType,
+	 * and that DataObjectType is contained. I.E the property value is not a pointer
+	 * to a DataObject somewhere else in the graph, it is an actual value.
+	 }
+   function isContainment() : Boolean;
+
+ 	{  isReference is true if the property value is not contained 
+	 *
+	 * IsReference returns true if this property represents a DataObjectType,
+	 * and that DataObjectType is not contained. I.E the property value is a pointer
+	 * to a DataObject somewhere else in the graph not an actual value.
+	 }
+   function isReference() : Boolean;
+  
+	{  getContainingType give the type which holds this property.
+	 *
+	 * Although many types may have a property of the same name, any given 
+	 * instance of a property belongs to only one type.
+	 * This method returns the type which holds this proeprty.
+	 }
+   function getContainingType() : ISDOType;
+
+
+	{  isReadOnly returns true if the property is unmodifiable.
+	 *
+	 * NOT IMPLEMENTED
+     * 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.
+	 }
+   function isReadOnly() : Boolean;
+
+	{  getOpposite  returns the opposite property or zero.
+	 *
+	 * NOT IMPLEMENTED
+	 }
+   function getOpposite() : ISDOProperty;
+
+	{  isDefaulted is true if a default has been set.
+	 *
+	 * A property value may be set or unset. If unset, requests to the
+	 * data object for the value will return a default if there is one.
+	 * If the property is not defaulted, an un specified value will be
+	 * returned. (Thism value will probably be zero).
+	 }
+
+	  function isDefaulted() : Boolean ;
+
+	{  setDefault sets the right sort of default.
+	 *
+	 * The many overrides of this method allow the setting
+	 * of a default value for any DataType property.
+	 *}
+    procedure setDefault(const AValue : TSDOBoolean);overload;
+    procedure setDefault(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure setDefault(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setDefault(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setDefaultCurrency(const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDefault(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDefault(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setDefault(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setDefault(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setDefault(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setDefault(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setDefault(const AValue : TSDOString);overload;
+	{  getDefault gets the right sort of default.
+	 *
+	 * The many overrides of this method allow the getting
+	 * of a default value for any DataType property.
+	 }
+    function getStringDefault() : TSDOString;
+{$IFDEF HAS_SDO_BYTES}
+    function getBytesDefault() : TSDOBytes;
+{$ENDIF HAS_SDO_BYTES}    
+    function getBooleanDefault() : TSDOBoolean;
+    function getByteDefault() : TSDOByte;
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacterDefault() : TSDOChar;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrencyDefault() : TSDOCurrency;
+{$ENDIF HAS_SDO_CURRENCY}
+    function getDateDefault() : TSDODate;
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDoubleDefault() : TSDODouble;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloatDefault() : TSDOFloat;
+{$ENDIF HAS_SDO_FLOAT}
+    function getIntegerDefault() : TSDOInteger;
+{$IFDEF HAS_SDO_LONG}
+    function getLongDefault() : TSDOLong;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function getShortDefault() : TSDOShort;
+{$ENDIF HAS_SDO_SHORT}
+
+    function isNullable() : Boolean;
+    //Extensions ...
+    function isAttribute() : Boolean;
+  end;
+
+  ISDOPropertyList = interface
+    ['{1253EA5C-D19C-434E-ADE5-A7639D582102}']
+    function getCount() : Integer;
+    function getItem(const AIndex : Integer) : ISDOProperty;
+    function find(const APropertyName : string) : ISDOProperty;
+    function getIndex(const APropertyName : string) : Integer;
+  end;
+
+  ISDOTypeList = interface
+    ['{7A07FC8B-FA82-41AF-87F3-8BE3C2F228E1}']
+    function getCount() : Integer;
+    function getItem(const AIndex : Integer) : ISDOType;
+    function find(const AUri, AName : string) : ISDOType;
+    function getIndex(const AUri, AName : string) : Integer;
+  end;
+
+  ISDODataFactory = interface
+    ['{8898CB64-1E83-464D-AE50-4DDB6D7770FE}']
+		{
+		 *  clone copies a data factory
+		 *
+		 * Copy the data factory, and return a new data factory which
+		 * has the same properties and types, but is still able to have
+		 * new types added to it.
+		 }
+
+		//SDO_API virtual DataFactoryPtr clone();
+
+		{
+		 *  DataFactory::create creates a data object.
+		 *
+		 * Create a data object based on the type specified as a parameter
+		 * Once a data object has been created by this factory, the metadata
+		 * (types and properties) may no longer be altered.
+		 }
+    function CreateNew(const AType : ISDOType) : ISDODataObject;overload;
+    function CreateNew(const AUri, ATypeName : string) : ISDODataObject;overload;
+
+		{
+		 *  DataFactory::getType gets a type back from the factory.
+		 *
+		 * Get a type as specified in the data factory. Useful for creating
+		 * data objects or querying properties.
+		 }
+    function getType(const AUri, ATypeName : string) : ISDOType;
+
+		{
+		 *  DataFactory::getTypes gets a list of types back from the factory.
+		 *
+		 * Get all the types available within this data factory. Useful for
+		 * validating whether a data object is of the correct type to be
+		 * usable.
+		 }
+
+		function getTypes() : ISDOTypeList;
+
+		{
+		 *  DataFactory::addType adds a type definition.
+		 *
+		 * Add a type defintion to the factory. (Properties may be added later).
+		 * The type is defined by its uri and name.
+		 * -# The type may be sequenced - and therefore work with a sequence API.
+		 * -# The type may be open, indicating that it may have extra properties
+		 * added at runtime.
+		 * -# The type may be abstract, so the data factory will not permit creation
+		 * of instances.
+		 * -# The type may be a data type, indicating that is will not have properties.
+		 * The Type may inherit from another type, but that is specified later with a
+		 * call to setBaseType().
+		 }
+    procedure AddType(
+      const AUri,
+            ATypeName : string;
+      const AFlags    : TTypeFlags
+    );
+
+		{
+		 *  DataFactory::setBaseType allows inheritance
+		 *
+		 * The type specified second in the parameters becomes the basetype
+		 * of the first parameter.
+		 * The second type will have all the properties of its baser type, followed
+		 * by any additional properties of its own. The property indices of the properties
+		 * of the subclass will begin at one more than the total number of
+		 * properties of the supertype
+		 * This relationship is fixed when the first data object of any type is
+		 * created by the factory. Up to that point the base type may be changed.
+		 *
+		 }
+    procedure setBaseType(const AType, ABase : ISDOType);overload;
+    procedure setBaseType(
+      const ATypeURI, ATypeName,
+            ABaseURI, ABaseName : string
+    );overload;
+
+		{
+		 *  DataFactory::setAlias sets an alternative name
+		 *
+		 * A Type may be known to the data factory by several different names.
+		 * This method adds a new name for an existing property.
+		 *
+		 }
+    procedure setAlias(const ATypeURI, ATypeName, AAlias : string);overload;
+
+		{
+		 *  DataFactory::addPropertyToType adds properties
+		 *
+		 * The various addPropertyToType methods add a property to an
+		 * existing type in the factory, specifying the name of the new property,
+		 * and the type of the new property - which must also be an existing type
+		 * in this factory.
+		 * -# The new property may be many-valued - so it will be a list of values.
+		 * -# The property may be read-only , and may not be altered by user code -
+		 * However the value may be changed by data access service code.
+		 * -# The property may be containment.
+		 * The type of a property may be DataType, or DataObjectType (see Types).
+		 * If the property is a DataType, then the actual value of the property is held
+		 * within the data object containing the property.
+		 * If the property is a DataObjectType, it may be containment, or reference.
+		 * Containment indicates that the value of the property is contained in the
+		 * data object, whilst reference indicates that the property is only a pointer to
+		 * a value somewhere else in the data graph.
+		 *
+		 }
+    procedure addProperty(
+      const ATypeURI, ATypeName,
+            APropName, APropTypeUri, APropTypeName : string;
+      const AFlags : TPropertyFlags
+    );overload;
+    procedure addProperty(
+      const ATypeURI, ATypeName,
+            APropName            : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );overload;
+    procedure addProperty(
+      const AType     : ISDOType;
+      const APropName : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );overload;
+    procedure addProperty(
+      const AType : ISDOType;
+      const APropName, APropTypeUri, APropTypeName : string;
+      const AFlags : TPropertyFlags
+    );overload;
+
+
+		{
+		 *  DataFactory::setAlias sets a property alias name
+		 *
+		 * A property, like a type, may be known to the factory by several
+		 * names.
+		 }
+    procedure setAlias(const ATypeUri, ATypeName, APropName, AAlias : string);overload;
+
+    { for open Type support - this is an implementation extension!
+        the "ADataObject" parameter must be of open type
+    }
+    procedure addProperty(
+            ADataObject : ISDODataObject;
+      const APropName : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );overload;
+
+    //Implementation extension
+    function CreateList(AType : ISDOType) : ISDODataObjectList;overload;
+    function CreateList(const AUri, ATypeName : string) : ISDODataObjectList;overload;
+  end;
+
+
+  ISDODataObject = interface
+    ['{74EFD05B-438F-4193-8AF0-3E28195A034B}']
+
+    {  getPropertyIndex gets the unique index of a property
+     *
+       * A property of a data object has a unique index associated with it.
+     * This method gets a property index for this object from the property,
+     * or throw SDOPropertyNotFoundException if the property is not part
+     * of this data object.
+     }
+    function getPropertyIndex(const AProperty : ISDOProperty) : PtrInt;
+
+      {  getInstanceProperties gets the props of the current object.
+     *
+     * 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
+       * Returns the list of Properties currently used in this DataObject.
+     }
+    function getInstanceProperties() : ISDOPropertyList;
+
+    {
+     * These are just like getType().getProperty(), but may return
+     * values other than the property list for open types.
+     }
+    function getProperty(const AIndex : PtrUInt) : ISDOProperty;overload;
+    function getProperty(const AProp : string) : ISDOProperty;overload;
+
+    {  getContainer get the containing object
+     *
+     * Returns the containing data object
+     * or 0 if there is no container.
+     }
+    function getContainer() : ISDODataObject;
+
+    {  getContainmentProperty returns the property containing this object
+     *
+     *  Return the Property of the data object containing this data object
+     *  or throw an SDOPropertyNotFoundException if there is no container.
+     }
+    function getContainmentProperty() : ISDOProperty;
+
+    {  getType  returns the data object's type.
+     *
+     * getType returns the data object's type.
+     * The type defines the properties available for reflective access.
+       }
+    function getType() : ISDOType;
+
+    {  getTypeEnum returns an enumerator for the type
+     *
+     * Returns an enumerator for the type for easy switching on basic types.
+     * The enumerator is part of the Type class
+     }
+    function getTypeEnum() : TSDOTypeKind;
+
+    {  getDataObject returns a data object by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getDataObject(const APath : string) : ISDODataObject; overload;
+    function getDataObject(const APropertyIndex : PtrUInt) : ISDODataObject; overload;
+    function getDataObject(const AProperty : ISDOProperty) : ISDODataObject; overload;
+
+    {  setDataObject sets a value by path, index or property
+     *
+     * Sets a property of either this object or an object reachable from it,
+     * as identified by the specified path,
+     * to the specified value.
+     }
+    procedure setDataObject(const APath : string; AValue : ISDODataObject); overload;
+    procedure setDataObject(const APropertyIndex : PtrUInt; AValue : ISDODataObject); overload;
+    procedure setDataObject(const AProperty : ISDOProperty; AValue : ISDODataObject); overload;
+
+    {  getBoolean returns a TSDOBoolean by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getBoolean(const APath : string) : TSDOBoolean; overload;
+    function getBoolean(const APropertyIndex : PtrUInt) : TSDOBoolean; overload;
+    function getBoolean(const AProperty : ISDOProperty) : TSDOBoolean; overload;
+
+    procedure setBoolean(const APath : string; const AValue : TSDOBoolean); overload;
+    procedure setBoolean(const APropertyIndex : PtrUInt; const AValue : TSDOBoolean); overload;
+    procedure setBoolean(const AProperty : ISDOProperty; const AValue : TSDOBoolean); overload;
+
+    {  getByte returns a char by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getByte(const APath : string) : TSDOByte;overload;
+    function getByte(const APropertyIndex : PtrUInt) : TSDOByte;overload;
+    function getByte(const AProperty : ISDOProperty) : TSDOByte;overload;
+
+    procedure setByte(const APath : string; const AValue : TSDOByte);overload;
+    procedure setByte(const APropertyIndex : PtrUInt; const AValue : TSDOByte);overload;
+    procedure setByte(const AProperty : ISDOProperty; const AValue : TSDOByte);overload;
+
+{$IFDEF HAS_SDO_CHAR}
+    {  getCharacter returns a wchar_t by path, index or property
+     *
+     * Returns the value of a property of either this object or an object
+       * reachable from it, as identified by the specified path.
+     }
+    function getCharacter(const APath : string) : TSDOChar;overload;
+    function getCharacter(const APropertyIndex : PtrUInt) : TSDOChar;overload;
+    function getCharacter(const AProperty : ISDOProperty) : TSDOChar;overload;
+
+    procedure setCharacter(const APath : string; const AValue : TSDOChar);overload;
+    procedure setCharacter(const APropertyIndex : PtrUInt; const AValue : TSDOChar);overload;
+    procedure setCharacter(const AProperty : ISDOProperty; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency(const APath : string) : TSDOCurrency;overload;
+    function getCurrency(const APropertyIndex : PtrUInt) : TSDOCurrency;overload;
+    function getCurrency(const AProperty : ISDOProperty) : TSDOCurrency;overload;
+
+    procedure setCurrency(const APath : string; const AValue : TSDOCurrency);overload;
+    procedure setCurrency(const APropertyIndex : PtrUInt; const AValue : TSDOCurrency);overload;
+    procedure setCurrency(const AProperty : ISDOProperty; const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_BYTES}
+    {  getBytes returns a byte buffer
+     *
+     * A DataObject of type Bytes holds an array of bytes as its value. These
+     * methods transfer the contents of that buffer into an array of chars allocated
+     * by the users program. The return value is the number of bytes actually 
+     * copied.
+     * The byte array is not necessarily null terminated. If a null terminated
+     * C style string is required, then getCString is an alternative.
+     * The third paarameter is the length of the allocated buffer, which may be more
+     * than the length of the byte array. If the length specified is less than the
+     * length of the byte array, then only a portion of the 
+     * byte array is returned.
+       }
+    function getBytes(const APath : string) : TSDOBytes;overload;
+    function getBytes(const APropertyIndex : PtrUInt) : TSDOBytes;overload;
+    function getBytes(const AProperty : ISDOProperty) : TSDOBytes;overload;
+
+    procedure setBytes(const APath : string; AValue : TSDOBytes);overload;
+    procedure setBytes(const APropertyIndex : PtrUInt; AValue : TSDOBytes);overload;
+    procedure setBytes(const AProperty : ISDOProperty; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+
+    {  getString returns a wide char buffer
+     *
+     * A DataObject of type String holds an array of wide characters as its value. These
+     * methods transfer the contents of that buffer into an array of wchar_t allocated
+     * by the users program. The return value is the number of wchar_t actually 
+     * copied.
+     * The array is not necessarily null terminated. 
+     * The third paarameter is the length of the allocated buffer, which may be more
+     * than the length of the array. If the length specified is less than the
+     * length of the array, then only a portion of the array is returned.
+       }
+    function getString(const APath : string) : TSDOString;overload;
+    function getString(const APropertyIndex : PtrUInt) : TSDOString;overload;
+    function getString(const AProperty : ISDOProperty) : TSDOString;overload;
+
+    procedure setString(const APath : string; const AValue : TSDOString);overload;
+    procedure setString(const APropertyIndex : PtrUInt; const AValue : TSDOString);overload;
+    procedure setString(const AProperty : ISDOProperty; const AValue : TSDOString);overload;
+
+    { Extension : Variant support }
+    function getVariant(const APath : string) : TSDOVariant;overload;
+    function getVariant(const APropertyIndex : PtrUInt) : TSDOVariant;overload;
+    function getVariant(const AProperty : ISDOProperty) : TSDOVariant;overload;
+
+    procedure setVariant(const APath : string; const AValue : TSDOVariant);overload;
+    procedure setVariant(const APropertyIndex : PtrUInt; const AValue : TSDOVariant);overload;
+    procedure setVariant(const AProperty : ISDOProperty; const AValue : TSDOVariant);overload;
+
+
+    {  getDate returns an SDODate by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getDate(const APath : string) : TSDODate;overload;
+    function getDate(const APropertyIndex : PtrUInt) : TSDODate;overload;
+    function getDate(const AProperty : ISDOProperty) : TSDODate;overload;
+
+    procedure setDate(const APath : string; const AValue : TSDODate);overload;
+    procedure setDate(const APropertyIndex : PtrUInt; const AValue : TSDODate);overload;
+    procedure setDate(const AProperty : ISDOProperty; const AValue : TSDODate);overload;
+
+{$IFDEF HAS_SDO_DOUBLE}
+    {  getDouble returns a long double by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getDouble(const APath : string) : TSDODouble;overload;
+    function getDouble(const APropertyIndex : PtrUInt) : TSDODouble;overload;
+    function getDouble(const AProperty : ISDOProperty) : TSDODouble;overload;
+
+    procedure setDouble(const APath : string; const AValue : TSDODouble);overload;
+    procedure setDouble(const APropertyIndex : PtrUInt; const AValue : TSDODouble);overload;
+    procedure setDouble(const AProperty : ISDOProperty; const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+    {  getFloat returns a float by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getFloat(const APath : string) : TSDOFloat;overload;
+    function getFloat(const APropertyIndex : PtrUInt) : TSDOFloat;overload;
+    function getFloat(const AProperty : ISDOProperty) : TSDOFloat;overload;
+
+    procedure setFloat(const APath : string; const AValue : TSDOFloat);overload;
+    procedure setFloat(const APropertyIndex : PtrUInt; const AValue : TSDOFloat);overload;
+    procedure setFloat(const AProperty : ISDOProperty; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+
+    {  getInteger returns a long by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getInteger(const APath : string) : TSDOInteger;overload;
+    function getInteger(const APropertyIndex : PtrUInt) : TSDOInteger;overload;
+    function getInteger(const AProperty : ISDOProperty) : TSDOInteger;overload;
+
+    procedure setInteger(const APath : string; const AValue : TSDOInteger);overload;
+    procedure setInteger(const APropertyIndex : PtrUInt; const AValue : TSDOInteger);overload;
+    procedure setInteger(const AProperty : ISDOProperty; const AValue : TSDOInteger);overload;
+
+    {  getLong returns a int64_t by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getLong(const APath : string) : TSDOLong;overload;
+    function getLong(const APropertyIndex : PtrUInt) : TSDOLong;overload;
+    function getLong(const AProperty : ISDOProperty) : TSDOLong;overload;
+
+    procedure setLong(const APath : string; const AValue : TSDOLong);overload;
+    procedure setLong(const APropertyIndex : PtrUInt; const AValue : TSDOLong);overload;
+    procedure setLong(const AProperty : ISDOProperty; const AValue : TSDOLong);overload;
+
+    {  getShort returns a short by path, index or property
+     *
+     * Returns the value of a property of either this object or an object 
+       * reachable from it, as identified by the specified path.
+     }
+    function getShort(const APath : string) : TSDOShort;overload;
+    function getShort(const APropertyIndex : PtrUInt) : TSDOShort;overload;
+    function getShort(const AProperty : ISDOProperty) : TSDOShort;overload;
+
+    procedure setShort(const APath : string; const AValue : TSDOShort);overload;
+    procedure setShort(const APropertyIndex : PtrUInt; const AValue : TSDOShort);overload;
+    procedure setShort(const AProperty : ISDOProperty; const AValue : TSDOShort);overload;
+
+    {  setNull sets a data object value to null.
+     *
+     * A DataObjectType or DataType value may be set or unset. If it is set, then
+     * it may have a value, or it may be set to null. A distinction is drawn between
+     * being unset, having the default value, being set and being null.
+     * When the value of an integer (for example) is returned as zero, it could have
+     * been set to zero, or it could be null. Use isNull() to verify.
+       }
+    procedure setNull(const APath : string);overload;
+    procedure setNull(const APropertyIndex : PtrUInt);overload;
+    procedure setNull(const AProperty : ISDOProperty);overload;
+
+    function isNull(const APath : string) : Boolean;overload;
+    function isNull(const APropertyIndex : PtrUInt) : Boolean;overload;
+    function isNull(const AProperty : ISDOProperty) : Boolean;overload;
+
+
+    {  isSet test whether the value has been set
+     *
+     * 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.
+     }
+    function isSet(const APath : string) : Boolean;overload;
+    function isSet(const APropertyIndex : PtrUInt) : Boolean;overload;
+    function isSet(const AProperty : ISDOProperty) : Boolean;overload;
+
+
+    { unset unsets a value previously set.
+     *
+     * unsets a property of either this object or an object reachable 
+     * from it, as identified by the specified path.
+     }
+
+    procedure unset(const APath : string);overload;
+    procedure unset(const APropertyIndex : PtrUInt);overload;
+    procedure unset(const AProperty : ISDOProperty);overload;
+
+    { setUserData sets a reserved field in the data object.
+     *
+     * Each data object has precisely one 32 bit slot available to 
+     * be used by applications. This is not part of the data, its
+     * just a place to store anything for later retrieval. 
+     }
+
+    {virtual SDO_API void setUserData(const char* path,void* value) = 0;
+    virtual SDO_API void setUserData(unsigned int propertyIndex, void* value) = 0;
+    virtual SDO_API void setUserData(const Property& property, void* value) = 0;
+    virtual SDO_API void setUserData(void* value) = 0;
+    virtual SDO_API void* getUserData(const char* path) = 0;
+    virtual SDO_API void* getUserData(unsigned int propertyIndex) = 0;
+    virtual SDO_API void* getUserData(const Property& property) = 0;
+    virtual SDO_API void* getUserData() = 0;
+    }
+
+    {  getSequence returns the sequence for a data object
+     *
+     * Returns the value of a Sequence property identified by 
+     * the specified path. See Sequence.
+     }
+
+    {virtual SDO_API SequencePtr getSequence() = 0;
+    virtual SDO_API SequencePtr getSequence(const char* path) = 0;
+    virtual SDO_API SequencePtr getSequence(unsigned int propertyIndex) = 0;
+    virtual SDO_API SequencePtr getSequence(const Property& property) = 0;
+    }
+
+
+    {  createDataObject creates a data object value
+     *
+     * Returns a new data object contained by this object using the 
+     * specified property,which must be a containment property.
+     * The type of the created object is the declared type
+     * of the specified property.
+     * If the property is many valued, this method adds an element to the
+     * list, otherwise it sets the value, removing any old value.
+     }
+    function createDataObject(const APath : string) : ISDODataObject; overload;
+    function createDataObject(const APropertyIndex : PtrUInt) : ISDODataObject; overload;
+    function createDataObject(const AProperty : ISDOProperty) : ISDODataObject; overload;
+
+    {  detach detaches an object from the graph
+     *
+     * This method removes the current data object from the graph, but does
+     * not destroy it. The DataObject can be re-attached to the graph later.
+     }
+
+    //procedure detach();
+
+    {  clear unsets all the properties
+     *
+     * This method unsets all the properties, and deletes all the data object 
+     * propertiy values from this data object.
+     }
+ 
+    procedure clear();
+
+
+      {  getList gets the value of a many-valued property
+     *
+     * Many valued properties are returned as lists of DataObjects.
+     * These lists may contain primitives or data objects, but they behave
+     * like data objects.
+     * Getting a many valued integer consists of getting the list, then
+     * using the DataObjectList API to getInteger() for each list element.
+     }
+    function getList(const APath : string) : ISDODataObjectList; overload;
+    function getList(const APropertyIndex : PtrUInt) : ISDODataObjectList; overload;
+    function getList(const AProperty : ISDOProperty) : ISDODataObjectList; overload;
+    {
+    virtual DataObjectList& getList() = 0;
+    }
+
+    {  getChangeSummary get the applicable change summary
+     *
+     * This method gets the applicable change summary for a data object.
+     * The summary is not necessarily attached to the data object, it may be
+     * the summary for a parent data object. No object with a summary attached
+     * may be a child of another object with a summary attached.
+     * See the ChangeSummary API for details of using the change sumamry.
+     }
+    function getChangeSummary() : ISDOChangeSummary;overload;
+    {function getChangeSummary(const APath : string) : ISDOChangeSummary;overload;
+    function getChangeSummary(const APropIndex : PtrUInt) : ISDOChangeSummary;overload;
+    function getChangeSummary(const AProp : ISDOProperty ) : ISDOChangeSummary;overload;}
+
+    {  objectToXPath - utility to find the xpath from the root.
+     *
+     * objectToXPath returns a string which could be used to locate this data
+     * object from the root data object of the graph.
+     }
+
+    //virtual SDO_SPI const char* objectToXPath() = 0;
+
+  end;
+
+
+  ISDOCursorBookmark = TLinkedListBookmark;
+  ISDOCursor = ILinkedListCursor;
+  ISDODataObjectList = interface
+    ['{54C2BFCE-60B4-492B-A7EF-0B43BC994840}']
+
+    function size() : PtrInt;
+    function getCursor() : ILinkedListCursor;
+
+    {These operations use the cursor location}
+    function getBoolean() : TSDOBoolean;overload;
+    function getByte() : TSDOByte;overload;
+{$IFDEF HAS_SDO_BYTES}
+    function getBytes() : TSDOBytes;overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacter() : TSDOChar;overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency() : TSDOCurrency;overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    function getDate() : TSDODate;overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble() : TSDODouble;overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat() : TSDOFloat;overload;
+{$ENDIF HAS_SDO_FLOAT}
+    function getInteger() : TSDOInteger;overload;
+{$IFDEF HAS_SDO_LONG}
+    function getLong() : TSDOLong;overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function getShort() : TSDOShort;overload;
+{$ENDIF HAS_SDO_SHORT}
+    function getString() : TSDOString;overload;
+    function getDataObject() : ISDODataObject;overload;
+    function getVariant() : TSDOVariant;overload;
+
+    {These operations use the cursor location}
+    procedure setBoolean(const AValue : TSDOBoolean);overload;
+    procedure setByte(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+   procedure setBytes(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setCharacter(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setCurrency(const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDate(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDouble(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setFloat(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setInteger(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setLong(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setShort(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setString(const AValue : TSDOString);overload;
+    procedure setDataObject(AValue : ISDODataObject);overload;
+    procedure setVariant(const AValue : TSDOVariant);overload;
+
+    {These operations use the cursor location}
+    procedure delete();overload;
+    procedure delete(const AIndex : PtrInt);overload;
+
+    function getBoolean(const AIndex : PtrInt) : TSDOBoolean;overload;
+    function getByte(const AIndex : PtrInt) : TSDOByte;overload;
+{$IFDEF HAS_SDO_BYTES}
+    function getBytes(const AIndex : PtrInt) : TSDOBytes;overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacter(const AIndex : PtrInt) : TSDOChar;overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency(const AIndex : PtrInt) : TSDOCurrency;overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    function getDate(const AIndex : PtrInt) : TSDODate;overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble(const AIndex : PtrInt) : TSDODouble;overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat(const AIndex : PtrInt) : TSDOFloat;overload;
+{$ENDIF HAS_SDO_FLOAT}
+    function getInteger(const AIndex : PtrInt) : TSDOInteger;overload;
+{$IFDEF HAS_SDO_LONG}
+    function getLong(const AIndex : PtrInt) : TSDOLong;overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function getShort(const AIndex : PtrInt) : TSDOShort;overload;
+{$ENDIF HAS_SDO_SHORT}
+    function getString(const AIndex : PtrInt) : TSDOString;overload;
+    function getDataObject(const AIndex : PtrInt) : ISDODataObject;overload;
+    function getVariant(const AIndex : PtrInt) : TSDOVariant;overload;
+
+    procedure setBoolean(const AIndex : PtrInt; const AValue : TSDOBoolean);overload;
+    procedure setByte(const AIndex : PtrInt; const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure setBytes(const AIndex : PtrInt; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setCharacter(const AIndex : PtrInt; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setCurrency(const AIndex : PtrInt; const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDate(const AIndex : PtrInt; const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDouble(const AIndex : PtrInt; const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setFloat(const AIndex : PtrInt; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setInteger(const AIndex : PtrInt; const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setLong(const AIndex : PtrInt; const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setShort(const AIndex : PtrInt; const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setString(const AIndex : PtrInt; const AValue : TSDOString);overload;
+    procedure setDataObject(const AIndex : PtrInt; AValue : ISDODataObject);overload;
+    procedure setVariant(const AIndex : PtrInt; const AValue : TSDOVariant);overload;
+
+    procedure insert(const AIndex : PtrInt; AValue : ISDODataObject);overload;
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOBoolean);overload;
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure insertBytes(const AIndex : PtrInt; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure insertCurrency(const AIndex : PtrInt; const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOString);overload;
+
+    procedure append(AValue : ISDODataObject);overload;
+    procedure append(const AValue : TSDOBoolean);overload;
+    procedure append(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure appendBytes(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure append(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure appendCurrency(const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure append(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure append(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure append(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure append(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure append(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure append(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure append(const AValue : TSDOString);overload;
+  end;
+
+  IXSDHelper = interface
+    ['{D8E3D8F1-E8AE-4EE8-B60E-1235C72DD532}']
+    procedure LoadFromStream(AStream : TStream);
+    procedure LoadFromFile(const AFileName : string);
+    procedure LoadFromString(const ASchemaString : string);
+
+    procedure Generate(
+            ATypeList : ISDOTypeList;
+            ADestStream : TStream;
+      const ATargetNamespace : string
+    );overload;
+    procedure Generate(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string;
+      const AFileName : string
+    );overload;
+    function Generate(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string
+    ) : string;overload;
+    procedure GenerateCode(
+            ATypeList : ISDOTypeList;
+            ADestStream : TStream;
+      const ATargetNamespace : string
+    );overload;
+    function GenerateCode(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string
+    ) : string;overload;
+    procedure GenerateCode(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string;
+      const AFileName : string
+    );overload;
+    function  GetDataFactory() : ISDODataFactory;
+  end;
+  
+  ISDOSerializer = interface
+    ['{AE41D827-E606-43A4-A56C-22CBFCA5F197}']
+    procedure save(
+      const AName : string;
+            AObject : ISDODataObject;
+      const ADestStream : TStream
+    );overload;
+    procedure save(
+            AObject : ISDODataObject;
+      const ADestStream : TStream
+    );overload;
+    procedure save(
+      const AName : string;
+            AObject : ISDODataObject;
+      const AFileName : string
+    );overload;
+    procedure save(
+            AObject : ISDODataObject;
+      const AFileName : string
+    );overload;
+    procedure load(
+      const AStream : TStream;
+            ADestList : ISDODataObjectList
+    );overload;
+    procedure load(
+      const AFileName : string;
+            ADestList : ISDODataObjectList
+    );overload;
+    function load(const AStream : TStream) : ISDODataObject;overload;
+    function load(const AFileName : string) : ISDODataObject;overload;
+
+    // these are the implementation's extensions
+    function getOptions() : TSerializerOptions;
+    procedure setOptions(const AValue : TSerializerOptions);
+    property Options : TSerializerOptions read getOptions write setOptions;
+  end;
+
+  ISDOChangedDataObjectList = interface
+    ['{E4E4A9F1-5287-44B6-876B-1A128E70BDA9}']
+    function size() : PtrInt;
+    function getType(const AIndex : PtrInt) : TChangeType;
+    function getDataObject(const AIndex : PtrInt) : ISDODataObject;
+  end;
+
+  TValueBuffer = packed record
+    case TSDOTypeKind of
+      BooleanType     : ( BooleanValue : TSDOBoolean );
+      ByteType        : ( ByteValue : TSDOByte );
+{$IFDEF HAS_SDO_BYTES}
+      BytesType       : ( BytesValue : PSDOBytes );
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType   : ( CharValue : TSDOChar );
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      CurrencyType    : ( CurrencyValue : TSDOCurrency );
+{$ENDIF HAS_SDO_CURRENCY}
+      DateTimeType    : ( DateValue : TSDODateTime );
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType      : ( DoubleValue : TSDODouble );
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType       : ( FloatValue : TSDOFloat );
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType     : ( IntegerValue : TSDOInteger );
+{$IFDEF HAS_SDO_LONG}
+      LongType        : ( LongValue : TSDOLong );
+{$ENDIF HAS_SDO_LONG}      
+      ObjectType      : ( ObjectValue : PSDODataObject );
+{$IFDEF HAS_SDO_SHORT}
+      ShortType       : ( ShortValue : TSDOShort );
+{$ENDIF HAS_SDO_SHORT}      
+      StringType      : ( StringValue : PSDOString ); 
+  end;
+  TValueSetting = class
+  private
+    FSet : Boolean;
+    FNull : Boolean;
+    FProperty : ISDOProperty;
+    FIndex : PtrInt;
+    FValue : TValueBuffer;
+  private
+    procedure PrepareBuffer();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure FreeBuffer();{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    procedure SetValue(const ABuffer);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  public
+    constructor Create(
+      const ASet, ANull : Boolean;
+      const AValue;
+      const AProperty   : ISDOProperty;
+			const AIndex      : PtrInt
+    );
+    destructor Destroy();override;
+    function getProperty() : ISDOProperty;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function isSet() : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function isNull() : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function getIndex() : PtrInt;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+    function getBooleanValue() : TSDOBoolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function getByteValue() : TSDOByte;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacterValue() : TSDOChar;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrencyValue() : TSDOCurrency;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_BYTES}
+    function getBytesValue() : TSDOBytes;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_BYTES}
+    function getStringValue() : TSDOString;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_SHORT}
+    function getShortValue() : TSDOShort;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+    function getIntegerValue() : TSDOInteger;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_LONG}
+    function getLongValue() : TSDOLong;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloatValue() : TSDOFloat;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDoubleValue() : TSDODouble;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_DOUBLE}
+    function getDateValue() : TSDODate;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function getDataObjectValue() : ISDODataObject;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  end;
+
+  ISDOSettingList = interface
+    ['{502BE24D-17C7-4537-883C-E213E4714852}']
+    function size() : PtrInt;
+    function getItem(const AIndex : PtrInt) : TValueSetting;
+    procedure insert (const AIndex : PtrInt; const ASetting : TValueSetting);
+    procedure append (const ASetting : TValueSetting);
+    procedure remove (const AIndex : PtrInt);
+  end;
+
+  ISDOChangeSummary = interface
+    ['{5DB0D74B-A1D8-446A-83A4-98CB35D446F2}']
+    function getChangedDataObjects() : ISDOChangedDataObjectList;
+    function getOldValues(const ADataObject : ISDODataObject) : ISDOSettingList;
+    function getOldXpath(const ADataObject : ISDODataObject) : string;
+    procedure beginLogging();
+    procedure endLogging();
+    function isLogging() : Boolean;
+    function isCreated(const ADataObject : ISDODataObject) : Boolean;
+    function isDeleted(const ADataObject : ISDODataObject) : Boolean;
+    function isModified(const ADataObject : ISDODataObject) : Boolean;
+    function getOldValue(const ADataObject : ISDODataObject; const AProperty : ISDOProperty) : TValueSetting;
+    function getOldContainer(const ADataObject : ISDODataObject) : ISDODataObject;
+    function getOldContainmentProperty(const ADataObject : ISDODataObject) : ISDOProperty;
+    procedure undoChanges() ;
+    //SequencePtr getOldSequence(DataObjectPtr dataObject);
+  end;
+
+  TSDOConvertHelper = class
+  public
+    class function BoolToByte(const AValue : TSDOBoolean) : TSDOByte;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_BYTES}
+    class function BoolToBytes(const AValue : TSDOBoolean) : TSDOBytes;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    class function BoolToChar(const AValue : TSDOBoolean) : TSDOChar;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+    class function BoolToInteger(const AValue : TSDOBoolean) : TSDOInteger;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_LONG}
+    class function BoolToLong(const AValue : TSDOBoolean) : TSDOLong;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    class function BoolToShort(const AValue : TSDOBoolean) : TSDOShort;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function BoolToString(const AValue : TSDOBoolean) : TSDOString;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+
+    class function IntegerToBool(const AValue : TSDOInteger) : TSDOBoolean; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_CHAR}
+    class function IntegerToChar(const AValue : TSDOInteger) : TSDOChar; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+    class function IntegerToString(const AValue : TSDOInteger) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+
+    class function ByteToBool(const AValue : TSDOByte) : TSDOBoolean; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_CHAR}
+    class function ByteToChar(const AValue : TSDOByte) : TSDOChar; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+    class function ByteToString(const AValue : TSDOByte) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+
+    class function StringToBool(const AValue : TSDOString) : TSDOBoolean; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function StringToByte(const AValue : TSDOString) : TSDOByte; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function StringToBytes(const AValue : TSDOString) : TSDOBytes; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_CHAR}
+    class function StringToChar(const AValue : TSDOString) : TSDOChar; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+    class function StringToDate(const AValue : TSDOString) : TSDODate; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function StringToInteger(const AValue : TSDOString) : TSDOInteger; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{ $IFDEF HAS_SDO_FLOAT}
+    class function StringToFloat(const AValue : TSDOString) : Extended; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{ $ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    class function StringToLong(const AValue : TSDOString) : TSDOLong; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    class function StringToShort(const AValue : TSDOString) : TSDOShort; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+
+{ $IFDEF HAS_SDO_FLOAT}
+    class function FloatToString(const AValue : Extended) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function FloatToBool(const AValue : Extended) : TSDOBoolean; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{ $ENDIF HAS_SDO_FLOAT}
+
+    class function DateToString(const AValue : TSDODate) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+
+{$IFDEF HAS_SDO_CHAR}
+    class function CharToBool(const AValue : TSDOChar) : TSDOBoolean; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function CharToByte(const AValue : TSDOChar) : TSDOByte; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function CharToInteger(const AValue : TSDOChar) : TSDOInteger; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function CharToLong(const AValue : TSDOChar) : TSDOLong; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function CharToShort(const AValue : TSDOChar) : TSDOShort; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_LONG}
+    class function LongToBool(const AValue : TSDOLong) : TSDOBoolean; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  {$IFDEF HAS_SDO_CHAR}
+    class function LongToChar(const AValue : TSDOLong) : TSDOChar; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  {$ENDIF HAS_SDO_CHAR}
+    class function LongToString(const AValue : TSDOLong) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+    class function ShortToBool(const AValue : TSDOShort) : TSDOBoolean; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  {$IFDEF HAS_SDO_CHAR}
+    class function ShortToChar(const AValue : TSDOShort) : TSDOChar; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  {$ENDIF HAS_SDO_CHAR}
+    class function ShortToString(const AValue : TSDOShort) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+
+    class function BytesToString(const AValue : TSDOBytes) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_CURRENCY}
+    class function CurrencyToString(const AValue : TSDOCurrency) : TSDOString; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function StringToCurrency(const AValue : TSDOString) : TSDOCurrency; {$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CURRENCY}
+  end;
+  TSDOConvertHelperClass = class of TSDOConvertHelper;
+
+  TSDOCopyHelper = class
+  private
+    class procedure copyProperty(const A, B : ISDODataObject; const AProp : ISDOProperty);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    class procedure copyPropertyList(const A, B : ISDODataObjectList; const AType : ISDOType; const ADeepCopy : Boolean);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function internalCopy(const ADataObject : ISDODataObject; const ADeepCopy : Boolean) : ISDODataObject;
+  public
+    class function copyShallow(const ADataObject : ISDODataObject) : ISDODataObject;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function copy(const ADataObject : ISDODataObject) : ISDODataObject;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  end;
+  TSDOCopyHelperClass = class of TSDOCopyHelper;
+
+  //implementation extension
+  procedure CopySimpleList(
+    const ASource, ADest : ISDODataObjectList;
+    const AType : TSDOTypeKind
+  );
+
+type
+
+  TSDOEqualityHelper = class
+  private
+    class function CompareProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function CompareList(const A,B : ISDODataObjectList; const AType : ISDOType) : Boolean;
+    class function InternalEqual(const A,B : ISDODataObject; const AFullCompare : Boolean) : Boolean;
+  public
+    class function equalShallow(const A,B : ISDODataObject) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    class function equal(const A,B : ISDODataObject) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  end;
+  TSDOEqualityHelperClass = class of TSDOEqualityHelper;
+
+const
+  NIL_OBJECT : ISDODataObject = nil;
+
+  procedure InitBufferResources(const ADataType : TSDOTypeKind; var ABuffer : TValueBuffer);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  procedure FreeBufferResources(const ADataType : TSDOTypeKind; var ABuffer : TValueBuffer);{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+implementation
+
+uses
+  StrUtils;
+
+procedure InitBufferResources(const ADataType : TSDOTypeKind; var ABuffer : TValueBuffer);
+begin
+  case ADataType of
+{$IFDEF HAS_SDO_BYTES}
+    BytesType     : New(ABuffer.BytesValue);
+{$ENDIF HAS_SDO_BYTES}
+    ObjectType    : New(ABuffer.ObjectValue);
+    StringType   : New(ABuffer.StringValue);
+  end;
+end;
+
+procedure FreeBufferResources(const ADataType : TSDOTypeKind; var ABuffer : TValueBuffer);
+begin
+  case ADataType of
+{$IFDEF HAS_SDO_BYTES}
+    BytesType     :
+      begin
+        ABuffer.BytesValue^ := nil;
+        Dispose(ABuffer.BytesValue);
+        ABuffer.BytesValue := nil;
+      end;
+{$ENDIF HAS_SDO_BYTES}
+    ObjectType    :
+      begin
+        ABuffer.ObjectValue^ := nil;
+        Dispose(ABuffer.ObjectValue);
+        ABuffer.ObjectValue := nil;
+      end;
+    StringType   :
+      begin
+        ABuffer.StringValue^ := '';
+        Dispose(ABuffer.StringValue);
+        ABuffer.StringValue := nil;
+      end;
+  end;
+end;
+
+{ ESDOPropertyNotFoundException }
+
+constructor ESDOPropertyNotFoundException.Create(const APropName: string);
+begin
+  inherited CreateFmt('Property not found : %s.',[APropName]);
+  FPropertyName := APropName;
+end;
+
+{ ESDOUnsupportedOperationException }
+
+constructor ESDOUnsupportedOperationException.Create(const AOperation: string);
+begin
+  inherited CreateFmt('Unsupported Operation : %s.',[AOperation]);
+  FOperation := AOperation;
+end;
+
+{ ESDOIllegalArgumentException }
+
+constructor ESDOIllegalArgumentException.Create(const AArgumentName: string);
+begin
+  inherited CreateFmt('Illegal Argument : %s.',[AArgumentName]);
+  FArgumentName := AArgumentName;
+end;
+
+{ ESDOIndexOutOfRangeException }
+
+constructor ESDOIndexOutOfRangeException.Create(const AValue: Integer);
+begin
+  inherited CreateFmt('Index out of range : %d',[AValue]);
+  FValue := AValue;
+end;
+
+{ ESDOTypeNotFoundException }
+
+constructor ESDOTypeNotFoundException.Create(const AName: string);
+begin
+  inherited CreateFmt('Type not found : %s.',[AName]);
+  FName := AName;
+end;
+
+{ ESDOIncompleteTypeException }
+
+constructor ESDOIncompleteTypeException.Create(const ATypeName: string);
+begin
+  inherited CreateFmt('Incomplete Type definition : %s.',[ATypeName]);
+  FTypeName := ATypeName;
+end;
+
+{ ESDODuplicatedItemException }
+
+constructor ESDODuplicatedItemException.Create(const AName: string);
+begin
+  inherited CreateFmt('Duplicated item : %s.',[AName]);
+  FName := AName;
+end;
+
+{ ESDOInvalidConversionException }
+
+constructor ESDOInvalidConversionException.Create(const AName: string);
+begin
+  inherited CreateFmt('Invalid conversion : %s.',[AName]);
+  FName := AName;
+end;
+
+{ TValueSetting }
+
+constructor TValueSetting.Create(
+  const ASet, ANull : Boolean;
+  const AValue;
+  const AProperty: ISDOProperty;
+  const AIndex: PtrInt
+);
+begin
+  if ( AProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  FSet := ASet;
+  FNull := ANull;
+  FProperty := AProperty;
+  FIndex := AIndex;
+  PrepareBuffer();
+  if FSet and ( not FNull ) then
+    SetValue(AValue);
+end;
+
+destructor TValueSetting.Destroy();
+begin
+  if Assigned(FProperty) then begin
+    FreeBuffer();
+  end;
+  inherited;
+end;
+
+procedure TValueSetting.FreeBuffer();
+begin
+  FreeBufferResources(FProperty.getTypeEnum(), FValue);
+end;
+
+function TValueSetting.getBooleanValue() : TSDOBoolean;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := FValue.BooleanValue;
+    ByteType      : Result := TSDOConvertHelper.ByteToBool(FValue.ByteValue);
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : Result := TSDOConvertHelper.CharToBool(FValue.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+    IntegerType   : Result := TSDOConvertHelper.IntegerToBool(FValue.IntegerValue);
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := TSDOConvertHelper.LongToBool(FValue.LongValue);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := TSDOConvertHelper.ShortToBool(FValue.ShortValue);
+{$ENDIF HAS_SDO_SHORT}
+    StringType   : Result := TSDOConvertHelper.StringToBool(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getBooleanValue() this with DataType.');
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+function TValueSetting.getBytesValue() : TSDOBytes;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := TSDOConvertHelper.BoolToBytes(FValue.BooleanValue);
+    BytesType     : Result := FValue.BytesValue^;
+    StringType    : Result := TSDOConvertHelper.StringToBytes(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getBytesValue() this with DataType.');
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+function TValueSetting.getByteValue() : TSDOByte;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := TSDOConvertHelper.BoolToByte(FValue.BooleanValue);
+    ByteType      : Result := FValue.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : Result := TSDOConvertHelper.CharToByte(FValue.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+    IntegerType   : Result := FValue.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := FValue.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := FValue.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType   : Result := TSDOConvertHelper.StringToByte(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getByteValue() this with DataType.');
+  end;
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+function TValueSetting.getCharacterValue() : TSDOChar;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := TSDOConvertHelper.BoolToChar(FValue.BooleanValue);
+    ByteType      : Result := TSDOConvertHelper.ByteToChar(FValue.ByteValue);
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : Result := FValue.CharValue;
+{$ENDIF HAS_SDO_CHAR}
+    IntegerType   : Result := TSDOConvertHelper.IntegerToChar(FValue.IntegerValue);
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := TSDOConvertHelper.LongToChar(FValue.LongValue);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := TSDOConvertHelper.ShortToChar(FValue.ShortValue);
+{$ENDIF HAS_SDO_SHORT}
+    StringType   : Result := TSDOConvertHelper.StringToChar(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getCharacterValue() this with DataType.');
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY }
+function TValueSetting.getCurrencyValue() : TSDOCurrency;
+begin
+  case FProperty.getTypeEnum() of
+    ByteType      : Result := FValue.ByteValue;
+    CurrencyType  : Result := FValue.CurrencyValue;
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType    : Result := FValue.DoubleValue;
+{$ENDIF HAS_SDO_DOUBLE}
+    IntegerType   : Result := FValue.IntegerValue;
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType     : Result := FValue.FloatValue;
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := FValue.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := FValue.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType    : Result := TSDOConvertHelper.StringToInteger(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getFloatValue() this with DataType.');
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY }
+
+function TValueSetting.getDataObjectValue() : ISDODataObject;
+begin
+  if ( FProperty.getTypeEnum() = ObjectType ) then
+    Result := FValue.ObjectValue^
+  else
+    raise ESDONotImplementedException.Create('getDataObjectValue() this with DataType.');;
+end;
+
+function TValueSetting.getDateValue() : TSDODate;
+begin
+  case FProperty.getTypeEnum() of
+    DateTimeType  : Result := FValue.DateValue;
+    StringType    : Result := TSDOConvertHelper.StringToDate(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getDateValue() this with DataType.');
+  end;
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+function TValueSetting.getDoubleValue() : TSDODouble;
+begin
+  case FProperty.getTypeEnum() of
+    ByteType      : Result := FValue.ByteValue;
+{$IFDEF HAS_SDO_CURRENCY }
+    CurrencyType  : Result := FValue.CurrencyValue;
+{$ENDIF HAS_SDO_CURRENCY }
+    DoubleType    : Result := FValue.DoubleValue;
+    IntegerType   : Result := FValue.IntegerValue;
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType     : Result := FValue.FloatValue;
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := FValue.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := FValue.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType    : Result := TSDOConvertHelper.StringToInteger(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getFloatValue() this with DataType.');
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+function TValueSetting.getFloatValue() : TSDOFloat;
+begin
+  case FProperty.getTypeEnum() of
+    ByteType      : Result := FValue.ByteValue;
+{$IFDEF HAS_SDO_CURRENCY }
+    CurrencyType  : Result := FValue.CurrencyValue;
+{$ENDIF HAS_SDO_CURRENCY }
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType    : Result := FValue.DoubleValue;
+{$ENDIF HAS_SDO_DOUBLE}
+    IntegerType   : Result := FValue.IntegerValue;
+    FloatType     : Result := FValue.FloatValue;
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := FValue.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := FValue.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType    : Result := TSDOConvertHelper.StringToInteger(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getFloatValue() this with DataType.');
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+function TValueSetting.getIndex() : PtrInt;
+begin
+  Result := FIndex;
+end;
+
+function TValueSetting.getIntegerValue() : TSDOInteger;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := TSDOConvertHelper.BoolToInteger(FValue.BooleanValue);
+    ByteType      : Result := FValue.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : Result := TSDOConvertHelper.CharToInteger(FValue.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+    IntegerType   : Result := FValue.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := FValue.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := FValue.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType    : Result := TSDOConvertHelper.StringToInteger(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getIntegerValue() this with DataType.');
+  end;
+end;
+
+{$IFDEF HAS_SDO_LONG}
+function TValueSetting.getLongValue() : TSDOLong;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := TSDOConvertHelper.BoolToLong(FValue.BooleanValue);
+    ByteType      : Result := FValue.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : Result := TSDOConvertHelper.CharToLong(FValue.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+    IntegerType   : Result := FValue.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := FValue.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := FValue.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType    : Result := TSDOConvertHelper.StringToLong(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getLongValue() this with DataType.');
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+function TValueSetting.getProperty() : ISDOProperty;
+begin
+  Result := FProperty;
+end;
+
+{$IFDEF HAS_SDO_SHORT}
+function TValueSetting.getShortValue() : TSDOShort;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := TSDOConvertHelper.BoolToShort(FValue.BooleanValue);
+    ByteType      : Result := FValue.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : Result := TSDOConvertHelper.CharToShort(FValue.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+    IntegerType   : Result := FValue.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := FValue.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := FValue.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType    : Result := TSDOConvertHelper.StringToShort(FValue.StringValue^);
+    else
+      raise ESDONotImplementedException.Create('getShortValue() this with DataType.');
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+function TValueSetting.getStringValue() : TSDOString;
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : Result := TSDOConvertHelper.BoolToString(FValue.BooleanValue);
+    ByteType      : Result := TSDOConvertHelper.ByteToString(FValue.ByteValue);
+{$IFDEF HAS_SDO_BYTES}
+    BytesType     : Result := TSDOConvertHelper.BytesToString(FValue.BytesValue^);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : Result := FValue.CharValue;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType  : Result := TSDOConvertHelper.CurrencyToString(FValue.CurrencyValue);
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType  : Result := TSDOConvertHelper.DateToString(FValue.DateValue);
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType    : Result := TSDOConvertHelper.FloatToString(FValue.DoubleValue);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType     : Result := TSDOConvertHelper.FloatToString(FValue.FloatValue);
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType   : Result := TSDOConvertHelper.IntegerToString(FValue.IntegerValue);
+{$IFDEF HAS_SDO_LONG}
+    LongType      : Result := TSDOConvertHelper.LongToString(FValue.LongValue);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : Result := TSDOConvertHelper.ShortToString(FValue.ShortValue);
+{$ENDIF HAS_SDO_SHORT}
+    StringType    : Result := FValue.StringValue^;
+    else
+      raise ESDONotImplementedException.Create('getStringValue() this with DataType.');
+  end;
+end;
+
+function TValueSetting.isNull() : Boolean;
+begin
+  Result := FNull;
+end;
+
+function TValueSetting.isSet() : Boolean;
+begin
+  Result := FSet;
+end;
+
+procedure TValueSetting.PrepareBuffer();
+begin
+  case FProperty.getTypeEnum() of
+{$IFDEF HAS_SDO_BYTES}  
+    BytesType     : New(FValue.BytesValue);
+{$ENDIF HAS_SDO_BYTES}
+    ObjectType    : New(FValue.ObjectValue);
+    StringType    : New(FValue.StringValue);
+  end;
+end;
+
+procedure TValueSetting.SetValue(const ABuffer);
+begin
+  case FProperty.getTypeEnum() of
+    BooleanType   : FValue.BooleanValue := TSDOBoolean(ABuffer);
+    ByteType      : FValue.ByteValue := TSDOByte(ABuffer);
+{$IFDEF HAS_SDO_BYTES}
+    BytesType     : FValue.BytesValue^ := TSDOBytes(ABuffer);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : FValue.CharValue := TSDOChar(ABuffer);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType  : FValue.CurrencyValue := TSDOCurrency(ABuffer);
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType  : FValue.DateValue := TSDODate(ABuffer);
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType    : FValue.DoubleValue := TSDODouble(ABuffer);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType     : FValue.FloatValue := TSDOFloat(ABuffer);
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType   : FValue.IntegerValue := TSDOInteger(ABuffer);
+{$IFDEF HAS_SDO_LONG}
+    LongType      : FValue.LongValue := TSDOLong(ABuffer);
+{$ENDIF HAS_SDO_LONG}
+    ObjectType    : FValue.ObjectValue^ := ISDODataObject(ABuffer);
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : FValue.ShortValue := TSDOShort(ABuffer);
+{$ENDIF HAS_SDO_SHORT}    
+    StringType    : FValue.StringValue^ := TSDOString(ABuffer);
+  end;
+end;
+
+{ ESDOCircularDependencyTypeException }
+
+constructor ESDOCircularDependencyTypeException.Create(
+  const ATypeName,
+        APropertyName,
+        APropertyType: string
+);
+begin
+  inherited Create(APropertyName);
+  Message := Format(
+               'A circular dependendy has been found the type definition ' + sLineBreak +
+               '  Type name : "%s"' + sLineBreak +
+               '  Property name : "%s"' + sLineBreak +
+               '  Property type : "%s"',
+               [ATypeName,APropertyName,APropertyType]
+             );
+  FTypeName := ATypeName;
+  FPropertyType := APropertyType;
+  FPropertyName := APropertyName; 
+end;
+
+{ ESDOInvalidPathException }
+
+constructor ESDOInvalidPathException.Create(const APath: string);
+begin
+  FPath := APath;
+end;
+
+var
+  ConverterFormatSetting : TFormatSettings;
+function sdo_TryStrToInt(const s: string; out i : Int64) : Boolean;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+var
+  e: Integer;
+begin
+  Val(s,i,e);
+  Result := ( e = 0 );
+end;
+
+function sdo_TryStrToInt(const s: string; out i : Integer) : Boolean;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+var
+  e: Integer;
+begin
+  Val(s,i,e);
+  Result := ( e = 0 );
+end;
+
+function sdo_TryStrToInt(const s: string; out i : Smallint) : Boolean;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+var
+  e: Integer;
+begin
+  Val(s,i,e);
+  Result := ( e = 0 );
+end;
+
+function sdo_TryStrToInt(const s: string; out i : TSDOByte) : Boolean;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+var
+  e: Integer;
+begin
+  Val(s,i,e);
+  Result := ( e = 0 );
+end;
+
+{ TSDOConvertHelper }
+
+class function TSDOConvertHelper.BoolToByte(const AValue: TSDOBoolean): TSDOByte;
+begin
+  if AValue then
+    Result := 1
+  else
+    Result := 0;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+class function TSDOConvertHelper.BoolToBytes(const AValue: TSDOBoolean): TSDOBytes;
+const
+  ITEM_LENGTH = 5;
+  STR_BOOL : array[TSDOBoolean] of String[ITEM_LENGTH] = ( 'false', 'true' );
+begin
+  SetLength(Result,Length(STR_BOOL[AValue]));
+  Move(STR_BOOL[AValue][0],Result[0],ITEM_LENGTH);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+class function TSDOConvertHelper.BoolToChar(const AValue: TSDOBoolean) : TSDOChar;
+begin
+  if AValue then
+    Result := '1'
+  else
+    Result := '0';
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+class function TSDOConvertHelper.BoolToInteger(const AValue: TSDOBoolean): TSDOInteger;
+begin
+  Result := BoolToByte(AValue)
+end;
+
+class function TSDOConvertHelper.BoolToLong(const AValue: TSDOBoolean): TSDOLong;
+begin
+  Result := BoolToByte(AValue);
+end;
+
+class function TSDOConvertHelper.BoolToShort(const AValue: TSDOBoolean): TSDOShort;
+begin
+  Result := BoolToByte(AValue);
+end;
+
+class function TSDOConvertHelper.BoolToString(const AValue: TSDOBoolean): TSDOString;
+begin
+  if AValue then
+    Result := '1'
+  else
+    Result := '0';
+end;
+
+class function TSDOConvertHelper.BytesToString(const AValue: TSDOBytes): TSDOString;
+var
+  locRes : AnsiString;
+begin
+  if (  Length(AValue) > 0 ) then begin
+    SetLength(locRes, ( 2 * Length(AValue) ) );
+    BinToHex(PAnsiChar(@(AValue[0])),PAnsiChar(@(locRes[1])),Length(AValue));
+    Result := locRes;
+  end;
+end;
+
+class function TSDOConvertHelper.ByteToBool(const AValue: TSDOByte): TSDOBoolean;
+begin
+  Result := ( AValue <> 0 );
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+class function TSDOConvertHelper.ByteToChar(const AValue: TSDOByte): TSDOChar;
+begin
+  Result := TSDOChar(AValue);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+class function TSDOConvertHelper.ByteToString(const AValue: TSDOByte): TSDOString;
+begin
+  Result := IntToStr(AValue);
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+class function TSDOConvertHelper.CharToBool(const AValue: TSDOChar): TSDOBoolean;
+begin
+  Result := ( Ord(AValue) <> 0 );
+end;
+
+class function TSDOConvertHelper.CharToByte(const AValue: TSDOChar): TSDOByte;
+begin
+{$IF SizeOf(TSDOChar) = SizeOf(Byte)}
+  Result := Ord(AValue);
+{$ELSE}
+  case Ord(AValue) of
+    Low(Byte)..High(Byte) : Result := Ord(AValue);
+    else
+      Result := 0;
+  end;
+{$IFEND}
+end;
+
+class function TSDOConvertHelper.CharToInteger(const AValue: TSDOChar): TSDOInteger;
+begin
+  Result := Ord(AValue);
+end;
+
+class function TSDOConvertHelper.CharToLong(const AValue: TSDOChar): TSDOLong;
+begin
+  Result := Ord(AValue);
+end;
+
+class function TSDOConvertHelper.CharToShort(const AValue: TSDOChar): TSDOShort;
+begin
+  Result := Ord(AValue);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+class function TSDOConvertHelper.DateToString(const AValue: TSDODate): TSDOString;
+begin
+  Result := xsd_DateTimeToStr(AValue,xdkDateTime);
+end;
+
+{ $IFDEF HAS_SDO_FLOAT}
+class function TSDOConvertHelper.FloatToBool(const AValue: Extended): TSDOBoolean;
+begin
+  Result := ( AValue <> 0 );
+end;
+
+class function TSDOConvertHelper.FloatToString(const AValue: Extended) : TSDOString;
+begin
+  Result := FloatToStrF(AValue,ffGeneral,18,18,ConverterFormatSetting);
+end;
+{ $ENDIF HAS_SDO_FLOAT}
+
+class function TSDOConvertHelper.IntegerToBool(const AValue: TSDOInteger): TSDOBoolean;
+begin
+  Result := ( AValue <> 0 );
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+class function TSDOConvertHelper.IntegerToChar(const AValue: TSDOInteger): TSDOChar;
+begin
+  Result := TSDOChar(AValue);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+class function TSDOConvertHelper.IntegerToString(const AValue: TSDOInteger): TSDOString;
+begin
+  Result := IntToStr(AValue);
+end;
+
+class function TSDOConvertHelper.LongToBool(const AValue: TSDOLong): TSDOBoolean;
+begin
+  Result := ( AValue <> 0 );
+end;
+
+{$IFDEF HAS_SDO_LONG}
+  {$IFDEF HAS_SDO_CHAR}
+class function TSDOConvertHelper.LongToChar(const AValue: TSDOLong): TSDOChar;
+begin
+  Result := TSDOChar(AValue);
+end;
+  {$ENDIF HAS_SDO_CHAR}
+
+class function TSDOConvertHelper.LongToString(const AValue: TSDOLong): TSDOString;
+begin
+  Result := IntToStr(AValue);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+class function TSDOConvertHelper.ShortToBool(const AValue: TSDOShort): TSDOBoolean;
+begin
+  Result := ( AValue <> 0 );
+end;
+
+{$IFDEF HAS_SDO_SHORT}
+  {$IFDEF HAS_SDO_CHAR}
+class function TSDOConvertHelper.ShortToChar(const AValue: TSDOShort): TSDOChar;
+begin
+  Result := TSDOChar(AValue);
+end;
+  {$ENDIF HAS_SDO_CHAR}
+
+class function TSDOConvertHelper.ShortToString(const AValue: TSDOShort): TSDOString;
+begin
+  Result := IntToStr(AValue);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+class function TSDOConvertHelper.StringToBool(const AValue: TSDOString): TSDOBoolean;
+begin
+  case AnsiIndexStr(LowerCase(AValue),['0', '1', 'false', 'true'] ) of
+    0, 2 : Result := False;
+    1, 3 : Result := True;
+    else
+      raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToBool');
+  end;
+end;
+
+class function TSDOConvertHelper.StringToByte(const AValue: TSDOString): TSDOByte;
+begin
+  if not sdo_TryStrToInt(AValue, Result) then
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToInteger');
+end;
+
+class function TSDOConvertHelper.StringToBytes(const AValue: TSDOString): TSDOBytes;
+var
+  locValue : AnsiString;
+begin
+  if ( Length(AValue) > 0 ) then begin
+    locValue := AValue;
+    SetLength(Result,( Length(locValue) div 2 ));
+    HexToBin(PAnsiChar(locValue),PAnsiChar(@(Result[0])),Length(Result));
+  end;
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+class function TSDOConvertHelper.StringToChar(const AValue: TSDOString): TSDOChar;
+begin
+  if ( Length(AValue) > 0 ) then
+    Result := AValue[1]
+  else
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToChar');
+end;
+{$ENDIF HAS_SDO_ENDIF}
+
+class function TSDOConvertHelper.StringToDate(const AValue: TSDOString): TSDODate;
+begin
+  if not xsd_TryStrToDate(AValue,Result,xdkDateTime) then
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToDate');
+end;
+
+{ $IFDEF HAS_SDO_FLOAT}
+class function TSDOConvertHelper.StringToFloat(const AValue: TSDOString): Extended;
+begin
+  if not TryStrToFloat(AValue,Result,ConverterFormatSetting) then
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToFloat');
+end;
+{ $ENDIF HAS_SDO_FLOAT}
+
+class function TSDOConvertHelper.StringToInteger(const AValue: TSDOString): TSDOInteger;
+begin
+  if not sdo_TryStrToInt(AValue, Result) then
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToInteger');
+end;
+
+{$IFDEF HAS_SDO_LONG}
+class function TSDOConvertHelper.StringToLong(const AValue: TSDOString): TSDOLong;
+begin
+  if not sdo_TryStrToInt(AValue, Result) then
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToLong');
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+class function TSDOConvertHelper.StringToShort(const AValue: TSDOString): TSDOShort;
+begin
+  if not sdo_TryStrToInt(AValue, Result) then
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToShort');
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+{$IFDEF HAS_SDO_CURRENCY}
+class function TSDOConvertHelper.CurrencyToString(const AValue: TSDOCurrency): TSDOString;
+begin
+  Result := CurrToStrF(AValue,ffFixed,4,ConverterFormatSetting);
+end;
+
+class function TSDOConvertHelper.StringToCurrency(const AValue: TSDOString): TSDOCurrency;
+begin
+  if not TryStrToCurr(AValue,Result,ConverterFormatSetting) then
+    raise ESDOInvalidConversionException.Create('TSDOConvertHelper.StringToCurrency');
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+
+
+type
+  TSimpleTypeCopyProc = procedure (const A,B : ISDODataObject; const AProp : ISDOProperty);
+  TListTypeCopyProc = procedure (const A,B : ISDODataObjectList);
+  TCopyProcRecord = record
+    Simple : TSimpleTypeCopyProc;
+    List   : TListTypeCopyProc;
+  end;
+
+procedure NotImplementedSimplePROC(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  raise ESDONotImplementedException.Create('');
+end;
+
+procedure NotImplementedListPROC(const A,B : ISDODataObjectList);
+begin
+  raise ESDONotImplementedException.Create('');
+end;
+
+procedure CopyBoolProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setBoolean(AProp,A.getBoolean(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+procedure CopyByteProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setByte(AProp,A.getByte(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure CopyBytesProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setBytes(AProp,Copy(A.getBytes(AProp)));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+procedure CopyListBytes(const A,B : ISDODataObjectList);
+begin
+  B.appendBytes(Copy(A.getBytes()));
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure CopyCharProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setCharacter(AProp,A.getCharacter(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+procedure CopyListChar(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getCharacter());
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure CopyCurrencyProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setCurrency(AProp,A.getCurrency(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+procedure CopyListCurrency(const A,B : ISDODataObjectList);
+begin
+  B.appendCurrency(A.getCurrency());
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure CopyDoubleProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setDouble(AProp,A.getDouble(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+procedure CopyListDouble(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getDouble());
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+procedure CopyDateProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setDate(AProp,A.getDate(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure CopyFloatProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setFloat(AProp,A.getFloat(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+procedure CopyListFloat(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getFloat());
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure CopyIntegerProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setInteger(AProp,A.getInteger(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure CopyLongProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setLong(AProp,A.getLong(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure CopyShortProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setShort(AProp,A.getShort(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure CopyStringProperty(const A,B : ISDODataObject; const AProp : ISDOProperty);
+begin
+  if A.isSet(AProp) then begin
+    if A.isNull(AProp) then
+      B.setNull(AProp)
+    else
+      B.setString(AProp,A.getString(AProp));
+  end else begin
+    B.unset(AProp);
+  end;
+end;
+
+procedure CopyListBool(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getBoolean());
+end;
+
+procedure CopyListByte(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getByte());
+end;
+
+procedure CopyListDate(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getDate());
+end;
+
+procedure CopyListInteger(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getInteger());
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure CopyListLong(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getLong());
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure CopyListShort(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getShort());
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure CopyListObjectRef(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getDataObject());
+end;
+
+procedure CopyListString(const A,B : ISDODataObjectList);
+begin
+  B.append(A.getString());
+end;
+
+var
+  ValueCopyFunctions : array[TSDOTypeKind] of TCopyProcRecord =(
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyBoolProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListBool ), // BooleanType,
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyByteProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListByte ), //ByteType,
+{$IFDEF HAS_SDO_BYTES}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyBytesProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListBytes ), //BytesType,
+{$ENDIF HAS_SDO_BYTES}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}NotImplementedSimplePROC; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}NotImplementedListPROC ), //ChangeSummaryType,
+{$IFDEF HAS_SDO_CHAR}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyCharProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListChar ), //CharacterType,
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyCurrencyProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListCurrency ), //CurrencyType,
+{$ENDIF HAS_SDO_CURRENCY}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyDateProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListDate ), //DateTimeType,
+{$IFDEF HAS_SDO_DOUBLE}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyDoubleProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListDouble ), //DoubleType,
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyFloatProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListFloat ), //FloatType,
+{$ENDIF HAS_SDO_FLOAT}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyIntegerProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListInteger ), //IntegerType,
+{$IFDEF HAS_SDO_LONG}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyLongProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListLong ), //LongType,
+{$ENDIF HAS_SDO_LONG}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}NotImplementedSimplePROC; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListObjectRef ), //ObjectType,
+{$IFDEF HAS_SDO_SHORT}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyShortProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListShort ), //ShortType,
+{$ENDIF HAS_SDO_SHORT}
+    ( Simple : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyStringProperty; List : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyListString ) //StringType,
+
+  );
+
+procedure CopySimpleList(
+  const ASource, ADest : ISDODataObjectList;
+  const AType : TSDOTypeKind
+);
+var
+  crsA : ILinkedListCursor;
+  func : TListTypeCopyProc;
+  bmkA : TLinkedListBookmark;
+begin
+//  if not ( AType in SDODataTypeKinds ) then
+  //  raise ESDOIllegalArgumentException.Create('AType');
+  func := ValueCopyFunctions[AType].List;
+  crsA := ASource.getCursor();
+  bmkA := crsA.GetBookmark();
+  try
+    crsA.Reset();
+    while crsA.MoveNext() do begin
+      func(ASource,ADest);
+    end;
+  finally
+    crsA.GotoBookmark(bmkA);
+  end;
+end;
+
+{ TSDOCopyHelper }
+
+class function TSDOCopyHelper.copy(const ADataObject: ISDODataObject): ISDODataObject;
+begin
+  Result := internalCopy(ADataObject,True);
+end;
+
+class procedure TSDOCopyHelper.copyProperty(const A, B: ISDODataObject; const AProp: ISDOProperty);
+begin
+  ValueCopyFunctions[AProp.getTypeEnum()].Simple(A,B,AProp);
+end;
+
+class procedure TSDOCopyHelper.copyPropertyList(
+  const A, B : ISDODataObjectList;
+  const AType : ISDOType;
+  const ADeepCopy : Boolean
+);
+var
+  crsA : ILinkedListCursor;
+  func : TListTypeCopyProc;
+  bmkA : TLinkedListBookmark;
+begin
+  func := ValueCopyFunctions[AType.getTypeEnum()].List;
+  crsA := A.getCursor();
+  bmkA := crsA.GetBookmark();
+  try
+    crsA.Reset();
+    if AType.isDataType() then begin
+      while crsA.MoveNext() do begin
+        func(A,B);
+      end;
+    end else begin
+      while crsA.MoveNext() do begin
+        B.append(internalCopy(A.getDataObject(),ADeepCopy));
+      end;
+    end;
+  finally
+    crsA.GotoBookmark(bmkA);
+  end;
+end;
+
+class function TSDOCopyHelper.copyShallow(const ADataObject: ISDODataObject): ISDODataObject;
+begin
+  Result := internalCopy(ADataObject,False);
+end;
+
+class function TSDOCopyHelper.internalCopy(
+  const ADataObject: ISDODataObject;
+  const ADeepCopy: Boolean
+) : ISDODataObject;
+var
+  locType, locPropType : ISDOType;
+  a, b : ISDODataObject;
+  al, bl : ISDODataObjectList;
+  locProps : ISDOPropertyList;
+  locProp : ISDOProperty;
+  i, c : PtrInt;
+begin
+  if ( ADataObject = nil ) then begin
+    b := nil;
+  end else begin
+    a := ADataObject;
+    locType := ADataObject.getType();
+    locProps := locType.getProperties();
+    b := locType.getOwner().CreateNew(locType);
+    c := locProps.getCount();
+    for i := 0 to Pred(c) do begin
+      locProp := locProps.getItem(i);
+      if not locProp.isReadOnly() then begin
+        locPropType := locProp.getType();
+        if locProp.isMany() then begin
+          al := a.getList(locProp);
+          bl := b.getList(locProp);
+          copyPropertyList(al,bl,locPropType,ADeepCopy);
+        end else begin
+          if locPropType.isDataType() then
+            copyProperty(a,b,locProp)
+          else if locPropType.isDataObjectType() then
+            b.setDataObject(locProp,internalCopy(a.getDataObject(locProp),ADeepCopy));
+        end;
+      end;
+    end;
+  end;
+  Result := b;
+end;
+
+
+type
+  TSimpleTypeCompareFunction = function (const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+  TListTypeCompareFunction = function (const A,B : ISDODataObjectList) : Boolean;
+  TCompareFunctionRecord = record
+    SimpleFunction : TSimpleTypeCompareFunction;
+    ListFunction   : TListTypeCompareFunction;
+  end;
+
+{$WARNINGS OFF}
+function NotImplementedSimpleFUNC(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  raise ESDONotImplementedException.Create('');
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function NotImplementedListFUNC(const A,B : ISDODataObjectList) : Boolean;
+begin
+  raise ESDONotImplementedException.Create('');
+end;
+{$WARNINGS ON}
+
+{$IFNDEF EQUALITY_USE_SET_NULL}
+function CompareBoolProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getBoolean(AProp.getName()) = B.getBoolean(AProp.getName()) );
+end;
+
+function CompareByteProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getByte(AProp.getName()) = B.getByte(AProp.getName()) );
+end;
+
+function CompareDateProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ValueEquals(A.getDate(AProp.getName()),B.getDate(AProp.getName()));
+end;
+
+function CompareIntegerProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getInteger(AProp.getName()) = B.getInteger(AProp.getName()) );
+end;
+
+function CompareStringProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getString(AProp.getName()) = B.getString(AProp.getName()) );
+end;
+{$ENDIF EQUALITY_USE_SET_NULL}
+
+{$IFDEF EQUALITY_USE_SET_NULL}
+function CompareBoolProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( ( A.isSet(AProp.getName()) = False ) and
+              ( B.isSet(AProp.getName()) = False )
+            ) or
+            ( ( ( A.isSet(AProp.getName()) = True ) and
+                ( B.isSet(AProp.getName()) = True )
+              ) and
+              ( A.getBoolean(AProp.getName()) = B.getBoolean(AProp.getName()) )
+            ) ;
+end;
+
+function CompareByteProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( ( A.isSet(AProp.getName()) = False ) and
+              ( B.isSet(AProp.getName()) = False )
+            ) or
+            ( ( ( A.isSet(AProp.getName()) = True ) and
+                ( B.isSet(AProp.getName()) = True )
+              ) and
+              ( A.getByte(AProp.getName()) = B.getByte(AProp.getName()) )
+            ) ;
+end;
+
+function CompareIntegerProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( ( A.isSet(AProp.getName()) = False ) and
+              ( B.isSet(AProp.getName()) = False )
+            ) or
+            ( ( ( A.isSet(AProp.getName()) = True ) and
+                ( B.isSet(AProp.getName()) = True )
+              ) and
+              ( A.getInteger(AProp.getName()) = B.getInteger(AProp.getName()) )
+            ) ;
+end;
+
+function CompareStringProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( ( A.isSet(AProp.getName()) = False ) and
+              ( B.isSet(AProp.getName()) = False )
+            ) or
+            ( ( ( A.isSet(AProp.getName()) = True ) and
+                ( B.isSet(AProp.getName()) = True )
+              ) and
+              ( A.getString(AProp.getName()) = B.getString(AProp.getName()) )
+            ) ;
+end;
+
+{$ENDIF EQUALITY_USE_SET_NULL}
+
+function CompareListChangeSummary(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := True;
+end;
+
+function CompareChangeSummaryProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := True;
+end;
+
+function CompareListBool(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getBoolean() = B.getBoolean() );
+end;
+
+function CompareListByte(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getByte() = B.getByte() );
+end;
+
+function CompareListDate(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ValueEquals(A.getDate(),B.getDate());
+end;
+
+function CompareListInteger(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getInteger() = B.getInteger() );
+end;
+
+function CompareListString(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getString() = B.getString() );
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+function CompareBytesProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+var
+  av, bv : TSDOBytes;
+begin
+  av := A.getBytes(AProp.getName());
+  bv := B.getBytes(AProp.getName());
+  Result := ( ( av = nil ) and ( bv = nil ) ) or
+            ( ( av <> nil ) and ( bv <> nil) and ( Length(av) = Length(bv) ) and CompareMem(Pointer(av),Pointer(av),Length(av)) );
+end;
+
+function CompareListBytes(const A,B : ISDODataObjectList) : Boolean;
+var
+  av, bv : TSDOBytes;
+begin
+  av := A.getBytes();
+  bv := B.getBytes();
+  Result := ( ( av = nil ) and ( bv = nil ) ) or
+            ( ( av <> nil ) and ( bv <> nil) and ( Length(av) = Length(bv) ) and CompareMem(Pointer(av),Pointer(av),Length(av)) );
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+function CompareCharProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getCharacter(AProp.getName()) = B.getCharacter(AProp.getName()) );
+end;
+
+function CompareListChar(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getCharacter() = B.getCharacter() );
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+function CompareCurrencyProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getCurrency(AProp.getName()) = B.getCurrency(AProp.getName()) );
+end;
+
+function CompareListCurrency(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getCurrency() = B.getCurrency() );
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+function CompareDoubleProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getDouble(AProp.getName()) = B.getDouble(AProp.getName()) );
+end;
+
+function CompareListDouble(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getDouble() = B.getDouble() );
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+function CompareFloatProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getFloat(AProp.getName()) = B.getFloat(AProp.getName()) );
+end;
+
+function CompareListFloat(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getFloat() = B.getFloat() );
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+function CompareLongProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getLong(AProp.getName()) = B.getLong(AProp.getName()) );
+end;
+
+function CompareListLong(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getLong() = B.getLong() );
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+function CompareShortProperty(const A,B : ISDODataObject; const AProp : ISDOProperty) : Boolean;
+begin
+  Result := ( A.getShort(AProp.getName()) = B.getShort(AProp.getName()) );
+end;
+
+function CompareListShort(const A,B : ISDODataObjectList) : Boolean;
+begin
+  Result := ( A.getShort() = B.getShort() );
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+var
+  ValueCompareFunctions : array[TSDOTypeKind] of TCompareFunctionRecord =(
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareBoolProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListBool ), // BooleanType,
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareByteProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListByte ), //ByteType,
+{$IFDEF HAS_SDO_BYTES}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareBytesProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListBytes ), //BytesType,
+{$ENDIF HAS_SDO_BYTES}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareChangeSummaryProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListChangeSummary ), //ChangeSummaryType,
+{$IFDEF HAS_SDO_CHAR}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareCharProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListChar ), //CharacterType,
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareCurrencyProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListCurrency ), //CurrencyType,
+{$ENDIF HAS_SDO_CURRENCY}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareDateProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListDate ), //DateTimeType,
+{$IFDEF HAS_SDO_DOUBLE}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareDoubleProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListDouble ), //DoubleType,
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareFloatProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListFloat ), //FloatType,
+{$ENDIF HAS_SDO_FLOAT}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareIntegerProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListInteger ), //IntegerType,
+{$IFDEF HAS_SDO_LONG}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareLongProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListLong ), //LongType,
+{$ENDIF HAS_SDO_LONG}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}NotImplementedSimpleFUNC; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}NotImplementedListFUNC ), //ObjectType,
+{$IFDEF HAS_SDO_SHORT}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareShortProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListShort ), //ShortType,
+{$ENDIF HAS_SDO_SHORT}
+    ( SimpleFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareStringProperty; ListFunction : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListString ) //StringType,
+
+  );
+
+(*procedure Init();
+begin
+  FillChar(ValueCompareFunctions,SizeOf(ValueCompareFunctions),#0);
+  ValueCompareFunctions[BooleanType].SimpleFunction := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareBoolProperty;
+    ValueCompareFunctions[BooleanType].ListFunction := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListBool;
+  ValueCompareFunctions[IntegerType].SimpleFunction := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareIntegerProperty;
+    ValueCompareFunctions[IntegerType].ListFunction := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListInteger;
+  ValueCompareFunctions[StringType].SimpleFunction  := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareStringProperty;
+    ValueCompareFunctions[StringType].ListFunction  := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CompareListString;
+end;
+*)
+
+{ TSDOEqualityHelper }
+
+class function TSDOEqualityHelper.CompareList(
+  const A,B: ISDODataObjectList;
+  const AType : ISDOType
+) : Boolean;
+var
+  c : PtrInt;
+  crsA, crsB : ISDOCursor;
+  ok : Boolean;
+  func : TListTypeCompareFunction;
+  bmkA, bmkB : ISDOCursorBookmark;
+begin
+  if ( A = nil ) and ( B = nil ) then begin
+    Result := True;
+  end else if ( A <> nil ) and ( B <> nil ) then begin
+    Result := False;
+    c := A.size();
+    if ( c = B.size() ) then begin
+      ok := True;
+      if ( c > 0 ) then begin
+        func := ValueCompareFunctions[AType.getTypeEnum()].ListFunction;
+        crsA := A.getCursor();
+        crsB := B.getCursor();
+        bmkA := crsA.GetBookmark();
+        bmkB := crsB.GetBookmark();
+        try
+          crsA.Reset();
+          crsB.Reset();
+          if AType.isDataType() then begin
+            while crsA.MoveNext() do begin
+              if not ( crsB.MoveNext() and func(A,B) ) then begin
+                ok := False;
+                Break;
+              end;
+            end;
+          end else begin
+            while crsA.MoveNext() do begin
+              if not ( crsB.MoveNext() and InternalEqual(A.getDataObject(),B.getDataObject(),True) ) then begin
+                ok := False;
+                Break;
+              end;
+            end;
+          end;
+        finally
+          crsB.GotoBookmark(bmkB);
+          crsA.GotoBookmark(bmkA);
+        end;
+      end;
+      Result := ok;
+    end;
+  end else begin
+    Result := False;
+  end;
+end;
+
+class function TSDOEqualityHelper.CompareProperty(
+  const A, B : ISDODataObject;
+  const AProp : ISDOProperty
+) : Boolean;
+begin
+  Result := ValueCompareFunctions[AProp.getTypeEnum()].SimpleFunction(A,B,AProp);
+end;
+
+class function TSDOEqualityHelper.equal(const A, B: ISDODataObject): Boolean;
+begin
+  Result := InternalEqual(A,B,True);
+end;
+
+class function TSDOEqualityHelper.equalShallow(const A,B: ISDODataObject): Boolean;
+begin
+  Result := InternalEqual(A,B,False);
+end;
+
+class function TSDOEqualityHelper.InternalEqual(
+  const A, B: ISDODataObject;
+  const AFullCompare: Boolean
+) : Boolean;
+var
+  i, c : PtrInt;
+  plsA, plsB : ISDOPropertyList;
+  ok : Boolean;
+  pA, pB : ISDOProperty;
+begin
+  if ( A = nil ) and ( B = nil ) then begin
+    Result := True;
+  end else if ( A <> nil ) and ( B <> nil ) then begin
+    Result := False;
+    if A.getType().equals(B.getType()) then begin
+      plsA := A.getInstanceProperties();
+      plsB := B.getInstanceProperties();
+      c := plsA.getCount();
+      if ( c = plsB.getCount() ) then begin
+        ok := True;
+        if ( c > 0 ) then begin
+          for i := 0 to Pred(c) do begin
+            pA := plsA.getItem(i);
+            pB := plsB.find(pA.getName());
+            if ( pB = nil ) then begin
+              ok := False;
+              Break;
+            end;
+            if ( pA.getType().isDataType() <> pB.getType().isDataType() ) then begin
+              ok := False;
+              Break;
+            end;
+            if pA.getType().isDataType() then begin
+              if pA.isMany() then
+                ok := CompareList(A.getList(pA),B.getList(pB),pA.getType())
+              else
+                ok := CompareProperty(A,B,pA);
+              if not ok then
+                Break;
+            end else if AFullCompare then begin
+              if pA.isMany() then
+                ok := CompareList(A.getList(pA),B.getList(pB),pA.getType())
+              else
+                ok := InternalEqual(A.getDataObject(pA.getName()),B.getDataObject(pA.getName()),True);
+              if not ok then
+                Break;
+            end;
+          end;
+        end;
+        if ok then
+          Result := True;
+      end;
+    end;
+  end else begin
+    Result := False;
+  end;
+end;
+
+
+initialization
+{$IFDEF DELPHI}
+  GetLocaleFormatSettings(GetThreadLocale(),ConverterFormatSetting);
+{$ENDIF}
+{$IFDEF FPC}
+  ConverterFormatSetting := DefaultFormatSettings;
+{$ENDIF}
+  ConverterFormatSetting.DecimalSeparator := '.';
+
+end.

+ 699 - 0
packages/fcl-sdo/src/base/sdo_binary_streamer.pas

@@ -0,0 +1,699 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements basic SDO serialization for RTTI
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+{$RANGECHECKS OFF}
+unit sdo_binary_streamer;
+
+interface
+
+uses
+  Classes, SysUtils, Types, sdo_types;
+
+Const
+  MAX_ARRAY_LENGTH = 1024*1024;
+
+Type
+
+  TInt8U  = Byte; TInt8S  = ShortInt;
+  TInt16U = Word; TInt16S = SmallInt;
+  TInt32U = LongWord; TInt32S = LongInt;
+  TInt64S = Int64; TInt64U = QWord;
+  TBoolData = Boolean;
+  TEnumData = Int64;
+  TAnsiStringData = TBinaryString;
+  TWideStringData = WideString;
+{$IFDEF USE_UNICODE}
+  TUnicodeStringData = UnicodeString;
+  UnicodeChar = WideChar;
+{$ELSE USE_UNICODE}
+  UnicodeString = WideString;
+  TUnicodeStringData = UnicodeString;
+  UnicodeChar = WideChar;
+{$ENDIF USE_UNICODE}
+  TAnsiCharacter = AnsiChar;
+  TWideCharacter = WideChar;
+  TByteDynArray = sdo_types.TByteDynArray;
+  
+  TFloat_Single_4    = Single;
+  TFloat_Double_8    = Double;
+  TFloat_Extended_10 = Extended;
+  TFloat_Currency_8  = Currency;
+
+  IDataStore = Interface
+    ['{CA767A0E-7660-4765-9959-6960A69B1660}']
+    procedure WriteInt8U(Const AData : TInt8U);
+    procedure WriteInt8S(Const AData : TInt8S);
+    
+    procedure WriteInt16U(Const AData : TInt16U);
+    procedure WriteInt16S(Const AData : TInt16S);
+
+    procedure WriteInt32U(Const AData : TInt32U);
+    procedure WriteInt32S(Const AData : TInt32S);
+    
+    procedure WriteInt64U(Const AData : TInt64U);
+    procedure WriteInt64S(Const AData : TInt64S);
+    
+    procedure WriteBool(Const AData : TBoolData);
+    procedure WriteAnsiChar(const AData : TAnsiCharacter);
+    procedure WriteWideChar(const AData : TWideCharacter);
+    procedure WriteEnum(Const AData : TEnumData);
+    procedure WriteAnsiStr(Const AData : TAnsiStringData);
+    procedure WriteWideStr(Const AData : TWideStringData);
+{ $IFDEF USE_UNICODE}
+    procedure WriteUnicodeStr(Const AData : TUnicodeStringData);
+{ $ENDIF USE_UNICODE}
+    procedure WriteBinary(const AData : TByteDynArray);
+    
+    procedure WriteSingle(Const AData : TFloat_Single_4);
+    procedure WriteDouble(Const AData : TFloat_Double_8);
+    procedure WriteExtended(Const AData : TFloat_Extended_10);
+    procedure WriteCurrency(Const AData : TFloat_Currency_8);
+  End;
+
+  IDataStoreReader = Interface
+    ['{AF50317E-6DD6-40C5-A2F6-3ED5F478564F}']
+    function IsAtEof():Boolean;
+    function ReadInt8U():TInt8U;
+    function ReadInt8S():TInt8S;
+    
+    function ReadInt16U():TInt16U;
+    function ReadInt16S():TInt16S;
+
+    function ReadInt32U():TInt32U;
+    function ReadInt32S():TInt32S;
+
+    function ReadInt64U():TInt64U;
+    function ReadInt64S():TInt64S;
+    
+    function ReadBool():TBoolData;
+    function ReadAnsiChar() : TAnsiCharacter;
+    function ReadWideChar() : TWideCharacter;
+    function ReadEnum():TEnumData;
+    function ReadAnsiStr():TAnsiStringData;
+    function ReadWideStr():TWideStringData;
+{ $IFDEF USE_UNICODE}
+    function ReadUnicodeStr():TUnicodeStringData;
+{ $ENDIF USE_UNICODE}
+    function ReadBinary() : TByteDynArray;
+
+    function ReadSingle():TFloat_Single_4;
+    function ReadDouble():TFloat_Double_8;
+    function ReadExtended():TFloat_Extended_10;
+    function ReadCurrency():TFloat_Currency_8;
+  End;
+
+  function CreateBinaryReader(AStream : TStream):IDataStoreReader;
+  function CreateBinaryWriter(AStream : TStream):IDataStore;
+  
+{These routines transform their argument to "Big Endian" alignment}
+  procedure ReverseBytes(var AData; const ALength : Integer);{$IFDEF USE_INLINE}{$IFDEF ENDIAN_BIG}inline;{$ENDIF}{$ENDIF}
+  function Reverse_16(const AValue:Word):Word;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function Reverse_32(const AValue:DWord):DWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function Reverse_64(const AValue:QWord):QWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  
+  function Reverse_Single(const AValue:Single):Single;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function Reverse_Double(const AValue:Double):Double;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function Reverse_Extended(const AValue:Extended):Extended;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function Reverse_Currency(const AValue:Currency):Currency;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+implementation
+
+{$IFDEF ENDIAN_BIG}
+procedure ReverseBytes(var AData; const ALength : Integer); {$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+end;
+{$ELSE} // assume ENDIAN_LITTLE
+procedure ReverseBytes(var AData; const ALength : Integer);
+Var
+  i,j : PtrInt;
+  c : Byte;
+  pDt : {$IFDEF FPC}^Byte{$ELSE}PByteArray{$ENDIF};
+begin
+  pDt := @AData;
+  j := ALength div 2;
+  For i := 0 To Pred(j) Do Begin
+    c := pDt{$IFNDEF FPC}^{$ENDIF}[i];
+    pDt[i] := pDt[(ALength - 1 ) - i];
+    pDt[(ALength - 1 ) - i] := c;
+  End;
+end;
+{$ENDIF}
+
+function Reverse_16(const AValue:Word):Word;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := AValue;
+  ReverseBytes(Result,2)
+end;
+
+function Reverse_32(const AValue:DWord):DWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := AValue;
+  ReverseBytes(Result,4)
+end;
+
+function Reverse_64(const AValue:QWord):QWord;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := AValue;
+  ReverseBytes(Result,8)
+end;
+
+function Reverse_Single(const AValue:Single):Single;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := AValue;
+  ReverseBytes(Result,4)
+end;
+
+function Reverse_Double(const AValue:Double):Double;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := AValue;
+  ReverseBytes(Result,8)
+end;
+
+function Reverse_Extended(const AValue:Extended):Extended;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := AValue;
+  ReverseBytes(Result,10);
+end;
+
+function Reverse_Currency(const AValue:Currency):Currency;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := AValue;
+  ReverseBytes(Result,8);
+end;
+
+{$IFDEF ENDIAN_BIG}
+procedure Reverse_Array(var AValue; const AArrayLength, AItemSize : PtrInt);{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+end;
+{$ELSE ENDIAN_BIG}
+procedure Reverse_Array(var AValue; const AArrayLength, AItemSize : PtrInt);
+var
+  p : PByte;
+  i : PtrInt;
+begin
+  if ( AArrayLength > 0 ) and ( AItemSize > 1 ) then begin
+    p := @AValue;
+    for i := 0 to Pred(AArrayLength) do begin
+      ReverseBytes(p^,AItemSize);
+      Inc(p,AItemSize);
+    end;
+  end;
+end;
+{$ENDIF ENDIAN_BIG}
+
+Type
+  { TDataStore }
+
+  TDataStore = class(TInterfacedObject,IDataStore)
+  Private
+    FStream : TStream;
+  Protected
+    procedure WriteInt8U(Const AData : TInt8U);
+    procedure WriteInt8S(Const AData : TInt8S);
+    
+    procedure WriteInt16U(Const AData : TInt16U);
+    procedure WriteInt16S(Const AData : TInt16S);
+
+    procedure WriteInt32U(Const AData : TInt32U);
+    procedure WriteInt32S(Const AData : TInt32S);
+
+    procedure WriteInt64U(Const AData : TInt64U);
+    procedure WriteInt64S(Const AData : TInt64S);
+    
+    procedure WriteBool(Const AData : TBoolData);
+    procedure WriteAnsiChar(const AData : TAnsiCharacter);
+    procedure WriteWideChar(const AData : TWideCharacter);
+    procedure WriteEnum(Const AData : TEnumData);
+    procedure WriteAnsiStr(Const AData : TAnsiStringData);
+    procedure WriteWideStr(Const AData : TWideStringData);
+{ $IFDEF USE_UNICODE}
+    procedure WriteUnicodeStr(Const AData : TUnicodeStringData);
+{ $ENDIF USE_UNICODE}
+    procedure WriteBinary(const AData : TByteDynArray);
+    
+    procedure WriteSingle(Const AData : TFloat_Single_4);
+    procedure WriteDouble(Const AData : TFloat_Double_8);
+    procedure WriteExtended(Const AData : TFloat_Extended_10);
+    procedure WriteCurrency(Const AData : TFloat_Currency_8);
+  Public
+    constructor Create(AStream : TStream);
+  End;
+
+  { TDataStoreReader }
+
+  TDataStoreReader = class(TInterfacedObject,IDataStoreReader)
+  Private
+    FStream : TStream;
+  Protected
+    function IsAtEof():Boolean;
+    function ReadInt8U():TInt8U;
+    function ReadInt8S():TInt8S;
+    
+    function ReadInt16U():TInt16U;
+    function ReadInt16S():TInt16S;
+
+    function ReadInt32U():TInt32U;
+    function ReadInt32S():TInt32S;
+    
+    function ReadInt64U():TInt64U;
+    function ReadInt64S():TInt64S;
+    
+    function ReadBool():TBoolData;
+    function ReadAnsiChar() : TAnsiCharacter;
+    function ReadWideChar() : TWideCharacter;
+    function ReadEnum():TEnumData;
+    function ReadAnsiStr():TAnsiStringData;
+    function ReadWideStr():TWideStringData;
+{ $IFDEF USE_UNICODE}
+    function ReadUnicodeStr():TUnicodeStringData;
+{ $ENDIF USE_UNICODE}
+    function ReadBinary() : TByteDynArray;
+
+    function ReadSingle():TFloat_Single_4;
+    function ReadDouble():TFloat_Double_8;
+    function ReadExtended():TFloat_Extended_10;
+    function ReadCurrency():TFloat_Currency_8;
+  Public
+    constructor Create(AStream : TStream);
+  End;
+
+function CreateBinaryWriter(AStream : TStream):IDataStore;
+begin
+  Result := TDataStore.Create(AStream) As IDataStore;
+end;
+
+function CreateBinaryReader(AStream : TStream):IDataStoreReader;
+begin
+  Result := TDataStoreReader.Create(AStream) As IDataStoreReader;
+end;
+
+{ TDataStore }
+
+procedure TDataStore.WriteInt8U(const AData: TInt8U);
+begin
+  FStream.Write(AData,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt8S(const AData: TInt8S);
+begin
+  FStream.Write(AData,SizeOf(AData));
+end;
+
+{$IFDEF FPC}
+procedure TDataStore.WriteInt16U(const AData: TInt16U);
+begin
+  FStream.Write(Reverse_16(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt16S(const AData: TInt16S);
+begin
+  FStream.Write(Reverse_16(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt32U(const AData: TInt32U);
+begin
+  FStream.Write(Reverse_32(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt32S(const AData: TInt32S);
+begin
+  FStream.Write(Reverse_32(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt64U(const AData: TInt64U);
+begin
+  FStream.Write(Reverse_64(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt64S(const AData: TInt64S);
+begin
+  FStream.Write(Reverse_64(AData),SizeOf(AData));
+end;
+{$ELSE}
+procedure TDataStore.WriteInt16U(const AData: TInt16U);
+var
+  bffr : TInt16U;
+begin
+  bffr := Reverse_16(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt16S(const AData: TInt16S);
+var
+  bffr : TInt16U;
+begin
+  bffr := Reverse_16(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt32U(const AData: TInt32U);
+var
+  bffr : TInt32U;
+begin
+  bffr := Reverse_32(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt32S(const AData: TInt32S);
+var
+  bffr : TInt32U;
+begin
+  bffr := Reverse_32(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt64U(const AData: TInt64U);
+var
+  bffr : TInt64U;
+begin
+  bffr := Reverse_64(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteInt64S(const AData: TInt64S);
+var
+  bffr : TInt64U;
+begin
+  bffr := Reverse_64(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+{$ENDIF}
+
+procedure TDataStore.WriteBool(const AData: TBoolData);
+Var
+  i : TInt8U;
+begin
+  If AData Then
+    i := 1
+  Else
+    i := 0;
+  WriteInt8U(i);
+end;
+
+procedure TDataStore.WriteAnsiChar(const AData: TAnsiCharacter);
+begin
+  WriteInt8U(Ord(AData));
+end;
+
+procedure TDataStore.WriteWideChar(const AData: TWideCharacter);
+begin
+  WriteInt16U(Ord(AData));
+end;
+
+procedure TDataStore.WriteEnum(const AData: TEnumData);
+begin
+  WriteInt64S(AData);
+end;
+
+procedure TDataStore.WriteAnsiStr(const AData: TAnsiStringData);
+Var
+  i : TInt32S;
+begin
+  i := Length(AData);
+  WriteInt32S(i);
+  If ( i > 0 ) Then
+    FStream.Write(AData[1],i);
+end;
+
+procedure TDataStore.WriteWideStr(const AData: TWideStringData);
+
+  procedure LocalWrite();
+  var
+    locData : TWideStringData;
+  begin
+    locData := AData;
+    UniqueString(locData);
+    Reverse_Array(Pointer(locData)^,Length(locData),SizeOf(WideChar));
+    FStream.Write(Pointer(locData)^, ( Length(locData) * SizeOf(WideChar) ) );
+  end;
+
+var
+  i : TInt32S;
+begin
+  i := Length(AData);
+  WriteInt32S(i);
+  if ( i > 0 ) then begin
+    LocalWrite();
+  end;
+end;
+
+procedure TDataStore.WriteBinary(const AData : TByteDynArray);
+var
+  i : TInt32S;
+begin
+  i := Length(AData);
+  WriteInt32S(i);
+  if ( i > 0 ) then
+    FStream.Write(AData[0],i);
+end;
+
+{ $IFDEF USE_UNICODE}
+procedure TDataStore.WriteUnicodeStr(const AData: TUnicodeStringData);
+
+  procedure LocalWrite();
+  var
+    locData : TUnicodeStringData;
+  begin
+    locData := AData;
+    UniqueString(locData);
+    Reverse_Array(Pointer(locData)^,Length(locData),SizeOf(UnicodeChar));
+    FStream.Write(Pointer(locData)^, ( Length(locData) * SizeOf(UnicodeChar) ) );
+  end;
+
+var
+  i : TInt32S;
+begin
+  i := Length(AData);
+  WriteInt32S(i);
+  if ( i > 0 ) then begin
+    LocalWrite();
+  end;
+end;
+{ $ENDIF USE_UNICODE}
+
+{
+procedure TDataStore.WriteSingle(const AData: TFloat_Single_4);
+begin
+  FStream.Write(Reverse_Single(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteDouble(const AData: TFloat_Double_8);
+begin
+  FStream.Write(Reverse_Double(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteExtended(const AData: TFloat_Extended_10);
+begin
+  FStream.Write(Reverse_Extended(AData),SizeOf(AData));
+end;
+
+procedure TDataStore.WriteCurrency(const AData: TFloat_Currency_8);
+begin
+  FStream.Write(Reverse_Currency(AData),SizeOf(AData));
+end;
+}
+procedure TDataStore.WriteSingle(const AData: TFloat_Single_4);
+var
+  bffr : TFloat_Single_4;
+begin
+  bffr := Reverse_Single(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteDouble(const AData: TFloat_Double_8);
+var
+  bffr : TFloat_Double_8;
+begin
+  bffr := Reverse_Double(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteExtended(const AData: TFloat_Extended_10);
+var
+  bffr : TFloat_Extended_10;
+begin
+  bffr := Reverse_Extended(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+procedure TDataStore.WriteCurrency(const AData: TFloat_Currency_8);
+var
+  bffr : TFloat_Currency_8;
+begin
+  bffr := Reverse_Currency(AData);
+  FStream.Write(bffr,SizeOf(AData));
+end;
+
+constructor TDataStore.Create(AStream: TStream);
+begin
+  Assert(Assigned(AStream));
+  FStream := AStream;
+end;
+
+{ TDataStoreReader }
+
+function TDataStoreReader.IsAtEof(): Boolean;
+begin
+  Result := ( FStream.Position >= FStream.Size );
+end;
+
+{$HINTS OFF}
+function TDataStoreReader.ReadInt8U(): TInt8U;
+begin
+  FStream.Read(Result,SizeOf(Result));
+end;
+
+function TDataStoreReader.ReadInt8S(): TInt8S;
+begin
+  FStream.Read(Result,SizeOf(Result));
+end;
+
+function TDataStoreReader.ReadInt16U(): TInt16U;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_16(Result);
+end;
+
+function TDataStoreReader.ReadInt16S(): TInt16S;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_16(Result);
+end;
+
+function TDataStoreReader.ReadInt32U(): TInt32U;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_32(Result);
+end;
+
+function TDataStoreReader.ReadInt32S(): TInt32S;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_32(Result);
+end;
+
+function TDataStoreReader.ReadInt64U(): TInt64U;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_64(Result);
+end;
+
+function TDataStoreReader.ReadInt64S(): TInt64S;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_64(Result);
+end;
+{$HINTS ON}
+
+function TDataStoreReader.ReadBool(): TBoolData;
+begin
+  Result := ( ReadInt8U() > 0 );
+end;
+
+function TDataStoreReader.ReadAnsiChar(): TAnsiCharacter;
+begin
+  Result := TAnsiCharacter(ReadInt8U());
+end;
+
+function TDataStoreReader.ReadWideChar(): TWideCharacter;
+begin
+  Result := TWideCharacter(ReadInt16U());
+end;
+
+function TDataStoreReader.ReadEnum(): TEnumData;
+begin
+  Result := ReadInt64S();
+end;
+
+function TDataStoreReader.ReadAnsiStr(): TAnsiStringData;
+Var
+  i : TInt32S;
+begin
+  i := ReadInt32S();
+  SetLength(Result,i);
+  If ( i > 0 ) Then
+    FStream.ReadBuffer(Result[1],i);
+end;
+
+function TDataStoreReader.ReadWideStr(): TWideStringData;
+var
+  i : TInt32S;
+begin
+  i := ReadInt32S();
+  SetLength(Result,i);
+  if ( i > 0 ) then begin
+    FStream.ReadBuffer(Pointer(Result)^, ( i * SizeOf(WideChar) ) );
+    Reverse_Array(Pointer(Result)^,i,SizeOf(WideChar));
+  end;
+end;
+
+function TDataStoreReader.ReadBinary() : TByteDynArray;
+var
+  i : TInt32S;
+begin
+  i := ReadInt32S();
+  SetLength(Result,i);
+  if ( i > 0 ) then
+    FStream.ReadBuffer(Result[0],i);
+end;
+
+{ $IFDEF USE_UNICODE}
+function TDataStoreReader.ReadUnicodeStr(): TUnicodeStringData;
+var
+  i : TInt32S;
+begin
+  i := ReadInt32S();
+  SetLength(Result,i);
+  if ( i > 0 ) then begin
+    FStream.ReadBuffer(Pointer(Result)^, ( i * SizeOf(UnicodeChar) ) );
+    Reverse_Array(Pointer(Result)^,i,SizeOf(UnicodeChar));
+  end;
+end;
+{ $ENDIF USE_UNICODE}
+
+{$HINTS OFF}
+function TDataStoreReader.ReadSingle(): TFloat_Single_4;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_Single(Result);
+end;
+
+function TDataStoreReader.ReadDouble(): TFloat_Double_8;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_Double(Result);
+end;
+
+function TDataStoreReader.ReadExtended(): TFloat_Extended_10;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_Extended(Result);
+end;
+
+function TDataStoreReader.ReadCurrency(): TFloat_Currency_8;
+begin
+  FStream.Read(Result,SizeOf(Result));
+  Result := Reverse_Currency(Result);
+end;
+{$HINTS ON}
+
+constructor TDataStoreReader.Create(AStream: TStream);
+begin
+  Assert(Assigned(AStream));
+  FStream := AStream;
+end;
+
+end.

+ 2535 - 0
packages/fcl-sdo/src/base/sdo_changesummary.pas

@@ -0,0 +1,2535 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements the change summary handling
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+{ some notes :
+    > DataObject Life cycle
+        Dataobject life cycle starts by their inclusion as a containment property value of :
+          - a DataObject with an attached ChangeSummary ( the root ),
+          - a DataObject that ultime containment parent is a DataObject with an attached ChangeSummary
+        Dataobject life cycle ends when their containment parent is set to null.
+
+        It is important to note that Dataobject life cycle is a logical one, not
+        a memory reference one. Once a DataObject leave a Dataobject containment tree,
+        it will be accepted later _only_ as a new DataObject regardless of the fact that
+        it was an ancient member.
+}
+unit sdo_changesummary;
+
+interface
+uses
+  SysUtils, Classes, Contnrs,
+  sdo, sdo_types;
+
+type
+
+  TDataObjectChangeInfo = class;
+  TChangeRecorder = class;
+  TManyValuePropChanges = class;
+  TManyValuePropChangesList = class;
+
+  ISDOChangedDataObjectListEx = interface(ISDOChangedDataObjectList)
+    ['{FCF8810B-EBC0-47CF-B029-12E4C3826D83}']
+    function append(const ADataObject : ISDODataObject; const AChange : TChangeType) : TDataObjectChangeInfo;
+    function find(const ADataObject : ISDODataObject; out AIndex : PtrInt) : Boolean;
+    function getInfo(const AIndex : PtrInt) : TDataObjectChangeInfo;
+    procedure Delete(const AIndex : PtrInt);
+    procedure Extract(const AItem : TDataObjectChangeInfo);
+    procedure Clear();
+  end;
+
+  ISDOChangeSummaryEx = interface(ISDOChangeSummary)
+    ['{715F0043-8F48-4AAA-AC87-A8BFA6A135D8}']
+    function getRecorder() : TChangeRecorder;
+    // Suspends the logging without clearing the log
+    procedure suspend();
+    // resumes the logging without clearing the log
+    procedure resume();
+
+    function FindManyValueChanges(const ADataObject : ISDODataObject) : TManyValuePropChangesList;
+  end;
+
+  TSDOSettingList = class(TInterfacedObject,IInterface,ISDOSettingList)
+  private
+    FList : TObjectList;
+  private
+    procedure CheckIndex(const AIndex : PtrInt);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    function size() : PtrInt;
+    function getItem(const AIndex : PtrInt) : TValueSetting;
+    procedure insert (const AIndex : PtrInt; const ASetting : TValueSetting);
+    procedure append (const ASetting : TValueSetting);
+    procedure remove (const AIndex : PtrInt);
+  public
+    constructor Create();
+    destructor Destroy();override;
+  end;
+
+  TManyValuePropAction = ( mvpaAppend, mvpaInsert, mvpaChange, mvpaDelete );
+
+  TManyValuePropRecordData = class
+  private
+    FIndex: PtrInt;
+    FAction: TManyValuePropAction;
+    FValue: TValueBuffer;
+    FOwner: TManyValuePropChanges;
+  public
+    constructor Create(const AOwner: TManyValuePropChanges);
+    destructor Destroy();override;
+    property Owner : TManyValuePropChanges read FOwner;
+    property Action : TManyValuePropAction read FAction;
+    property Index : PtrInt read FIndex;
+    property Value : TValueBuffer read FValue;
+  end;
+
+  TManyValuePropChanges = class
+  private
+    FList : TObjectList;
+    FProp: ISDOProperty;
+  private
+    function InternalAdd(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const ALocation : PtrInt = -1
+    ) : TManyValuePropRecordData;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  public
+    constructor Create(const AProp : ISDOProperty);
+    destructor Destroy();override;
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOBoolean
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_CHAR}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOChar
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function AddCurrency(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOCurrency
+    ) : TManyValuePropRecordData;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDODouble
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOFloat
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOLong
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOShort
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+{$IFDEF HAS_SDO_BYTES}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOBytes
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_BYTES}
+
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOInteger
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : ISDODataObject
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function AddAt(
+      const ALocation : PtrInt;
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : ISDODataObject
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TValueBuffer
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOString
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDOByte
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Add(
+      const AAction : TManyValuePropAction;
+      const AIndex : PtrInt;
+      const AValue : TSDODateTime
+    ) : TManyValuePropRecordData;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Count() : PtrInt;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetItem(const AIndex : PtrInt) : TManyValuePropRecordData;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    property Prop : ISDOProperty read FProp;
+  end;
+
+  TManyValuePropChangesList = class
+  private
+    FList : TObjectList;
+  private
+    function GetItem(const AIndex: PtrInt): TManyValuePropChanges;
+  protected
+    procedure Add(const AItem : TManyValuePropChanges);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function IndexOf(const AProperty : ISDOProperty) : PtrInt;
+  public
+    constructor Create();
+    destructor Destroy();override;
+    function Count() : PtrInt; {$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Find(const AProperty : ISDOProperty) : TManyValuePropChanges;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    property Item[const AIndex : PtrInt] : TManyValuePropChanges read GetItem;default;
+  end;
+
+  TDataObjectChangeInfo = class
+  private
+    FDataObject : Pointer;
+    FChangeList : ISDOSettingList;
+    FChangeType : TChangeType;
+    FOldContainer : Pointer;
+    FOldContainmentProperty: ISDOProperty;
+    FManyValuePropChangesList : TManyValuePropChangesList;
+    // Contains the list properties that do not have their old values in FChangeList
+    FManyValuePropPending : IInterfaceList;
+    FIndex: PtrInt;
+  private
+    function GetDataObject: ISDODataObject;
+    function getOldContainer: ISDODataObject;
+  public
+    constructor Create(
+      const ADataObject : ISDODataObject;
+      const AChangeType : TChangeType
+    );
+    destructor Destroy();override;
+    procedure CaptureOldContainment();
+    //procedure SetChangeType(const AChangeType : TChangeType);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure ExtractPendingOldValues();
+    function FindChanges(const AProp : ISDOProperty) : TManyValuePropChanges;
+    function GetChanges(const AProp : ISDOProperty) : TManyValuePropChanges;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    property DataObject : ISDODataObject read GetDataObject;
+    property ChangeType : TChangeType read FChangeType;
+    property Index : PtrInt read FIndex;
+    property ChangeList : ISDOSettingList read FChangeList;
+    property OldContainer : ISDODataObject read getOldContainer;
+    property OldContainmentProperty : ISDOProperty read FOldContainmentProperty;
+    property ManyValuePropChangesList : TManyValuePropChangesList read FManyValuePropChangesList;
+  end;
+
+  TSDOChangedDataObjectList = class(
+    TInterfacedObject,
+    IInterface,
+    ISDOChangedDataObjectList,
+    ISDOChangedDataObjectListEx
+  )
+  private
+    FList : TObjectList;
+  private
+    procedure CheckIndex(const AIndex : PtrInt);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    // ISDOChangedDataObjectList
+    function size() : PtrInt;
+    function getType(const AIndex : PtrInt) : TChangeType;
+    function getDataObject(const AIndex : PtrInt) : ISDODataObject;
+    //ISDOChangedDataObjectListEx
+    function append(const ADataObject : ISDODataObject; const AChange : TChangeType) : TDataObjectChangeInfo;
+    function find(const ADataObject : ISDODataObject; out AIndex : PtrInt) : Boolean;
+    function getInfo(const AIndex : PtrInt) : TDataObjectChangeInfo;
+    procedure Delete(const AIndex : PtrInt);
+    procedure Extract(const AItem : TDataObjectChangeInfo);
+    procedure Clear();
+  public
+    constructor Create();
+    destructor Destroy();override;
+  end;
+
+  TRecordingStyle = (
+    rsDontOverwrite, rsOverwrite
+    //rsRecordNestedObjects, rsRecordNestedObjectRef, rsRecordNestedObjectCopy
+  );
+  TRecordingStyleSet = set of TRecordingStyle;
+  TChangeRecorder = class
+  private
+    FStore : ISDOChangedDataObjectListEx;
+    FOwner : Pointer; // do not keep a reference
+    FDeserializing: Boolean;
+  private
+    function GetStore() : ISDOChangedDataObjectList;
+    function GetOwner() : ISDOChangeSummaryEx;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function recordChange(
+      const ADataObject : ISDODataObject;
+      const AChangeType : TChangeType
+    ) : TDataObjectChangeInfo;overload;
+  public
+    constructor Create(
+      const AStore : ISDOChangedDataObjectList;
+      const AOwner : ISDOChangeSummary
+    );
+    property Store : ISDOChangedDataObjectList read GetStore;
+    procedure recordChange(
+      const ADataObject : ISDODataObject;
+      const AProperty   : ISDOProperty;
+      const AOptions : TRecordingStyleSet = [rsDontOverwrite]
+    );overload;
+    // this method suppose the property cursor is set to "AIndex" position
+    procedure recordChange(
+      const ADataObject : ISDODataObject;
+      const AProperty   : ISDOProperty;
+      const AIndex      : PtrInt;
+      const AAction     : TManyValuePropAction
+    );overload;
+
+    procedure recordCreation(const ADataObject : ISDODataObject);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure recordCreation(const ADataObject : ISDODataObject; const AIndex : PtrInt);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure recordDeletion(const ADataObject : ISDODataObject);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure recordDeletion(const ADataObject : ISDODataObject; const AIndex : PtrInt);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function recordUpdate(const ADataObject : ISDODataObject) : TDataObjectChangeInfo;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure UndoChangeItem(
+      const AItem : TDataObjectChangeInfo;
+      const AProcessNestedObjProps : Boolean
+    );
+
+    property Deserializing : Boolean read FDeserializing write FDeserializing;
+  end;
+
+  TSDOChangeSummary = class(
+    TInterfacedObject,
+    IInterface,
+    ISDOChangeSummary,
+    ISDOChangeSummaryEx
+  )
+  private
+    FLogging : Boolean;
+    FChangesData : ISDOChangedDataObjectListEx;
+    FRecorder : TChangeRecorder;
+  private
+    procedure Clear();
+  protected
+    function getChangedDataObjects() : ISDOChangedDataObjectList;
+    function getOldValues(const ADataObject : ISDODataObject) : ISDOSettingList;
+    function getOldXpath(const ADataObject : ISDODataObject) : string;
+    procedure beginLogging();
+    procedure endLogging();
+    function isLogging() : Boolean;
+    function isCreated(const ADataObject : ISDODataObject) : Boolean;
+    function isDeleted(const ADataObject : ISDODataObject) : Boolean;
+    function isModified(const ADataObject : ISDODataObject) : Boolean;
+    function getOldValue(const ADataObject : ISDODataObject; const AProperty : ISDOProperty) : TValueSetting;
+    function getOldContainer(const ADataObject : ISDODataObject) : ISDODataObject;
+    function getOldContainmentProperty(const ADataObject : ISDODataObject) : ISDOProperty;
+    procedure undoChanges() ;
+    //SequencePtr getOldSequence(DataObjectPtr dataObject);
+    // -- > ISDOChangeSummaryEx
+    function getRecorder() : TChangeRecorder;
+    // Suspends the logging without clearing the log
+    procedure suspend();
+    // resumes the logging without clearing the log
+    procedure resume();
+
+    function FindManyValueChanges(const ADataObject : ISDODataObject) : TManyValuePropChangesList;
+  public
+    constructor Create(const AChangesData : ISDOChangedDataObjectList);
+    destructor Destroy();override;
+  end;
+
+  {TfindDichoExtractor = function(const AList : TObjectList; const AIndex : PtrInt) : PtrInt;
+  function findDicho(
+    const AList  : TObjectList;
+    const AItem  : PtrInt;
+    out   AIndex : PtrInt;
+    const AExtractor : TfindDichoExtractor
+  ) : Boolean; }
+
+implementation
+
+uses
+  sdo_utils;
+
+{function DataObjectExtractor(const AList : TObjectList; const AIndex : PtrInt) : PtrInt;
+begin
+  Result := PtrInt(TDataObjectChangeInfo(AList[AIndex]).DataObject);
+end;
+
+function findDicho(
+  const AList  : TObjectList;
+  const AItem  : PtrInt;
+  out   AIndex : PtrInt;
+  const AExtractor : TfindDichoExtractor
+) : Boolean;
+var
+  i, j, k, betterPos, objValue, listObjvalue : PtrInt;
+  ok : Boolean;
+begin
+  ok := False;
+  if ( AList.Count = 0 ) then begin
+    betterPos := 0;
+  end else begin
+    objValue := AItem;
+    i := 1;
+    j := AList.Count;
+    ok := False;
+    while True do begin
+      k := ( i + j ) div 2;
+      listObjvalue := AExtractor(AList,(k - 1));
+      if ( listObjvalue = objValue ) then begin
+        ok := True;
+        Break;
+      end else if ( listObjvalue < objValue ) then begin
+        if ( i = j ) then begin
+          k := k + 1;
+          Break;
+        end;
+        if ( i = k ) then
+          Inc(i)
+        else
+          i := k;
+      end else begin
+        if ( i = j ) then begin
+          k := k;
+          Break;
+        end;
+        if ( j = k ) then
+          Dec(j)
+        else
+          j := k;
+      end;
+    end;
+    Dec(k);
+    betterPos := k;
+  end;
+  AIndex := betterPos;
+  Result := ok;
+end; }
+
+procedure listUndo_error(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  raise ESDONotImplementedException.CreateFmt('TListUndoItemProcs not implemented for this type : "%s".',[AItm.Owner.Prop.getType().getName()]);
+end;
+
+//--------------- START : Boolean procs -----------------------------
+procedure listUndo_append_bool(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_bool');
+  AList.delete();
+end;
+
+procedure listUndo_insert_bool(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_bool');
+  AList.delete();
+end;
+
+procedure listUndo_delete_bool(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end;
+  AList.insert(AItm.Index,AItm.Value.BooleanValue);
+end;
+
+procedure listUndo_change_bool(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_bool');
+  AList.setBoolean(AItm.Index,AItm.Value.BooleanValue);
+end;
+//--------------- END: Boolean procs -----------------------------
+
+//--------------- START : Byte procs -----------------------------
+procedure listUndo_append_byte(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_byte');
+  AList.delete();
+end;
+
+procedure listUndo_insert_byte(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_byte');
+  AList.delete();
+end;
+
+procedure listUndo_delete_byte(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_byte');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_byte');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_byte');
+  end;
+  AList.insert(AItm.Index,AItm.Value.ByteValue);
+end;
+
+procedure listUndo_change_byte(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_byte');
+  AList.setByte(AItm.Index,AItm.Value.ByteValue);
+end;
+//--------------- END: Byte procs -----------------------------
+
+{$IFDEF HAS_SDO_BYTES}
+//--------------- START : Char procs -----------------------------
+procedure listUndo_append_bytes(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_bytes');
+  AList.delete();
+end;
+
+procedure listUndo_insert_bytes(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_bytes');
+  AList.delete();
+end;
+
+procedure listUndo_delete_bytes(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_bytes');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_bytes');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_bytes');
+  end;
+  AList.insertBytes(AItm.Index,AItm.Value.BytesValue^);
+end;
+
+procedure listUndo_change_bytes(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_bytes');
+  AList.setBytes(AItm.Index,AItm.Value.BytesValue^);
+end;
+//--------------- END: Bytes procs -----------------------------
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+//--------------- START : Char procs -----------------------------
+procedure listUndo_append_char(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_char');
+  AList.delete();
+end;
+
+procedure listUndo_insert_char(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_char');
+  AList.delete();
+end;
+
+procedure listUndo_delete_char(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_char');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_char');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_char');
+  end;
+  AList.insert(AItm.Index,AItm.Value.CharValue);
+end;
+
+procedure listUndo_change_char(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_char');
+  AList.setCharacter(AItm.Index,AItm.Value.CharValue);
+end;
+//--------------- END: Char procs -----------------------------
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+//--------------- START : Currency procs -----------------------------
+procedure listUndo_append_currency(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_currency');
+  AList.delete();
+end;
+
+procedure listUndo_insert_currency(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_currency');
+  AList.delete();
+end;
+
+procedure listUndo_delete_currency(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_currency');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_currency');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_currency');
+  end;
+  AList.insertCurrency(AItm.Index,AItm.Value.CurrencyValue);
+end;
+
+procedure listUndo_change_currency(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_currency');
+  AList.setCurrency(AItm.Index,AItm.Value.CurrencyValue);
+end;
+//--------------- END: Currency procs -----------------------------
+{$ENDIF HAS_SDO_CURRENCY}
+
+//--------------- START : Date procs -----------------------------
+procedure listUndo_append_date(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_date');
+  AList.delete();
+end;
+
+procedure listUndo_insert_date(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_date');
+  AList.delete();
+end;
+
+procedure listUndo_delete_date(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_date');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_date');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_date');
+  end;
+  AList.insert(AItm.Index,AItm.Value.DateValue);
+end;
+
+procedure listUndo_change_date(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_date');
+  AList.setDate(AItm.Index,AItm.Value.DateValue);
+end;
+//--------------- END: Date procs -----------------------------
+
+{$IFDEF HAS_SDO_DOUBLE}
+//--------------- START : Double procs -----------------------------
+procedure listUndo_append_double(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_double');
+  AList.delete();
+end;
+
+procedure listUndo_insert_double(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_double');
+  AList.delete();
+end;
+
+procedure listUndo_delete_double(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_double');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_double');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_double');
+  end;
+  AList.insert(AItm.Index,AItm.Value.DoubleValue);
+end;
+
+procedure listUndo_change_double(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_double');
+  AList.setDouble(AItm.Index,AItm.Value.DoubleValue);
+end;
+//--------------- END: Double procs -----------------------------
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+//--------------- START : Float procs -----------------------------
+procedure listUndo_append_float(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_float');
+  AList.delete();
+end;
+
+procedure listUndo_insert_float(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_float');
+  AList.delete();
+end;
+
+procedure listUndo_delete_float(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_float');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_float');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_float');
+  end;
+  AList.insert(AItm.Index,AItm.Value.FloatValue);
+end;
+
+procedure listUndo_change_float(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_float');
+  AList.setFloat(AItm.Index,AItm.Value.FloatValue);
+end;
+//--------------- END: Float procs -----------------------------
+{$ENDIF HAS_SDO_FLOAT}
+
+//--------------- START : Integer procs -----------------------------
+procedure listUndo_append_integer(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_integer');
+  AList.delete();
+end;
+
+procedure listUndo_insert_integer(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_integer');
+  AList.delete();
+end;
+
+procedure listUndo_delete_integer(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_integer');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_integer');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_integer');
+  end;
+  AList.insert(AItm.Index,AItm.Value.IntegerValue);
+end;
+
+procedure listUndo_change_integer(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_integer');
+  AList.setInteger(AItm.Index,AItm.Value.IntegerValue);
+end;
+//--------------- END: Integer procs -----------------------------
+
+{$IFDEF HAS_SDO_LONG}
+//--------------- START : Long procs -----------------------------
+procedure listUndo_append_long(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_long');
+  AList.delete();
+end;
+
+procedure listUndo_insert_long(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_long');
+  AList.delete();
+end;
+
+procedure listUndo_delete_long(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_long');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_long');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_long');
+  end;
+  AList.insert(AItm.Index,AItm.Value.LongValue);
+end;
+
+procedure listUndo_change_long(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_long');
+  AList.setLong(AItm.Index,AItm.Value.LongValue);
+end;
+//--------------- END: Long procs -----------------------------
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+//--------------- START : Short procs -----------------------------
+procedure listUndo_append_short(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_short');
+  AList.delete();
+end;
+
+procedure listUndo_insert_short(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_short');
+  AList.delete();
+end;
+
+procedure listUndo_delete_short(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_short');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_short');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_short');
+  end;
+  AList.insert(AItm.Index,AItm.Value.ShortValue);
+end;
+
+procedure listUndo_change_short(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_short');
+  AList.setShort(AItm.Index,AItm.Value.ShortValue);
+end;
+//--------------- END: Short procs -----------------------------
+{$ENDIF HAS_SDO_SHORT}
+
+//--------------- START : Object procs -----------------------------
+procedure listUndo_append_object(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_object');
+  AList.delete();
+end;
+
+procedure listUndo_insert_object(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_object');
+  AList.delete();
+end;
+
+procedure listUndo_delete_object(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end;
+  AList.insert(AItm.Index,AItm.Value.ObjectValue^);
+end;
+
+procedure listUndo_change_object(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_object');
+  AList.setDataObject(AItm.Index,AItm.Value.ObjectValue^);
+end;
+//--------------- END : Object procs -----------------------------
+
+//--------------- START : String procs -----------------------------
+procedure listUndo_append_string(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveLast() then
+    raise ESDOInvalidStateOperationException.Create('listUndo_append_string');
+  AList.delete();
+end;
+
+procedure listUndo_insert_string(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_insert_string');
+  AList.delete();
+end;
+
+procedure listUndo_delete_string(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+var
+  crs : ISDOCursor;
+begin
+  crs := AList.getCursor();
+  if ( AList.size() = 0 ) then begin
+    if ( AItm.Index > 0 ) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end else if ( AList.size() = AItm.Index ) then begin
+    if not crs.MoveLast() then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end else begin
+    if not crs.MoveTo(AItm.Index) then
+      raise ESDOInvalidStateOperationException.Create('listUndo_delete_object');
+  end;
+  AList.insert(AItm.Index,AItm.Value.StringValue^);
+end;
+
+procedure listUndo_change_string(const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+begin
+  if not AList.getCursor().MoveTo(AItm.Index) then
+    raise ESDOInvalidStateOperationException.Create('listUndo_change_string');
+  AList.setString(AItm.Index,AItm.Value.StringValue^);
+end;
+//--------------- END : String procs -----------------------------
+
+
+type
+  TListUndoItemProc = procedure (const AList : ISDODataObjectList; const AItm : TManyValuePropRecordData);
+  TListUndoItemProcs = record
+    appendProc : TListUndoItemProc;
+    insertProc : TListUndoItemProc;
+    deleteProc : TListUndoItemProc;
+    changeProc : TListUndoItemProc;
+  end;
+
+var
+  LIST_UNDO_PROCS : array[TSDOTypeKind] of TListUndoItemProcs = (
+    ( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_bool;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_bool;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_bool;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_bool;
+    ), //BooleanType,
+    ( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_byte;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_byte;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_byte;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_byte;
+    ),//ByteType,
+{$IFDEF HAS_SDO_BYTES}
+   ( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_bytes;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_bytes;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_bytes;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_bytes;
+    ),//BytesType,
+{$ENDIF HAS_SDO_BYTES}
+    ( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_error;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_error;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_error;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_error;
+    ), //ChangeSummaryType,
+{$IFDEF HAS_SDO_CHAR}
+    ( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_char;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_char;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_char;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_char;
+    ), //CharacterType,
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    ( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_currency;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_currency;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_currency;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_currency;
+    ), //CurrencyType,
+{$ENDIF HAS_SDO_CURRENCY}
+    ( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_date;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_date;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_date;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_date;
+    ) //DateTimeType,
+{$IFDEF HAS_SDO_DOUBLE}
+   ,( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_double;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_double;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_double;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_double;
+    )//DoubleType,
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+   ,( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_float;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_float;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_float;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_float;
+    )//FloatType,
+{$ENDIF HAS_SDO_FLOAT}
+   ,( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_integer;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_integer;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_integer;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_integer;
+    )  //IntegerType,
+{$IFDEF HAS_SDO_LONG}
+   ,( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_long;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_long;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_long;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_long;
+    ) //LongType,
+{$ENDIF HAS_SDO_LONG}
+   ,( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_object;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_object;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_object;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_object;
+    )//ObjectType,
+{$IFDEF HAS_SDO_SHORT}
+   ,( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_short;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_short;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_short;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_short;
+    )//ShortType,
+{$ENDIF HAS_SDO_SHORT}
+   ,( appendProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_append_string;
+      insertProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_insert_string;
+      deleteProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_delete_string;
+      changeProc : {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}listUndo_change_string;
+    ) //StringType,
+
+  );
+procedure UndoChanges(
+  const AList : ISDODataObjectList;
+  const AChangesList : TManyValuePropChanges
+);
+var
+  i, c : PtrInt;
+  itm : TManyValuePropRecordData;
+  procs : TListUndoItemProcs;
+begin
+  c := AChangesList.Count;
+  if ( c > 0 ) then begin
+    procs := LIST_UNDO_PROCS[AChangesList.GetItem(0).Owner.Prop.getTypeEnum()];
+    for i := Pred(c) downto 0 do begin
+      itm := AChangesList.GetItem(i);
+      case itm.Action of
+        mvpaAppend : procs.appendProc(AList,itm);
+        mvpaInsert : procs.insertProc(AList,itm);
+        mvpaChange : procs.changeProc(AList,itm);
+        mvpaDelete : procs.deleteProc(AList,itm);
+      end;
+    end;
+  end;
+end;
+
+{ TSDOSettingList }
+
+procedure TSDOSettingList.append(const ASetting: TValueSetting);
+begin
+  if ( ASetting = nil ) then
+    raise ESDOIllegalArgumentException.Create('ASetting');
+  if ( FList.IndexOf(ASetting) = -1 ) then
+    FList.Add(ASetting);
+end;
+
+procedure TSDOSettingList.CheckIndex(const AIndex: PtrInt);
+begin
+  if ( AIndex < 0 ) or ( AIndex >= FList.Count ) then
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+end;
+
+constructor TSDOSettingList.Create();
+begin
+  inherited Create();
+  FList := TObjectList.Create(True);
+end;
+
+destructor TSDOSettingList.Destroy();
+begin
+  FList.Free();
+  inherited;
+end;
+
+function TSDOSettingList.getItem(const AIndex: PtrInt): TValueSetting;
+begin
+  CheckIndex(AIndex);
+  Result := TValueSetting(FList[AIndex]);
+end;
+
+procedure TSDOSettingList.insert(const AIndex : PtrInt; const ASetting: TValueSetting);
+begin
+  if ( ASetting = nil ) then
+    raise ESDOIllegalArgumentException.Create('ASetting');
+  if ( FList.IndexOf(ASetting) = -1 ) then begin
+    if ( AIndex <> 0 ) then
+      CheckIndex(AIndex);
+    FList.Insert(AIndex,ASetting);
+  end;
+end;
+
+procedure TSDOSettingList.remove(const AIndex: PtrInt);
+begin
+  CheckIndex(AIndex);
+  FList.Delete(AIndex);
+end;
+
+function TSDOSettingList.size() : PtrInt;
+begin
+  Result := FList.Count;
+end;
+
+{ TChangeRecorder }
+
+constructor TChangeRecorder.Create(
+  const AStore: ISDOChangedDataObjectList;
+  const AOwner : ISDOChangeSummary
+);
+var
+  oX : ISDOChangeSummaryEx;
+begin
+  if ( AStore = nil ) or ( not Supports(AStore,ISDOChangedDataObjectListEx,FStore)) then
+    raise ESDOIllegalArgumentException.Create('AStore');
+  if ( AOwner = nil ) or ( not Supports(AOwner,ISDOChangeSummaryEx,oX) ) then
+    raise ESDOIllegalArgumentException.Create('AOwner');
+  FOwner := Pointer(oX);
+end;
+
+procedure TChangeRecorder.recordChange(
+  const ADataObject : ISDODataObject;
+  const AProperty : ISDOProperty;
+  const AOptions : TRecordingStyleSet
+);
+var
+  changeInfo : TDataObjectChangeInfo;
+  i, c, oldSettingPos : PtrInt;
+  propValue : TValueBuffer;
+  propValueStr : TSDOString;
+  propValueObj : ISDODataObject;
+  propValueBytes : TSDOBytes;
+  stg, xstg : TValueSetting;
+  locProp : ISDOProperty;
+begin
+  if ( ADataObject = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADataObject');
+  if ( AProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+
+  locProp := AProperty as ISDOProperty;
+  oldSettingPos := -1;
+  if FStore.find(ADataObject,i) then begin
+    changeInfo := FStore.getInfo(i);
+    c := changeInfo.ChangeList.size();
+    for i := 0 to Pred(c) do begin
+      xstg := changeInfo.ChangeList.getItem(i);
+      if ( xstg.getProperty() = locProp ) then begin
+        oldSettingPos := i;
+        Break;
+      end;
+    end;
+  end else begin
+    changeInfo := recordChange(ADataObject,ctChange);
+  end;
+  if ( changeInfo.ChangeType <> ctCreate ) and ( oldSettingPos = -1 ) or ( rsOverwrite in AOptions ) then begin
+    case locProp.getTypeEnum() of
+      BooleanType     : propValue.BooleanValue := ADataObject.getBoolean(locProp);
+      ByteType        : propValue.ByteValue := ADataObject.getByte(locProp);
+{$IFDEF HAS_SDO_BYTES}
+      BytesType       : propValueBytes := ADataObject.getBytes(locProp);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType   : propValue.CharValue := ADataObject.getCharacter(locProp);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      CurrencyType    : propValue.CurrencyValue := ADataObject.getCurrency(locProp);
+{$ENDIF HAS_SDO_CURRENCY}
+      DateTimeType    : propValue.DateValue := ADataObject.getDate(locProp);
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType      : propValue.DoubleValue := ADataObject.getDouble(locProp);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType       : propValue.FloatValue := ADataObject.getFloat(locProp);
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType     : propValue.IntegerValue := ADataObject.getInteger(locProp);
+{$IFDEF HAS_SDO_LONG}
+      LongType        : propValue.LongValue := ADataObject.getLong(locProp);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType       : propValue.ShortValue := ADataObject.getShort(locProp);
+{$ENDIF HAS_SDO_SHORT}
+      ObjectType      : propValueObj := ADataObject.getDataObject(locProp);
+      StringType      : propValueStr := ADataObject.getString(locProp);
+    end;
+    case locProp.getTypeEnum() of
+      BooleanType, ByteType, DateTimeType, IntegerType
+{$IFDEF HAS_SDO_CHAR}
+      ,CharacterType
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      ,CurrencyType
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+      ,DoubleType
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      ,FloatType
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+      ,LongType
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ,ShortType 
+{$ENDIF HAS_SDO_SHORT}
+       :
+        begin
+          stg := TValueSetting.Create(
+                   ADataObject.isSet(locProp),
+                   ADataObject.isNull(locProp),
+                   propValue,
+                   locProp,
+                   0
+                 );
+        end;
+{$IFDEF HAS_SDO_BYTES}
+      BytesType       :
+        begin
+         stg := TValueSetting.Create(
+                  ADataObject.isSet(locProp),
+                  ADataObject.isNull(locProp),
+                  propValueBytes,
+                  locProp,
+                  0
+                );
+        end;
+{$ENDIF HAS_SDO_BYTES}
+      ObjectType :
+        begin
+          stg := TValueSetting.Create(
+                   ADataObject.isSet(locProp),
+                   ADataObject.isNull(locProp),
+                   propValueObj,
+                   locProp,
+                   0
+                 );
+        end;
+      StringType  :
+        begin
+         stg := TValueSetting.Create(
+                  ADataObject.isSet(locProp),
+                  ADataObject.isNull(locProp),
+                  propValueStr,
+                  locProp,
+                  0
+                );
+        end;
+      else
+        raise ESDOException.CreateFmt('This data type is not supported yet by ChangeSummary API : "%s".',[SDOTypeDefaultTypeNames[locProp.getTypeEnum()]]);
+    end;
+    if ( oldSettingPos > -1 ) then
+      changeInfo.ChangeList.remove(oldSettingPos);
+    changeInfo.ChangeList.append(stg);
+  end;
+end;
+
+procedure TChangeRecorder.recordChange(
+  const ADataObject : ISDODataObject;
+  const AProperty : ISDOProperty;
+  const AIndex : PtrInt;
+  const AAction : TManyValuePropAction
+);
+var
+  changeInfo : TDataObjectChangeInfo;
+  locProp : ISDOProperty;
+  changesList : TManyValuePropChanges;
+  i : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  if ( ADataObject = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADataObject');
+  if ( AProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  locProp := AProperty as ISDOProperty;
+  if FStore.find(ADataObject,i) then begin
+    changeInfo := FStore.getInfo(i);
+  end else begin
+    changeInfo := recordChange(ADataObject,ctChange);
+  end;
+  changesList := changeInfo.GetChanges(locProp);
+  ls := ADataObject.getList(locProp);
+  if ( AAction in [mvpaChange, mvpaDelete, mvpaAppend, mvpaInsert] ) then begin
+    case locProp.getTypeEnum() of
+      BooleanType     : changesList.Add(AAction,AIndex,ls.getBoolean());
+      ByteType        : changesList.Add(AAction,AIndex,ls.getByte());
+{$IFDEF HAS_SDO_BYTES}
+      BytesType       : changesList.Add(AAction,AIndex,ls.getBytes());
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType   : changesList.Add(AAction,AIndex,ls.getCharacter());
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      CurrencyType   : changesList.AddCurrency(AAction,AIndex,ls.getCurrency());
+{$ENDIF HAS_SDO_CURRENCY}
+      DateTimeType    : changesList.Add(AAction,AIndex,ls.getDate());
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType      : changesList.Add(AAction,AIndex,ls.getDouble());
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType       : changesList.Add(AAction,AIndex,ls.getFloat());
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType     : changesList.Add(AAction,AIndex,ls.getInteger());
+{$IFDEF HAS_SDO_LONG}
+      LongType        : changesList.Add(AAction,AIndex,ls.getLong());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType       : changesList.Add(AAction,AIndex,ls.getShort());
+{$ENDIF HAS_SDO_SHORT}
+      ObjectType      : changesList.Add(AAction,AIndex,ls.getDataObject());
+      StringType      : changesList.Add(AAction,AIndex,ls.getString());
+      else
+        raise ESDOException.CreateFmt('This data type is not supported yet by ChangeSummary API : "%s".',[SDOTypeDefaultTypeNames[locProp.getTypeEnum()]]);
+    end;
+  end else begin
+    changesList.Add(AAction,AIndex);
+  end;
+  if ( locProp.getTypeEnum() = ObjectType ) then begin
+    case AAction of
+      mvpaAppend, mvpaInsert :
+        recordChange(ls.getDataObject(),ctCreate).FIndex := ls.getCursor().GetPosition();
+      mvpaDelete :
+        begin
+          changeInfo := recordChange(ls.getDataObject(),ctDelete);
+          if ( changeInfo <> nil ) then
+            changeInfo.FIndex := ls.getCursor().GetPosition();
+        end;
+    end;
+  end;
+end;
+
+function TChangeRecorder.GetStore() : ISDOChangedDataObjectList;
+begin
+  Result := FStore;
+end;
+
+function TChangeRecorder.recordChange(
+  const ADataObject: ISDODataObject;
+  const AChangeType: TChangeType
+) : TDataObjectChangeInfo;
+
+  procedure UndoContainedObjectsChanges(const AObj : ISDODataObject);
+
+    procedure ProcessItem(const AProperty : ISDOProperty);
+    var
+      d : PtrInt;
+      po : ISDODataObject;
+      poc : TDataObjectChangeInfo;
+    begin
+      po := AObj.getDataObject(AProperty);
+      if ( po <> nil ) then begin
+        if FStore.find(po,d) then begin
+          poc := FStore.getInfo(d);
+          UndoChangeItem(poc,True);
+          FStore.Extract(poc);
+          FreeAndNil(poc);
+          po := AObj.getDataObject(AProperty);
+          if FStore.find(po,d) then begin
+            poc := FStore.getInfo(d);
+            UndoChangeItem(poc,True);
+            FStore.Extract(poc);
+            FreeAndNil(poc);
+          end;
+        end;
+        if ( po <> nil ) then
+          UndoContainedObjectsChanges(po);
+      end;
+    end;
+
+    procedure ProcessMultiItem(const AProperty : ISDOProperty);
+    var
+      d : PtrInt;
+      po : ISDODataObject;
+      poc : TDataObjectChangeInfo;
+      ls : ISDODataObjectList;
+      crs : ISDOCursor;
+    begin
+      ls := AObj.getList(AProperty);
+      crs := ls.getCursor();
+      crs.Reset();
+      while crs.MoveNext() do begin
+        po := ls.getDataObject();
+        if ( po <> nil ) then begin
+          if FStore.find(po,d) then begin
+            poc := FStore.getInfo(d);
+            UndoChangeItem(poc,True);
+            FStore.Extract(poc);
+            FreeAndNil(poc);
+          end;
+          if ( po <> nil ) then
+            UndoContainedObjectsChanges(po);
+        end;
+      end;
+    end;
+
+  var
+    k, q : PtrInt;
+    pls : ISDOPropertyList;
+    p : ISDOProperty;
+    oldLoggingState : Boolean;
+  begin
+    if not Deserializing then begin
+      pls := AObj.getInstanceProperties();
+      q := pls.getCount();
+      if ( q > 0 ) then begin
+        oldLoggingState := GetOwner().isLogging();
+        if oldLoggingState then
+          GetOwner().suspend();
+        try
+          for k := 0 to Pred(q) do begin
+            p := pls.getItem(k);
+            if p.getType().isDataObjectType() and p.isContainment() then begin
+              if p.isMany() then
+                ProcessMultiItem(p)
+              else
+                ProcessItem(p);
+            end;
+          end;
+        finally
+          if oldLoggingState then
+            GetOwner().resume();
+        end;
+      end;
+    end;
+  end;
+
+var
+  i : PtrInt;
+  locInfoOLD, locInfo : TDataObjectChangeInfo;
+  locDoCreate, locOldLogginState : Boolean;
+begin
+  if ( ADataObject = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADataObject');
+  locInfoOLD := nil;
+  locDoCreate := True;
+  if FStore.find(ADataObject,i) then begin
+    locInfo := FStore.getInfo(i);
+  end else begin
+    i := -1;
+    locInfo := nil;
+  end;
+  if ( i > -1 ) and ( locInfo.ChangeType <> AChangeType ) then begin
+    case AChangeType of
+      ctCreate :
+        begin
+          case locInfo.ChangeType of
+            ctChange : Assert(False, 'This should not happen because a object the life''cycle is Create->(Modify)*->(Delete)*');
+            ctDelete : Assert(False, 'This should not happen because on deletion it is a copy of the object that is keep in TDataObjectChangeInfo.');
+          end;
+        end;
+      ctChange :
+        begin
+          case locInfo.ChangeType of
+            ctCreate : ; //Normal in the life's cycle Create->(Modify)*->(Delete)*
+            ctDelete : Assert(False, 'This should not happen because on deletion it is a copy of the object that is keep in TDataObjectChangeInfo.');
+          end;
+        end;
+      ctDelete :
+        begin
+          case locInfo.ChangeType of
+            //Normal in the life's cycle Create->(Modify)*->(Delete)*
+            ctCreate :
+              begin
+                locDoCreate := False;
+                FStore.extract(locInfo);
+                FreeAndNil(locInfo);
+              end;
+            ctChange :
+              begin
+                locOldLogginState := GetOwner().isLogging();
+                locInfoOLD := locInfo;
+                FStore.extract(locInfoOLD);
+                locInfo := nil;
+                GetOwner().suspend();
+                try
+                  //UndoContainedObjectsChanges(ADataObject);
+                  UndoChangeItem(locInfoOLD,True);
+                finally
+                  try
+                    if ( locOldLogginState <> GetOwner().isLogging() ) then begin
+                      if locOldLogginState then
+                        GetOwner().resume()
+                      else
+                        GetOwner().suspend();
+                    end;
+                  finally
+                    FreeAndNil(locInfoOLD);
+                  end;
+                end;
+              end;
+          end;
+        end;
+    end;
+  end;
+  if ( locInfo = nil ) and locDoCreate then begin
+    locInfo := FStore.append(ADataObject,AChangeType);
+  end;
+  if ( AChangeType = ctDelete ) then
+    UndoContainedObjectsChanges(ADataObject);
+  Result := locInfo;
+end;
+
+procedure TChangeRecorder.recordDeletion(const ADataObject: ISDODataObject);
+begin
+  recordChange(ADataObject,ctDelete);
+end;
+
+procedure TChangeRecorder.recordCreation(const ADataObject: ISDODataObject);
+begin
+  recordChange(ADataObject,ctCreate);
+end;
+
+function TChangeRecorder.recordUpdate(const ADataObject: ISDODataObject): TDataObjectChangeInfo;
+begin
+  Result := recordChange(ADataObject,ctChange);
+end;
+
+procedure TChangeRecorder.UndoChangeItem(
+  const AItem: TDataObjectChangeInfo;
+  const AProcessNestedObjProps : Boolean
+);
+
+  procedure UndoManyPropsChanges();
+  var
+    changesList : TManyValuePropChangesList;
+    elt : TManyValuePropChanges;
+    q, k, x, y : PtrInt;
+    tmpObj : ISDODataObject;
+  begin
+    changesList := AItem.ManyValuePropChangesList;
+    if ( changesList <> nil ) then begin
+      q := changesList.Count;
+      if ( q > 0 ) then begin
+        for k := 0 to ( q - 1 ) do begin
+          elt := changesList[k];
+          UndoChanges(AItem.DataObject.getList(elt.Prop),elt);
+          if elt.Prop.getType().isDataObjectType() and elt.Prop.isContainment() then begin
+            if ( elt.Count > 0 ) then begin
+              for x := 0 to ( elt.Count - 1 ) do begin
+                tmpObj := elt.GetItem(x).Value.ObjectValue^;
+                if ( tmpObj <> nil ) then begin
+                  if FStore.find(tmpObj,y) then begin
+                    FStore.Delete(y);
+                  end;
+                end;
+              end;
+            end;
+          end;
+        end;
+      end;
+    end;
+  end;
+
+  procedure UndoModify();
+  var
+    stg : TValueSetting;
+
+    procedure ProcessNestedProp(const AProp : ISDOProperty);
+    var
+      propVal : ISDODataObject;
+      kk : PtrInt;
+      storeX : ISDOChangedDataObjectListEx;
+    begin
+      propVal := AItem.DataObject.getDataObject(stg.getProperty());
+      storeX := Store as ISDOChangedDataObjectListEx;
+      if ( propVal <> nil ) and ( propVal <> stg.getDataObjectValue() ) then begin
+        if storeX.find(propVal,kk) then
+          UndoChangeItem(storeX.getInfo(kk),True);
+      end;
+      if storeX.find(stg.getDataObjectValue(),kk) then begin
+        UndoChangeItem(storeX.getInfo(kk),True);
+      end;
+    end;
+
+  var
+    q, k : Ptrint;
+  begin
+    q := AItem.ChangeList.size();
+    if ( q > 0 ) then begin
+      for k := Pred(q) downto 0 do begin
+        stg := AItem.ChangeList.getItem(k);
+        if not stg.getProperty().isMany() then begin
+          case stg.getProperty().getTypeEnum() of
+            BooleanType   : AItem.DataObject.setBoolean(stg.getProperty(),stg.getBooleanValue());
+            ByteType      : AItem.DataObject.setByte(stg.getProperty(),stg.getByteValue());
+{$IFDEF HAS_SDO_BYTES}
+            BytesType     : AItem.DataObject.setBytes(stg.getProperty(),stg.getBytesValue());
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+            CharacterType : AItem.DataObject.setCharacter(stg.getProperty(),stg.getCharacterValue());
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+            CurrencyType  : AItem.DataObject.setCurrency(stg.getProperty(),stg.getCurrencyValue());
+{$ENDIF HAS_SDO_CURRENCY}
+            DateTimeType  : AItem.DataObject.setDate(stg.getProperty(),stg.getDateValue());
+{$IFDEF HAS_SDO_DOUBLE}
+            DoubleType    : AItem.DataObject.setDouble(stg.getProperty(),stg.getDoubleValue());
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+            FloatType     : AItem.DataObject.setFloat(stg.getProperty(),stg.getFloatValue());
+{$ENDIF HAS_SDO_FLOAT}
+            IntegerType   : AItem.DataObject.setInteger(stg.getProperty(),stg.getIntegerValue());
+{$IFDEF HAS_SDO_LONG}
+            LongType      : AItem.DataObject.setLong(stg.getProperty(),stg.getLongValue());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+            ShortType     : AItem.DataObject.setShort(stg.getProperty(),stg.getShortValue());
+{$ENDIF HAS_SDO_SHORT}
+            ObjectType    :
+              begin
+                if AProcessNestedObjProps then begin
+                  if stg.getProperty().isContainment() then
+                    ProcessNestedProp(stg.getProperty())
+                  else
+                    AItem.DataObject.setDataObject(stg.getProperty(),stg.getDataObjectValue());
+                end else begin
+                  // In the Containment case, the creation of the contained object will set the value.
+                  if stg.getProperty().isReference() then
+                    AItem.DataObject.setDataObject(stg.getProperty(),stg.getDataObjectValue());
+                end;
+              end;
+            StringType  : AItem.DataObject.setString(stg.getProperty(),stg.getStringValue());
+            else
+              raise ESDONotImplementedException.CreateFmt('UndoModify() not implemented for this type : %s',[stg.getProperty().getType().getName()]);
+          end;
+          if stg.isNull() then
+            AItem.DataObject.setNull(stg.getProperty());
+          if not stg.isSet() then
+            AItem.DataObject.unset(stg.getProperty());
+        end;
+      end;
+    end;
+    if ( AItem.ManyValuePropChangesList <> nil ) then
+      UndoManyPropsChanges();
+  end;
+
+  procedure UndoDelete();{$IFDEF USE_INLINE}inline;{$ENDIF}
+  begin
+    Assert(AItem.OldContainer <> nil);
+    Assert(AItem.OldContainmentProperty <> nil);
+    UndoManyPropsChanges();
+    if not AItem.OldContainmentProperty.isMany() then
+      AItem.OldContainer.setDataObject(AItem.OldContainmentProperty,AItem.DataObject);
+  end;
+
+  procedure UndoCreate();{$IFDEF USE_INLINE}inline;{$ENDIF}
+  begin
+    Assert(AItem.OldContainer <> nil);
+    Assert(AItem.OldContainmentProperty <> nil);
+    UndoManyPropsChanges();
+    if not AItem.OldContainmentProperty.isMany() then
+      AItem.OldContainer.setDataObject(AItem.OldContainmentProperty,nil);
+  end;
+
+begin
+  case AItem.ChangeType of
+    ctCreate : UndoCreate();
+    ctChange : UndoModify();
+    ctDelete : UndoDelete();
+  end;
+end;
+
+function TChangeRecorder.GetOwner() : ISDOChangeSummaryEx;
+begin
+  Result := ISDOChangeSummaryEx(FOwner);
+end;
+
+procedure TChangeRecorder.recordCreation(
+  const ADataObject: ISDODataObject;
+  const AIndex: PtrInt
+);
+begin
+  recordChange(ADataObject,ctCreate).FIndex := AIndex;
+end;
+
+procedure TChangeRecorder.recordDeletion(
+  const ADataObject: ISDODataObject;
+  const AIndex: PtrInt
+);
+var
+  locInfo : TDataObjectChangeInfo;
+begin
+  locInfo := recordChange(ADataObject,ctDelete);
+  if ( locInfo <> nil ) then
+    locInfo.FIndex := AIndex;
+end;
+
+{ TDataObjectChangeInfo }
+
+procedure TDataObjectChangeInfo.CaptureOldContainment();
+var
+  ls : ISDODataObjectList;
+  crs : ISDOCursor;
+  oldPos : ISDOCursorBookmark;
+  obj : ISDODataObject;
+begin
+  if ( FChangeType in [ctDelete,ctCreate] ) then begin
+    obj := DataObject;
+    FOldContainer := Pointer(obj.getContainer());
+    if ( FOldContainer <> nil ) then begin
+      FOldContainmentProperty := obj.getContainmentProperty();
+      if ( FChangeType = ctCreate ) and obj.getContainmentProperty().isMany() then begin
+        ls := obj.getContainer().getList(obj.getContainmentProperty());
+        crs := ls.getCursor();
+        if crs.IsPosValid() and ( ls.getDataObject() = DataObject ) then begin
+          FIndex := crs.GetPosition();
+        end else begin
+          oldPos := crs.GetBookmark();
+          try
+            obj := DataObject;
+            crs.Reset();
+            while crs.MoveNext() do begin
+              if ( ls.getDataObject() = obj ) then
+                Break;
+            end;
+            if not crs.IsPosValid() then
+              raise ESDOInvalidStateOperationException.Create('CaptureOldContainment');
+            FIndex := crs.GetPosition();
+          finally
+            crs.GotoBookmark(oldPos);
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+constructor TDataObjectChangeInfo.Create(
+  const ADataObject: ISDODataObject;
+  const AChangeType: TChangeType
+);
+begin
+  if ( ADataObject = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADataObject');
+  if ( AChangeType = ctDelete ) then
+    ISDODataObject(FDataObject) := ADataObject
+  else
+    FDataObject := Pointer(ADataObject);
+  FChangeType := AChangeType;
+  FChangeList := TSDOSettingList.Create();
+  CaptureOldContainment();
+end;
+
+destructor TDataObjectChangeInfo.Destroy();
+begin
+  FreeAndNil(FManyValuePropChangesList);
+  if ( FChangeType = ctDelete ) then
+    ISDODataObject(FDataObject) := nil
+  else
+    FDataObject := nil;
+  inherited;
+end;
+
+procedure CreateSettingsFromList(
+  const AProperty : ISDOProperty;
+  const AList : ISDODataObjectList;
+  const ASettingList : ISDOSettingList
+);
+var
+  crs : ISDOCursor;
+  extractProc : TListValueExtractProc;
+  buffer : TValueBuffer;
+  pbuffer : Pointer;
+  i : PtrInt;
+  typKind : TSDOTypeKind;
+begin
+  typKind := AProperty.getTypeEnum();
+  InitBufferResources(typKind, buffer);
+  try
+    case typKind of
+{$IFDEF HAS_SDO_BYTES}
+      BytesType     : pbuffer := buffer.BytesValue;
+{$ENDIF HAS_SDO_BYTES}
+      ObjectType    : pbuffer := buffer.ObjectValue;
+      StringType    : pbuffer := buffer.StringValue;
+      else
+        pbuffer := @buffer;
+    end;
+    crs := AList.getCursor();
+    crs.Reset();
+    i := 0;
+    extractProc := getExtractor(typKind);
+    while crs.MoveNext() do begin
+      extractProc(AList,buffer);
+      ASettingList.append(TValueSetting.Create(True, False, pbuffer^, AProperty, i));
+      Inc(i);
+    end;
+  finally
+    FreeBufferResources(AProperty.getTypeEnum(), buffer);
+  end;
+end;
+
+procedure TDataObjectChangeInfo.ExtractPendingOldValues();
+var
+  i, c : PtrInt;
+  p : ISDOProperty;
+  locChangeList : TManyValuePropChanges;
+  ls : ISDODataObjectList;
+begin
+  if ( FManyValuePropPending <> nil ) then begin
+    c := FManyValuePropPending.Count;
+    for i := 0 to Pred(c) do begin
+      p := FManyValuePropPending.First() as ISDOProperty;
+      FManyValuePropPending.Delete(0);
+      locChangeList := FindChanges(p);
+      if ( locChangeList <> nil ) then begin
+        ls := p.getType().getOwner().CreateList(p.getType());
+        CopySimpleList(DataObject.getList(p),ls,p.getTypeEnum());
+        UndoChanges(ls,locChangeList);
+        CreateSettingsFromList(p, ls, FChangeList);
+      end;
+    end;
+  end;
+end;
+
+function TDataObjectChangeInfo.FindChanges(const AProp: ISDOProperty): TManyValuePropChanges;
+begin
+  if not AProp.isMany() then
+    raise ESDOIllegalArgumentException.Create('AProp');
+  if ( FManyValuePropChangesList = nil ) then
+    FManyValuePropChangesList := TManyValuePropChangesList.Create();
+  Result := ManyValuePropChangesList.Find(AProp);
+end;
+
+function TDataObjectChangeInfo.GetChanges(const AProp: ISDOProperty) : TManyValuePropChanges;
+begin
+  Result := FindChanges(AProp);
+  if ( Result = nil ) then begin
+    Result := TManyValuePropChanges.Create(AProp);
+    ManyValuePropChangesList.Add(Result);
+    if ( FManyValuePropPending = nil ) then
+      FManyValuePropPending := TInterfaceList.Create();
+    FManyValuePropPending.Add(AProp);
+  end;
+end;
+
+function TDataObjectChangeInfo.GetDataObject: ISDODataObject;
+begin
+  Result := ISDODataObject(FDataObject);
+end;
+
+function TDataObjectChangeInfo.getOldContainer: ISDODataObject;
+begin
+  Result := ISDODataObject(FOldContainer);
+end;
+
+{procedure TDataObjectChangeInfo.SetChangeType(const AChangeType: TChangeType);
+begin
+  if ( AChangeType <> FChangeType ) then begin
+    FChangeType := AChangeType;
+  end;
+end;}
+
+{ TSDOChangedDataObjectList }
+
+function TSDOChangedDataObjectList.append(
+  const ADataObject: ISDODataObject;
+  const AChange: TChangeType
+): TDataObjectChangeInfo;
+var
+  i : PtrInt;
+begin
+  if find(ADataObject,i) then
+    raise ESDODuplicatedItemException.Create('ADataObject');
+  Result := TDataObjectChangeInfo.Create(ADataObject,AChange);
+  //FList.Insert(i, Result);
+  FList.Add(Result);
+end;
+
+procedure TSDOChangedDataObjectList.CheckIndex(const AIndex: PtrInt);
+begin
+  if ( AIndex < 0 ) or ( AIndex >= FList.Count ) then
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+end;
+
+procedure TSDOChangedDataObjectList.Clear();
+begin
+  FList.Clear();
+end;
+
+constructor TSDOChangedDataObjectList.Create();
+begin
+  FList := TObjectList.Create(True);
+end;
+
+procedure TSDOChangedDataObjectList.Delete(const AIndex: PtrInt);
+begin
+  CheckIndex(AIndex);
+  FList.Delete(AIndex);
+end;
+
+destructor TSDOChangedDataObjectList.Destroy();
+begin
+  FreeAndNil(FList);
+  inherited;
+end;
+
+procedure TSDOChangedDataObjectList.Extract(const AItem: TDataObjectChangeInfo);
+begin
+  FList.Extract(AItem);
+end;
+
+function TSDOChangedDataObjectList.find(const ADataObject: ISDODataObject; out AIndex: PtrInt) : Boolean;
+var
+  c, i : PtrInt;
+begin
+  Result := False;
+  c := FList.Count;
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      if ( Pointer(ADataObject) = TDataObjectChangeInfo(FList[i]).FDataObject ) then begin
+        AIndex := i;
+        Result := True;
+        Break;
+      end;
+    end;
+  end;
+  //The list is no longer sorted!
+  //Result := findDicho(FList,PtrInt(ADataObject),AIndex,@DataObjectExtractor);
+end;
+
+function TSDOChangedDataObjectList.getDataObject(const AIndex: PtrInt): ISDODataObject;
+begin
+  Result := getInfo(AIndex).DataObject;
+end;
+
+function TSDOChangedDataObjectList.getInfo(const AIndex: PtrInt): TDataObjectChangeInfo;
+begin
+  CheckIndex(AIndex);
+  Result := TDataObjectChangeInfo(FList[AIndex]);
+end;
+
+function TSDOChangedDataObjectList.getType(const AIndex: PtrInt): TChangeType;
+begin
+  Result := getInfo(AIndex).ChangeType;
+end;
+
+function TSDOChangedDataObjectList.size() : PtrInt;
+begin
+  Result := FList.Count;
+end;
+
+{ TSDOChangeSummary }
+
+procedure TSDOChangeSummary.beginLogging();
+begin
+  if not FLogging then begin
+    Clear();
+    FLogging := True;
+  end;
+end;
+
+procedure TSDOChangeSummary.Clear();
+begin
+  FChangesData.Clear();
+end;
+
+constructor TSDOChangeSummary.Create(const AChangesData: ISDOChangedDataObjectList);
+begin
+  if ( AChangesData = nil ) or ( not Supports(AChangesData,ISDOChangedDataObjectListEx,FChangesData)) then
+    raise ESDOIllegalArgumentException.Create('AChangesData');
+  FRecorder := TChangeRecorder.Create(AChangesData,Self as ISDOChangeSummary);
+end;
+
+destructor TSDOChangeSummary.Destroy();
+begin
+  Clear();
+  FreeAndNil(FRecorder);
+  inherited;
+end;
+
+procedure TSDOChangeSummary.endLogging();
+begin
+  FLogging := False;
+end;
+
+function TSDOChangeSummary.FindManyValueChanges(const ADataObject: ISDODataObject): TManyValuePropChangesList;
+var
+  i : PtrInt;
+begin
+  if FChangesData.find(ADataObject,i) then
+    Result := FChangesData.getInfo(i).ManyValuePropChangesList
+  else
+    Result := nil;
+end;
+
+function TSDOChangeSummary.getChangedDataObjects() : ISDOChangedDataObjectList;
+begin
+  Result := FChangesData;
+end;
+
+function TSDOChangeSummary.getOldContainer(const ADataObject: ISDODataObject): ISDODataObject;
+var
+  i : PtrInt;
+begin
+  if FChangesData.find(ADataObject,i) then
+    Result := FChangesData.getInfo(i).OldContainer
+  else
+    Result := nil;
+end;
+
+function TSDOChangeSummary.getOldContainmentProperty(const ADataObject: ISDODataObject): ISDOProperty;
+var
+  i : PtrInt;
+begin
+  if FChangesData.find(ADataObject,i) then
+    Result := FChangesData.getInfo(i).OldContainmentProperty
+  else
+    Result := nil;
+  if ( Result = nil ) then
+    raise ESDOInvalidStateOperationException.Create('getOldContainmentProperty');
+end;
+
+function TSDOChangeSummary.getOldValue(
+  const ADataObject: ISDODataObject;
+  const AProperty: ISDOProperty
+) : TValueSetting;
+var
+  locLs : ISDOSettingList;
+  i, c : PtrInt;
+  locSetting : TValueSetting;
+begin
+  Result := nil;
+  locLs := getOldValues(ADataObject);
+  c := locLs.size();
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      locSetting := locLs.getItem(i);
+      if ( locSetting.getProperty() = AProperty ) then begin
+        Result := locSetting;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+function TSDOChangeSummary.getOldValues(const ADataObject: ISDODataObject): ISDOSettingList;
+var
+  i : PtrInt;
+  ci : TDataObjectChangeInfo;
+begin
+  if FChangesData.find(ADataObject,i) then begin
+    ci := FChangesData.getInfo(i);
+    ci.ExtractPendingOldValues();
+    Result := ci.ChangeList;
+  end else begin
+    Result := TSDOSettingList.Create() as ISDOSettingList;
+  end;
+end;
+
+function TSDOChangeSummary.getOldXpath(const ADataObject: ISDODataObject): string;
+var
+  locBuffer : string;
+  obj : ISDODataObject;
+begin
+  if Assigned(ADataObject) and isDeleted(ADataObject) then begin
+    obj := ADataObject;
+    locBuffer := '';
+    while ( obj <> nil ) do begin
+      if ( obj.getContainer() = nil ) then
+        Break;
+      locBuffer := obj.getContainmentProperty().getName() + '/' + locBuffer;
+      obj := obj.getContainer();
+    end;
+    while ( obj <> nil ) and isDeleted(obj) do begin
+      if ( getOldContainer(obj) <> nil ) then begin
+        locBuffer := getOldContainmentProperty(obj).getName() + '/' + locBuffer;
+        obj := getOldContainer(obj);
+      end else begin
+        //obj := nil;
+        Break;
+      end;
+    end;
+  end;
+  if ( Length(locBuffer) > 0 ) and ( locBuffer[Length(locBuffer)] = '/' ) then
+    Delete(locBuffer,Length(locBuffer),1);
+  Result := locBuffer;
+end;
+
+function TSDOChangeSummary.getRecorder() : TChangeRecorder;
+begin
+  Result := FRecorder;
+end;
+
+function TSDOChangeSummary.isCreated(const ADataObject: ISDODataObject): Boolean;
+var
+  i : PtrInt;
+begin
+  Result := FChangesData.find(ADataObject,i) and ( FChangesData.getInfo(i).ChangeType = ctCreate );
+end;
+
+function TSDOChangeSummary.isDeleted(const ADataObject: ISDODataObject): Boolean;
+var
+  i : PtrInt;
+begin
+  Result :=
+    ( ADataObject <> nil ) and
+    ( ( FChangesData.find(ADataObject,i) and ( FChangesData.getInfo(i).ChangeType = ctDelete ) ) or
+      ( ( ADataObject.getContainer() <> nil ) and isDeleted(ADataObject.getContainer()) )
+    );
+end;
+
+function TSDOChangeSummary.isLogging() : Boolean;
+begin
+  Result := FLogging;
+end;
+
+function TSDOChangeSummary.isModified(const ADataObject: ISDODataObject): Boolean;
+var
+  i : PtrInt;
+begin
+  Result := FChangesData.find(ADataObject,i) and ( FChangesData.getInfo(i).ChangeType = ctChange );
+end;
+
+procedure TSDOChangeSummary.resume();
+begin
+  if not FLogging then
+    FLogging := True;
+end;
+
+procedure TSDOChangeSummary.suspend();
+begin
+  if FLogging then
+    FLogging := False;
+end;
+
+procedure TSDOChangeSummary.undoChanges();
+var
+  ls : ISDOChangedDataObjectList;
+  lsX : ISDOChangedDataObjectListEx;
+  i, c : PtrInt;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  endLogging();
+  ls := FChangesData;
+  if ( ls <> nil ) then begin
+    lsX := ls as ISDOChangedDataObjectListEx;
+    c := lsX.size();
+    for i := Pred(c) downto 0 do begin
+      locChangeInfo := lsX.getInfo(i);
+      FRecorder.undoChangeItem(locChangeInfo,True);
+      lsX.Delete(i);
+    end;
+    lsX.Clear();
+  end;
+end;
+
+{ TManyValuePropChanges }
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOInteger
+): TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.IntegerValue := AValue;
+end;
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOBoolean
+): TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.BooleanValue := AValue;
+end;
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOString
+): TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.StringValue^ := AValue;
+end;
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+end;
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TValueBuffer
+) : TManyValuePropRecordData;
+begin
+  case Prop.getTypeEnum() of
+    BooleanType    : Result := Add(AAction,AIndex,AValue.BooleanValue);
+    ByteType       : Result := Add(AAction,AIndex,AValue.ByteValue);
+{$IFDEF HAS_SDO_BYTES}
+    BytesType      : Result := Add(AAction,AIndex,AValue.BytesValue^);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType  : Result := Add(AAction,AIndex,AValue.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType   : Result := AddCurrency(AAction,AIndex,AValue.CurrencyValue);
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType   : Result := Add(AAction,AIndex,AValue.DateValue);
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType     : Result := Add(AAction,AIndex,AValue.DoubleValue);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType      : Result := Add(AAction,AIndex,AValue.FloatValue);
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    LongType       : Result := Add(AAction,AIndex,AValue.LongValue);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType      : Result := Add(AAction,AIndex,AValue.ShortValue);
+{$ENDIF HAS_SDO_SHORT}
+    IntegerType    : Result := Add(AAction,AIndex,AValue.IntegerValue);
+    ObjectType     : Result := Add(AAction,AIndex,AValue.ObjectValue^);
+    StringType     : Result := Add(AAction,AIndex,AValue.StringValue^);
+    else
+      raise ESDONotImplementedException.CreateFmt('TManyValuePropChanges.Add not implemented for this type : "%s".',[Prop.getType().getName()]);
+  end;
+end;
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: ISDODataObject
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.ObjectValue^ := AValue;
+end;
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOByte
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.ByteValue := AValue;
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOChar
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.CharValue := AValue;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+function TManyValuePropChanges.AddCurrency(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOCurrency
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.CurrencyValue := AValue;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDODouble
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.DoubleValue := AValue;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOFloat
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.FloatValue := AValue;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOLong
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.LongValue := AValue;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOShort
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.ShortValue := AValue;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+{$IFDEF HAS_SDO_BYTES}
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDOBytes
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.BytesValue^ := AValue;  
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+function TManyValuePropChanges.Add(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: TSDODateTime
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex);
+  Result.FValue.DateValue := AValue;
+end;
+
+function TManyValuePropChanges.AddAt(
+  const ALocation: PtrInt;
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const AValue: ISDODataObject
+) : TManyValuePropRecordData;
+begin
+  Result := InternalAdd(AAction,AIndex,ALocation);
+  Result.FValue.ObjectValue^ := AValue;
+end;
+
+function TManyValuePropChanges.Count() : PtrInt;
+begin
+  Result := FList.Count;
+end;
+
+constructor TManyValuePropChanges.Create(const AProp: ISDOProperty);
+begin
+  if ( AProp = nil ) then
+    raise ESDOIllegalArgumentException.Create('AProp');
+  FProp := AProp;
+  FList := TObjectList.Create(True);
+end;
+
+destructor TManyValuePropChanges.Destroy();
+begin
+  FreeAndNil(FList);
+  inherited;
+end;
+
+function TManyValuePropChanges.GetItem(const AIndex: PtrInt): TManyValuePropRecordData;
+begin
+  if ( AIndex >= 0 ) and ( AIndex < FList.Count ) then
+    Result := TManyValuePropRecordData(FList[AIndex])
+  else
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+end;
+
+function TManyValuePropChanges.InternalAdd(
+  const AAction: TManyValuePropAction;
+  const AIndex: PtrInt;
+  const ALocation : PtrInt
+): TManyValuePropRecordData;
+begin
+  Result := TManyValuePropRecordData.Create(Self);
+  if ( ALocation = -1 ) or ( ALocation = FList.Count ) then
+    FList.Add(Result)
+  else
+    FList.Insert(ALocation,Result);
+  Result.FAction := AAction;
+  Result.FIndex := AIndex;
+end;
+
+{ TManyValuePropRecordData }
+
+constructor TManyValuePropRecordData.Create(const AOwner: TManyValuePropChanges);
+begin
+  FOwner := AOwner;
+  InitBufferResources(FOwner.Prop.getTypeEnum(), FValue);
+end;
+
+destructor TManyValuePropRecordData.Destroy();
+begin
+  if ( FOwner <> nil ) then
+    FreeBufferResources(FOwner.Prop.getTypeEnum(), FValue);
+  inherited;
+end;
+
+{ TManyValuePropChangesList }
+
+procedure TManyValuePropChangesList.Add(const AItem: TManyValuePropChanges);
+begin
+  if ( FList.IndexOf(AItem) = -1 ) then
+    FList.Add(AItem);
+end;
+
+function TManyValuePropChangesList.Count() : PtrInt;
+begin
+  Result := FList.Count;
+end;
+
+constructor TManyValuePropChangesList.Create();
+begin
+  FList := TObjectList.Create(True);
+end;
+
+destructor TManyValuePropChangesList.Destroy();
+begin
+  FreeAndNil(FList);
+  inherited;
+end;
+
+function TManyValuePropChangesList.Find(const AProperty: ISDOProperty): TManyValuePropChanges;
+var
+  i : PtrInt;
+begin
+  i := IndexOf(AProperty);
+  if ( i = -1 ) then
+    Result := nil
+  else
+    Result := TManyValuePropChanges(FList[i]);
+end;
+
+function TManyValuePropChangesList.GetItem(const AIndex: PtrInt): TManyValuePropChanges;
+begin
+  Result := TManyValuePropChanges(FList[AIndex]);
+end;
+
+function TManyValuePropChangesList.IndexOf(const AProperty: ISDOProperty): PtrInt;
+var
+  i, c : PtrInt;
+begin
+  Result := -1;
+  c := FList.Count;
+  if ( c > 0 ) then begin
+    for i := 0 to ( c - 1 ) do begin
+      if ( GetItem(i).Prop = AProperty ) then begin
+        Result := i;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+end.

+ 138 - 0
packages/fcl-sdo/src/base/sdo_consts.pas

@@ -0,0 +1,138 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements sdo constants
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit sdo_consts;
+
+interface
+
+const
+  s_any           = 'any';
+  s_anyAttribute  = 'anyAttribute';
+  s_append        = 'append';
+  s_change        = 'change';
+  s_changeSummary = 'changeSummary';
+  s_changeSummaryListObject = 'changeSummaryListObject';
+  s_create        = 'create';
+  s_datagraph     = 'datagraph';
+  s_dataValues    = 'dataValues';
+  s_delete        = 'delete';
+  s_index         = 'index';
+  s_insert        = 'insert';
+  s_item          = 'item';
+  s_kind          = 'kind';
+  s_listChanges   = 'listChanges';
+  s_nil           = 'nil';
+  s_propertyType  = 'propertyType';
+  s_ref           = 'ref';
+  s_schema        = 'schema';
+  s_sdo           = 'sdo';
+  s_unset         = 'unset';
+  s_xml           = 'xml';
+  s_xml_ns        = 'xmlns';
+  s_xsd           = 'xsd';
+  s_xsd_namespace = 'http://www.w3.org/2001/XMLSchema';
+  s_xsi_namespace = 'http://www.w3.org/2001/XMLSchema-instance';
+
+  // Database related constants
+  s_db_namespace     = 'sdo.db';
+  s_DataRowType      = 'DataRowType';
+  s_DataSetType      = 'DatasetType';
+  s_Row              = 'Row';
+  s_RowCount         = 'RowCount';
+
+resourcestring
+  SMSG_FileNotFound = 'File not found : "%s"';
+
+  SERR_BaseTypeNotSpecfifiedForSimpleType = 'Base type is not specified for the simple type, parsing : "%s".';
+  SERR_CannotMakeInternalSymbolName  ='Unable to make an internal symbol Name from "%s".';
+  SERR_CannotResolveNamespace        = 'Unable to resolve this namespace : "%s".';
+  SERR_DataFilterNotFound            = 'Data Filter not found : "%s".';
+  SERR_DuplicateBindingName          = 'Duplicated binding : "%s".';
+  SERR_ExpectedButFound              = '%s expected but %s found.';
+  SERR_ExpectedTypeDefinition        = '"%s" was expected to be a type definition.';
+  SERR_ExpectingRemotableObjectClass = 'Expecting remotable object class but found "%s".';
+  SERR_FailedTransportRequest        = '%s Request to %s failed.';
+  SERR_HeaderNotUnderstood         = 'Header "%s" not Understood.';
+  SERR_IllegalChar                 = 'Illegal character for that encoding : "%s".';
+  SERR_IndexOutOfBound             = 'Index out of bound : %d.';
+  SERR_IncompleteParamTypeRegistration  = 'Incomplete type registration for the type of this parameter : "%s".';
+  SERR_InnerScopeMustBeSimpleType       = 'Inner Scope value must be a "simple type" value.';
+  SERR_InvalidArrayBounds          = 'Invalid array bounds.';
+  SERR_InvalidArrayItemType        = 'Invalid array type definition, invalid item type definition : "%s".';
+  SERR_InvalidArrayLength          = 'Invalid array length : %d.';
+  SERR_InvalidAttributeDef_EmptyName = 'Invalid Attribute definition : empty "name".';
+  SERR_InvalidAttributeDef_EmptyType = 'Invalid Attribute definition : empty "type".';
+  SERR_InvalidAttributeDef_EmptyUse = 'Invalid Attribute definition : empty "use".';
+  SERR_InvalidAttributeDef_InvalidUse = 'Invalid Attribute definition : invalid "use" value "%s".';
+  SERR_InvalidAttributeDef_MissingName = 'Invalid Attribute definition : missing "name" attribute.';
+  SERR_InvalidAttributeDef_MissingType = 'Invalid Attribute definition : missing "type" attribute.';     
+  SERR_InvalidCollectionLength     = 'Invalid collection length : %d.';
+  SERR_InvalidComplexSimpleTypeDef_NoRestOrExt = 'Invalid "complexeType.simpleType" definition : restriction/extension not found.';
+  SERR_InvalidDataTypeInContext    = 'Invalid data type in this context : "%s".';
+  SERR_InvalidDomDocument          = 'Invalid DOM document.';
+  SERR_InvalidElementDef_MissingNameOrRef = 'Invalid <element> definition : missing "name" or "ref" attribute.';
+  SERR_InvalidElementDef_EmptyName = 'Invalid <element> definition : empty "name".';
+  SERR_InvalidElementDef_EmptyType = 'Invalid <element> definition : empty "type".';
+  SERR_InvalidElementDef_Type      = 'Invalid <element> definition : unable to determine the type. Type name : "%s"; Element name :"%s".';
+  SERR_InvalidEncodedData          = 'Invalid encoded data.';
+  SERR_InvalidEnumItemNode_NoValueAttribute = 'Invalid "enum" item node : no value attribute, type = "%s".';
+  SERR_InvalidHourOffetValue       = '"%d" is not a valid hour offset value.';
+  SERR_InvalidMaxOccursValue       = 'Invalid "maxOccurs" value : "%s.%s".';
+  SERR_InvalidMinOccursValue       = 'Invalid "minOccurs" value : "%s.%s".';
+  SERR_InvalidMinuteOffetValue     = '"%d" is not a valid minute offset value.';
+  SERR_InvalidEmbeddedScopeOperation    = 'Invalid opération on scope, their are no embedded scope.';
+  SERR_InvalidParameter            = 'Invalid parameter : "%s".';
+  SERR_InvalidPropertyValue        = 'Invalid property ("%s") value : "%s".';
+  SERR_InvalidParameterProc        = 'Invalid parameter : "%s"; Procedure = "%s".';
+  SERR_InvalidParameters           = 'Invalid parameters.';
+  SERR_InvalidPoolParametersArgs   = 'Invalid pool arguments Min = %d; Max = %d .';
+  SERR_InvalidSchemaDoc_NamespaceNotFound = 'Invalid Schema document, namespace not found : %s.';
+  SERR_InvalidSchemaDoc_NamespaceNotFoundShort = 'Invalid Schema document, namespace not found ( short names ) : %s.';
+  SERR_InvalidSchemaNode           = 'Invalid schema node.';
+  SERR_InvalidSymbolTable          = 'Invalid Symbol table.';
+  SERR_InvalidTypeDef_AttributeNotFound = 'Invalid type definition, attributes not found : "%s".';
+  SERR_InvalidTypeDef_BaseAttributeNotFound = 'Invalid extention/restriction of type "%s" : "base" attribute not found.';
+  SERR_InvalidTypeDef_NamedAttributeNotFound = 'Invalid type definition, unable to find the "%s" attribute : "%s".';
+  SERR_InvalidTypeDef_NoChild      = 'Invalid type definition, this element must have children.';
+  SERR_InvalidTypeName             = 'Invalid type/element name( the name is empty ).';
+  SERR_IsNotAFieldOf               = '"%s" is not a field of "%s".';
+  SERR_NodeNotFoundByID            = 'Node not found with this ID in the document : "%s".';
+  SERR_NoHandlerForThatVerb        = 'No handler for that verb : "%s".';
+  SERR_NoReaderProc                = 'No reader proc for that type, Prop : "(%s : %s)".';
+  SERR_NoScope                     = 'There is no scope.';  
+  SERR_NoSerializerFoThisType      = 'No serializer for this type : "%s".';
+  SERRE_ObjectCreationTimeOut      = 'Unable to create the object : Timeout expired.';
+  SERR_OperationNotAllowedOnActivePool = 'Operation not allowed on an active pool.';
+  SERR_ParamaterNotFound           = 'Parameter non found : "%s".';
+  SERR_Parsing                     = 'Parsing "%s" ...';
+  SERR_RecordExtendedRttiNotFound  = 'Record extended RTTI informations not found in type registry : "%s".';
+  SERR_RootObjectCannotBeNIL       = 'The root object cannot be NIL.';
+  SERR_SchemaNodeRequiredAttribute = 'The Schema node must have at least the "%s" attribute.';
+  SERR_SerializerInitializationException = 'Unable to initialize the serializer of that type : "%s".';
+  SERR_ServiceNotFound                   = 'Service not found : "%s".';
+  SERR_ScopeNotFound                     = 'Scope not found : "%s".';
+  SERR_TypeDefinitionNotFound            = 'Type definition not found %s : "%s"';
+  SERR_TypeNodeFoundButUnableToParseIt   = 'Type node found but unable to parse it : "%s"';
+  SERR_TypeNotRegistered                 = 'Type not registered : "%s".';
+  SERR_TypeStyleNotSupported             = 'This type style is not supported : "%s".';
+  SERR_UnableToFindNameTagInNode         = 'Unable to find the <name> tag in the type/element node attributes.';
+  SERR_UnableToResolveNamespace          = 'Unable to resolve namespace, short name = "%s".';
+  SERR_UnexpectedEndOfData               = 'Unexpected end of data.';
+  SERR_UnknownProperty                   = 'Unknown property : "%s".';
+  SERR_UnsupportedOperation        = 'Unsupported operation : "%s".';
+
+implementation
+
+end.

+ 226 - 0
packages/fcl-sdo/src/base/sdo_cursor_intf.pas

@@ -0,0 +1,226 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a basic cursor interface (enumerator)
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_cursor_intf;
+
+interface
+
+uses
+  Classes, SysUtils, sdo_types;
+
+type
+
+  TFilterConnector = ( fcNone, fcAnd, fcOr );
+
+  IInterfaceCursor = interface;
+  IObjectCursor  = interface;
+  IDefaultTypedCursor = {$IFDEF INTF_DOM}IInterfaceCursor{$ELSE}IObjectCursor{$ENDIF};
+  IDefaultItemType = {$IFDEF INTF_DOM}IInterface{$ELSE}TObject{$ENDIF};
+
+  ECursorException = class(Exception)
+  end;
+
+  ICursor = interface
+    ['{2B7756B1-E239-4B6F-A7A3-4B57B98FAD4F}']
+    procedure Reset();
+    function MoveNext() : Boolean;
+    //It is just the cursor that is cloned, the underliying datas are shared
+    function Clone():ICursor;
+    function GetCount() : PtrInt;
+  end;
+  
+  IObjectFilter = interface
+    ['{3DFB1A26-ED2D-428A-9F62-2091A076D97B}']
+    function Evaluate(const AObject : TObject) : Boolean;
+  end;
+
+  IObjectCursor = interface(ICursor)
+    ['{13E9C22D-0508-4D7A-A969-96E2291B4FE8}']
+    function GetCurrent() : TObject;
+  end;
+
+  IInterfaceCursor = interface(ICursor)
+    ['{82FCF6F3-8008-4CCA-99DA-88945B250B92}']
+    function GetCurrent() : IInterface;
+  end;
+
+  IFilterableObjectCursor = interface(IObjectCursor)
+    ['{F11B588A-E8CF-45D3-98D2-B49755FFC22D}']
+    function GetFilter() : IObjectFilter;
+    function SetFilter(const AFilter : IObjectFilter) : IObjectFilter;
+  end;
+
+  { TAggregatedFilter }
+
+  TAggregatedFilter = class(TInterfacedObject,IObjectFilter)
+  private
+    FLeft : IObjectFilter;
+    FRight : IObjectFilter;
+    FConnector : TFilterConnector;
+  protected
+    function Evaluate(const AObject : TObject) : Boolean;
+  public
+    constructor Create(
+      const ALeft, ARight : IObjectFilter;
+      const AConnector : TFilterConnector
+    );
+  end;
+
+  function CreateCursorOn(
+    AInputCursor : IObjectCursor;
+    AFilter      : IObjectFilter
+  ) : IFilterableObjectCursor ;
+  
+implementation
+
+type
+
+  { TSimpleObjectFilterableCursor }
+
+  TSimpleObjectFilterableCursor = class(
+    TInterfacedObject,
+    ICursor,IObjectCursor,IFilterableObjectCursor
+  )
+  private
+    FBaseCursor : IObjectCursor;
+    FFilter : IObjectFilter;
+  protected
+    procedure Reset();
+    function MoveNext() : Boolean;
+    function Clone():ICursor;
+    function GetCurrent() : TObject;
+    function GetCount() : PtrInt;
+    function GetFilter() : IObjectFilter;
+    function SetFilter(const AFilter : IObjectFilter) : IObjectFilter;
+  public
+    constructor Create(
+      AInputCursor : IObjectCursor;
+      AFilter      : IObjectFilter
+    );
+  end;
+
+{ TAggregatedFilter }
+
+function TAggregatedFilter.Evaluate(const AObject: TObject): Boolean;
+begin
+  Result := FLeft.Evaluate(AObject);
+  case FConnector of
+    fcAnd : Result := Result and FRight.Evaluate(AObject);
+    fcOr  : Result := Result or FRight.Evaluate(AObject);
+  end;
+end;
+
+constructor TAggregatedFilter.Create(
+  const ALeft, ARight: IObjectFilter;
+  const AConnector: TFilterConnector
+);
+begin
+  Assert(ALeft <> nil);
+  Assert( ( AConnector = fcNone ) or ( ARight <> nil ));
+  FLeft := ALeft;
+  FRight := ARight;
+  FConnector := AConnector;
+end;
+
+function CreateCursorOn(
+  AInputCursor : IObjectCursor;
+  AFilter      : IObjectFilter
+) : IFilterableObjectCursor ;
+begin
+  if ( AInputCursor <> nil ) then
+    Result := TSimpleObjectFilterableCursor.Create(AInputCursor,AFilter)
+  else
+    Result := nil;
+end;
+
+
+{ TSimpleObjectFilterableCursor }
+
+procedure TSimpleObjectFilterableCursor.Reset();
+begin
+  FBaseCursor.Reset();
+end;
+
+function TSimpleObjectFilterableCursor.MoveNext(): Boolean;
+begin
+  if ( FFilter = nil ) then begin
+    Result := FBaseCursor.MoveNext();
+  end else begin
+    while FBaseCursor.MoveNext() do begin
+      if FFilter.Evaluate(FBaseCursor.GetCurrent()) then begin
+        Result := True;
+        exit;
+      end;
+    end;
+    Result := False;
+  end;
+end;
+
+function TSimpleObjectFilterableCursor.Clone(): ICursor;
+var
+  baseClone : ICursor;
+begin
+  Result := nil;
+  baseClone := FBaseCursor.Clone();
+  if ( baseClone <> nil ) then
+    Result := TSimpleObjectFilterableCursor.Create(baseClone as IObjectCursor,FFilter);
+end;
+
+function TSimpleObjectFilterableCursor.GetCurrent(): TObject;
+begin
+  Result := FBaseCursor.GetCurrent();
+end;
+
+function TSimpleObjectFilterableCursor.GetCount() : PtrInt;
+var
+  crs : ICursor;
+begin
+  if ( FFilter = nil ) then begin
+    Result := FBaseCursor.GetCount();
+  end else begin
+    crs := Self.Clone();
+    crs.Reset();
+    Result := 0;
+    while crs.MoveNext() do begin
+      Result := Result + 1;
+    end;
+  end;
+end;
+
+function TSimpleObjectFilterableCursor.GetFilter(): IObjectFilter;
+begin
+  Result := FFilter;
+end;
+
+function TSimpleObjectFilterableCursor.SetFilter(const AFilter: IObjectFilter): IObjectFilter;
+begin
+  FFilter := AFilter;
+  Result := FFilter;
+end;
+
+constructor TSimpleObjectFilterableCursor.Create(
+  AInputCursor : IObjectCursor;
+  AFilter      : IObjectFilter
+);
+begin
+  Assert(Assigned(AInputCursor));
+  inherited Create();
+  FBaseCursor := AInputCursor;
+  FFilter := AFilter;
+end;
+
+
+end.

+ 612 - 0
packages/fcl-sdo/src/base/sdo_datafactory.pas

@@ -0,0 +1,612 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a SDO data factory
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_datafactory;
+
+interface
+uses SysUtils, Classes,
+     sdo, sdo_type, sdo_types;
+
+type
+
+  { TSDOBaseDataFactory }
+
+  TSDOBaseDataFactory = class(TInterfacedObject,IInterface,ISDODataFactory)
+  private
+    FTypeList : ISDOTypeListEx;
+  private
+    procedure Clear();
+  protected
+    function findType(const ATypeURI, ATypeName : string) : ISDOTypeEx;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure CheckCircularDependencies(const AType : ISDOType);
+  protected
+		//SDO_API virtual DataFactoryPtr clone();
+    function createNew(const AType : ISDOType) : ISDODataObject;overload;
+    function createNew(const AUri, ATypeName : string) : ISDODataObject;overload;
+
+    function getType(const AUri, ATypeName : string) : ISDOType;
+		function getTypes() : ISDOTypeList;
+    procedure AddType(
+      const AUri,
+            ATypeName      : string;
+      const AisSequenced,
+            AisOpen,
+            AisAbstract,
+            AisDataType    : Boolean
+    );overload;
+    procedure AddType(
+      const AUri,
+            ATypeName : string;
+      const AFlags    : TTypeFlags
+    );overload;
+    procedure setBaseType(const AType, ABase : ISDOType);overload;
+    procedure setBaseType(
+      const ATypeURI, ATypeName,
+            ABaseURI, ABaseName : string
+    );overload;
+    procedure setAlias(const ATypeURI, ATypeName, AAlias : string);overload;
+    procedure addProperty(
+      const ATypeURI, ATypeName,
+            APropName, APropTypeUri, APropTypeName : string;
+      const AFlags : TPropertyFlags
+    );overload;
+    procedure addProperty(
+      const ATypeURI, ATypeName,
+            APropName            : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );overload;
+    procedure addProperty(
+      const AType : ISDOType;
+      const APropName, APropTypeUri, APropTypeName : string;
+      const AFlags : TPropertyFlags
+    );overload;
+    procedure addProperty(
+      const AType     : ISDOType;
+      const APropName : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );overload;
+    procedure setAlias(const ATypeUri, ATypeName, APropName, AAlias : string);overload;
+    procedure addProperty(
+            ADataObject : ISDODataObject;
+      const APropName : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );overload;
+    function CreateList(AType : ISDOType) : ISDODataObjectList;overload;
+    function CreateList(const AUri, ATypeName : string) : ISDODataObjectList;overload;
+  public
+    constructor Create();
+    destructor Destroy();override;
+  end;
+
+  TSDODataFactory = class(TSDOBaseDataFactory,IInterface,ISDODataFactory)
+  end;
+
+implementation
+
+uses
+  sdo_imp_utils, sdo_dataobject, sdo_consts;
+
+{ TSDOBaseDataFactory }
+
+procedure TSDOBaseDataFactory.AddType(
+  const AUri, ATypeName: string;
+  const AisSequenced, AisOpen, AisAbstract, AisDataType: Boolean
+);
+var
+  typ : ISDOType;
+begin
+  if not IsValidName(ATypeName) then
+    raise ESDOIllegalArgumentException.Create('ATypeName');
+  if AisDataType then begin
+    if AisSequenced then
+      raise ESDOIllegalArgumentException.Create('AisSequenced');
+    if AisOpen then
+      raise ESDOIllegalArgumentException.Create('AisOpen');
+  end;
+  if ( findType(AUri,ATypeName) <> nil ) then
+    raise ESDODuplicatedItemException.Create(AUri + ':' + ATypeName);
+  if AisDataType then
+    typ := TSDOUserDefinedSimpleType.Create(Self as ISDODataFactory, ATypeName,AUri,AisAbstract)
+  else
+    typ := TSDOObjectType.Create(Self as ISDODataFactory, ATypeName,AUri,AisSequenced,AisOpen,AisAbstract);
+  FTypeList.insert(typ);
+end;
+
+type
+  TCircularDependencyStackItem = packed record
+    _theType : ISDOType;
+    _property : ISDOProperty;
+    _listIndex : PtrInt;
+  end;
+procedure TSDOBaseDataFactory.addProperty(
+  const ATypeURI, ATypeName,
+        APropName, APropTypeUri, APropTypeName: string;
+  const AFlags: TPropertyFlags
+);
+begin
+  addProperty(
+    getType(ATypeURI, ATypeName),
+    APropName, APropTypeUri, APropTypeName,
+    AFlags
+  );
+end;
+
+procedure TSDOBaseDataFactory.AddType(
+  const AUri, ATypeName: string;
+  const AFlags: TTypeFlags
+);
+begin
+  AddType(
+    AUri,
+    ATypeName,
+    tfIsSequenced in AFlags,
+    tfIsOpen      in AFlags,
+    tfIsAbstract  in AFlags,
+    tfIsDataType  in AFlags
+  );
+end;
+
+procedure TSDOBaseDataFactory.CheckCircularDependencies(const AType: ISDOType);
+const
+  MAX_DEPT = 256;
+var
+  stack : array[0..(MAX_DEPT - 1)] of TCircularDependencyStackItem;
+    stackIndex : PtrInt;
+  typeList : array[0..(MAX_DEPT - 1)] of ISDOType;
+    typeListIndex : PtrInt;
+  currentType : ISDOType;
+
+  procedure StackPush(const ALocType : ISDOType; const AProperty : ISDOProperty);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  begin
+    Inc(stackIndex);
+    with stack[stackIndex] do begin
+      _theType := ALocType;
+      _property := AProperty;
+      _listIndex := typeListIndex;
+    end;
+  end;
+
+  function StackPop():Boolean ;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  begin
+    Result := ( stackIndex >= 0 );
+    if Result then begin
+      with stack[stackIndex] do begin
+        currentType := _theType;
+        typeListIndex := _listIndex;
+      end;
+      Dec(stackIndex);
+    end;
+  end;
+
+  procedure LocalAddType(const ALocType : ISDOType);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  var
+    k : PtrInt;
+    k_found : Boolean;
+    k_type : ISDOObjectType;
+  begin
+    k_type := ALocType as ISDOObjectType;
+    while ( k_type <> nil ) do begin
+      k_found := False;
+      if ( typeListIndex < 0 ) then begin
+        typeListIndex := -1;
+      end else begin
+        for k := 0 to typeListIndex do begin
+          if ( typeList[k] = k_type ) then begin
+            k_found := True;
+            Break;
+          end;
+        end;
+      end;
+      if not k_found then begin
+        Inc(typeListIndex);
+        typeList[typeListIndex] := k_type;
+      end;
+      k_type := k_type.getBaseType() as ISDOObjectType;
+    end;
+  end;
+
+  function isInTypeList(const ALocType : ISDOType) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  var
+    k : PtrInt;
+  begin
+    Result := False;
+    if ( typeListIndex >= 0 ) then begin
+      for k := 0 to typeListIndex do begin
+        if ( typeList[k] = ALocType ) then begin
+          Result := True;
+          Break;
+        end;
+      end;
+    end;
+  end;
+
+  function isInStack(const ALocType : ISDOType) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  var
+    k : PtrInt;
+  begin
+    Result := False;
+    if ( stackIndex >= 0 ) then begin
+      for k := 0 to stackIndex do begin
+        if ( stack[k]._theType = ALocType ) then begin
+          Result := True;
+          Break;
+        end;
+      end;
+    end;
+  end;
+
+  function getErrorPath(const ACurrentProp : ISDOProperty) : string;
+  var
+    locPath : string;
+  begin
+    Result := '';
+    while ( stackIndex > 0 ) do begin
+      if ( stack[stackIndex]._property <> nil ) then
+        locPath := stack[stackIndex]._property.getName()
+      else
+        locPath := '(Parent)';
+      Result := Format('%s->%s',[locPath,Result]);
+      Dec(stackIndex);
+    end;
+    if ( ACurrentProp <> nil ) then
+      Result := Format('%s->%s',[ACurrentProp.getName(),Result]);
+    if ( Length(Result) > 0 ) then
+      Delete(Result,Pred(Length(Result)),2);
+  end;
+  
+var
+  typeX : ISDOTypeEx;
+  prpLs : ISDOPropertyList;
+  prp : ISDOProperty;
+  prpType : ISDOType;
+  i, c : PtrInt;
+begin
+  if ( AType <> nil ) and AType.isDataObjectType() then begin
+    typeX := AType as ISDOTypeEx;
+    if ( not typeX.isUsed ) then begin
+      stackIndex := -1;
+      typeListIndex := -1;
+
+      try
+        StackPush(AType,nil);
+        while StackPop() do begin
+          if currentType.isDataObjectType() then begin
+            LocalAddType(currentType);
+            prpLs := currentType.getProperties();
+            c := prpLs.getCount();
+            for i := 0 to Pred(c) do begin
+              prp := prpLs.getItem(i);
+              prpType := prp.getType();
+              if ( not prpType.equals(currentType) ) and isInTypeList(prpType) then begin
+                raise ESDOCircularDependencyTypeException.Create(
+                        currentType.getName(),
+                        prp.getName(),
+                        prpType.getName()
+                      );
+              end;
+              if ( not prpType.equals(currentType) ) and ( not isInStack(prpType) ) then
+                StackPush(prpType,prp);
+            end;
+          end;
+        end;
+      except
+        on e : ESDOCircularDependencyTypeException do begin
+          e.Message := Format('%s%sPath : %s',[e.Message,sLineBreak,getErrorPath(prp)]);
+          raise;
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOBaseDataFactory.Clear();
+var
+  i, c : PtrInt;
+  t : ISDOTypeEx;
+  toX : ISDOObjectType;
+begin
+  if ( FTypeList <> nil ) then begin
+    c := FTypeList.getCount();
+    if ( c > 0 ) then begin
+      for i := Pred(c) downto 0 do begin
+        t := FTypeList.getItem(i) as ISDOTypeEx;
+        if t.isDataObjectType() and ( not t.isUsed() ) then begin
+          toX := t as ISDOObjectType;
+          toX.Clear();
+        end;
+      end;
+    end;
+  end;
+end;
+
+constructor TSDOBaseDataFactory.Create();
+  procedure AddPrimitiveTypes(const ATypeList : ISDOTypeListEx);
+    procedure AddAlias(
+      const AType  : ISDOTypeEx;
+      const AALias : array of TSDOString
+    );
+    var
+      k : Integer;
+    begin
+      for k := Low(AALias) to High(AALias) do
+        AType.setAlias(AALias[k]);
+    end;
+
+  var
+    selfIntf : ISDODataFactory;
+    typeRef : ISDOTypeEx;
+  begin
+    selfIntf := Self as ISDODataFactory;
+    typeRef := TSDOBooleanType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      typeRef.setAlias('boolean');
+    typeRef := TSDOByteType.Create(selfIntf);
+    ATypeList.insert(typeRef);   
+      typeRef.setAlias('byte');
+{$IFDEF HAS_SDO_BYTES}
+    ATypeList.insert(TSDOBytesType.Create(selfIntf));
+{$ENDIF HAS_SDO_BYTES}
+    ATypeList.insert(TSDOChangeSummaryType.Create(selfIntf));
+{$IFDEF HAS_SDO_CHAR}
+    ATypeList.insert(TSDOCharacterType.Create(selfIntf));
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    typeRef := TSDOCurrencyType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['decimal']);
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    typeRef := TSDODoubleType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['double','decimal']);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    typeRef := TSDOFloatType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['float']);
+{$ENDIF HAS_SDO_FLOAT}
+    typeRef := TSDODateTimeType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['dateTime']);
+    typeRef := TSDOIntegerType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['int']);
+{$IFDEF HAS_SDO_LONG}             
+    typeRef := TSDOLongType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['long']);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    typeRef := TSDOShortType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['short']);
+{$ENDIF HAS_SDO_SHORT}
+    ATypeList.insert(TSDOObjectType.Create(selfIntf,SDOTypeDefaultTypeNames[ObjectType],sdo_namespace,False,False,True));
+    typeRef := TSDOStringType.Create(selfIntf);
+    ATypeList.insert(typeRef);
+      AddAlias(typeRef,['string','anyURI','ID','token','language']);
+  end;
+
+begin
+  inherited;
+  FTypeList := TSDOTypeList.Create();
+  AddPrimitiveTypes(FTypeList);
+  AddType(sdo_namespace,s_datagraph,[]);
+  AddType(sdo_namespace,s_xsd,[]);
+  AddType(sdo_namespace,s_changeSummaryListObject,[tfIsOpen]);
+end;
+
+function TSDOBaseDataFactory.createNew(const AType : ISDOType): ISDODataObject;
+var
+  typ : ISDOType;
+  objType : ISDOObjectType;
+begin
+  if ( AType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  typ := getType(AType.getURI(),AType.getName());
+  if not Supports(typ,ISDOObjectType,objType) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if typ.isAbstractType() then
+    raise ESDOAbstractTypeException.Create(typ.getName());
+  CheckCircularDependencies(AType);
+  if AType.isOpenType() then
+    Result := TSDOOpenedDataObject.Create(objType,nil,nil) as ISDODataObject
+  else
+    Result := TSDODataObject.Create(objType,nil,nil) as ISDODataObject;
+end;
+
+function TSDOBaseDataFactory.createNew(const AUri,ATypeName: string): ISDODataObject;
+begin
+  Result := createNew(getType(AUri,ATypeName));
+end;
+
+destructor TSDOBaseDataFactory.Destroy();
+begin
+  Clear();
+  FTypeList := nil;
+  inherited;
+end;
+
+function TSDOBaseDataFactory.findType(const ATypeURI,ATypeName: string): ISDOTypeEx;
+begin
+  Result := getTypes().find(ATypeURI,ATypeName) as ISDOTypeEx;
+end;
+
+function TSDOBaseDataFactory.getType(const AUri,ATypeName: string): ISDOType;
+begin
+  Result := findType(AUri,ATypeName);
+  if ( Result = nil ) then
+    raise ESDOTypeNotFoundException.Create(ATypeName);
+end;
+
+function TSDOBaseDataFactory.getTypes() : ISDOTypeList;
+begin
+  Result := FTypeList;
+end;
+
+procedure TSDOBaseDataFactory.setAlias(const ATypeUri, ATypeName, APropName, AAlias: string);
+var
+  typ : ISDOTypeEx;
+  prp : ISDOPropertyEx;
+begin
+  typ := findType(ATypeURI,ATypeName);
+  if ( typ = nil ) then
+    raise ESDOTypeNotFoundException.Create(ATypeName);
+  if typ.isUsed() then
+    raise ESDOUnsupportedOperationException.Create('setAlias');
+  prp := typ.getProperty(APropName) as ISDOPropertyEx;
+  prp.setAlias(AAlias);
+end;
+
+procedure TSDOBaseDataFactory.setAlias(const ATypeURI, ATypeName, AAlias: string);
+var
+  typ : ISDOTypeEx;
+begin
+  typ := findType(ATypeURI,ATypeName);
+  if ( typ = nil ) then
+    raise ESDOTypeNotFoundException.Create(ATypeName);
+  if typ.isUsed() then
+    raise ESDOUnsupportedOperationException.Create('setAlias');
+  typ.setAlias(AAlias);
+end;
+
+procedure TSDOBaseDataFactory.setBaseType(const AType, ABase: ISDOType);
+var
+  typ : ISDOTypeEx;
+begin
+  if ( AType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  typ := findType(AType.getURI(),AType.getName());
+  if ( typ = nil ) then
+    raise ESDOTypeNotFoundException.Create(AType.getName());
+  if typ.isUsed() then
+    raise ESDOUnsupportedOperationException.Create('setAlias');
+  typ.setBaseType(ABase);
+end;
+
+procedure TSDOBaseDataFactory.setBaseType(
+  const ATypeURI, ATypeName, ABaseURI, ABaseName: string
+);
+var
+  typ : ISDOTypeEx;
+begin
+  typ := findType(ATypeURI,ATypeName);
+  if ( typ = nil ) then
+    raise ESDOTypeNotFoundException.Create(ATypeName);
+  if typ.isUsed() then
+    raise ESDOUnsupportedOperationException.Create('setAlias');
+  typ.setBaseType(getType(ABaseURI,ABaseName));
+end;
+
+
+procedure TSDOBaseDataFactory.addProperty(
+  const ATypeURI, ATypeName,
+        APropName: string;
+  const APropType: ISDOType;
+  const AFlags: TPropertyFlags
+);
+begin
+  addProperty(
+    getType(ATypeURI, ATypeName),
+    APropName, APropType,
+    AFlags
+  );
+end;
+
+procedure TSDOBaseDataFactory.addProperty(
+  const AType: ISDOType;
+  const APropName: string;
+  const APropType: ISDOType;
+  const AFlags: TPropertyFlags
+);
+var
+  typ : ISDOTypeEx;
+  prpList : ISDOPropertyListEx;
+begin
+  if ( AType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if IsStrEmpty(APropName) then
+    raise ESDOIllegalArgumentException.Create('APropType');
+  if ( APropType = nil ) then
+    raise ESDOIllegalArgumentException.Create('APropType');
+  typ := findType(AType.getURI(),AType.getName());
+  if ( typ = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if ( typ <> AType ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if typ.isUsed() then
+    raise ESDOUnsupportedOperationException.Create('addProperty');
+  prpList := typ.getProperties() as ISDOPropertyListEx;
+  if ( prpList.find(APropName) <> nil ) then
+    raise ESDODuplicatedItemException.Create(APropName);
+  if APropType.isDataType() and ( pfIsContainment in AFlags ) then
+    raise ESDOIllegalArgumentException.Create('AIsContainment');
+  if APropType.isChangeSummaryType() then begin
+    if ( pfIsMany in AFlags ) then
+      raise ESDOIllegalArgumentException.Create('AIsMany');
+    if not ( pfIsReadOnly in AFlags ) then
+      raise ESDOIllegalArgumentException.Create('AIsReadOnly');  
+    if (pfIsAttribute in AFlags) then
+      raise ESDOIllegalArgumentException.Create('AIsAttribute');
+  end;
+  prpList.add(TSDOProperty.Create(APropName,APropType,AFlags,typ));
+end;
+
+procedure TSDOBaseDataFactory.addProperty(
+  const AType: ISDOType;
+  const APropName, APropTypeUri, APropTypeName: string;
+  const AFlags: TPropertyFlags
+);
+begin
+  addProperty(
+    AType,
+    APropName, getType(APropTypeUri, APropTypeName),
+    AFlags
+  );
+end;
+
+procedure TSDOBaseDataFactory.addProperty(
+        ADataObject: ISDODataObject;
+  const APropName: string; const APropType: ISDOType; const AFlags: TPropertyFlags
+);
+var
+ oX : ISDODataObjectEx;
+begin
+  if ( ADataObject = nil ) or
+     ( not ADataObject.getType().isOpenType() ) or
+     ( not Supports(ADataObject,ISDODataObjectEx,oX) )
+  then begin
+    raise ESDOIllegalArgumentException.Create('ADataObject');
+  end;
+  oX.addProperty(APropName,APropType,AFlags);
+end;
+
+function TSDOBaseDataFactory.CreateList(AType : ISDOType) : ISDODataObjectList;
+begin
+  Result := TSDODataObjectList.Create(AType) as ISDODataObjectList;
+end;
+
+function TSDOBaseDataFactory.CreateList(
+  const AUri, ATypeName : string
+) : ISDODataObjectList;
+begin
+  Result := TSDODataObjectList.Create(getType(AUri,ATypeName)) as ISDODataObjectList;
+end;
+
+end.

+ 4199 - 0
packages/fcl-sdo/src/base/sdo_dataobject.pas

@@ -0,0 +1,4199 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements the basic SDO objects
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_dataobject;
+
+interface
+uses
+  SysUtils, Classes, Contnrs,
+  sdo_types, sdo, sdo_type, sdo_changesummary, sdo_xpath_helper, sdo_linked_list,
+  sdo_field_imp;
+
+type
+
+  IDataObjectObserver = interface
+    ['{EF23F339-EF10-4312-B202-43AA5C743841}']
+    procedure NotifyDeletion(
+      const ADataObject : ISDODataObject;
+      const AProperty : ISDOProperty
+    );
+  end;
+
+  ISDODataObjectEx = interface(ISDODataObject)
+    ['{2EA33304-D190-425F-A952-685619896AB2}']
+    //Return TRUE if this instance is an instance or a derived class
+    function IsInstanceOf(const AType : ISDOType) : Boolean;
+
+    function IsAncestorOf(const AObject : ISDODataObject) : Boolean;
+    procedure setContainer(
+      const AContainer : ISDODataObject;
+      const AContainerProperty : ISDOProperty
+    );
+    procedure AddReference(
+      const AReferencer : ISDODataObject;
+      const AReferenceProperty : ISDOProperty
+    );
+    procedure RemoveReference(
+      const AReferencer : ISDODataObject;
+      const AReferenceProperty : ISDOProperty
+    );
+    procedure NotifyContainedObjectsForDeletion(const ACallFromParent : Boolean);// logical deletion
+
+    // for open Type support
+    procedure addProperty(
+      const APropName : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );
+  end;
+
+  TObserverInfo = class
+  private
+    FDataObject  : Pointer;
+    FRefProperty : Pointer;
+  public
+    constructor Create(const ADataObject : ISDODataObject; const ARefProperty : ISDOProperty);
+    function GetDataObject() : ISDODataObject;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetRefProperty() : ISDOProperty;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  end;
+
+  TDataObjectObserverList = class
+  private
+    FList : TObjectList;
+  public
+    constructor Create();
+    destructor Destroy();override;
+    procedure Add(const ADataObject : ISDODataObject; const ARefProperty : ISDOProperty);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function IndexOf(const ADataObject : ISDODataObject; const ARefProperty : ISDOProperty) : PtrInt;
+    function Find(const ADataObject : ISDODataObject; const ARefProperty : ISDOProperty) : TObserverInfo;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetCount() : PtrInt;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetItem(const AIndex : PtrInt) : TObserverInfo;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function Extract(const AIndex : PtrInt) : TObserverInfo;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure Delete(const AIndex : PtrInt);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  end;
+
+  TSDOBaseDataObjectClass = class of TSDOBaseDataObject;
+  TSDOBaseDataObject = class(
+    TInterfacedObject,
+    IInterface,
+    ISDODataObject,
+    ISDODataObjectEx,
+    IDataObjectObserver
+  )
+  private
+    FDestroying : Boolean;
+    FType : ISDOObjectType;
+    FContainer : Pointer;
+    FContainerProperty : Pointer;
+    FBuffer : TSDOFieldBuffer;
+    FBufferLength : PtrUInt;
+    FChangeSummary : Pointer;//ISDOChangeSummaryEx;
+    FReferenceLinkList : TDataObjectObserverList;
+  private
+    FXPathExpression : TXPathExpression;
+    FXPathProcessor : TXPathProcessor;
+  protected
+    function _Release: LongInt; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
+    procedure PrepareDataBuffer();
+    procedure FreeBuffer();
+    function parsePropertyPath(const APath : string) : TXPathExecContext;
+    function IsOwnerOf(const AProp : ISDOProperty) : Boolean;virtual;//{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function CreateList(const AProperty : ISDOProperty) : ISDODataObjectList;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure InitializeDefaultValues();
+  protected
+    procedure RecordChange(const AProperty : ISDOProperty);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure NotifyReferencersForDeletion();
+  protected
+    // ISDODataObjectEx
+    function IsInstanceOf(const AType : ISDOType) : Boolean;
+    function IsAncestorOf(const AObject : ISDODataObject) : Boolean;
+    procedure setContainer(
+      const AContainer : ISDODataObject;
+      const AContainerProperty : ISDOProperty
+    );
+
+    //ISDODataObject
+    function getPropertyIndex(const AProperty : ISDOProperty) : PtrInt;
+    function getInstanceProperties() : ISDOPropertyList;virtual;
+
+    function getProperty(const AIndex : PtrUInt) : ISDOProperty;overload;
+    function getProperty(const AProp : string) : ISDOProperty;overload;
+
+    function getContainer() : ISDODataObject;
+    function getContainmentProperty() : ISDOProperty;
+    function getType() : ISDOType;
+    function getTypeEnum() : TSDOTypeKind;
+
+    function getList(const APath : string) : ISDODataObjectList; overload;
+    function getList(const APropertyIndex : PtrUInt) : ISDODataObjectList; overload;
+    function getList(const AProperty : ISDOProperty) : ISDODataObjectList; overload;
+
+    function getDataObject(const APath : string) : ISDODataObject; overload;
+    function getDataObject(const APropertyIndex : PtrUInt) : ISDODataObject; overload;
+    function getDataObject(const AProperty : ISDOProperty) : ISDODataObject; overload;
+
+    procedure setDataObject(const APath : string; AValue : ISDODataObject); overload; virtual;
+    procedure setDataObject(const APropertyIndex : PtrUInt; AValue : ISDODataObject); overload;
+    procedure setDataObject(const AProperty : ISDOProperty; AValue : ISDODataObject); overload;
+
+    function getBoolean(const APath : string) : TSDOBoolean; overload;
+    function getBoolean(const APropertyIndex : PtrUInt) : TSDOBoolean; overload;
+    function getBoolean(const AProperty : ISDOProperty) : TSDOBoolean; overload;
+
+    procedure setBoolean(const APath : string; const AValue : TSDOBoolean); overload; virtual;
+    procedure setBoolean(const APropertyIndex : PtrUInt; const AValue : TSDOBoolean); overload;
+    procedure setBoolean(const AProperty : ISDOProperty; const AValue : TSDOBoolean); overload;
+
+    function getByte(const APath : string) : TSDOByte;overload;
+    function getByte(const APropertyIndex : PtrUInt) : TSDOByte;overload;
+    function getByte(const AProperty : ISDOProperty) : TSDOByte;overload;
+
+    procedure setByte(const APath : string; const AValue : TSDOByte);overload; virtual;
+    procedure setByte(const APropertyIndex : PtrUInt; const AValue : TSDOByte);overload;
+    procedure setByte(const AProperty : ISDOProperty; const AValue : TSDOByte);overload;
+
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacter(const APath : string) : TSDOChar;overload;
+    function getCharacter(const APropertyIndex : PtrUInt) : TSDOChar;overload;
+    function getCharacter(const AProperty : ISDOProperty) : TSDOChar;overload;
+
+    procedure setCharacter(const APath : string; const AValue : TSDOChar);overload; virtual;
+    procedure setCharacter(const APropertyIndex : PtrUInt; const AValue : TSDOChar);overload;
+    procedure setCharacter(const AProperty : ISDOProperty; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_BYTES}
+    function getBytes(const APath : string) : TSDOBytes;overload;
+    function getBytes(const APropertyIndex : PtrUInt) : TSDOBytes;overload;
+    function getBytes(const AProperty : ISDOProperty) : TSDOBytes;overload;
+
+    procedure setBytes(const APath : string; AValue : TSDOBytes);overload; virtual;
+    procedure setBytes(const APropertyIndex : PtrUInt; AValue : TSDOBytes);overload;
+    procedure setBytes(const AProperty : ISDOProperty; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency(const APath : string) : TSDOCurrency;overload;
+    function getCurrency(const APropertyIndex : PtrUInt) : TSDOCurrency;overload;
+    function getCurrency(const AProperty : ISDOProperty) : TSDOCurrency;overload;
+
+    procedure setCurrency(const APath : string; const AValue : TSDOCurrency);overload;  virtual;
+    procedure setCurrency(const APropertyIndex : PtrUInt; const AValue : TSDOCurrency);overload;
+    procedure setCurrency(const AProperty : ISDOProperty; const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+
+    function getString(const APath : string) : TSDOString;overload;
+    function getString(const APropertyIndex : PtrUInt) : TSDOString;overload;
+    function getString(const AProperty : ISDOProperty) : TSDOString;overload;
+
+    procedure setString(const APath : string; const AValue : TSDOString);overload;virtual;
+    procedure setString(const APropertyIndex : PtrUInt; const AValue : TSDOString);overload;
+    procedure setString(const AProperty : ISDOProperty; const AValue : TSDOString);overload;
+
+    function getDate(const APath : string) : TSDODate;overload;
+    function getDate(const APropertyIndex : PtrUInt) : TSDODate;overload;
+    function getDate(const AProperty : ISDOProperty) : TSDODate;overload;
+
+    procedure setDate(const APath : string; const AValue : TSDODate);overload;virtual;
+    procedure setDate(const APropertyIndex : PtrUInt; const AValue : TSDODate);overload;
+    procedure setDate(const AProperty : ISDOProperty; const AValue : TSDODate);overload;
+
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble(const APath : string) : TSDODouble;overload;
+    function getDouble(const APropertyIndex : PtrUInt) : TSDODouble;overload;
+    function getDouble(const AProperty : ISDOProperty) : TSDODouble;overload;
+
+    procedure setDouble(const APath : string; const AValue : TSDODouble);overload; virtual;
+    procedure setDouble(const APropertyIndex : PtrUInt; const AValue : TSDODouble);overload;
+    procedure setDouble(const AProperty : ISDOProperty; const AValue : TSDODouble);overload; 
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat(const APath : string) : TSDOFloat;overload;
+    function getFloat(const APropertyIndex : PtrUInt) : TSDOFloat;overload;
+    function getFloat(const AProperty : ISDOProperty) : TSDOFloat;overload;
+
+    procedure setFloat(const APath : string; const AValue : TSDOFloat);overload; virtual;
+    procedure setFloat(const APropertyIndex : PtrUInt; const AValue : TSDOFloat);overload;
+    procedure setFloat(const AProperty : ISDOProperty; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+
+    function getInteger(const APath : string) : TSDOInteger;overload;
+    function getInteger(const APropertyIndex : PtrUInt) : TSDOInteger;overload;
+    function getInteger(const AProperty : ISDOProperty) : TSDOInteger;overload;
+
+    procedure setInteger(const APath : string; const AValue : TSDOInteger);overload;virtual;
+    procedure setInteger(const APropertyIndex : PtrUInt; const AValue : TSDOInteger);overload;
+    procedure setInteger(const AProperty : ISDOProperty; const AValue : TSDOInteger);overload;
+
+{$IFDEF HAS_SDO_LONG}
+    function getLong(const APath : string) : TSDOLong;overload;
+    function getLong(const APropertyIndex : PtrUInt) : TSDOLong;overload;
+    function getLong(const AProperty : ISDOProperty) : TSDOLong;overload;
+
+    procedure setLong(const APath : string; const AValue : TSDOLong);overload; virtual;
+    procedure setLong(const APropertyIndex : PtrUInt; const AValue : TSDOLong);overload;
+    procedure setLong(const AProperty : ISDOProperty; const AValue : TSDOLong);overload; 
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+    function getShort(const APath : string) : TSDOShort;overload;
+    function getShort(const APropertyIndex : PtrUInt) : TSDOShort;overload;
+    function getShort(const AProperty : ISDOProperty) : TSDOShort;overload;
+
+    procedure setShort(const APath : string; const AValue : TSDOShort);overload; virtual;
+    procedure setShort(const APropertyIndex : PtrUInt; const AValue : TSDOShort);overload;
+    procedure setShort(const AProperty : ISDOProperty; const AValue : TSDOShort);overload; 
+{$ENDIF HAS_SDO_SHORT}
+
+    function getVariant(const APath : string) : TSDOVariant;overload;
+    function getVariant(const APropertyIndex : PtrUInt) : TSDOVariant;overload;
+    function getVariant(const AProperty : ISDOProperty) : TSDOVariant;overload;
+
+    procedure setVariant(const APath : string; const AValue : TSDOVariant);overload;
+    procedure setVariant(const APropertyIndex : PtrUInt; const AValue : TSDOVariant);overload;
+    procedure setVariant(const AProperty : ISDOProperty; const AValue : TSDOVariant);overload;
+
+    procedure setNull(const APath : string);overload;
+    procedure setNull(const APropertyIndex : PtrUInt);overload;
+    procedure setNull(const AProperty : ISDOProperty);overload;
+
+    function isNull(const APath : string) : Boolean;overload;
+    function isNull(const APropertyIndex : PtrUInt) : Boolean;overload;
+    function isNull(const AProperty : ISDOProperty) : Boolean;overload;
+
+    function isSet(const APath : string) : Boolean;overload;
+    function isSet(const APropertyIndex : PtrUInt) : Boolean;overload;
+    function isSet(const AProperty : ISDOProperty) : Boolean;overload;
+
+    procedure unset(const APath : string);overload;
+    procedure unset(const APropertyIndex : PtrUInt);overload;
+    procedure unset(const AProperty : ISDOProperty);overload;
+
+    function createDataObject(const APath : string) : ISDODataObject; overload;
+    function createDataObject(const APropertyIndex : PtrUInt) : ISDODataObject; overload;
+    function createDataObject(const AProperty : ISDOProperty) : ISDODataObject; overload;
+
+    function getChangeSummary() : ISDOChangeSummary;overload;
+    {function getChangeSummary(const APath : string) : ISDOChangeSummary;overload;
+    function getChangeSummary(const APropIndex : PtrUInt) : ISDOChangeSummary;overload;
+    function getChangeSummary(const AProp : ISDOProperty ) : ISDOChangeSummary;overload;
+    }
+    procedure clear();
+
+    // IDataObjectObserver implementation
+    procedure NotifyDeletion(
+      const ADataObject : ISDODataObject;
+      const AProperty : ISDOProperty
+    );
+    procedure AddReference(
+      const AReferencer : ISDODataObject;
+      const AReferenceProperty : ISDOProperty
+    );
+    procedure RemoveReference(
+      const AReferencer : ISDODataObject;
+      const AReferenceProperty : ISDOProperty
+    );
+    procedure NotifyContainedObjectsForDeletion(const ACallFromParent : Boolean);// logical deletion
+    // for open Type support
+    procedure addProperty(
+      const APropName : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );
+  public
+    constructor Create(
+      const AType : ISDOTypeEx;
+      const AContainer : ISDODataObject;
+      const AContainerProperty : ISDOProperty
+    );virtual;
+    destructor Destroy();override;
+  end;
+
+  TSDODataObject = class(TSDOBaseDataObject, IInterface, ISDODataObject)
+  end;
+
+  TSDOOpenedDataObject = class(
+    TSDOBaseDataObject,
+    IInterface,
+    ISDODataObject,
+    ISDODataObjectEx
+  )
+  private
+    FInstanceProperties : ISDOPropertyListEx;
+  protected
+    function IsOwnerOf(const AProp : ISDOProperty) : Boolean; override;
+    function getInstanceProperties() : ISDOPropertyList;override;
+    procedure setBoolean(const APath : string; const AValue : TSDOBoolean); overload; override;
+    procedure setByte(const APath : string; const AValue : TSDOByte); overload; override;
+{$IFDEF HAS_SDO_BYTES}
+    procedure setBytes(const APath : string; AValue : TSDOBytes); overload; override;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setCharacter(const APath : string; const AValue : TSDOChar); overload; override;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setCurrency(const APath : string; const AValue : Currency); overload; override;
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDate(const APath : string; const AValue : TSDODate);overload;override;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDouble(const APath : string; const AValue : TSDODouble); overload; override;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setFloat(const APath : string; const AValue : TSDOFloat); overload; override;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setInteger(const APath : string; const AValue : TSDOInteger);overload;override;
+{$IFDEF HAS_SDO_LONG}
+    procedure setLong(const APath : string; const AValue : TSDOLong); overload; override;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setShort(const APath : string; const AValue : TSDOShort); overload; override;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setString(const APath : string; const AValue : TSDOString);overload;override;
+    procedure setDataObject(const APath : string; AValue : ISDODataObject); overload; override;
+
+    // for open Type support
+    procedure addProperty(
+      const APropName : string;
+      const APropType : ISDOType;
+      const AFlags : TPropertyFlags
+    );
+  public
+    constructor Create(
+      const AType : ISDOTypeEx;
+      const AContainer : ISDODataObject;
+      const AContainerProperty : ISDOProperty
+    );override;
+  end;
+
+  TSDODataObjectList = class(TInterfacedObject,IInterface,ISDODataObjectList)
+  private
+    FItemType : ISDOType;
+    FData : TDoubleLinkedList;
+    FCursor : ILinkedListCursor;
+    FField : ISDOField;
+  private
+    procedure Clear();
+    procedure InternalDelete(const AData : PLinkedNode);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function InternalAppend() : PLinkedNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure CheckCursorPosition();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure MoveTo(const AIndex : PtrInt);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    function getItemType() : ISDOType;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function size() : PtrInt;
+    function getCursor() : ILinkedListCursor;
+
+    {These operations use the cursor location}
+    function getBoolean() : TSDOBoolean;overload;
+    function getByte() : TSDOByte;overload;
+{$IFDEF HAS_SDO_BYTES}
+    function getBytes() : TSDOBytes;overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacter() : TSDOChar;overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency() : TSDOCurrency;overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    function getDate() : TSDODate;overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble() : TSDODouble;overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat() : TSDOFloat;overload;
+{$ENDIF HAS_SDO_FLOAT}
+    function getInteger() : TSDOInteger;overload;
+{$IFDEF HAS_SDO_LONG}
+    function getLong() : TSDOLong;overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function getShort() : TSDOShort;overload;
+{$ENDIF HAS_SDO_SHORT}
+    function getString() : TSDOString;overload;
+    function getDataObject() : ISDODataObject;overload;
+    function getVariant() : TSDOVariant;overload;
+
+
+    procedure setBoolean(const AValue : TSDOBoolean);overload;
+    procedure setByte(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+   procedure setBytes(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setCharacter(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setCurrency(const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDate(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDouble(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setFloat(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setInteger(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setLong(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setShort(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setString(const AValue : TSDOString);overload;
+    procedure setDataObject(AValue : ISDODataObject);overload;
+    procedure setVariant(const AValue : TSDOVariant);overload;
+
+
+    function getBoolean(const AIndex : PtrInt) : TSDOBoolean;overload;
+    function getByte(const AIndex : PtrInt) : TSDOByte;overload;
+{$IFDEF HAS_SDO_BYTES}
+    function getBytes(const AIndex : PtrInt) : TSDOBytes;overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacter(const AIndex : PtrInt) : TSDOChar;overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency(const AIndex : PtrInt) : TSDOCurrency;overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    function getDate(const AIndex : PtrInt) : TSDODate;overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble(const AIndex : PtrInt) : TSDODouble;overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat(const AIndex : PtrInt) : TSDOFloat;overload;
+{$ENDIF HAS_SDO_FLOAT}
+    function getInteger(const AIndex : PtrInt) : TSDOInteger;overload;
+{$IFDEF HAS_SDO_LONG}
+    function getLong(const AIndex : PtrInt) : TSDOLong;overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function getShort(const AIndex : PtrInt) : TSDOShort;overload;
+{$ENDIF HAS_SDO_SHORT}
+    function getString(const AIndex : PtrInt) : TSDOString;overload;
+    function getDataObject(const AIndex : PtrInt) : ISDODataObject;overload;
+    function getVariant(const AIndex : PtrInt) : TSDOVariant;overload;
+
+
+    procedure setBoolean(const AIndex : PtrInt; const AValue : TSDOBoolean);overload;
+    procedure setByte(const AIndex : PtrInt; const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure setBytes(const AIndex : PtrInt; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setCharacter(const AIndex : PtrInt; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setCurrency(const AIndex : PtrInt; const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDate(const AIndex : PtrInt; const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDouble(const AIndex : PtrInt; const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setFloat(const AIndex : PtrInt; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setInteger(const AIndex : PtrInt; const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setLong(const AIndex : PtrInt; const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setShort(const AIndex : PtrInt; const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setString(const AIndex : PtrInt; const AValue : TSDOString);overload;
+    procedure setVariant(const AIndex : PtrInt; const AValue : TSDOVariant);overload;
+    procedure setDataObject(const AIndex : PtrInt; AValue : ISDODataObject);overload;
+
+
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOBoolean);overload;
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure insertBytes(const AIndex : PtrInt; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure insertCurrency(const AIndex : PtrInt; const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOString);overload;
+    procedure insert(const AIndex : PtrInt; AValue : ISDODataObject);overload;
+
+
+    procedure append(const AValue : TSDOBoolean);overload;
+    procedure append(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure appendBytes(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure append(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure appendCurrency(const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure append(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure append(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure append(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure append(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure append(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure append(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure append(const AValue : TSDOString);overload;
+    procedure append(AValue : ISDODataObject);overload;
+
+
+    procedure delete(const AIndex : PtrInt);overload;
+    procedure delete();overload;
+  public
+    constructor Create(const AItemType : ISDOType);
+    destructor Destroy();override;
+  end;
+
+  TSDOOwnedDataObjectList = class(TSDODataObjectList,IInterface,ISDODataObjectList)
+  private
+    FOwner : Pointer; // do not add a reference count!
+    FOwnerProperty : ISDOProperty;
+  protected
+    procedure RecordChange(const AChange : TManyValuePropAction);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function getOwner() : ISDODataObject;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure InternalSetDataObject(const AValue : ISDODataObject; const ADoRecordChange : Boolean);
+  protected
+    procedure setBoolean(const AValue : TSDOBoolean);overload;
+    procedure setByte(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure setBytes(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setCharacter(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setCurrency(const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDate(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDouble(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setFloat(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setInteger(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setLong(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setShort(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setString(const AValue : TSDOString);overload;
+    procedure setDataObject(AValue : ISDODataObject);overload;
+    procedure setVariant(const AValue : TSDOVariant);overload;
+
+    procedure setBoolean(const AIndex : PtrInt; const AValue : TSDOBoolean);overload;
+    procedure setByte(const AIndex : PtrInt; const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure setBytes(const AIndex : PtrInt; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setCharacter(const AIndex : PtrInt; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setCurrency(const AIndex : PtrInt; const AValue : TSDOCurrency);overload;
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure setDate(const AIndex : PtrInt; const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDouble(const AIndex : PtrInt; const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setFloat(const AIndex : PtrInt; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setInteger(const AIndex : PtrInt; const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setLong(const AIndex : PtrInt; const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setShort(const AIndex : PtrInt; const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setString(const AIndex : PtrInt; const AValue : TSDOString);overload;
+    procedure setDataObject(const AIndex : PtrInt; AValue : ISDODataObject);overload;
+    procedure setVariant(const AIndex : PtrInt; const AValue : TSDOVariant);overload;
+
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOBoolean);overload;
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure insertBytes(const AIndex : PtrInt; AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure insertCurrency(const AIndex : PtrInt; const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure insert(const AIndex : PtrInt; const AValue : TSDOString);overload;
+    procedure insert(const AIndex : PtrInt; AValue : ISDODataObject);overload;
+
+    procedure append(const AValue : TSDOBoolean);overload;
+    procedure append(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure appendBytes(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure append(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure appendCurrency(const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure append(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure append(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure append(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure append(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure append(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure append(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure append(AValue : ISDODataObject);overload;
+    procedure append(const AValue : TSDOString);overload;
+
+    procedure delete(const AIndex : PtrInt);overload;
+    procedure delete();overload;
+  public
+    constructor Create(
+      const AOwner : ISDODataObject;
+      const AProperty : ISDOProperty
+    );
+  end;
+
+implementation
+
+uses
+  sdo_imp_utils, sdo_utils;
+
+{ TSDOBaseDataObject }
+
+procedure TSDOBaseDataObject.clear;
+begin
+
+end;
+
+constructor TSDOBaseDataObject.Create(
+  const AType: ISDOTypeEx;
+  const AContainer : ISDODataObject;
+  const AContainerProperty : ISDOProperty
+);
+begin
+  if ( AType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if ( AContainer <> nil ) and ( AContainerProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AContainerProperty');
+  FType := AType as ISDOObjectType;
+  FContainer := Pointer(AContainer);
+  FContainerProperty := Pointer(AContainerProperty);
+  FXPathExpression := TXPathExpression.Create();
+  FXPathProcessor := TXPathProcessor.Create();
+  PrepareDataBuffer();
+  InitializeDefaultValues();
+  FType.setUsedFlag(True);
+end;
+
+function TSDOBaseDataObject.createDataObject(const APath: string): ISDODataObject;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  Result := locCtx.PropertyOwner.createDataObject(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.createDataObject(const AProperty: ISDOProperty) : ISDODataObject;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or ( not Self.IsOwnerOf(AProperty) ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  prp := AProperty as ISDOPropertyEx;
+  Result := TSDOBaseDataObjectClass(Self.ClassType).Create(
+              prp.getType() as ISDOTypeEx,
+              nil, //Self as ISDODataObject,
+              prp
+            ) as ISDODataObject;
+  if not AProperty.isMany() then
+    setDataObject(prp,Result);
+end;
+
+function TSDOBaseDataObject.createDataObject(const APropertyIndex: PtrUInt): ISDODataObject;
+begin
+  Result := createDataObject(getProperty(APropertyIndex));
+end;
+
+destructor TSDOBaseDataObject.Destroy();
+begin
+  FDestroying := True;
+  FreeBuffer();
+  FType := nil;
+  FContainer := nil;
+  FContainerProperty := nil;
+  FChangeSummary := nil;
+  FreeAndNil(FReferenceLinkList);
+  FreeAndNil(FXPathExpression);
+  FreeAndNil(FXPathProcessor);
+  inherited;
+end;
+
+function TSDOBaseDataObject.getBoolean(const APath: string): TSDOBoolean;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getBoolean()
+  else
+    Result := locCtx.PropertyOwner.getBoolean(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getBoolean(const APropertyIndex: PtrUInt): TSDOBoolean;
+begin
+  Result := getBoolean(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getBoolean(const AProperty: ISDOProperty): TSDOBoolean;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getBoolean(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getByte(const APath: string): TSDOByte;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getByte()
+  else
+    Result := locCtx.PropertyOwner.getByte(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getByte(const APropertyIndex: PtrUInt): TSDOByte;
+begin
+  Result := getByte(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getByte(const AProperty: ISDOProperty): TSDOByte;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getByte(FBuffer,prp.getBufferOffset());
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+function TSDOBaseDataObject.getBytes(const AProperty: ISDOProperty): TSDOBytes;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getBytes(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getBytes(const APath: string): TSDOBytes;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getBytes()
+  else
+    Result := locCtx.PropertyOwner.getBytes(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getBytes(const APropertyIndex: PtrUInt): TSDOBytes;
+begin
+  Result := getBytes(getProperty(APropertyIndex));
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+function TSDOBaseDataObject.getCharacter(const AProperty: ISDOProperty): TSDOChar;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getCharacter(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getCharacter(const APropertyIndex: PtrUInt): TSDOChar;
+begin
+  Result := getCharacter(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getCharacter(const APath: string): TSDOChar;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getCharacter()
+  else
+    Result := locCtx.PropertyOwner.getCharacter(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getContainer() : ISDODataObject;
+begin
+  Result := ISDODataObject(FContainer);
+end;
+
+function TSDOBaseDataObject.getContainmentProperty() : ISDOProperty;
+begin
+  if not Assigned(FContainerProperty) then
+    raise ESDOPropertyNotFoundException.Create('ContainmentProperty');
+  Result := ISDOProperty(FContainerProperty);
+end;
+
+{$IFDEF HAS_SDO_CURRENCY }
+function TSDOBaseDataObject.getCurrency(const AProperty: ISDOProperty): TSDOCurrency;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getCurrency(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getCurrency(const APropertyIndex: PtrUInt): TSDOCurrency;
+begin
+  Result := getCurrency(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getCurrency(const APath: string): TSDOCurrency;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getCurrency()
+  else
+    Result := locCtx.PropertyOwner.getCurrency(locCtx.CurrentProperty);
+end;
+{$ENDIF HAS_SDO_CURRENCY }
+
+function TSDOBaseDataObject.getDataObject(const APath: string): ISDODataObject;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  Result := locCtx.ObjectItem;
+  {if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getDataObject()
+  else
+    Result := locCtx.PropertyOwner.getDataObject(locCtx.CurrentProperty);}
+end;
+
+function TSDOBaseDataObject.getDataObject(const APropertyIndex: PtrUInt): ISDODataObject;
+begin
+  Result := getDataObject(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getDataObject(const AProperty: ISDOProperty): ISDODataObject;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or ( not Self.IsOwnerOf(AProperty) ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  if AProperty.isMany() then begin
+    Result := getList(AProperty).getDataObject();
+  end else begin
+    prp := AProperty as ISDOPropertyEx;
+    Result := getField(prp.getTypeEnum()).getDataObject(FBuffer,prp.getBufferOffset());
+  end;
+end;
+
+function TSDOBaseDataObject.getDate(const APropertyIndex: PtrUInt): TSDODate;
+begin
+  Result := getDate(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getDate(const APath: string): TSDODate;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getDate()
+  else
+    Result := locCtx.PropertyOwner.getDate(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getDate(const AProperty: ISDOProperty): TSDODate;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getDate(FBuffer,prp.getBufferOffset());
+end;
+
+{$IFDEF HAS_SDO_DOUBLE }
+function TSDOBaseDataObject.getDouble(const AProperty: ISDOProperty): TSDODouble;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getDouble(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getDouble(const APropertyIndex: PtrUInt): TSDODouble;
+begin
+  Result := getDouble(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getDouble(const APath: string): TSDODouble;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getDouble()
+  else
+    Result := locCtx.PropertyOwner.getDouble(locCtx.CurrentProperty);
+end;
+{$ENDIF HAS_SDO_DOUBLE }
+
+{$IFDEF HAS_SDO_FLOAT }
+function TSDOBaseDataObject.getFloat(const AProperty: ISDOProperty): TSDOFloat;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getFloat(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getFloat(const APropertyIndex: PtrUInt): TSDOFloat;
+begin
+  Result := getFloat(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getFloat(const APath: string): TSDOFloat;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getFloat()
+  else
+    Result := locCtx.PropertyOwner.getFloat(locCtx.CurrentProperty);
+end;
+{$ENDIF HAS_SDO_FLOAT }
+
+function TSDOBaseDataObject.getInstanceProperties() : ISDOPropertyList;
+begin
+  Result := FType.getProperties();
+end;
+
+function TSDOBaseDataObject.getInteger(const AProperty: ISDOProperty): TSDOInteger;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getInteger(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getInteger(const APropertyIndex: PtrUInt): TSDOInteger;
+begin
+  Result := getInteger(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getInteger(const APath: string): TSDOInteger;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getInteger()
+  else
+    Result := locCtx.PropertyOwner.getInteger(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getLong(const AProperty: ISDOProperty): TSDOLong;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getLong(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getLong(const APropertyIndex: PtrUInt): TSDOLong;
+begin
+   Result := getLong(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getLong(const APath: string): TSDOLong;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getLong()
+  else
+    Result := locCtx.PropertyOwner.getLong(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getProperty(const AIndex: PtrUInt): ISDOProperty;
+begin
+  Result := getInstanceProperties().getItem(AIndex);//FType.getProperty(AIndex);
+end;
+
+function TSDOBaseDataObject.getProperty(const AProp: string): ISDOProperty;
+begin
+  Result := getInstanceProperties().find(AProp);
+  if ( Result = nil ) then
+    raise ESDOPropertyNotFoundException.Create(AProp);
+end;
+
+function TSDOBaseDataObject.getPropertyIndex(const AProperty: ISDOProperty): PtrInt;
+begin
+  Result := FType.getPropertyIndex(AProperty.getName());
+end;
+
+function TSDOBaseDataObject.getShort(const APropertyIndex: PtrUInt): TSDOShort;
+begin
+  Result := getShort(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getShort(const APath: string): TSDOShort;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getShort()
+  else
+    Result := locCtx.PropertyOwner.getShort(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getShort(const AProperty: ISDOProperty): TSDOShort;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getShort(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getString(const AProperty: ISDOProperty): TSDOString;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getString(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getString(const APropertyIndex: PtrUInt): TSDOString;
+begin
+  Result := getString(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getString(const APath: string): TSDOString;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getString()
+  else
+    Result := locCtx.PropertyOwner.getString(locCtx.CurrentProperty);
+end;
+
+function TSDOBaseDataObject.getType() : ISDOType;
+begin
+  Result := FType as ISDOType;
+end;
+
+function TSDOBaseDataObject.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := FType.getTypeEnum();
+end;
+
+function TSDOBaseDataObject.isNull(const APath: string): Boolean;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  case locCtx.ContentKind of
+    xckNull    : Result := True;
+    xckObject  : Result := False;
+    xckList    :
+      begin
+        Result := locCtx.CurrentProperty.getType().isDataObjectType and ( locCtx.ListItem.getDataObject() = nil );
+      end;
+    xckValue : Result := locCtx.ObjectItem.isNull(locCtx.CurrentProperty);
+    else
+      Result := False;
+  end;
+end;
+
+function TSDOBaseDataObject.isNull(const AProperty: ISDOProperty): Boolean;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or ( not Self.IsOwnerOf(AProperty) ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  if AProperty.isMany() then begin
+    Result := ( getList(AProperty).size > 0 );
+  end else begin
+    prp := AProperty as ISDOPropertyEx;
+    Result := getField(prp.getTypeEnum()).isNull(FBuffer,prp.getBufferOffset());
+  end;
+end;
+
+function TSDOBaseDataObject.isNull(const APropertyIndex: PtrUInt): Boolean;
+begin
+  Result := isNull(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.isSet(const APropertyIndex: PtrUInt): Boolean;
+begin
+  Result := isSet(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.isSet(const APath: string): Boolean;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  case locCtx.ContentKind of
+    xckNull    : Result := not locCtx.PropertyOwner.getType().isDataObjectType();
+    xckObject  : Result := locCtx.PropertyOwner.isSet(locCtx.CurrentProperty);
+    xckList    : Result := ( locCtx.ListItem.size() > 0 );
+    xckValue   : Result := locCtx.ObjectItem.isSet(locCtx.CurrentProperty);
+    else
+      Result := False;    
+  end;
+end;
+
+function TSDOBaseDataObject.isSet(const AProperty: ISDOProperty): Boolean;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or ( not Self.IsOwnerOf(AProperty) ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  if AProperty.isMany() then begin
+    Result := ( getList(AProperty).size > 0 );
+  end else begin
+    prp := AProperty as ISDOPropertyEx;
+    Result := getField(prp.getTypeEnum()).isSet(FBuffer,prp.getBufferOffset());
+  end;
+end;
+
+procedure TSDOBaseDataObject.setBoolean(const APropertyIndex: PtrUInt;const AValue: TSDOBoolean);
+begin
+  setBoolean(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.PrepareDataBuffer();
+var
+  prpCount : PtrInt;
+  prpList : ISDOPropertyList;
+  csPrp : ISDOPropertyEx;
+
+  procedure InitializeListsBuffer();
+  var
+    k : PtrInt;
+    locPrp : ISDOPropertyEx;
+    locBuffer : PPSDODataObjectList;
+  begin
+    for k := 0 to Pred(prpCount) do begin
+      locPrp := prpList.getItem(k) as ISDOPropertyEx;
+      if locPrp.isMany() then begin
+        locBuffer := PPSDODataObjectList( PtrUInt(FBuffer) + locPrp.getBufferOffset() );
+        GetMem(locBuffer^,SizeOf(Pointer));
+        FillChar(locBuffer^^,SizeOf(ISDODataObjectList),#0);
+        locBuffer^^ := CreateList(locPrp);
+      end;
+    end;
+  end;
+
+  procedure InitChangeSummary();
+  var
+    locStore : ISDOChangedDataObjectList;
+    locCS : ISDOChangeSummary;
+    locCSX : ISDOChangeSummaryEx;
+  begin
+    locStore := TSDOChangedDataObjectList.Create() as ISDOChangedDataObjectList;
+    locCSX := TSDOChangeSummary.Create(locStore) as ISDOChangeSummaryEx;//ISDOChangeSummaryEx
+    FChangeSummary := Pointer(locCSX);
+    locCS := locCSX as ISDOChangeSummary;
+    getField(ChangeSummaryType).setChangeSummary(FBuffer,csPrp.getBufferOffset(),locCS);
+  end;
+
+var
+  i, loc_fieldAddress : PtrUInt;
+  prp : ISDOPropertyEx;
+  prpType : ISDOTypeEx;
+  prpStorageLength : PtrUInt;
+  multiPrpCount : PtrInt;
+begin
+  csPrp := nil;
+  prpList := getType().getProperties();
+  prpCount := prpList.getCount();
+  FBufferLength := 0;
+  loc_fieldAddress := 0;
+  multiPrpCount := 0;
+  if ( prpCount > 0 ) then begin
+    { TODO -oInoussa :
+    The property BufferOffset  computation should be moved to the type
+    definition and done _only once_ }
+    for i := 0 to Pred(prpCount) do begin
+      prp := prpList.getItem(i) as ISDOPropertyEx;
+      if prp.isMany() then begin
+        prpStorageLength := SizeOf(Pointer);
+        Inc(multiPrpCount);
+      end else begin
+        prpType := prp.getType() as ISDOTypeEx;
+        prpStorageLength := prpType.getFieldSize();
+        if ( csPrp = nil ) and prpType.isChangeSummaryType() then
+          csPrp := prp;
+      end;
+      Inc(FBufferLength,prpStorageLength);
+      loc_fieldAddress := prp.setBufferOffset(loc_fieldAddress);
+    end;
+    GetMem(FBuffer,FBufferLength);
+    FillChar(FBuffer^,FBufferLength,#0);
+    if ( multiPrpCount > 0 ) then
+      InitializeListsBuffer();
+    if ( csPrp <> nil ) then
+      InitChangeSummary();
+  end;
+end;
+
+procedure TSDOBaseDataObject.setBoolean(
+  const AProperty: ISDOProperty;
+  const AValue: TSDOBoolean
+);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setBoolean(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setBoolean(const APath: string; const AValue: TSDOBoolean);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setBoolean(AValue)
+  else
+    locCtx.PropertyOwner.setBoolean(locCtx.CurrentProperty,AValue);
+end;
+
+procedure TSDOBaseDataObject.setByte(
+  const APath: string;
+  const AValue: TSDOByte
+);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setByte(AValue)
+  else
+    locCtx.PropertyOwner.setByte(locCtx.CurrentProperty,AValue);
+end;
+
+procedure TSDOBaseDataObject.setByte(
+  const AProperty: ISDOProperty;
+  const AValue: TSDOByte
+);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setByte(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setByte(
+  const APropertyIndex: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  setByte(getProperty(APropertyIndex),AValue);
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOBaseDataObject.setBytes(const AProperty: ISDOProperty; AValue: TSDOBytes);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setBytes(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setBytes(const APropertyIndex: PtrUInt; AValue : TSDOBytes);
+begin
+  setBytes(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setBytes(const APath: string; AValue : TSDOBytes);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setBytes(AValue)
+  else
+    locCtx.PropertyOwner.setBytes(locCtx.CurrentProperty,AValue);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+procedure TSDOBaseDataObject.setCharacter(const AProperty: ISDOProperty; const AValue: TSDOChar);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setCharacter(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setCharacter(const APropertyIndex: PtrUInt; const AValue: TSDOChar);
+begin
+  setCharacter(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setCharacter(const APath: string; const AValue: TSDOChar);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setCharacter(AValue)
+  else
+    locCtx.PropertyOwner.setCharacter(locCtx.CurrentProperty,AValue);
+end;
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOBaseDataObject.setCurrency(const AProperty: ISDOProperty; const AValue: TSDOCurrency);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setCurrency(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setCurrency(const APropertyIndex: PtrUInt; const AValue: TSDOCurrency);
+begin
+  setCurrency(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setCurrency(const APath: string; const AValue: TSDOCurrency);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setCurrency(AValue)
+  else
+    locCtx.PropertyOwner.setCurrency(locCtx.CurrentProperty,AValue);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+procedure TSDOBaseDataObject.setDataObject(
+  const APath: string;
+        AValue: ISDODataObject
+);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setDataObject(AValue)
+  else
+    locCtx.PropertyOwner.setDataObject(locCtx.CurrentProperty,AValue);
+end;
+
+procedure TSDOBaseDataObject.setDataObject(
+  const APropertyIndex: PtrUInt;
+        AValue: ISDODataObject
+);
+begin
+  setDataObject(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setDataObject(
+  const AProperty: ISDOProperty;
+        AValue: ISDODataObject
+);
+var
+  prp : ISDOPropertyEx;
+  fld : ISDOField;
+  oldObj, newObj : ISDODataObjectEx;
+  off : PtrInt;
+  selfIntf, oldContainer : ISDODataObject;
+begin
+  if ( AProperty = nil ) or ( not Self.IsOwnerOf(AProperty) ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+
+  if AProperty.isMany() then begin
+    getList(AProperty).setDataObject(AValue);
+  end else begin
+    prp := AProperty as ISDOPropertyEx;
+    selfIntf := Self as ISDODataObject;
+    if ( AValue <> nil ) then begin
+      newObj := AValue as ISDODataObjectEx;
+      if not newObj.IsInstanceOf(prp.getType()) then
+        raise ESDOIllegalArgumentException.Create('AProperty');
+      if prp.isContainment() then begin
+        if newObj.IsAncestorOf(selfIntf) then
+          raise ESDOCycleContainmentException.Create('AValue');
+      end;
+    end;
+
+    fld := getField(prp.getTypeEnum());
+    off := prp.getBufferOffset();
+
+    oldObj := fld.getDataObject(FBuffer,off) as ISDODataObjectEx;
+    if Assigned(oldObj) then begin
+      if prp.isContainment() then
+        oldObj.setContainer(nil,nil);
+      if prp.isReference() then
+        oldObj.RemoveReference(selfIntf,AProperty);
+    end;
+
+    RecordChange(AProperty);
+    if ( AValue <> nil ) then begin
+      if prp.isContainment() then begin
+        oldContainer := newObj.getContainer();
+        if Assigned(oldContainer) then
+          oldContainer.setDataObject(newObj.getContainmentProperty(),nil);
+      end;
+      fld.setDataObject(FBuffer,off,AValue);
+      if prp.isContainment() then
+        newObj.setContainer(selfIntf,AProperty);
+      if prp.isReference() then
+        newObj.AddReference(selfIntf,AProperty);
+    end else begin;
+      fld.setDataObject(FBuffer,off,nil);
+    end;
+  end;
+end;
+
+procedure TSDOBaseDataObject.setDate(const AProperty: ISDOProperty; const AValue: TSDODate);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setDate(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setDate(const APropertyIndex: PtrUInt; const AValue: TSDODate);
+begin
+  setDate(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setDate(const APath: string; const AValue: TSDODate);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setDate(AValue)
+  else
+    locCtx.PropertyOwner.setDate(locCtx.CurrentProperty,AValue);
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOBaseDataObject.setDouble(const AProperty: ISDOProperty; const AValue: TSDODouble);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setDouble(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setDouble(const APropertyIndex: PtrUInt; const AValue: TSDODouble);
+begin
+  setDouble(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setDouble(const APath: string; const AValue: TSDODouble);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setDouble(AValue)
+  else
+    locCtx.PropertyOwner.setDouble(locCtx.CurrentProperty,AValue);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOBaseDataObject.setFloat(const AProperty: ISDOProperty; const AValue: TSDOFloat);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setFloat(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setFloat(const APropertyIndex: PtrUInt; const AValue: TSDOFloat);
+begin
+  setFloat(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setFloat(const APath: string; const AValue: TSDOFloat);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setFloat(AValue)
+  else
+    locCtx.PropertyOwner.setFloat(locCtx.CurrentProperty,AValue);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure TSDOBaseDataObject.setInteger(
+  const APath: string;
+  const AValue: TSDOInteger
+);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setInteger(AValue)
+  else
+    locCtx.PropertyOwner.setInteger(locCtx.CurrentProperty,AValue);
+end;
+
+procedure TSDOBaseDataObject.setInteger(
+  const APropertyIndex: PtrUInt;
+  const AValue: TSDOInteger
+);
+begin
+  setInteger(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setInteger(
+  const AProperty: ISDOProperty;
+  const AValue: TSDOInteger
+);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setInteger(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setLong(const APath: string; const AValue: TSDOLong);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setLong(AValue)
+  else
+    locCtx.PropertyOwner.setLong(locCtx.CurrentProperty,AValue);
+end;
+
+procedure TSDOBaseDataObject.setLong(const APropertyIndex: PtrUInt; const AValue: TSDOLong);
+begin
+  setLong(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setLong(const AProperty: ISDOProperty; const AValue: TSDOLong);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setLong(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setNull(const AProperty: ISDOProperty);
+var
+  prp : ISDOPropertyEx;
+  oldObj : ISDODataObjectEx;
+  selfIntf : ISDODataObject;
+  fld : ISDOField;
+  off : PtrInt;
+begin
+  if ( AProperty = nil ) or ( not Self.IsOwnerOf(AProperty) ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  RecordChange(AProperty);
+
+  if AProperty.isMany() then begin
+    ClearList(getList(AProperty));
+  end else begin
+    prp := AProperty as ISDOPropertyEx;
+    fld := getField(prp.getTypeEnum());
+    off := prp.getBufferOffset();
+    if prp.getType().isDataObjectType() then begin
+      oldObj := fld.getDataObject(FBuffer,off) as ISDODataObjectEx;
+      if Assigned(oldObj) then begin
+        if prp.isContainment() then
+          oldObj.setContainer(nil,nil);
+        if prp.isReference() then begin
+          selfIntf := Self as ISDODataObject;
+          oldObj.RemoveReference(selfIntf,AProperty);
+        end;
+      end;
+    end;
+    fld.setNull(FBuffer,off);
+  end;
+end;
+
+procedure TSDOBaseDataObject.setNull(const APropertyIndex: PtrUInt);
+begin
+  setNull(getProperty(APropertyIndex));
+end;
+
+procedure TSDOBaseDataObject.setNull(const APath: string);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  locCtx.PropertyOwner.setNull(locCtx.CurrentProperty);
+end;
+
+procedure TSDOBaseDataObject.setShort(const APath: string; const AValue: TSDOShort);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setShort(AValue)
+  else
+    locCtx.PropertyOwner.setShort(locCtx.CurrentProperty,AValue);
+end;
+
+procedure TSDOBaseDataObject.setShort(const APropertyIndex: PtrUInt; const AValue: TSDOShort);
+begin
+  setShort(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setShort(const AProperty: ISDOProperty; const AValue: TSDOShort);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setShort(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setString(const APath: string; const AValue: TSDOString);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setString(AValue)
+  else
+    locCtx.PropertyOwner.setString(locCtx.CurrentProperty,AValue);
+end;
+
+procedure TSDOBaseDataObject.setString(
+  const APropertyIndex: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  setString(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setString(
+  const AProperty: ISDOProperty;
+  const AValue: TSDOString
+);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setString(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.unset(const APath: string);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  locCtx.PropertyOwner.unset(locCtx.CurrentProperty);
+end;
+
+procedure TSDOBaseDataObject.unset(const APropertyIndex: PtrUInt);
+begin
+  unset(getProperty(APropertyIndex));
+end;
+
+procedure TSDOBaseDataObject.unset(const AProperty: ISDOProperty);
+var
+  prp : ISDOPropertyEx;
+  fld : ISDOField;
+  typeKind : TSDOTypeKind;
+  off : PtrInt;
+  oldObj : ISDODataObjectEx;
+  selfIntf : ISDODataObject;
+begin
+  if ( AProperty = nil ) or ( not Self.IsOwnerOf(AProperty) ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  if AProperty.getType().isChangeSummaryType() then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  RecordChange(AProperty);
+  if AProperty.isMany() then begin
+    ClearList(getList(AProperty));
+  end else begin
+    prp := AProperty as ISDOPropertyEx;
+    typeKind := prp.getTypeEnum();
+    fld := getField(typeKind);
+    off := prp.getBufferOffset();
+    case typeKind of
+      BooleanType   : fld.setBoolean(FBuffer,off,prp.getBooleanDefault());
+      ByteType      : fld.setByte(FBuffer,off,prp.getByteDefault());
+{$IFDEF HAS_SDO_BYTES}
+      BytesType     : fld.setBytes(FBuffer,off,prp.getBytesDefault());
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType : fld.setCharacter(FBuffer,off,prp.getCharacterDefault());
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      CurrencyType  : fld.setCurrency(FBuffer,off,prp.getCurrencyDefault());
+{$ENDIF HAS_SDO_CURRENCY}
+      DateTimeType  : fld.setDate(FBuffer,off,prp.getDateDefault());
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType    : fld.setDouble(FBuffer,off,prp.getDoubleDefault());
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType     : fld.setFloat(FBuffer,off,prp.getFloatDefault());
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType   : fld.setInteger(FBuffer,off,prp.getIntegerDefault());
+{$IFDEF HAS_SDO_LONG}
+      LongType      : fld.setLong(FBuffer,off,prp.getLongDefault());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : fld.setShort(FBuffer,off,prp.getShortDefault());
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : fld.setString(FBuffer,off,prp.getStringDefault());
+      ObjectType    :
+        begin
+          if prp.getType().isDataObjectType() then begin
+            oldObj := fld.getDataObject(FBuffer,off) as ISDODataObjectEx;
+            if Assigned(oldObj) then begin
+              if prp.isContainment() then
+                oldObj.setContainer(nil,nil);
+              if prp.isReference() then begin
+                selfIntf := Self as ISDODataObject;
+                oldObj.RemoveReference(selfIntf,AProperty);
+              end;
+            end;
+          end;
+          fld.setDataObject(FBuffer,off,nil);
+        end;
+      else
+        raise ESDOUnsupportedOperationException.Create('NOT-IMPLEMENTED-YET');
+    end;
+    fld.unset(FBuffer,off);
+  end;
+end;
+
+procedure TSDOBaseDataObject.FreeBuffer();
+var
+  prpCount , i: PtrInt;
+  prpList : ISDOPropertyList;
+  prp : ISDOProperty;
+  prpX : ISDOPropertyEx;
+  lstObjRef : PPSDODataObjectList;
+  obj, selfIntf : ISDODataObject;
+  objX : ISDODataObjectEx;
+  crs : ILinkedListCursor;
+  lstObj : ISDODataObjectList;
+begin
+  if ( FBuffer <> nil ) then begin
+    prpList := getInstanceProperties();
+    prpCount := prpList.getCount();
+    if ( prpCount > 0 ) then begin
+      selfIntf := Self as ISDODataObject;
+      for i := 0 to Pred(prpCount) do begin
+        prp := prpList.getItem(i);
+        prpX := prp as ISDOPropertyEx;
+        if prpX.isMany() then begin
+          lstObjRef := PPSDODataObjectList( PtrUInt(FBuffer) + prpX.getBufferOffset() );
+          if prpX.getType().isDataObjectType() and prpX.isReference() then begin
+            lstObj := lstObjRef^^;
+            crs := lstObj.getCursor();
+            crs.Reset();
+            while crs.MoveNext() do begin
+              obj := lstObj.getDataObject();
+              if ( obj <> nil ) then begin
+                objX := obj as ISDODataObjectEx;
+                objX.RemoveReference(selfIntf,prp);
+                objX := nil;
+                obj := nil;
+              end;
+            end;
+          end;
+          lstObj := nil;
+          lstObjRef^^ := nil;
+          FreeMem(lstObjRef^,SizeOf(Pointer));
+        end else begin
+          if prpX.getType().isDataObjectType() and prpX.isReference() then begin
+            obj := getField(prpX.getTypeEnum()).getDataObject(FBuffer,prpX.getBufferOffset());
+            if ( obj <> nil ) then begin
+              objX := obj as ISDODataObjectEx;
+              objX.RemoveReference(selfIntf,prp);
+              objX := nil;
+              obj := nil;
+            end;
+          end;
+          getField(prpX.getTypeEnum()).setNull(FBuffer,prpX.getBufferOffset());
+        end;
+      end;
+      selfIntf := nil;
+      FreeMem(FBuffer,FBufferLength);
+    end;
+    FBuffer := nil;
+    FBufferLength := 0;
+  end;
+end;
+
+function TSDOBaseDataObject.parsePropertyPath(const APath: string): TXPathExecContext;
+var
+  locSelf : ISDODataObject;
+begin
+  FXPathExpression.SetRoot(ParseXPath(APath));
+  locSelf := Self as ISDODataObject;
+  FXPathProcessor.Context.SetObject(locSelf,nil);
+  FXPathProcessor.Execute(FXPathExpression);
+  if ( FXPathProcessor.Context.CurrentProperty = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  Result := FXPathProcessor.Context;
+end;
+
+procedure TSDOBaseDataObject.setContainer(
+  const AContainer: ISDODataObject;
+  const AContainerProperty: ISDOProperty
+);
+var
+  locCS : ISDOChangeSummary;
+  locCSx : ISDOChangeSummaryEx;
+  locIsCreating : Boolean;
+begin
+  if Assigned(AContainerProperty) then begin
+    if not Assigned(AContainer) then
+      raise ESDOIllegalArgumentException.Create('AContainer');
+    if not sdo_utils.InheritsFrom(AContainer.getType(), AContainerProperty.getContainingType()) then //if ( AContainerProperty.getContainingType() <> AContainer.getType() ) then
+      raise ESDOIllegalArgumentException.Create('AContainerProperty');
+  end;
+  if Self.IsAncestorOf(AContainer) then
+    raise ESDOCycleContainmentException.Create('AContainer');
+  if ( AContainer = nil ) and ( FContainer <> nil ) then begin
+    //deleting the current object
+    {NotifyReferencersForDeletion();
+    NotifyContainedObjectsForDeletion(False); }
+    if not getContainmentProperty().isMany() then begin
+      locCS := getChangeSummary();
+      if ( locCS <> nil ) and locCS.isLogging() then begin
+        locCSx := locCS as ISDOChangeSummaryEx;
+        locCSx.getRecorder().recordDeletion(Self as ISDODataObject);
+      end;
+    end;
+    NotifyReferencersForDeletion();
+    NotifyContainedObjectsForDeletion(False);
+    FChangeSummary := nil;
+  end;
+  locIsCreating := ( FContainer = nil ) and ( AContainer <> nil );
+  FContainer := Pointer(AContainer);
+  FContainerProperty := Pointer(AContainerProperty);
+  if locIsCreating then begin
+    //creating the current object
+    if not AContainerProperty.isMany() then begin
+      locCS := AContainer.getChangeSummary();
+      if ( locCS <> nil ) and locCS.isLogging() then begin
+        locCSx := locCS as ISDOChangeSummaryEx;
+        locCSx.getRecorder().recordCreation(Self as ISDODataObject);
+      end;
+    end;
+  end;
+end;
+
+function TSDOBaseDataObject.IsAncestorOf(const AObject: ISDODataObject): Boolean;
+var
+  locSelf, locObj : ISDODataObject;
+begin
+  locObj := AObject as ISDODataObject;
+  locSelf := Self as ISDODataObject;
+  while Assigned(locObj) and ( locObj <> locSelf ) do begin
+    locObj := locObj.getContainer();
+  end;
+  Result := Assigned(AObject) and Assigned(locObj);
+end;
+
+function TSDOBaseDataObject.IsInstanceOf(const AType: ISDOType) : Boolean;
+var
+  locType : ISDOTypeEx;
+begin
+  locType := getType() as ISDOTypeEx;
+  Result := locType.inherits(AType);
+end;
+
+function TSDOBaseDataObject.IsOwnerOf(const AProp: ISDOProperty): Boolean;
+begin
+  Result := Assigned(AProp) and
+            ( ( ( AProp.getContainingType() as ISDOType ) = ( FType as ISDOType ) ) or
+              FType.IsOwnerOf(AProp)
+            );
+end;
+
+function TSDOBaseDataObject.CreateList(const AProperty : ISDOProperty) : ISDODataObjectList;
+begin
+  //Result := TSDODataObjectList.Create(AItemType) as ISDODataObjectList;
+  Result := TSDOOwnedDataObjectList.Create(Self as ISDODataObject, AProperty) as ISDODataObjectList;
+end;
+
+function TSDOBaseDataObject.getList(const APath: string): ISDODataObjectList;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind <> xckList ) then
+    raise ESDOIllegalArgumentException.Create('APath');
+  Result := locCtx.ListItem;
+end;
+
+function TSDOBaseDataObject.getList(const APropertyIndex: PtrUInt): ISDODataObjectList;
+begin
+  Result := getList(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getList(const AProperty: ISDOProperty): ISDODataObjectList;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( not AProperty.isMany() )
+  then begin
+    raise ESDOUnsupportedOperationException.Create('getList');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := PPSDODataObjectList( PtrUInt(FBuffer) + prp.getBufferOffset() )^^;
+end;
+
+function TSDOBaseDataObject.getChangeSummary() : ISDOChangeSummary;
+var
+  locCS : ISDOChangeSummary;
+  locCSX : ISDOChangeSummaryEx;
+begin
+  if ( FChangeSummary = nil ) then begin
+    if ( FContainer <> nil ) then begin
+      locCS := getContainer().getChangeSummary();
+      if ( locCS <> nil ) then begin
+        locCSX := locCS as ISDOChangeSummaryEx;
+        FChangeSummary := Pointer(locCSX);
+      end;
+    end;
+  end;
+  Result := ISDOChangeSummaryEx(FChangeSummary) as ISDOChangeSummary;
+end;
+
+procedure TSDOBaseDataObject.RecordChange(const AProperty : ISDOProperty);
+var
+  locCS : ISDOChangeSummaryEx;
+begin
+  if ( FChangeSummary = nil ) then
+    getChangeSummary();
+  locCS := ISDOChangeSummaryEx(FChangeSummary);
+  if Assigned(locCS) and locCS.isLogging() then begin
+    locCS.getRecorder().recordChange(Self as ISDODataObject,AProperty);
+  end;
+end;
+
+procedure TSDOBaseDataObject.NotifyDeletion(
+  const ADataObject: ISDODataObject;
+  const AProperty: ISDOProperty
+);
+var
+  cs : ISDOChangeSummary;
+begin
+  cs := getChangeSummary();
+  if ( ( cs = nil ) or ( not cs.isDeleted(Self as ISDODataObject) ) ) and
+     ( getDataObject(AProperty) = ADataObject )
+  then
+    setDataObject(AProperty,nil);
+end;
+
+procedure TSDOBaseDataObject.AddReference(
+  const AReferencer: ISDODataObject;
+  const AReferenceProperty: ISDOProperty
+);
+begin
+  if ( AReferencer = nil ) then
+    raise ESDOIllegalArgumentException.Create('AReferencer');
+  if ( AReferenceProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AReferenceProperty');
+  if ( FReferenceLinkList = nil ) then
+    FReferenceLinkList := TDataObjectObserverList.Create();
+  FReferenceLinkList.Add(AReferencer,AReferenceProperty);
+end;
+
+procedure TSDOBaseDataObject.NotifyReferencersForDeletion();
+var
+  i, c : PtrInt;
+  itm : TObserverInfo;
+  oX : IDataObjectObserver;
+  locSelf : ISDODataObject;
+begin
+  if ( FReferenceLinkList <> nil ) then begin
+    c := FReferenceLinkList.GetCount();
+    if ( c > 0 ) then begin
+      locSelf := Self as ISDODataObject;
+      itm := nil;
+      try
+        for i := Pred(c) downto 0 do begin
+          itm := FReferenceLinkList.Extract(i);
+          oX := itm.GetDataObject() as IDataObjectObserver;
+          oX.NotifyDeletion(locSelf,itm.GetRefProperty());
+          FreeAndNil(itm);
+        end;
+      finally
+        FreeAndNil(itm);
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOBaseDataObject.RemoveReference(
+  const AReferencer: ISDODataObject;
+  const AReferenceProperty: ISDOProperty
+);
+var
+  i : PtrInt;
+begin
+  if ( FReferenceLinkList <> nil ) then begin
+    i := FReferenceLinkList.IndexOf(AReferencer,AReferenceProperty);
+    if ( i > -1 ) then
+      FReferenceLinkList.Delete(i);
+  end;
+end;
+
+procedure TSDOBaseDataObject.NotifyContainedObjectsForDeletion(const ACallFromParent : Boolean);
+var
+  i, c : PtrInt;
+  ls : ISDOPropertyList;
+  prp : ISDOProperty;
+  po : ISDODataObject;
+  poX : ISDODataObjectEx;
+  ols : ISDODataObjectList;
+  ocrs : ILinkedListCursor;
+  oldPos : TLinkedListBookmark;
+begin
+  if ACallFromParent then
+    NotifyReferencersForDeletion();
+  ls := getInstanceProperties();
+  c := ls.getCount();
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      prp := ls.getItem(i);
+      if prp.isContainment() and ( prp.getType().isDataObjectType ) then begin
+        if prp.isMany() then begin
+          ols := getList(prp);
+          if ( ols.size() > 0 ) then begin
+            ocrs := ols.getCursor();
+            oldPos := ocrs.GetBookmark();
+            try
+              ocrs.Reset();
+              while ocrs.MoveNext() do begin
+                po := getDataObject(prp);
+                if ( po <> nil ) then begin
+                  poX := po as ISDODataObjectEx;
+                  poX.NotifyContainedObjectsForDeletion(True);
+                end;
+              end;
+            finally
+              ocrs.GotoBookmark(oldPos);
+            end;
+          end;
+        end else begin
+          po := getDataObject(prp);
+          if ( po <> nil ) then begin
+            poX := po as ISDODataObjectEx;
+            poX.NotifyContainedObjectsForDeletion(True);
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOBaseDataObject.InitializeDefaultValues();
+var
+  i, c : PtrInt;
+  pls : ISDOPropertyList;
+  p : ISDOPropertyEx;
+  f : ISDOField;
+begin
+  pls := FType.getProperties();
+  c := pls.getCount();
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      p := pls.getItem(i) as ISDOPropertyEx;
+      if p.isDefaulted() then begin
+        case p.getTypeEnum() of
+          BooleanType    :
+            begin
+              f := getField(BooleanType);
+              f.setBoolean(FBuffer,p.getBufferOffset(),p.getBooleanDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+          ByteType    :
+            begin
+              f := getField(ByteType);
+              f.setByte(FBuffer,p.getBufferOffset(),p.getByteDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$IFDEF HAS_SDO_BYTES}
+          BytesType :
+            begin
+              f := getField(BytesType);
+              f.setBytes(FBuffer,p.getBufferOffset(),p.getBytesDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+          CharacterType :
+            begin
+              f := getField(CharacterType);
+              f.setCharacter(FBuffer,p.getBufferOffset(),p.getCharacterDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$ENDIF HAS_SDO_CHAR}
+          DateTimeType :
+            begin
+              f := getField(DateTimeType);
+              f.setDate(FBuffer,p.getBufferOffset(),p.getDateDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$IFDEF HAS_SDO_CURRENCY}
+          CurrencyType :
+            begin
+              f := getField(CurrencyType);
+              f.setCurrency(FBuffer,p.getBufferOffset(),p.getCurrencyDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+          DoubleType :
+            begin
+              f := getField(DoubleType);
+              f.setDouble(FBuffer,p.getBufferOffset(),p.getDoubleDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+          FloatType :
+            begin
+              f := getField(FloatType);
+              f.setFloat(FBuffer,p.getBufferOffset(),p.getFloatDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$ENDIF HAS_SDO_FLOAT}
+          IntegerType    :
+            begin
+              f := getField(IntegerType);
+              f.setInteger(FBuffer,p.getBufferOffset(),p.getIntegerDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$IFDEF HAS_SDO_LONG}
+          LongType :
+            begin
+              f := getField(LongType);
+              f.setLong(FBuffer,p.getBufferOffset(),p.getLongDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+          ShortType :
+            begin
+              f := getField(ShortType);
+              f.setShort(FBuffer,p.getBufferOffset(),p.getShortDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+{$ENDIF HAS_SDO_SHORT}
+          StringType  :
+            begin
+              f := getField(StringType);
+              f.setString(FBuffer,p.getBufferOffset(),p.getStringDefault());
+              f.unset(FBuffer,p.getBufferOffset());
+            end;
+          else
+            raise ESDONotImplementedException.CreateFmt('NOT IMPLEMENTED for this type : "%s"',[SDOTypeDefaultTypeNames[p.getTypeEnum()]]);
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOBaseDataObject.addProperty(
+  const APropName : string;
+  const APropType : ISDOType;
+  const AFlags    : TPropertyFlags
+);
+begin
+  raise ESDOUnsupportedOperationException.Create('addProperty');
+end;
+
+function TSDOBaseDataObject._Release(): LongInt; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
+begin
+  if not FDestroying then
+    Result := inherited _Release()
+  else
+    Result := 0;
+end;
+
+function TSDOBaseDataObject.getVariant(const AProperty: ISDOProperty): TSDOVariant;
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  Result := getField(prp.getTypeEnum()).getVariant(FBuffer,prp.getBufferOffset());
+end;
+
+function TSDOBaseDataObject.getVariant(const APropertyIndex: PtrUInt): TSDOVariant;
+begin
+  Result := getVariant(getProperty(APropertyIndex));
+end;
+
+function TSDOBaseDataObject.getVariant(const APath: string): TSDOVariant;
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    Result := locCtx.ListItem.getVariant()
+  else
+    Result := locCtx.PropertyOwner.getVariant(locCtx.CurrentProperty);
+end;
+
+procedure TSDOBaseDataObject.setVariant(const AProperty: ISDOProperty; const AValue: TSDOVariant);
+var
+  prp : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) or
+     ( not Self.IsOwnerOf(AProperty) ) or
+     ( AProperty.isMany() )
+  then begin
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  prp := AProperty as ISDOPropertyEx;
+  RecordChange(AProperty);
+  getField(prp.getTypeEnum()).setVariant(FBuffer,prp.getBufferOffset(),AValue);
+end;
+
+procedure TSDOBaseDataObject.setVariant(const APropertyIndex: PtrUInt; const AValue: TSDOVariant);
+begin
+  setVariant(getProperty(APropertyIndex),AValue);
+end;
+
+procedure TSDOBaseDataObject.setVariant(const APath: string; const AValue: TSDOVariant);
+var
+  locCtx : TXPathExecContext;
+begin
+  locCtx := parsePropertyPath(APath);
+  if ( locCtx.PropertyOwner = nil ) then
+    raise ESDOInvalidPathException.Create(APath);
+  if ( locCtx.ContentKind = xckList ) then
+    locCtx.ListItem.setVariant(AValue)
+  else
+    locCtx.PropertyOwner.setVariant(locCtx.CurrentProperty,AValue);
+end;
+
+{ TObserverInfo }
+
+constructor TObserverInfo.Create(
+  const ADataObject: ISDODataObject;
+  const ARefProperty: ISDOProperty
+);
+begin
+  FDataObject := Pointer(ADataObject);
+  FRefProperty := Pointer(ARefProperty);
+end;
+
+function TObserverInfo.GetDataObject(): ISDODataObject;
+begin
+  Result := ISDODataObject(FDataObject);
+end;
+
+function TObserverInfo.GetRefProperty() : ISDOProperty;
+begin
+  Result := ISDOProperty(FRefProperty);
+end;
+
+{ TDataObjectObserverList }
+
+procedure TDataObjectObserverList.Add(
+  const ADataObject : ISDODataObject;
+  const ARefProperty : ISDOProperty
+);
+begin
+  if ( Find(ADataObject,ARefProperty) = nil ) then
+    FList.Add(TObserverInfo.Create(ADataObject,ARefProperty));
+end;
+
+constructor TDataObjectObserverList.Create();
+begin
+  FList := TObjectList.Create(True);
+end;
+
+procedure TDataObjectObserverList.Delete(const AIndex: PtrInt);
+begin
+  FList.Delete(AIndex);
+end;
+
+destructor TDataObjectObserverList.Destroy();
+begin
+  FreeAndNil(FList);
+  inherited;
+end;
+
+function TDataObjectObserverList.Extract(const AIndex: PtrInt): TObserverInfo;
+begin
+  Result := TObserverInfo(FList.Extract(GetItem(AIndex)));
+end;
+
+function TDataObjectObserverList.Find(
+  const ADataObject : ISDODataObject;
+  const ARefProperty : ISDOProperty
+) : TObserverInfo;
+var
+  i : PtrInt;
+begin
+  i := IndexOf(ADataObject,ARefProperty);
+  if ( i > -1  ) then
+    Result := GetItem(i)
+  else
+    Result := nil;
+end;
+
+function TDataObjectObserverList.GetCount() : PtrInt;
+begin
+  Result := FList.Count;
+end;
+
+function TDataObjectObserverList.GetItem(const AIndex: PtrInt): TObserverInfo;
+begin
+  if ( AIndex < 0 ) or ( AIndex >= GetCount() ) then
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+  Result := TObserverInfo(FList[AIndex]);
+end;
+
+function TDataObjectObserverList.IndexOf(
+  const ADataObject: ISDODataObject;
+  const ARefProperty: ISDOProperty
+) : PtrInt;
+var
+  i, c : PtrInt;
+  locInfo : TObserverInfo;
+  locObj : ISDODataObject;
+  locP : ISDOProperty;
+begin
+  Result := -1;
+  c := FList.Count;
+  for i := 0 to Pred(c) do begin
+    locInfo := TObserverInfo(FList[i]);
+    locObj := locInfo.GetDataObject();
+    locP := locInfo.GetRefProperty();
+    if ( locObj = ADataObject ) and ( locP = ARefProperty ) then begin
+      Result := i;
+      Break;
+    end;
+  end;
+end;
+
+{ TSDOOpenedDataObject }
+
+procedure TSDOOpenedDataObject.addProperty(
+  const APropName: string;
+  const APropType: ISDOType;
+  const AFlags: TPropertyFlags
+);
+var
+  p : ISDOPropertyEx;
+  pt : ISDOTypeEx;
+  fs, oldLength : PtrUInt;
+  locBuffer : PPSDODataObjectList;
+begin
+  if ( FInstanceProperties.find(APropName) <> nil ) then
+    raise ESDODuplicatedItemException.Create(APropName);
+  p := TSDOProperty.Create(
+         APropName,
+         APropType,
+         AFlags,
+         getType()
+       ) as ISDOPropertyEx;
+  oldLength := FBufferLength;
+  p.setBufferOffset(oldLength);
+  pt := p.getType() as ISDOTypeEx;
+  if p.isMany() then
+    fs := SizeOf(Pointer)
+  else
+    fs := pt.getFieldSize();
+  ReallocMem(FBuffer, ( oldLength + fs ));
+  FBufferLength := oldLength + fs;
+  FillChar(
+    Pointer(PtrUInt(FBuffer) + oldLength)^,
+    fs,
+    #0
+  );
+  if p.isMany() then begin
+    locBuffer := PPSDODataObjectList( PtrUInt(FBuffer) + p.getBufferOffset() );
+    GetMem(locBuffer^,SizeOf(Pointer));
+    FillChar(locBuffer^^,SizeOf(ISDODataObjectList),#0);
+    locBuffer^^ := CreateList(p);
+  end;
+  FInstanceProperties.add((p as ISDOProperty));
+end;
+
+constructor TSDOOpenedDataObject.Create(
+  const AType: ISDOTypeEx;
+  const AContainer: ISDODataObject;
+  const AContainerProperty: ISDOProperty
+);
+begin
+  if not AType.isOpenType() then
+    raise ESDOIllegalArgumentException.Create('AType');
+  inherited;
+  FInstanceProperties := TSDOPropertyList.Create(AType.getProperties());
+end;
+
+function TSDOOpenedDataObject.getInstanceProperties() : ISDOPropertyList;
+begin
+  Result := FInstanceProperties as ISDOPropertyList;
+end;
+
+function TSDOOpenedDataObject.IsOwnerOf(const AProp: ISDOProperty): Boolean;
+var
+  i, c : PtrInt;
+  locProp : ISDOProperty;
+begin
+  Result := False;
+  if ( AProp <> nil ) then begin
+    c := FInstanceProperties.getCount();
+    if ( c > 0 ) then begin
+      locProp := AProp as ISDOProperty;
+      for i := 0 to ( c - 1 ) do begin
+        if ( locProp = FInstanceProperties.getItem(i) ) then begin
+          Result := True;
+          Break;
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOOpenedDataObject.setBoolean(const APath: string; const AValue: TSDOBoolean);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOOpenedDataObject.setByte(const APath: string; const AValue: TSDOByte);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[ByteType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOOpenedDataObject.setBytes(const APath: string; AValue : TSDOBytes);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[BytesType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOOpenedDataObject.setCharacter(const APath: string; const AValue: TSDOChar);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[CharacterType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOOpenedDataObject.setCurrency(const APath: string; const AValue: Currency);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+procedure TSDOOpenedDataObject.setDataObject(const APath: string; AValue: ISDODataObject);
+var
+  pf : TPropertyFlags;
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        if ( AValue = nil ) then
+          raise;
+        pf := [];
+        if ( AValue.getContainer() = nil ) then
+          Include(pf,pfIsContainment);
+        addProperty(Trim(APath),AValue.getType(),pf);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOOpenedDataObject.setDate(const APath: string; const AValue: TSDODate);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[DateType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOOpenedDataObject.setDouble(const APath: string; const AValue: Double);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[DoubleType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOOpenedDataObject.setFloat(const APath: string; const AValue: TSDOFloat);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[FloatType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure TSDOOpenedDataObject.setInteger(const APath: string; const AValue: TSDOInteger);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOOpenedDataObject.setLong(const APath: string; const AValue: TSDOLong);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[LongType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOOpenedDataObject.setShort(const APath: string; const AValue: TSDOShort);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[ShortType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOOpenedDataObject.setString(const APath: string; const AValue: TSDOString);
+begin
+  try
+    inherited;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      if ( Pos('/', APath) = 0 ) and ( not IsStrEmpty(APath) ) then begin
+        addProperty(Trim(APath),FType.getOwner().getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),[pfIsAttribute]);
+        inherited;
+      end else begin
+        raise;
+      end;
+    end;
+  end;
+end;
+
+const
+  data_offset = 0;            { TSDODataObjectList }
+
+procedure TSDODataObjectList.append(const AValue: TSDOBoolean);
+begin
+  FField.setBoolean(GetData(InternalAppend()),0,AValue);
+end;
+
+procedure TSDODataObjectList.append(const AValue: TSDOInteger);
+begin
+  FField.setInteger(GetData(InternalAppend()),0,AValue);
+end;
+
+procedure TSDODataObjectList.append(const AValue: TSDOString);
+begin
+  FField.setString(GetData(InternalAppend()),0,AValue);
+end;
+
+procedure TSDODataObjectList.Clear();
+var
+  i : PtrInt;
+begin
+  if Assigned(FData) then begin
+    for i := 0 to Pred(FData.GetLength()) do begin
+      InternalDelete(FData.GetFirst());
+    end;
+  end;
+end;
+
+constructor TSDODataObjectList.Create(const AItemType: ISDOType);
+var
+  typEx : ISDOTypeEx;
+begin
+  if ( AItemType = nil ) or ( not Supports(AItemType,ISDOTypeEx,typEx) ) then
+    raise ESDOIllegalArgumentException.Create('AItemType');
+  FItemType := AItemType;
+  FField := getField(FItemType.getTypeEnum());
+  FData := TDoubleLinkedList.Create(typEx.getFieldSize());
+  FCursor := CreateIterator(FData);
+end;
+
+destructor TSDODataObjectList.Destroy();
+begin
+  Clear();
+  FCursor := nil;
+  FItemType := nil;
+  FreeAndNil(FData);
+  inherited;
+end;
+
+function TSDODataObjectList.getBoolean(const AIndex: PtrInt): TSDOBoolean;
+begin
+  MoveTo(AIndex);
+  Result := getBoolean();
+end;
+
+function TSDODataObjectList.getInteger(const AIndex: PtrInt): TSDOInteger;
+begin
+  MoveTo(AIndex);
+  Result := getInteger();
+end;
+
+function TSDODataObjectList.getString(const AIndex: PtrInt): TSDOString;
+begin
+  MoveTo(AIndex);
+  Result := getString();
+end;
+
+procedure TSDODataObjectList.delete(const AIndex: PtrInt);
+begin
+  MoveTo(AIndex);
+  delete();
+end;
+
+procedure TSDODataObjectList.setBoolean(const AIndex: PtrInt; const AValue: TSDOBoolean);
+begin
+  MoveTo(AIndex);
+  setBoolean(AValue);
+end;
+
+procedure TSDODataObjectList.setInteger(const AIndex: PtrInt; const AValue: TSDOInteger);
+begin
+  MoveTo(AIndex);
+  setInteger(AValue);
+end;
+
+procedure TSDODataObjectList.setString(const AIndex: PtrInt; const AValue: TSDOString);
+begin
+  MoveTo(AIndex);
+  setString(AValue);
+end;
+
+function TSDODataObjectList.size() : PtrInt;
+begin
+  Result := FData.GetLength();
+end;
+
+procedure TSDODataObjectList.InternalDelete(const AData: PLinkedNode);
+begin
+  FField.setNull(GetData(AData),0);
+  FData.Delete(AData);
+end;
+
+function TSDODataObjectList.getCursor() : ILinkedListCursor;
+begin
+  Result := FCursor;
+end;
+
+function TSDODataObjectList.getBoolean() : TSDOBoolean;
+begin
+  CheckCursorPosition();
+  Result := FField.getBoolean(GetData(FCursor.GetCurrent()),0);
+end;
+
+function TSDODataObjectList.getInteger() : TSDOInteger;
+begin
+  CheckCursorPosition();
+  Result := FField.getInteger(GetData(FCursor.GetCurrent()),0);
+end;
+
+function TSDODataObjectList.getString() : TSDOString;
+begin
+  CheckCursorPosition();
+  Result := FField.getString(GetData(FCursor.GetCurrent()),0);
+end;
+
+function TSDODataObjectList.InternalAppend() : PLinkedNode;
+begin
+  Result := FData.Append();
+  FCursor.MoveLast();
+end;
+
+procedure TSDODataObjectList.CheckCursorPosition();
+begin
+  if not FCursor.IsPosValid() then
+    raise ESDOIllegalArgumentException.Create('Cursor');
+end;
+
+procedure TSDODataObjectList.setBoolean(const AValue: TSDOBoolean);
+begin
+  CheckCursorPosition();
+  FField.setBoolean(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+procedure TSDODataObjectList.setInteger(const AValue: TSDOInteger);
+begin
+  CheckCursorPosition();
+  FField.setInteger(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+procedure TSDODataObjectList.setString(const AValue: TSDOString);
+begin
+  CheckCursorPosition();
+  FField.setString(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+procedure TSDODataObjectList.delete();
+var
+  p : PLinkedNode;
+begin
+  CheckCursorPosition();
+  p := FCursor.GetCurrent();
+  if FCursor.Bof() then
+    FCursor.MoveNext()
+  else if FCursor.Eof() then
+    FCursor.MovePrevious();
+  InternalDelete(p);
+end;
+
+{procedure TSDODataObjectList.MoveTo(const AIndex: PtrInt);
+var
+  c , j : PtrInt;
+begin
+  c := FData.GetLength();
+  if ( AIndex < 0 ) or ( AIndex >= c ) then
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+  j := AIndex;
+  if ( j <= ( Pred(c) div 2 ) ) then begin
+    if FCursor.MoveFirst() then begin
+      while ( j > 0 ) and FCursor.MoveNext() do begin
+        Dec(j);
+      end;
+    end;
+  end else begin
+    if FCursor.MoveLast() then begin
+      j := Pred(c) - j;
+      while ( j > 0 ) and FCursor.MovePrevious() do begin
+        Dec(j);
+      end;
+    end;
+  end;
+  if ( j > 0 ) then
+    raise ESDOIndexOutOfRangeException.Create(j);
+end; }
+procedure TSDODataObjectList.MoveTo(const AIndex: PtrInt);
+begin
+  if not FCursor.MoveTo(AIndex) then
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+end;
+
+procedure TSDODataObjectList.append(AValue: ISDODataObject);
+var
+  newObj : ISDODataObjectEx;
+begin
+  if ( AValue <> nil ) then begin
+    newObj := AValue as ISDODataObjectEx;
+    if not newObj.IsInstanceOf(FItemType) then
+      raise ESDOIllegalArgumentException.Create('AProperty');
+  end;
+  FField.setDataObject(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getDataObject(const AIndex: PtrInt): ISDODataObject;
+begin
+  MoveTo(AIndex);
+  Result := getDataObject();
+end;
+
+function TSDODataObjectList.getDataObject() : ISDODataObject;
+begin
+  CheckCursorPosition();
+  Result := FField.getDataObject(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setDataObject(AValue: ISDODataObject);
+begin
+  CheckCursorPosition();
+  FField.setDataObject(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+procedure TSDODataObjectList.setDataObject(const AIndex: PtrInt; AValue: ISDODataObject);
+begin
+  MoveTo(AIndex);
+  setDataObject(AValue);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOInteger);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setInteger(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setInteger(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOBoolean);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setBoolean(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setBoolean(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; AValue: ISDODataObject);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setDataObject(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setDataObject(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOString);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setString(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setString(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+
+function TSDODataObjectList.getItemType() : ISDOType;
+begin
+  Result := FItemType;
+end;
+
+procedure TSDODataObjectList.append(const AValue: TSDOByte);
+begin
+  FField.setByte(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getByte() : TSDOByte;
+begin
+  CheckCursorPosition();
+  Result := FField.getByte(GetData(FCursor.GetCurrent()),0);
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+function TSDODataObjectList.getBytes() : TSDOBytes;
+begin
+  CheckCursorPosition();
+  Result := FField.getBytes(GetData(FCursor.GetCurrent()),0);
+end;
+
+function TSDODataObjectList.getBytes(const AIndex: PtrInt): TSDOBytes;
+begin
+  MoveTo(AIndex);
+  Result := getBytes();
+end;
+
+procedure TSDODataObjectList.setBytes(AValue: TSDOBytes);
+begin
+  CheckCursorPosition();
+  FField.setBytes(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+procedure TSDODataObjectList.setBytes(const AIndex: PtrInt; AValue: TSDOBytes);
+begin
+  MoveTo(AIndex);
+  setBytes(AValue);
+end;
+
+procedure TSDODataObjectList.insertBytes(const AIndex: PtrInt; AValue: TSDOBytes);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setBytes(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      appendBytes(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setBytes(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+
+procedure TSDODataObjectList.appendBytes(AValue: TSDOBytes);
+begin
+  FField.setBytes(GetData(InternalAppend()),0,AValue);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+procedure TSDODataObjectList.setByte(const AValue: TSDOByte);
+begin
+  CheckCursorPosition();
+  FField.setByte(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getByte(const AIndex: PtrInt): TSDOByte;
+begin
+  MoveTo(AIndex);
+  Result := getByte();
+end;
+
+procedure TSDODataObjectList.setByte(const AIndex: PtrInt; const AValue: TSDOByte);
+begin
+  MoveTo(AIndex);
+  setByte(AValue);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOByte);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setByte(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setByte(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDODataObjectList.append(const AValue: TSDOChar);
+begin
+  FField.setCharacter(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getCharacter() : TSDOChar;
+begin
+  CheckCursorPosition();
+  Result := FField.getCharacter(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setCharacter(const AValue: TSDOChar);
+begin
+  CheckCursorPosition();
+  FField.setCharacter(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getCharacter(const AIndex: PtrInt): TSDOChar;
+begin
+  MoveTo(AIndex);
+  Result := getCharacter();
+end;
+
+procedure TSDODataObjectList.setCharacter(const AIndex: PtrInt; const AValue: TSDOChar);
+begin
+  MoveTo(AIndex);
+  setCharacter(AValue);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOChar);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setCharacter(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setCharacter(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDODataObjectList.appendCurrency(const AValue: TSDOCurrency);
+begin
+  FField.setCurrency(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getCurrency() : TSDOCurrency;
+begin
+  CheckCursorPosition();
+  Result := FField.getCurrency(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setCurrency(const AValue: TSDOCurrency);
+begin
+  CheckCursorPosition();
+  FField.setCurrency(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getCurrency(const AIndex: PtrInt): TSDOCurrency;
+begin
+  MoveTo(AIndex);
+  Result := getCurrency();
+end;
+
+procedure TSDODataObjectList.setCurrency(const AIndex: PtrInt; const AValue: TSDOCurrency);
+begin
+  MoveTo(AIndex);
+  setCurrency(AValue);
+end;
+
+procedure TSDODataObjectList.insertCurrency(const AIndex: PtrInt; const AValue: TSDOCurrency);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setCurrency(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      appendCurrency(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setCurrency(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDODataObjectList.append(const AValue: TSDODouble);
+begin
+  FField.setDouble(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getDouble() : TSDODouble;
+begin
+  CheckCursorPosition();
+  Result := FField.getDouble(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setDouble(const AValue: TSDODouble);
+begin
+  CheckCursorPosition();
+  FField.setDouble(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getDouble(const AIndex: PtrInt): TSDODouble;
+begin
+  MoveTo(AIndex);
+  Result := getDouble();
+end;
+
+procedure TSDODataObjectList.setDouble(const AIndex: PtrInt; const AValue: TSDODouble);
+begin
+  MoveTo(AIndex);
+  setDouble(AValue);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDODouble);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setDouble(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setDouble(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT }
+procedure TSDODataObjectList.append(const AValue: TSDOFloat);
+begin
+  FField.setFloat(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getFloat() : TSDOFloat;
+begin
+  CheckCursorPosition();
+  Result := FField.getFloat(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setFloat(const AValue: TSDOFloat);
+begin
+  CheckCursorPosition();
+  FField.setFloat(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getFloat(const AIndex: PtrInt): TSDOFloat;
+begin
+  MoveTo(AIndex);
+  Result := getFloat();
+end;
+
+procedure TSDODataObjectList.setFloat(const AIndex: PtrInt; const AValue: TSDOFloat);
+begin
+  MoveTo(AIndex);
+  setFloat(AValue);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOFloat);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setFloat(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setFloat(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+{$ENDIF HAS_SDO_FLOAT }
+
+procedure TSDODataObjectList.append(const AValue: TSDODate);
+begin
+  FField.setDate(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getDate() : TSDODate;
+begin
+  CheckCursorPosition();
+  Result := FField.getDate(GetData(FCursor.GetCurrent()),0);
+end;
+
+function TSDODataObjectList.getDate(const AIndex: PtrInt): TSDODate;
+begin
+  MoveTo(AIndex);
+  Result := getDate();
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDODate);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setDate(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setDate(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+
+procedure TSDODataObjectList.setDate(const AIndex: PtrInt; const AValue: TSDODate);
+begin
+  MoveTo(AIndex);
+  setDate(AValue);
+end;
+
+procedure TSDODataObjectList.setDate(const AValue: TSDODate);
+begin
+  CheckCursorPosition();
+  FField.setDate(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDODataObjectList.append(const AValue: TSDOLong);
+begin
+  FField.setLong(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getLong() : TSDOLong;
+begin
+  CheckCursorPosition();
+  Result := FField.getLong(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setLong(const AValue: TSDOLong);
+begin
+  CheckCursorPosition();
+  FField.setLong(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getLong(const AIndex: PtrInt): TSDOLong;
+begin
+  MoveTo(AIndex);
+  Result := getLong();
+end;
+
+procedure TSDODataObjectList.setLong(const AIndex: PtrInt; const AValue: TSDOLong);
+begin
+  MoveTo(AIndex);
+  setLong(AValue);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOLong);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setLong(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setLong(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDODataObjectList.append(const AValue: TSDOShort);
+begin
+  FField.setShort(GetData(InternalAppend()),0,AValue);
+end;
+
+function TSDODataObjectList.getShort() : TSDOShort;
+begin
+  CheckCursorPosition();
+  Result := FField.getShort(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setShort(const AValue: TSDOShort);
+begin
+  CheckCursorPosition();
+  FField.setShort(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getShort(const AIndex: PtrInt): TSDOShort;
+begin
+  MoveTo(AIndex);
+  Result := getShort();
+end;
+
+procedure TSDODataObjectList.setShort(const AIndex: PtrInt; const AValue: TSDOShort);
+begin
+  MoveTo(AIndex);
+  setShort(AValue);
+end;
+
+procedure TSDODataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOShort);
+begin
+  if ( AIndex = 0 ) then begin
+    FField.setShort(GetData(FData.InsertFirst()),0,AValue);
+  end else begin
+    if ( AIndex = FData.GetLength() ) then begin
+      append(AValue);
+    end else begin
+      MoveTo(AIndex);
+      FField.setShort(GetData(FData.InsertBefore(FCursor.GetCurrent())),0,AValue);
+    end;
+  end;
+  MoveTo(AIndex);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+function TSDODataObjectList.getVariant: TSDOVariant;
+begin
+  CheckCursorPosition();
+  Result := FField.getVariant(GetData(FCursor.GetCurrent()),0);
+end;
+
+procedure TSDODataObjectList.setVariant(const AValue: TSDOVariant);
+begin
+  CheckCursorPosition();
+  FField.setVariant(GetData(FCursor.GetCurrent()),0,AValue);
+end;
+
+function TSDODataObjectList.getVariant(const AIndex: PtrInt): TSDOVariant;
+begin
+  MoveTo(AIndex);
+  Result := getVariant();
+end;
+
+procedure TSDODataObjectList.setVariant(const AIndex: PtrInt; const AValue: TSDOVariant);
+begin
+  MoveTo(AIndex);
+  setVariant(AValue);
+end;
+
+{ TSDOOwnedDataObjectList }
+
+procedure TSDOOwnedDataObjectList.append(AValue: ISDODataObject);
+var
+  newObj : ISDODataObjectEx;
+  prp : ISDOProperty;
+  ownerIntf : ISDODataObject;
+begin
+  ownerIntf := getOwner();
+  prp := FOwnerProperty;
+  if ( AValue <> nil ) then begin
+    newObj := AValue as ISDODataObjectEx;
+    if not newObj.IsInstanceOf(getItemType()) then
+      raise ESDOIllegalArgumentException.Create('AProperty');
+    if prp.isContainment() then begin
+      if newObj.IsAncestorOf(ownerIntf) then
+        raise ESDOCycleContainmentException.Create('AValue');
+    end;
+  end;
+
+  inherited append(NIL_OBJECT);
+  InternalSetDataObject(AValue,False);
+  RecordChange(mvpaAppend);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOInteger);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+
+constructor TSDOOwnedDataObjectList.Create(
+  const AOwner : ISDODataObject;
+  const AProperty: ISDOProperty
+);
+begin
+  if ( AProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  if ( AOwner = nil ) then
+    raise ESDOIllegalArgumentException.Create('AOwner');
+  inherited Create(AProperty.getType());
+  FOwnerProperty := AProperty;
+  FOwner := Pointer(AOwner);
+end;
+
+procedure TSDOOwnedDataObjectList.delete(const AIndex: PtrInt);
+begin
+  MoveTo(AIndex);
+  delete();
+end;
+
+procedure TSDOOwnedDataObjectList.delete();
+begin
+  RecordChange(mvpaDelete);
+  if getItemType().isDataObjectType() then
+    InternalSetDataObject(nil, False);
+  inherited delete();
+end;
+
+function TSDOOwnedDataObjectList.getOwner() : ISDODataObject;
+begin
+  Result := ISDODataObject(FOwner);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOInteger);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; AValue: ISDODataObject);
+begin
+  inherited insert(AIndex, NIL_OBJECT);
+  InternalSetDataObject(AValue, False);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.InternalSetDataObject(
+  const AValue: ISDODataObject;
+  const ADoRecordChange: Boolean
+);
+var
+  prp : ISDOProperty;
+  fld : ISDOField;
+  oldObj, newObj : ISDODataObjectEx;
+  ownerIntf, oldContainer : ISDODataObject;
+  locBuffer : Pointer;
+  locCS : ISDOChangeSummaryEx;
+begin
+  CheckCursorPosition();
+  locBuffer := GetData(FCursor.GetCurrent());
+
+  ownerIntf := getOwner();
+  prp := FOwnerProperty;
+  if ( AValue <> nil ) then begin
+    newObj := AValue as ISDODataObjectEx;
+    if not newObj.IsInstanceOf(getItemType()) then
+      raise ESDOIllegalArgumentException.Create('AProperty');
+    if prp.isContainment() then begin
+      if newObj.IsAncestorOf(ownerIntf) then
+        raise ESDOCycleContainmentException.Create('AValue');
+    end;
+  end;
+
+  fld := FField;
+
+  oldObj := fld.getDataObject(locBuffer,data_offset) as ISDODataObjectEx;
+  if Assigned(oldObj) then begin
+    if prp.isContainment() then begin
+      if ADoRecordChange then begin
+        locCS := ownerIntf.getChangeSummary() as ISDOChangeSummaryEx;
+        if ( locCS <> nil ) and locCS.isLogging() then begin
+          locCS.getRecorder().recordDeletion(oldObj as ISDODataObject,getCursor().GetPosition());
+        end;
+      end;
+      oldObj.setContainer(nil,nil);
+    end;
+    if prp.isReference() then
+      oldObj.RemoveReference(ownerIntf,prp);
+  end;
+
+  if ADoRecordChange then
+    RecordChange(mvpaChange);
+  if ( AValue <> nil ) then begin
+    if prp.isContainment() then begin
+      oldContainer := newObj.getContainer();
+      if Assigned(oldContainer) then
+        oldContainer.setDataObject(newObj.getContainmentProperty(),nil);
+    end;
+    fld.setDataObject(locBuffer,data_offset,AValue);
+    if prp.isContainment() then begin
+      newObj.setContainer(ownerIntf,prp);
+      if ADoRecordChange then begin
+        if ( locCS = nil ) then
+          locCS := ownerIntf.getChangeSummary() as ISDOChangeSummaryEx;
+        if ( locCS <> nil ) and locCS.isLogging() then begin
+          locCS.getRecorder().recordCreation(newObj as ISDODataObject,getCursor().GetPosition());
+        end;
+      end;
+    end;
+    if prp.isReference() then
+      newObj.AddReference(ownerIntf,prp);
+  end else begin;
+    fld.setDataObject(locBuffer,data_offset,nil);
+  end;
+end;
+
+procedure TSDOOwnedDataObjectList.RecordChange(const AChange : TManyValuePropAction);
+var
+  locCS : ISDOChangeSummaryEx;
+begin
+  locCS := getOwner().getChangeSummary() as ISDOChangeSummaryEx;
+  if ( locCS <> nil ) and locCS.isLogging() then begin
+    locCS.getRecorder().recordChange(getOwner(),FOwnerProperty,getCursor().GetPosition(),AChange);
+  end;
+end;
+
+procedure TSDOOwnedDataObjectList.setDataObject(AValue: ISDODataObject);
+begin
+  InternalSetDataObject(AValue,True);
+end;
+
+procedure TSDOOwnedDataObjectList.setInteger(const AValue: TSDOInteger);
+begin
+  RecordChange(mvpaChange);
+  inherited setInteger(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setDataObject(const AIndex: PtrInt; AValue: ISDODataObject);
+begin
+  MoveTo(AIndex);
+  setDataObject(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setInteger(const AIndex: PtrInt; const AValue: TSDOInteger);
+begin
+  MoveTo(AIndex);
+  setInteger(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setBoolean(const AValue: TSDOBoolean);
+begin
+  RecordChange(mvpaChange);
+  inherited setBoolean(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setString(const AValue: TSDOString);
+begin
+  RecordChange(mvpaChange);
+  inherited setString(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setBoolean(const AIndex: PtrInt; const AValue: TSDOBoolean);
+begin
+  MoveTo(AIndex);
+  setBoolean(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setString(const AIndex: PtrInt; const AValue: TSDOString);
+begin
+  MoveTo(AIndex);
+  setString(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOBoolean);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOString);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOBoolean);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOString);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+
+procedure TSDOOwnedDataObjectList.setByte(const AValue: TSDOByte);
+begin
+  RecordChange(mvpaChange);
+  inherited setByte(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setByte(const AIndex: PtrInt; const AValue: TSDOByte);
+begin
+  MoveTo(AIndex);
+  setByte(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOByte);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOByte);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOOwnedDataObjectList.setBytes(AValue: TSDOBytes);
+begin
+  RecordChange(mvpaChange);
+  inherited setBytes(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setBytes(const AIndex: PtrInt; AValue: TSDOBytes);
+begin
+  MoveTo(AIndex);
+  setBytes(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insertBytes(const AIndex: PtrInt; AValue : TSDOBytes);
+begin
+  inherited insertBytes(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.appendBytes(AValue : TSDOBytes);
+begin
+  inherited appendBytes(AValue);
+  RecordChange(mvpaAppend);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+procedure TSDOOwnedDataObjectList.setDate(const AValue: TSDODate);
+begin
+  RecordChange(mvpaChange);
+  inherited setDate(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setDate(const AIndex: PtrInt; const AValue: TSDODate);
+begin
+  MoveTo(AIndex);
+  setDate(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDODate);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDODate);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOOwnedDataObjectList.setCharacter(const AValue: TSDOChar);
+begin
+  RecordChange(mvpaChange);
+  inherited setCharacter(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setCharacter(const AIndex: PtrInt; const AValue: TSDOChar);
+begin
+  MoveTo(AIndex);
+  setCharacter(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOChar);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOChar);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOOwnedDataObjectList.setCurrency(const AValue: TSDOCurrency);
+begin
+  RecordChange(mvpaChange);
+  inherited setCurrency(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setCurrency(const AIndex: PtrInt; const AValue: TSDOCurrency);
+begin
+  MoveTo(AIndex);
+  setCurrency(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insertCurrency(const AIndex: PtrInt; const AValue: TSDOCurrency);
+begin
+  inherited insertCurrency(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.appendCurrency(const AValue: TSDOCurrency);
+begin
+  inherited appendCurrency(AValue);
+  RecordChange(mvpaAppend);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOOwnedDataObjectList.setDouble(const AValue: TSDODouble);
+begin
+  RecordChange(mvpaChange);
+  inherited setDouble(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setDouble(const AIndex: PtrInt; const AValue: TSDODouble);
+begin
+  MoveTo(AIndex);
+  setDouble(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDODouble);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDODouble);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOOwnedDataObjectList.setFloat(const AValue: TSDOFloat);
+begin
+  RecordChange(mvpaChange);
+  inherited setFloat(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setFloat(const AIndex: PtrInt; const AValue: TSDOFloat);
+begin
+  MoveTo(AIndex);
+  setFloat(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOFloat);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOFloat);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOOwnedDataObjectList.setLong(const AValue: TSDOLong);
+begin
+  RecordChange(mvpaChange);
+  inherited setLong(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setLong(const AIndex: PtrInt; const AValue: TSDOLong);
+begin
+  MoveTo(AIndex);
+  setLong(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOLong);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOLong);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOOwnedDataObjectList.setShort(const AValue: TSDOShort);
+begin
+  RecordChange(mvpaChange);
+  inherited setShort(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setShort(const AIndex: PtrInt; const AValue: TSDOShort);
+begin
+  MoveTo(AIndex);
+  setShort(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.insert(const AIndex: PtrInt; const AValue: TSDOShort);
+begin
+  inherited insert(AIndex, AValue);
+  RecordChange(mvpaInsert);
+end;
+
+procedure TSDOOwnedDataObjectList.append(const AValue: TSDOShort);
+begin
+  inherited append(AValue);
+  RecordChange(mvpaAppend);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+
+procedure TSDOOwnedDataObjectList.setVariant(const AValue: TSDOVariant);
+begin
+  RecordChange(mvpaChange);
+  inherited setVariant(AValue);
+end;
+
+procedure TSDOOwnedDataObjectList.setVariant(const AIndex: PtrInt; const AValue: TSDOVariant);
+begin
+  MoveTo(AIndex);
+  setVariant(AValue);
+end;
+
+end.

+ 790 - 0
packages/fcl-sdo/src/base/sdo_date_utils.pas

@@ -0,0 +1,790 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements SDO date handling routines
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_date_utils;
+
+interface
+uses
+  SysUtils, sdo_types;
+  
+type
+
+  TDateTimeRec = packed record
+    Date : TDateTime;
+    HourOffset : Shortint;
+    MinuteOffset : Shortint;
+  end;
+
+  TTimeRec = packed record
+    Hour   : Byte;
+    Minute : Byte;
+    Second : Byte;
+    MilliSecond : Word;
+    HourOffset : Shortint;
+    MinuteOffset : Shortint;
+  end;
+
+  TDurationRec = packed record
+    Year : PtrUInt;
+    Month : PtrUInt;
+    Day : PtrUInt;
+    Hour : PtrUInt;
+    Minute : PtrUInt;
+    Second : PtrUInt;
+    FractionalSecond : PtrUInt;
+    Negative : Boolean;
+  end;
+
+const
+  ZERO_DATE : TDateTimeRec = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+  ZERO_TIME : TTimeRec = (
+                Hour         : 0;
+                Minute       : 0;
+                Second       : 0;
+                MilliSecond  : 0;
+                HourOffset   : 0;
+                MinuteOffset : 0;
+              );
+  ZERO_DURATION : TDurationRec = (
+                Year               : 0;
+                Month              : 0;
+                Day                : 0;
+                Hour               : 0;
+                Minute             : 0;
+                Second             : 0;
+                FractionalSecond   : 0;
+                Negative           : False;
+              );
+
+type
+  TXsdDateKind = ( xdkDateTime, xdkDate );
+  TValueCompareKind = (
+    vckEqual, vckLessThan, vckGreaterThan, vckNotEqual,
+    vckEqualOrLessThan, vckEqualOrGreaterThan
+  );
+
+  function xsd_TryStrToDate(
+    const AStr      : string;
+    out   ADate     : TDateTimeRec;
+    const ADateKind : TXsdDateKind
+  ) : Boolean;
+  function xsd_StrToDate(
+    const AStr : string;
+    const ADateKind : TXsdDateKind
+  ) : TDateTimeRec; {$IFDEF USE_INLINE}inline;{$ENDIF}
+
+  function xsd_DateTimeToStr(
+    const ADate : TDateTimeRec;
+    const ADateKind : TXsdDateKind
+  ) : string; overload;
+  function xsd_DateTimeToStr(
+    const ADate : TDateTime;
+    const ADateKind : TXsdDateKind
+  ) : string;overload;
+
+  function xsd_TimeToStr(const ATime : TTimeRec) : string;
+  function xsd_TryStrToTime(const AStr : string; out ADate : TTimeRec) : Boolean;
+  function xsd_StrToTime(const AStr : string) : TTimeRec;  {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function xsd_EncodeTime(
+    const AHour,
+          AMin,
+          ASec     : Byte;
+    const AMiliSec : Word
+  ) : TTimeRec; overload; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function xsd_EncodeTime(
+    const AHour,
+          AMin,
+          ASec     : Byte;
+    const AMiliSec : Word;
+    const AHourOffset   : Shortint;
+    const AMinuteOffset : Shortint
+  ) : TTimeRec; overload; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function DateTimeToTimeRec(const ADateTime : TDateTime) : TTimeRec; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function TimeRecToDateTime(const ATime : TTimeRec) : TDateTime; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function DateTimeToDateTimeRec(const ADateTime : TDateTime) : TDateTimeRec;
+
+  function xsd_TryStrToDuration(
+    const ABuffer : string;
+    out   AResult : TDurationRec
+  ) : Boolean;
+  function xsd_StrToDuration(const ABuffer : string) : TDurationRec;
+  function xsd_DurationToStr(const AValue : TDurationRec) : string;
+
+  function IncHour(const AValue: TDateTime; const ANumberOfHours: Int64): TDateTime;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function IncMinute(const AValue: TDateTime; const ANumberOfMinutes: Int64): TDateTime;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+  function NormalizeToUTC(const ADate : TDateTimeRec) : TDateTime; overload;
+  function NormalizeToUTC(const ATime : TTimeRec) : TTimeRec; overload;
+  function ValueEquals(const AA,AB: TDateTimeRec) : Boolean; overload;
+  function ValueEquals(const AA,AB: TTimeRec) : Boolean; overload;
+  function ValueEquals(const AA,AB: TDurationRec) : Boolean; overload;
+
+  function CompareValue(
+    const AA,AB        : TDateTimeRec;
+    const ACompareKind : TValueCompareKind
+  ) : Boolean;
+
+resourcestring
+  SERR_InvalidDate = '"%s" is not a valid date.';
+  SERR_InvalidTime = '"%s" is not a valid time.';
+  SERR_InvalidDuration = '"%s" is not a valid duration.';
+
+implementation
+
+uses DateUtils;
+
+function IncHour(const AValue: TDateTime; const ANumberOfHours: Int64): TDateTime;
+begin
+  Result := DateOf(AValue) + DateUtils.IncHour(TimeOf(AValue),ANumberOfHours);
+end;
+
+function IncMinute(const AValue: TDateTime; const ANumberOfMinutes: Int64): TDateTime;
+begin
+  Result := DateOf(AValue) + DateUtils.IncMinute(TimeOf(AValue),ANumberOfMinutes);
+end;
+
+function NormalizeToUTC(const ADate : TDateTimeRec) : TDateTime;
+begin
+  Result := ADate.Date;
+  if ( ADate.HourOffset <> 0 ) then
+    Result := IncHour(Result,-ADate.HourOffset);
+  if ( ADate.MinuteOffset <> 0 ) then
+    Result := IncMinute(Result,-ADate.MinuteOffset);
+end;
+
+function NormalizeToUTC(const ATime : TTimeRec) : TTimeRec;
+var
+  locDate : TDateTime;
+  e_h, e_mn, e_ss, e_ms : Word;
+begin
+  locDate := TimeRecToDateTime(ATime);
+  if ( ATime.HourOffset <> 0 ) then
+    locDate := IncHour(locDate,ATime.HourOffset);
+  if ( ATime.MinuteOffset <> 0 ) then
+    locDate := IncMinute(locDate,ATime.MinuteOffset);
+  DecodeTime(locDate,e_h,e_mn,e_ss,e_ms);
+  Result.Hour := e_h;
+  Result.Minute := e_mn;
+  Result.Second := e_ss;
+  Result.MilliSecond := e_ms;
+  Result.HourOffset := 0;
+  Result.MinuteOffset := 0;
+end;
+
+{$HINTS OFF}
+function ValueEquals(const AA,AB: TDateTimeRec) : Boolean;
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  e := NormalizeToUTC(AA);
+  a := NormalizeToUTC(AB);
+  DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+  DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+  Result := ( e_y = a_y ) and ( e_m = a_m ) and ( e_d = a_d ) and
+            (e_h = a_h ) and ( e_mn = a_mn ) and ( e_ss = a_ss ) and ( e_ms = a_ms );
+end;
+{$HINTS ON}
+
+function ValueEquals(const AA,AB: TTimeRec) : Boolean;
+var
+  a, b : TTimeRec;
+begin
+  a := NormalizeToUTC(AA);
+  b := NormalizeToUTC(AB);
+  Result := ( a.Hour = b.Hour ) and
+            ( a.Minute = b.Minute ) and
+            ( a.Second = b.Second ) and
+            ( a.MilliSecond = b.MilliSecond ) and
+            ( a.HourOffset = b.HourOffset ) and
+            ( a.MinuteOffset = b.MinuteOffset );
+end;
+
+function CompareValue(
+  const AA,AB        : TDateTimeRec;
+  const ACompareKind : TValueCompareKind
+) : Boolean;
+begin
+  case ACompareKind of
+    vckEqual              : Result := ValueEquals(AA,AB);
+    vckLessThan           : Result := ( NormalizeToUTC(AA) < NormalizeToUTC(AB) );
+    vckGreaterThan        : Result := ( NormalizeToUTC(AA) > NormalizeToUTC(AB) );
+    vckNotEqual           : Result := not ValueEquals(AA,AB);
+    vckEqualOrLessThan    : Result := ValueEquals(AA,AB) or ( NormalizeToUTC(AA) < NormalizeToUTC(AB) );
+    vckEqualOrGreaterThan : Result := ValueEquals(AA,AB) or ( NormalizeToUTC(AA) > NormalizeToUTC(AB) );
+    else begin
+      Assert(False);  // To suppress the warning
+      Result := False;
+    end;
+  end;
+end;
+
+function xsd_TryStrToDate(
+  const AStr      : string;
+  out   ADate     : TDateTimeRec;
+  const ADateKind : TXsdDateKind
+) : Boolean;
+const
+  DATE_SEP_CHAR = '-'; TIME_MARKER_CHAR = 'T'; TIME_SEP_CHAR = ':';
+var
+  buffer : string;
+  bufferPos, bufferLen : Integer;
+
+  function ReadInt(out AValue : Integer; const ASeparatorAtEnd : Char) : Boolean;
+  var
+    locStartPos : Integer;
+  begin
+    while ( bufferPos <= bufferLen ) and ( buffer[bufferPos] < #33 ) do begin
+      Inc(bufferPos);
+    end;
+    locStartPos := bufferPos;
+    if ( bufferPos <= bufferLen ) and ( buffer[bufferPos] in ['-','+'] ) then
+      Inc(bufferPos);
+    while ( bufferPos <= bufferLen ) and ( buffer[bufferPos] in ['0'..'9'] ) do begin
+      Inc(bufferPos);
+    end;
+    Result := ( bufferPos > locStartPos ) and
+              ( ( ASeparatorAtEnd = #0 ) or
+                ( ( bufferPos <= bufferLen ) and
+                  ( buffer[bufferPos] = ASeparatorAtEnd )
+                )
+              );
+    if Result then
+      Result := TryStrToInt(Copy(buffer,locStartPos,(bufferPos-locStartPos)),AValue);
+  end;
+
+  function ReadMiliSeconds(out AValue : Integer) : Boolean;
+  var
+    locDigitCount, locRes, itemp, locErcode : Integer;
+  begin
+    while ( bufferPos <= bufferLen ) and ( buffer[bufferPos] < #33 ) do begin
+      Inc(bufferPos);
+    end;
+    locRes := 0;
+    locDigitCount := 0;
+    while ( locDigitCount < 3 ) and ( bufferPos <= bufferLen ) and ( buffer[bufferPos] in ['0'..'9'] ) do begin
+      Val(buffer[bufferPos],itemp,locErcode);
+      locRes := ( locRes * 10 ) + itemp;
+      Inc(bufferPos);
+      Inc(locDigitCount);
+    end;
+    if ( locDigitCount >= 3 ) then begin
+      //Skip the remaining fractional part
+      while ( bufferPos <= bufferLen ) and ( buffer[bufferPos] in ['0'..'9'] ) do begin
+        Inc(bufferPos);
+      end;
+    end;
+    Result := ( locDigitCount > 0 );
+    if Result then begin
+      if ( locDigitCount < 3 ) and ( locRes > 0 ) then begin
+        while ( locDigitCount < 3 ) do begin
+          locRes := locRes * 10;
+          Inc(locDigitCount);
+        end;
+      end;
+      AValue := locRes;
+    end;
+  end;
+
+var
+  d, m, y : Integer;
+  hh, mn, ss, ssss : Integer;
+  tz_hh, tz_mn : Integer;
+  tz_negative : Boolean;
+  ok : Boolean;
+begin
+  //'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
+
+  buffer := Trim(AStr);
+  bufferPos := 1;
+  bufferLen := Length(buffer);
+  if ( bufferLen > 0 ) then begin
+    Result := False;
+    FillChar(ADate,SizeOf(ADate),#0);
+
+    if ReadInt(y,DATE_SEP_CHAR) then begin
+      Inc(bufferPos);
+      if ReadInt(m,DATE_SEP_CHAR) then begin
+        Inc(bufferPos);
+        if ReadInt(d,#0) then begin
+          tz_hh := 0;
+          tz_mn := 0;
+          hh := 0;
+          mn := 0;
+          ss := 0;
+          ssss := 0;
+          if ( bufferPos >= bufferLen ) then begin
+            ok := True;
+          end else begin
+            ok := ( buffer[bufferPos] in [TIME_MARKER_CHAR,'-','+'] );
+            if ok then begin
+              if ( buffer[bufferPos] = TIME_MARKER_CHAR ) then begin
+                Inc(bufferPos);
+                ok := ( ADateKind = xdkDateTime ) and ReadInt(hh,TIME_SEP_CHAR);
+                if ok then begin
+                  Inc(bufferPos);
+                  ok := ReadInt(mn,TIME_SEP_CHAR);
+                  if ok then begin
+                    Inc(bufferPos);
+                    ok := ReadInt(ss,#0);
+                    if ok and ( bufferPos < bufferLen ) and ( buffer[bufferPos] = '.' ) then begin
+                      Inc(bufferPos);
+                      ok := ReadMiliSeconds(ssss);
+                    end else begin
+                      ssss := 0;
+                    end;
+                  end;
+                end;
+              end;
+              if ok and ( bufferPos < bufferLen ) then begin
+                ok := ( buffer[bufferPos] in ['-','+'] );
+                if ok then begin
+                  tz_negative := ( buffer[bufferPos] = '-' );
+                  Inc(bufferPos);
+                  ok := ReadInt(tz_hh,TIME_SEP_CHAR);
+                  if ok then begin
+                    Inc(bufferPos);
+                    ok := ReadInt(tz_mn,#0);
+                    if ok and tz_negative then begin
+                      tz_hh := -tz_hh;
+                      tz_mn := -tz_mn;
+                    end;
+                  end;
+                end;
+              end;
+            end;
+          end;
+          if ok then begin
+            if ( ( y + m + d + hh + mn + ss + ssss ) = 0 ) then
+              ADate.Date := 0
+            else
+              ADate.Date := EncodeDate(y,m,d) + EncodeTime(hh,mn,ss,ssss);
+            ADate.HourOffset := tz_hh;
+            ADate.MinuteOffset := tz_mn;
+            Result := True;
+          end;
+        end;
+      end;
+    end;
+  end else begin
+    FillChar(ADate,SizeOf(ADate),#0);
+    Result := True;
+  end;
+end;
+
+function xsd_StrToDate(
+  const AStr : string;
+  const ADateKind : TXsdDateKind
+) : TDateTimeRec;
+begin
+  if not xsd_TryStrToDate(AStr,Result,ADateKind) then
+    raise EConvertError.CreateFmt(SERR_InvalidDate,[AStr]);
+end;
+
+{$HINTS OFF}
+function xsd_DateTimeToStr(
+  const ADate : TDateTimeRec;
+  const ADateKind : TXsdDateKind
+) : string;
+var
+  locDate : TDateTime;
+  d, m, y : Word;
+  hh, mn, ss, ssss : Word;
+  locRes : string;
+begin
+  //'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
+  locDate := ADate.Date;
+  if ( ADate.HourOffset <> 0 ) then
+    locDate := IncHour(locDate,-ADate.HourOffset);
+  if ( ADate.MinuteOffset <> 0 ) then
+    locDate := IncMinute(locDate,-ADate.MinuteOffset);
+  if ( ADateKind = xdkDate ) then begin
+    DecodeDate(locDate,y,m,d);
+    locRes := Format('%.4d-%.2d-%.2d',[y,m,d]);
+  end else begin
+    DecodeDateTime(locDate,y,m,d,hh,mn,ss,ssss);
+    if ( ssss = 0 ) then
+      locRes := Format('%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ',[y,m,d, hh,mn,ss])
+    else
+      locRes := Format('%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ',[y,m,d, hh,mn,ss,ssss]);
+  end;
+  Result := locRes;
+end;
+{$HINTS ON}
+
+function xsd_DateTimeToStr(
+    const ADate : TDateTime;
+    const ADateKind : TXsdDateKind
+) : string;
+var
+  tmpDate : TDateTimeRec;
+begin
+  FillChar(tmpDate,SizeOf(TDateTimeRec),#0);
+  tmpDate.Date := ADate;
+  Result := xsd_DateTimeToStr(tmpDate,ADateKind);
+end;
+
+function xsd_TimeToStr(const ATime : TTimeRec) : string;
+var
+  buffer : string;
+begin
+  //hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
+  if ( {( ATime.Hour < 0 ) or} ( ATime.Hour > 23 ) ) or
+     ( {( ATime.Minute < 0 ) or} ( ATime.Minute > 59 ) ) or
+     ( {( ATime.Second < 0 ) or} ( ATime.Second > 59 ) ) {or
+     ( ATime.MilliSecond < 0 )}
+  then begin
+    buffer := Format('{ Hour : %d; Minute : %d; Second : %d; SecondFractional : %d}',[ATime.Hour,ATime.Minute,ATime.Second,ATime.MilliSecond]);
+    raise EConvertError.CreateFmt(SERR_InvalidTime,[buffer]);
+  end;
+  if ( ATime.MilliSecond = 0 ) then
+    buffer := Format('%.2d:%.2d:%.2d',[ATime.Hour,ATime.Minute,ATime.Second])
+  else
+    buffer := Format('%.2d:%.2d:%.2d.%.3d',[ATime.Hour,ATime.Minute,ATime.Second,ATime.MilliSecond]);
+  if ( ATime.HourOffset <> 0 ) then begin
+    if ( ATime.HourOffset > 0 ) then
+      buffer := Format('%s+%.2d',[buffer,ATime.HourOffset])
+    else
+      buffer := Format('%s-%.2d',[buffer,-ATime.HourOffset]);
+    if ( ATime.MinuteOffset > 0 ) then
+      buffer := Format('%s:%.2d',[buffer,ATime.MinuteOffset])
+    else if ( ATime.MinuteOffset < 0 ) then
+      buffer := Format('%s:%.2d',[buffer,-ATime.MinuteOffset]);
+  end else if ( ATime.MinuteOffset <> 0 ) then begin
+    if ( ATime.MinuteOffset > 0 ) then
+      buffer := Format('%s+00:%.2d',[buffer,ATime.MinuteOffset])
+    else if ( ATime.MinuteOffset < 0 ) then
+      buffer := Format('%s-00:%.2d',[buffer,-ATime.MinuteOffset]);
+  end;
+  if ( ATime.HourOffset = 0 ) and ( ATime.MinuteOffset = 0 ) then
+    buffer := buffer + 'Z';
+  Result := buffer;
+end;
+
+function xsd_TryStrToTime(const AStr : string; out ADate : TTimeRec) : Boolean;
+const
+  TIME_SEP_CHAR = ':';
+var
+  buffer : string;
+  bufferPos, bufferLen : Integer;
+
+  function ReadInt(out AValue : Integer; const ASeparatorAtEnd : Char) : Boolean;
+  var
+    locStartPos : Integer;
+  begin
+    while ( bufferPos <= bufferLen ) and ( buffer[bufferPos] < #33 ) do begin
+      Inc(bufferPos);
+    end;
+    locStartPos := bufferPos;
+    if ( bufferPos <= bufferLen ) and ( buffer[bufferPos] in ['-','+'] ) then
+      Inc(bufferPos);
+    while ( bufferPos <= bufferLen ) and ( buffer[bufferPos] in ['0'..'9'] ) do begin
+      Inc(bufferPos);
+    end;
+    Result := ( bufferPos > locStartPos ) and
+              ( ( ASeparatorAtEnd = #0 ) or
+                ( ( bufferPos <= bufferLen ) and
+                  ( buffer[bufferPos] = ASeparatorAtEnd )
+                )
+              );
+    if Result then
+      Result := TryStrToInt(Copy(buffer,locStartPos,(bufferPos-locStartPos)),AValue);
+  end;
+
+var
+  hh, mn, ss, ssss : Integer;
+  tz_hh, tz_mn : Integer;
+  tz_negative : Boolean;
+  ok : Boolean;
+begin
+  //hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
+  buffer := Trim(AStr);
+  bufferPos := 1;
+  bufferLen := Length(buffer);
+  ok := False;
+  if ( bufferLen > 0 ) then begin
+    if ReadInt(hh,#0) then begin
+      Inc(bufferPos);
+      mn := 0;
+      ss := 0;
+      ssss := 0;
+      tz_hh := 0;
+      tz_mn := 0;
+      ok := True;
+      if ( bufferPos < bufferLen ) then begin
+        ok := ( buffer[bufferPos -1] = TIME_SEP_CHAR ) and ReadInt(mn,#0);
+        if ok then begin
+          Inc(bufferPos);
+          if ( bufferPos < bufferLen ) then begin
+            ok := ReadInt(ss,#0);
+            if ok then begin
+              if ( bufferPos < bufferLen ) then begin
+                if ( buffer[bufferPos] = '.' ) then begin
+                  Inc(bufferPos);
+                  ok := ReadInt(ssss,#0);
+                end else begin
+                  ssss := 0;
+                end;
+                if ok and ( bufferPos < bufferLen ) then begin
+                  ok := ( buffer[bufferPos] in ['+','-'] );
+                  if ok then begin
+                    tz_negative := ( buffer[bufferPos] = '-' );
+                    Inc(bufferPos);
+                    ok := ReadInt(tz_hh,#0);
+                    if ok then begin
+                      Inc(bufferPos);
+                      if ( bufferPos < bufferLen ) then
+                        ok := ReadInt(tz_mn,#0)
+                      else
+                        tz_mn := 0;
+                      if ok and tz_negative then begin
+                        tz_hh := -tz_hh;
+                        tz_mn := -tz_mn;
+                      end;
+                    end;
+                  end;
+                end;
+              end;
+            end;
+          end;
+        end;
+      end;
+      if ok then begin
+        ok := ( ( hh = 24 ) and ( mn = 0 ) and ( ss = 0 ) and ( ssss = 0 )
+              ) or
+              ( ( hh >= 0 ) and ( hh < 24 ) and
+                ( mn >= 0 ) and ( mn < 60 ) and
+                ( ss >= 0 ) and ( ss < 60 ) and
+                ( ssss >= 0 ) and ( ssss < 1000 )
+              );
+        ok := ok and
+              ( tz_hh > -60 ) and ( tz_hh < 60 ) and
+              ( tz_mn > -60 ) and ( tz_mn < 60 );
+      end;
+      if ok then begin
+        ADate.Hour := hh;
+        ADate.Minute := mn;
+        ADate.Second := ss;
+        ADate.MilliSecond := ssss;
+        ADate.HourOffset := tz_hh;
+        ADate.MinuteOffset := tz_mn;
+      end;
+    end;
+  end;
+  Result := ok;
+end;
+
+function xsd_StrToTime(const AStr : string) : TTimeRec;
+begin
+  if not xsd_TryStrToTime(AStr,Result) then
+    raise EConvertError.CreateFmt(SERR_InvalidTime,[AStr]);
+end;
+
+function xsd_EncodeTime(
+  const AHour,
+        AMin,
+        ASec     : Byte;
+  const AMiliSec : Word
+) : TTimeRec;
+begin
+  Result := xsd_EncodeTime(AHour,AMin,ASec,AMiliSec,0,0);
+end;
+
+function xsd_EncodeTime(
+  const AHour,
+        AMin,
+        ASec     : Byte;
+  const AMiliSec : Word;
+  const AHourOffset   : Shortint;
+  const AMinuteOffset : Shortint
+) : TTimeRec;
+begin
+  Result.Hour := AHour;
+  Result.Minute := AMin;
+  Result.Second := ASec;
+  Result.MilliSecond := AMiliSec;
+  Result.HourOffset := AHourOffset;
+  Result.MinuteOffset := AMinuteOffset;
+end;
+
+function DateTimeToTimeRec(const ADateTime : TDateTime) : TTimeRec;
+var
+  hh, mn, ss, ssss : Word;
+begin
+  DecodeTime(ADateTime,hh,mn,ss,ssss);
+  Result.Hour := hh;
+  Result.Minute := mn;
+  Result.Second := ss;
+  Result.MilliSecond := ssss;
+end;
+
+function TimeRecToDateTime(const ATime : TTimeRec) : TDateTime;
+begin
+  Result := EncodeTime(ATime.Hour,ATime.Minute,ATime.Second,ATime.MilliSecond);
+end;
+
+function DateTimeToDateTimeRec(const ADateTime : TDateTime) : TDateTimeRec;
+begin
+  Result.Date := ADateTime;
+  Result.HourOffset := 0;
+  Result.MinuteOffset := 0;
+end;
+
+type TDatePart = ( dpNone, dpYear, dpMonth, dpDay, dpHour, dpMinute, dpSecond, dpFractionalSecond );
+function xsd_TryStrToDuration(
+  const ABuffer : string;
+  out   AResult : TDurationRec
+) : Boolean;
+var
+  pc : PChar;
+  locIntBuffer : array[dpYear..dpFractionalSecond] of PtrUInt;
+  i, bufferLength, lastPos : PtrInt;
+  localBuffer : string;
+  part, oldPart : TDatePart;
+  inTimePart : Boolean;
+  isNeg : Boolean;
+begin
+  Result := False;
+  bufferLength := Length(ABuffer);
+  if ( bufferLength < 3 ) then
+    Exit;
+  pc := PChar(ABuffer);
+  i := 1;
+  isNeg := False;
+  if ( pc^ = '-' ) then begin
+    Inc(pc); Inc(i);
+    isNeg := True;
+  end;
+  if ( pc^ <> 'P' ) then
+    Exit;
+  Inc(pc); Inc(i); //eat 'P'
+  FillChar(locIntBuffer,SizeOf(locIntBuffer),#0);
+  part := dpNone;
+  inTimePart := False;
+
+  if ( pc^ = 'T' ) then begin
+    inTimePart := True;
+    Inc(pc); Inc(i);
+  end;
+  repeat
+    lastPos := i;
+    while ( i < bufferLength ) and ( pc^ in ['0'..'9'] ) do begin
+      Inc(pc); Inc(i);
+    end;
+    if ( ( lastPos = i ) and ( pc^ <> 'T' ) ) then
+      Exit;
+    localBuffer := Copy(ABuffer,lastPos,( i - lastPos ));
+    oldPart := part;
+    case pc^ of
+      'Y' : part := dpYear;
+      'M' :
+        begin
+          if inTimePart then
+            part := dpMinute
+          else
+            part := dpMonth;
+        end;
+      'D' : part := dpDay;
+      'H' : part := dpHour;
+      'S', '.' :
+        begin
+          if ( part < dpSecond ) then
+            part := dpSecond
+          else
+            part := dpFractionalSecond;
+        end;
+      'T' :
+        begin
+          inTimePart := True;
+          oldPart := dpNone;
+          part := dpNone;
+        end;
+      else
+        Exit;
+    end;
+    if inTimePart and ( part in [dpYear..dpDay] ) then
+      Exit;
+    if ( part > dpNone ) then begin
+      if ( part < oldPart ) then
+        Exit;
+      locIntBuffer[part] := StrToInt(localBuffer);
+    end;
+    Inc(pc); Inc(i);
+  until ( i >= bufferLength );
+  if ( i = bufferLength ) then
+    Exit;
+  AResult.Negative := isNeg;
+  AResult.Year := locIntBuffer[dpYear];
+  AResult.Month := locIntBuffer[dpMonth];
+  AResult.Day := locIntBuffer[dpDay];
+  AResult.Hour := locIntBuffer[dpHour];
+  AResult.Minute := locIntBuffer[dpMinute];
+  AResult.Second := locIntBuffer[dpSecond];
+  AResult.FractionalSecond := locIntBuffer[dpFractionalSecond];
+
+  Result := True;
+end;
+
+function xsd_StrToDuration(const ABuffer : string) : TDurationRec;
+begin
+  if not xsd_TryStrToDuration(ABuffer,Result) then
+    raise EConvertError.CreateFmt(SERR_InvalidDuration,[ABuffer]);
+end;
+
+function xsd_DurationToStr(const AValue : TDurationRec) : string;
+var
+  strTime, strDate : string;
+begin
+  if ( AValue.FractionalSecond > 0 ) then begin
+    strTime := IntToStr(AValue.Second) + '.' + IntToStr(AValue.FractionalSecond) + 'S';
+  end else begin
+    if ( AValue.Second > 0 ) then
+      strTime := IntToStr(AValue.Second) + 'S';
+  end;
+  if ( AValue.Minute > 0 ) then
+    strTime := IntToStr(AValue.Minute) + 'M' + strTime;
+  if ( AValue.Hour > 0 ) then
+    strTime := IntToStr(AValue.Hour) + 'H' + strTime;
+  if ( AValue.Day > 0 ) then
+    strDate := IntToStr(AValue.Day) + 'D';
+  if ( AValue.Month > 0 ) then
+    strDate := IntToStr(AValue.Month) + 'M' + strDate;
+  if ( AValue.Year > 0 ) then
+    strDate := IntToStr(AValue.Year) + 'Y' + strDate;
+  if ( strTime <> '' ) then
+    Result := 'T' + strTime;
+  Result := strDate + Result;
+  if ( Result = '' ) then
+    Result := '0Y';
+  Result := 'P' + Result;
+  if AValue.Negative and ( ( strDate <> '' ) or ( strTime <> '' ) ) then
+    Result := '-' + Result;
+end;
+
+function ValueEquals(const AA,AB: TDurationRec) : Boolean;
+begin
+  Result := ( AA.Negative = AB.Negative ) and
+            ( AA.Year = AB.Year ) and
+            ( AA.Month = AB.Month ) and
+            ( AA.Day = AB.Day ) and
+            ( AA.Hour = AB.Hour ) and
+            ( AA.Minute = AB.Minute ) and
+            ( AA.Second = AB.Second ) and
+            ( AA.FractionalSecond = AB.FractionalSecond );
+end;
+
+end.

+ 377 - 0
packages/fcl-sdo/src/base/sdo_dom_cursors.pas

@@ -0,0 +1,377 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a DOM cursor
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_dom_cursors;
+
+interface
+
+uses
+  Classes, SysUtils,
+  sdo_cursor_intf,
+{$IFNDEF FPC}
+  xmldom, sdo_win_xml,
+{$ELSE}
+  DOM, sdo_fpc_xml,
+{$ENDIF}
+  sdo_types;
+
+const
+
+  s_NODE_NAME = 'NodeName';
+  s_NODE_VALUE = 'NodeValue';
+
+type
+
+  TFreeAction = ( faNone, faFreeOnDestroy );
+
+  { TDOMNodeListCursor }
+
+  TDOMNodeListCursor = class(
+    TInterfacedObject,
+    ICursor,
+    IDefaultTypedCursor
+  )
+  private
+    FList : TDOMNodeList;
+    FCurrent : TDOMNode;
+    FFreeListOnDestroy : TFreeAction;
+    FHasItem : Boolean;
+  protected
+    procedure Reset();
+    function MoveNext() : Boolean;
+    function Clone():ICursor;
+    function GetCount() : PtrInt;
+    function GetCurrent() : IDefaultItemType;virtual;
+  public
+    constructor Create(
+            ADataList          : TDOMNodeList;
+      const AFreeListOnDestroy : TFreeAction
+    );
+    destructor Destroy();override;
+  end;
+
+  { TDOMNamedNodeMapCursor }
+
+  TDOMNamedNodeMapCursor = class(
+    TInterfacedObject,
+    ICursor,
+    IDefaultTypedCursor
+  )
+  private
+    FList : TDOMNamedNodeMap;
+    FCurrent : Integer;
+    FFreeListOnDestroy : TFreeAction;
+  protected
+    procedure Reset();
+    function MoveNext() : Boolean;
+    function Clone():ICursor;
+    function GetCount() : PtrInt;
+    function GetCurrent() : IDefaultItemType;
+  public
+    constructor Create(
+            ADataList : TDOMNamedNodeMap;
+      const AFreeListOnDestroy : TFreeAction
+    );
+    destructor Destroy();override;
+  end;
+
+  { TDOMNodeRttiExposer }
+
+  TDOMNodeRttiExposer = class(TPersistent)
+  private
+    FInnerObject: TDOMNode;
+    function GetNodeName: DOMString;
+    function GetNodeValue: DOMString;
+    procedure SetInnerObject(const AValue: TDOMNode);
+  public
+    constructor Create(AInnerObject : TDOMNode);
+    property InnerObject : TDOMNode read FInnerObject write SetInnerObject;
+  published
+    property NodeName: DOMString read GetNodeName;
+    property NodeValue: DOMString read GetNodeValue;
+  end;
+
+  { TDOMNodeRttiExposerCursor }
+
+  TDOMNodeRttiExposerCursor = class(
+    TInterfacedObject,
+    ICursor,
+    IObjectCursor
+  )
+  private
+    FCurrentExposer : TDOMNodeRttiExposer;
+    FBaseCursor : IDefaultTypedCursor;
+  protected
+    procedure Reset();
+    function MoveNext() : Boolean;
+    function Clone():ICursor;
+    function GetCount() : PtrInt;
+    function GetCurrent() : TObject;virtual;
+  public
+    constructor Create(ADataList : IDefaultTypedCursor);
+    destructor Destroy();override;
+  end;
+
+  TCursorExposedType = ( cetRttiNode {$IFDEF INTF_DOM},cetDomNode{$ENDIF} );
+
+
+  function CreateChildrenCursor(
+          ANode : TDOMNode;
+    const AExposedType : TCursorExposedType
+  ) : IObjectCursor;
+
+  function CreateAttributesCursor(
+          ANode : TDOMNode;
+    const AExposedType : TCursorExposedType
+  ) : IObjectCursor;
+
+
+implementation
+{$IFDEF INTF_DOM}
+  function CreateChildrenCursor(
+          ANode : TDOMNode;
+    const AExposedType : TCursorExposedType
+  ) : IObjectCursor;
+  var
+    locCrs : IInterfaceCursor;
+  begin
+    Result := nil;
+    if ( ANode <> nil ) and ANode.hasChildNodes() then begin
+      locCrs := TDOMNodeListCursor.Create(ANode.ChildNodes,faNone) ;
+      Result := TDOMNodeRttiExposerCursor.Create(locCrs);
+    end;
+  end;
+
+  function CreateAttributesCursor(ANode : TDOMNode; const AExposedType : TCursorExposedType):IObjectCursor;
+  var
+    locCrs : IInterfaceCursor;
+  begin
+    Result := nil;
+    if ( ANode <> nil ) and ( ANode.Attributes <> nil ) and ( ANode.Attributes.Length > 0 ) then begin
+      locCrs := TDOMNamedNodeMapCursor.Create(ANode.Attributes,faNone) ;
+      Result := TDOMNodeRttiExposerCursor.Create(locCrs);
+    end;
+  end;
+{$ENDIF INTF_DOM}
+
+{$IFNDEF INTF_DOM}
+  function CreateChildrenCursor(
+          ANode : TDOMNode;
+    const AExposedType : TCursorExposedType
+  ) : IObjectCursor;
+  begin
+    Result := nil;
+    if ( ANode <> nil ) and ANode.HasChildNodes() then begin
+      Result := TDOMNodeListCursor.Create(ANode.ChildNodes,faNone) ;
+      if ( AExposedType = cetRttiNode ) then
+        Result := TDOMNodeRttiExposerCursor.Create(Result);
+    end;
+  end;
+
+  function CreateAttributesCursor(ANode : TDOMNode; const AExposedType : TCursorExposedType):IObjectCursor;
+  begin
+    Result := nil;
+    if ( ANode <> nil ) and ( ANode.Attributes <> nil ) and ( ANode.Attributes.Length > 0 ) then begin
+      Result := TDOMNamedNodeMapCursor.Create(ANode.Attributes,faNone) ;
+      if ( AExposedType = cetRttiNode ) then
+        Result := TDOMNodeRttiExposerCursor.Create(Result);
+    end;
+  end;
+{$ENDIF !INTF_DOM}
+
+
+{ TDOMNodeListCursor }
+
+procedure TDOMNodeListCursor.Reset();
+begin
+  FCurrent := nil;
+end;
+
+function TDOMNodeListCursor.MoveNext(): Boolean;
+begin
+  if ( FCurrent = nil ) then begin
+    if FHasItem then
+      FCurrent := FList.Item[0];
+  end else begin
+    FCurrent := FCurrent.NextSibling;
+  end;
+  Result := ( FCurrent <> nil ) ;
+end;
+
+function TDOMNodeListCursor.Clone(): ICursor;
+begin
+  Result := TDOMNodeListCursor.Create(FList,faNone);
+end;
+
+function TDOMNodeListCursor.GetCount() : PtrInt;
+begin
+  Result := GetNodeListCount(FList);
+end;
+
+function TDOMNodeListCursor.GetCurrent(): IDefaultItemType;
+begin
+  Result := FCurrent;
+end;
+
+constructor TDOMNodeListCursor.Create(
+        ADataList          : TDOMNodeList;
+  const AFreeListOnDestroy : TFreeAction
+);
+begin
+  Assert(Assigned(ADataList));
+  FFreeListOnDestroy := AFreeListOnDestroy;
+  FList := ADataList;
+  FHasItem := ( GetNodeListCount(FList) > 0 );
+  Reset();
+end;
+
+destructor TDOMNodeListCursor.Destroy();
+begin
+  FCurrent := nil;
+  if ( FFreeListOnDestroy = faFreeOnDestroy ) then
+    ReleaseDomNode(FList)
+  else
+    FList := nil;
+  inherited Destroy();
+end;
+
+{ TDOMNodeRttiExposer }
+
+function TDOMNodeRttiExposer.GetNodeName: DOMString;
+begin
+  Result := InnerObject.NodeName;
+end;
+
+function TDOMNodeRttiExposer.GetNodeValue: DOMString;
+begin
+  Result := InnerObject.NodeValue;
+end;
+
+procedure TDOMNodeRttiExposer.SetInnerObject(const AValue: TDOMNode);
+begin
+  if ( FInnerObject = AValue ) then
+    exit;
+  FInnerObject := AValue;
+end;
+
+constructor TDOMNodeRttiExposer.Create(AInnerObject: TDOMNode);
+begin
+  Inherited Create();
+  SetInnerObject(AInnerObject);
+end;
+
+{ TDOMNodeRttiExposerCursor }
+
+procedure TDOMNodeRttiExposerCursor.Reset();
+begin
+  FBaseCursor.Reset();
+end;
+
+function TDOMNodeRttiExposerCursor.MoveNext(): Boolean;
+begin
+  Result := FBaseCursor.MoveNext();
+end;
+
+function TDOMNodeRttiExposerCursor.Clone(): ICursor;
+var
+  baseClone : ICursor;
+begin
+  Result := nil;
+  baseClone := FBaseCursor.Clone();
+  if ( baseClone <> nil ) then
+    Result := TDOMNodeRttiExposerCursor.Create(baseClone as IDefaultTypedCursor) ;
+end;
+
+function TDOMNodeRttiExposerCursor.GetCount() : PtrInt;
+begin
+  Result := FBaseCursor.GetCount();
+end;
+
+function TDOMNodeRttiExposerCursor.GetCurrent(): TObject;
+begin
+  FCurrentExposer.InnerObject := FBaseCursor.GetCurrent() as TDOMNode;
+  if ( FCurrentExposer.InnerObject = nil ) then
+    Result := nil
+  else
+    Result := FCurrentExposer;
+end;
+
+constructor TDOMNodeRttiExposerCursor.Create(ADataList : IDefaultTypedCursor);
+begin
+  Assert(Assigned(ADataList));
+  inherited Create();
+  FBaseCursor := ADataList;
+  FCurrentExposer := TDOMNodeRttiExposer.Create(nil);
+end;
+
+destructor TDOMNodeRttiExposerCursor.Destroy();
+begin
+  FreeAndNil(FCurrentExposer);;
+  inherited Destroy();
+end;
+
+{ TDOMNamedNodeMapCursor }
+
+procedure TDOMNamedNodeMapCursor.Reset();
+begin
+  FCurrent := -1;
+end;
+
+function TDOMNamedNodeMapCursor.MoveNext(): Boolean;
+begin
+  Inc(FCurrent);
+  Result := ( FCurrent < GetNodeListCount(FList) );
+end;
+
+function TDOMNamedNodeMapCursor.Clone(): ICursor;
+begin
+  Result := TDOMNamedNodeMapCursor.Create(FList,faNone);
+end;
+
+function TDOMNamedNodeMapCursor.GetCount() : PtrInt;
+begin
+  Result := GetNodeListCount(FList);
+end;
+
+function TDOMNamedNodeMapCursor.GetCurrent(): IDefaultItemType;
+begin
+  if ( FCurrent > -1 ) and ( FCurrent < GetNodeListCount(FList) ) then
+    Result := FList.Item[FCurrent]
+  else
+    Result := nil;
+end;
+
+constructor TDOMNamedNodeMapCursor.Create(
+        ADataList : TDOMNamedNodeMap;
+  const AFreeListOnDestroy : TFreeAction
+);
+begin
+  Assert(Assigned(ADataList));
+  FFreeListOnDestroy := AFreeListOnDestroy;
+  FList := ADataList;
+  Reset();
+end;
+
+destructor TDOMNamedNodeMapCursor.Destroy();
+begin
+  if ( FFreeListOnDestroy = faFreeOnDestroy ) then
+    ReleaseDomNode(FList)
+  else
+    FList := nil;
+  inherited Destroy();
+end;
+
+end.

+ 3647 - 0
packages/fcl-sdo/src/base/sdo_field_imp.pas

@@ -0,0 +1,3647 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements basic SDO Field definitions
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_field_imp;
+
+interface
+uses SysUtils, Classes,
+     sdo_types, sdo, sdo_type;
+
+const
+  BIT_ORDER_SET  = 1;
+  BIT_ORDER_NULL = 2;
+  BIT_ORDER_BUFFER = 3;
+
+type
+
+  ISDOField = interface
+    ['{BD6E436E-0274-4B55-8346-593BA9FD5F4F}']
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    );
+
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );
+
+{$IFDEF HAS_SDO_BYTES}
+    function getBytes(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBytes;
+    procedure setBytes(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+            AValue  : TSDOBytes
+    );
+{$ENDIF HAS_SDO_BYTES}
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    );
+
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOCurrency;
+    procedure setCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOCurrency
+    );
+{$ENDIF HAS_SDO_CURRENCY}
+
+    function getDate(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODate;
+    procedure setDate(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODate
+    );
+
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODouble;
+    procedure setDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODouble
+    );
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOFloat;
+    procedure setFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOFloat
+    );
+{$ENDIF HAS_SDO_FLOAT}
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    );
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    );
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );
+
+    function getDataObject(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : ISDODataObject;
+    procedure setDataObject(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : ISDODataObject
+    );
+
+    function getChangeSummary(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : ISDOChangeSummary;
+    procedure setChangeSummary(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : ISDOChangeSummary
+    );
+
+    function isSet(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : Boolean;
+    procedure unset(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );
+    function isNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : Boolean;
+    procedure setNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );
+  end;
+
+  TSDOBaseField = class(TInterfacedObject,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; virtual;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); virtual;
+
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean; virtual;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    ); virtual;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte; virtual;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    ); virtual;
+
+{$IFDEF HAS_SDO_BYTES}
+    function getBytes(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBytes; virtual;
+    procedure setBytes(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+            AValue  : TSDOBytes
+    ); virtual;
+{$ENDIF HAS_SDO_BYTES}
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; virtual;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); virtual;
+
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOCurrency; virtual;
+    procedure setCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOCurrency
+    ); virtual;
+{$ENDIF HAS_SDO_CURRENCY}
+
+    function getDate(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODate;virtual;
+    procedure setDate(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODate
+    ); virtual;
+
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODouble; virtual;
+    procedure setDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODouble
+    ); virtual;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOFloat; virtual;
+    procedure setFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOFloat
+    ); virtual;
+{$ENDIF HAS_SDO_FLOAT}
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger; virtual;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    ); virtual;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; virtual;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); virtual;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; virtual;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); virtual;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString; virtual;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    ); virtual;
+
+    function getDataObject(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : ISDODataObject; virtual;
+    procedure setDataObject(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : ISDODataObject
+    ); virtual;
+
+    function getChangeSummary(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : ISDOChangeSummary; virtual;
+    procedure setChangeSummary(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : ISDOChangeSummary
+    ); virtual;
+
+
+    function isSet(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : Boolean;virtual;
+    procedure unset(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );virtual;
+    function isNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : Boolean;virtual;
+    procedure setNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );virtual;
+  end;
+
+  TSDOBooleanField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+      
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;override;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );override;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte;override;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );override;
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; override;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); override;
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;override;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );override;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; override;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); override;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; override;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+  end;
+
+  TSDOIntegerField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;override;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );override;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte;override;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );override;
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; override;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); override;
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;override;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );override;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; override;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); override;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; override;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+  end;
+
+  TSDOBaseStringField = class(TSDOBaseField,IInterface,ISDOField)
+  private
+    procedure FreeBuffer(const ABuffer : TSDOFieldBuffer);
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+      
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;override;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );override;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte;override;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );override;
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; override;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); override;
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;override;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );override;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; override;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); override;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; override;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+    procedure unset(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );override;
+    procedure setNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );override;
+  end;
+
+  TSDOStringField = class(TSDOBaseStringField)
+  end;
+
+  TSDOObjectField = class(TSDOBaseField,IInterface,ISDOField)
+  private
+    procedure FreeBuffer(const ABuffer : TSDOFieldBuffer);
+  protected
+    function getDataObject(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : ISDODataObject;override;
+    procedure setDataObject(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : ISDODataObject
+    );override;
+    procedure unset(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );override;
+    procedure setNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );override;
+  end;
+
+  TSDOChangeSummaryField = class(TSDOBaseField,IInterface,ISDOField)
+  private
+    procedure FreeBuffer(const ABuffer : TSDOFieldBuffer);
+  protected
+    function getChangeSummary(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : ISDOChangeSummary;override;
+    procedure setChangeSummary(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : ISDOChangeSummary
+    );override;
+    procedure unset(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );override;
+    procedure setNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );override;
+  end;
+
+  TSDOByteField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+      
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;override;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );override;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte; override;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );override;
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; override;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); override;
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;override;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );override;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; override;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); override;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; override;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+  end;
+
+{$IFDEF HAS_SDO_BYTES}
+  TSDOBytesField = class(TSDOBaseField,IInterface,ISDOField)
+  private
+    procedure FreeBuffer(const ABuffer : TSDOFieldBuffer);
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+      
+    function getBytes(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBytes; override;
+    procedure setBytes(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+            AValue  : TSDOBytes
+    );override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+    procedure setNull(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    );override;
+  end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  TSDOCharField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;override;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );override;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte; override;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );override;
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; override;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); override;
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;override;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );override;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; override;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); override;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; override;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+  end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  TSDOCurrencyField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+    function getCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOCurrency; override;
+    procedure setCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOCurrency
+    ); override;
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODouble; override;
+    procedure setDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODouble
+    ); override;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOFloat; override;
+    procedure setFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOFloat
+    ); override;
+{$ENDIF HAS_SDO_FLOAT}
+  end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+  TSDODateField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getDate(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODate; override;
+    procedure setDate(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODate
+    );override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+  end;
+
+{$IFDEF HAS_SDO_LONG}
+  TSDOLongField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;override;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );override;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte; override;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );override;
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; override;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); override;
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;override;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );override;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; override;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); override;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; override;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+  end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  TSDOShortField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOBoolean;override;
+    procedure setBoolean(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOBoolean
+    );override;
+
+    function getByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOByte; override;
+    procedure setByte(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOByte
+    );override;
+
+    function getCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOChar; override;
+    procedure setCharacter(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOChar
+    ); override;
+
+    function getInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOInteger;override;
+    procedure setInteger(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOInteger
+    );override;
+
+    function getLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOLong; override;
+    procedure setLong(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOLong
+    ); override;
+
+    function getShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOShort; override;
+    procedure setShort(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOShort
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+  end;
+{$ENDIF HAS_SDO_SHORT}
+
+{$IFDEF HAS_SDO_DOUBLE}
+  TSDODoubleField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+    function getCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOCurrency; override;
+    procedure setCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOCurrency
+    ); override;
+
+    function getDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODouble; override;
+    procedure setDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODouble
+    ); override;
+
+    function getFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOFloat; override;
+    procedure setFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOFloat
+    ); override;
+  end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  TSDOFloatField = class(TSDOBaseField,IInterface,ISDOField)
+  protected
+    function getVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOVariant; override;
+    procedure setVariant(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOVariant
+    ); override;
+
+    function getString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOString;override;
+    procedure setString(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOString
+    );override;
+
+    function getCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOCurrency; override;
+    procedure setCurrency(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOCurrency
+    ); override;
+
+    function getDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDODouble; override;
+    procedure setDouble(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDODouble
+    ); override;
+
+    function getFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt
+    ) : TSDOFloat; override;
+    procedure setFloat(
+      const ABuffer : TSDOFieldBuffer;
+      const AOffset : PtrUInt;
+      const AValue  : TSDOFloat
+    ); override;
+  end;
+{$ENDIF HAS_SDO_FLOAT}
+
+  function getField(const AKind : TSDOTypeKind) : ISDOField ;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+
+implementation
+
+uses
+  sdo_imp_utils, sdo_date_utils, Variants;
+
+var
+  FieldMAP : array[TSDOTypeKind] of ISDOField;
+
+function getField(const AKind : TSDOTypeKind) : ISDOField ;
+begin
+  Result := FieldMAP[AKind];
+end;
+
+procedure PrepareMap();
+begin
+  FieldMAP[BooleanType] := TSDOBooleanField.Create();
+  FieldMAP[ByteType] := TSDOByteField.Create();
+{$IFDEF HAS_SDO_BYTES}
+  FieldMAP[BytesType] := TSDOBytesField.Create();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+  FieldMAP[CharacterType] := TSDOCharField.Create();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  FieldMAP[CurrencyType] := TSDOCurrencyField.Create();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+  FieldMAP[DoubleType] := TSDODoubleField.Create();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  FieldMAP[FloatType] := TSDOFloatField.Create();
+{$ENDIF HAS_SDO_FLOAT}
+  FieldMAP[DateTimeType] := TSDODateField.Create();
+  FieldMAP[IntegerType] := TSDOIntegerField.Create();
+{$IFDEF HAS_SDO_LONG}
+  FieldMAP[LongType] := TSDOLongField.Create();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  FieldMAP[ShortType] := TSDOShortField.Create();
+{$ENDIF HAS_SDO_ShORT}
+  FieldMAP[StringType] := TSDOStringField.Create();
+
+  FieldMAP[ObjectType] := TSDOObjectField.Create();
+  FieldMAP[ChangeSummaryType] := TSDOChangeSummaryField.Create();
+end;
+
+procedure UnprepareMap();
+var
+  e : TSDOTypeKind;
+begin
+  for e := Low(TSDOTypeKind) to High(TSDOTypeKind) do begin
+    FieldMAP[e] := nil;
+  end;
+end;
+
+{ TSDOBaseField }
+
+{$WARNINGS OFF}
+function TSDOBaseField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBoolean;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOByte;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getBytes(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBytes;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getChangeSummary(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : ISDOChangeSummary;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getDataObject(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+): ISDODataObject;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getDate(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDODate;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOString;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+function TSDOBaseField.isNull(const ABuffer: TSDOFieldBuffer; const AOffset: PtrUInt): Boolean;
+var
+  locBuffer : PByte;
+begin
+  locBuffer := ABuffer;
+  if ( AOffset <> 0 ) then
+    Inc(locBuffer,AOffset);
+  Result := IsBitON(locBuffer^,BIT_ORDER_NULL);
+end;
+
+function TSDOBaseField.isSet(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : Boolean;
+var
+  locBuffer : PByte;
+begin
+  locBuffer := ABuffer;
+  if ( AOffset <> 0 ) then
+    Inc(locBuffer,AOffset);
+  Result := IsBitON(locBuffer^,BIT_ORDER_SET);
+end;
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt; const AValue: TSDOBoolean
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setBytes(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+        AValue: TSDOBytes
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setChangeSummary(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: ISDOChangeSummary
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setDataObject(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue  : ISDODataObject
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setDate(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDODate
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOInteger
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+procedure TSDOBaseField.setNull(const ABuffer: TSDOFieldBuffer; const AOffset: PtrUInt);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  SetBit(rawBuffer^,BIT_ORDER_SET,True);
+  SetBit(rawBuffer^,BIT_ORDER_NULL,True);
+end;
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+procedure TSDOBaseField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+procedure TSDOBaseField.unset(const ABuffer: TSDOFieldBuffer; const AOffset: PtrUInt);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  SetBit(rawBuffer^,BIT_ORDER_SET,False);
+end;
+
+{$IFDEF HAS_SDO_CURRENCY}
+{$WARNINGS OFF}
+function TSDOBaseField.getCurrency(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOCurrency;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+
+procedure TSDOBaseField.setCurrency(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOCurrency
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+{$WARNINGS OFF}
+function TSDOBaseField.getDouble(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDODouble;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+
+procedure TSDOBaseField.setDouble(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDODouble
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+{$WARNINGS OFF}
+function TSDOBaseField.getFloat(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOFloat;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+
+procedure TSDOBaseField.setFloat(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOFloat
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+{$ENDIF HAS_SDO_FLOAT}
+
+{ TSDOBooleanField }
+
+function TSDOBooleanField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+): TSDOBoolean;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := False;
+  end else begin
+    Inc(buff);
+    Result := ( buff^ <> 0 );
+  end;
+end;
+
+function TSDOBooleanField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOByte;
+begin
+  Result := TSDOConvertHelper.BoolToByte(getBoolean(ABuffer,AOffset));
+end;
+
+function TSDOBooleanField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+begin
+  Result := TSDOConvertHelper.BoolToChar(getBoolean(ABuffer,AOffset));
+end;
+
+function TSDOBooleanField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+begin
+  Result := TSDOConvertHelper.BoolToInteger(getBoolean(ABuffer,AOffset));
+end;
+
+function TSDOBooleanField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+begin
+  Result := TSDOConvertHelper.BoolToLong(getBoolean(ABuffer,AOffset));
+end;
+
+function TSDOBooleanField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+begin
+  Result := TSDOConvertHelper.BoolToShort(getBoolean(ABuffer,AOffset));
+end;
+
+function TSDOBooleanField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+): TSDOString;
+begin
+  Result := TSDOConvertHelper.BoolToString(getBoolean(ABuffer,AOffset));
+end;
+
+function TSDOBooleanField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getBoolean(ABuffer,AOffset);
+end;
+
+procedure TSDOBooleanField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOBoolean
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  if AValue then
+    buff^ := 1
+  else
+    buff^ := 0;
+end;
+
+procedure TSDOBooleanField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  setBoolean(ABuffer,AOffset,( AValue <> 0 ));
+end;
+
+procedure TSDOBooleanField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+begin
+  setBoolean(ABuffer,AOffset,TSDOConvertHelper.CharToBool(AValue));
+end;
+
+procedure TSDOBooleanField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOInteger
+);
+begin
+  setBoolean(ABuffer,AOffset,TSDOConvertHelper.IntegerToBool(AValue));
+end;
+
+procedure TSDOBooleanField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+begin
+  setBoolean(ABuffer,AOffset,TSDOConvertHelper.LongToBool(AValue));
+end;
+
+procedure TSDOBooleanField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort
+);
+begin
+  setBoolean(ABuffer,AOffset,TSDOConvertHelper.ShortToBool(AValue));
+end;
+
+procedure TSDOBooleanField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  setBoolean(ABuffer,AOffset,TSDOConvertHelper.StringToBool(AValue));
+end;
+
+procedure TSDOBooleanField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setBoolean(ABuffer,AOffset,AValue);
+end;
+
+{ TSDOIntegerField }
+
+function TSDOIntegerField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+): TSDOBoolean;
+begin
+  Result := TSDOConvertHelper.IntegerToBool(getInteger(ABuffer,AOffset));
+end;
+
+function TSDOIntegerField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOByte;
+begin
+  Result := getInteger(ABuffer,AOffset);
+end;
+
+function TSDOIntegerField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+begin
+  Result := TSDOConvertHelper.IntegerToChar(getInteger(ABuffer,AOffset));
+end;
+
+function TSDOIntegerField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := 0;
+  end else begin
+    Inc(buff);
+    Result := PSDOInteger(buff)^;
+  end;
+end;
+
+function TSDOIntegerField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+begin
+  Result := getInteger(ABuffer,AOffset);
+end;
+
+function TSDOIntegerField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+begin
+  Result := getInteger(ABuffer,AOffset);
+end;
+
+function TSDOIntegerField.getString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.IntegerToString(getInteger(ABuffer,AOffset));
+end;
+
+function TSDOIntegerField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getInteger(ABuffer,AOffset);
+end;
+
+procedure TSDOIntegerField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt; const AValue: TSDOBoolean
+);
+begin
+  setInteger(ABuffer,AOffset,TSDOConvertHelper.BoolToInteger(AValue));
+end;
+
+procedure TSDOIntegerField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  setInteger(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOIntegerField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+begin
+  setInteger(ABuffer,AOffset,TSDOConvertHelper.CharToInteger(AValue));
+end;
+
+procedure TSDOIntegerField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt; const AValue: TSDOInteger
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDOInteger(buff)^ := AValue;
+end;
+
+procedure TSDOIntegerField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+begin
+  setInteger(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOIntegerField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort
+);
+begin
+  setInteger(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOIntegerField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt; const AValue: TSDOString
+);
+begin
+  setInteger(ABuffer,AOffset,TSDOConvertHelper.StringToInteger(AValue));
+end;
+
+procedure TSDOIntegerField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setInteger(ABuffer,AOffset,AValue);
+end;
+
+{ TSDOBaseStringField }
+
+procedure TSDOBaseStringField.FreeBuffer(const ABuffer : TSDOFieldBuffer);
+var
+  rawBuffer : PByte;
+  strBuffer : PPSDOString;
+begin
+  rawBuffer := PByte(ABuffer);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    Inc(rawBuffer);
+    strBuffer := PPSDOString(rawBuffer);
+    SetLength(strBuffer^^,0);
+    FreeMem(strBuffer^,SizeOf(PSDOString));
+    strBuffer^ := nil;
+    Dec(rawBuffer);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,False);
+  end;
+end;
+
+function TSDOBaseStringField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBoolean;
+begin
+  Result := TSDOConvertHelper.StringToBool(getString(ABuffer,AOffset));
+end;
+
+function TSDOBaseStringField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOByte;
+begin
+  Result := TSDOConvertHelper.StringToByte(getString(ABuffer,AOffset));
+end;
+
+function TSDOBaseStringField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+begin
+  Result := TSDOConvertHelper.StringToChar(getString(ABuffer,AOffset));
+end;
+
+function TSDOBaseStringField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+begin
+  Result := TSDOConvertHelper.StringToInteger(getString(ABuffer,AOffset));
+end;
+
+function TSDOBaseStringField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+begin
+  Result := TSDOConvertHelper.StringToLong(getString(ABuffer,AOffset));
+end;
+
+function TSDOBaseStringField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+begin
+  Result := TSDOConvertHelper.StringToShort(getString(ABuffer,AOffset));
+end;
+
+function TSDOBaseStringField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOString;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := '';
+  end else begin
+    if IsBitON(buff^,BIT_ORDER_BUFFER) then begin
+      Inc(buff);
+      Result := PPSDOString(buff)^^
+    end else begin
+      Result := '';
+    end;
+  end;
+end;
+
+function TSDOBaseStringField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getString(ABuffer,AOffset);
+end;
+
+procedure TSDOBaseStringField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOBoolean
+);
+begin
+  setString(ABuffer,AOffset,TSDOConvertHelper.BoolToString(AValue));
+end;
+
+procedure TSDOBaseStringField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  setString(ABuffer,AOffset,TSDOConvertHelper.ByteToString(AValue));
+end;
+
+procedure TSDOBaseStringField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+begin
+  setString(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOBaseStringField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt; const AValue: TSDOInteger
+);
+begin
+  setString(ABuffer,AOffset,TSDOConvertHelper.IntegerToString(AValue));
+end;
+
+procedure TSDOBaseStringField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+begin
+  setString(ABuffer,AOffset,TSDOConvertHelper.LongToString(AValue));
+end;
+
+procedure TSDOBaseStringField.setNull(const ABuffer: TSDOFieldBuffer; const AOffset: PtrUInt);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    FreeBuffer(rawBuffer);
+  end;
+  inherited setNull(ABuffer,AOffset);
+end;
+
+procedure TSDOBaseStringField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort
+);
+begin
+  setString(ABuffer,AOffset,TSDOConvertHelper.ShortToString(AValue));
+end;
+
+procedure TSDOBaseStringField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt; const AValue: TSDOString
+);
+var
+  rawBuffer : PByte;
+  strBuffer : PPSDOString;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  SetBit(rawBuffer^,BIT_ORDER_SET,True);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    Inc(rawBuffer);
+    strBuffer := PPSDOString(rawBuffer);
+  end else begin;
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,True);
+    Inc(rawBuffer);
+    strBuffer := PPSDOString(rawBuffer);
+    GetMem(strBuffer^,SizeOf(PSDOString));
+    FillChar(strBuffer^^,SizeOf(TSDOString),#0);
+  end;
+  strBuffer^^ := AValue;
+end;
+
+procedure TSDOBaseStringField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setString(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOBaseStringField.unset(const ABuffer: TSDOFieldBuffer; const AOffset: PtrUInt);
+//var
+  //rawBuffer : PByte;
+begin
+  {rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  do not free the buffer, in case of a default value!
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    FreeBuffer(rawBuffer);
+  end;}
+  inherited unset(ABuffer,AOffset);
+end;
+
+
+{ TSDOObjectField }
+
+procedure TSDOObjectField.FreeBuffer(const ABuffer: TSDOFieldBuffer);
+var
+  rawBuffer : PByte;
+  objBuffer : PPSDODataObject;
+begin
+  rawBuffer := PByte(ABuffer);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    Inc(rawBuffer);
+    objBuffer := PPSDODataObject(rawBuffer);
+    objBuffer^^ := nil;
+    FreeMem(objBuffer^,SizeOf(PSDODataObject));
+    objBuffer^ := nil;
+    Dec(rawBuffer);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,False);
+  end;
+end;
+
+function TSDOObjectField.getDataObject(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : ISDODataObject;
+var
+  buff : PByte;
+  objBuffer : PPSDODataObject;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := nil;
+  end else begin
+    if IsBitON(buff^,BIT_ORDER_BUFFER) then begin
+      Inc(buff);
+      objBuffer := PPSDODataObject(buff);
+      Result := objBuffer^^;
+    end else begin
+      Result := nil;
+    end;
+  end;
+end;
+
+procedure TSDOObjectField.setDataObject(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue  : ISDODataObject
+);
+var
+  rawBuffer : PByte;
+  objBuffer : PPSDODataObject;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    Inc(rawBuffer);
+    objBuffer := PPSDODataObject(rawBuffer);
+  end else begin;
+    SetBit(rawBuffer^,BIT_ORDER_SET,True);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,True);
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    Inc(rawBuffer);
+    objBuffer := PPSDODataObject(rawBuffer);
+    GetMem(objBuffer^,SizeOf(PSDODataObject));
+    FillChar(objBuffer^^,SizeOf(ISDODataObject),#0);
+  end;
+  objBuffer^^ := AValue;
+end;
+
+procedure TSDOObjectField.setNull(const ABuffer: TSDOFieldBuffer; const AOffset: PtrUInt);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    FreeBuffer(rawBuffer);
+  end;
+  inherited setNull(ABuffer,AOffset);
+end;
+
+procedure TSDOObjectField.unset(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    FreeBuffer(rawBuffer);
+  end;
+  inherited unset(ABuffer,AOffset);
+end;
+
+{ TSDOChangeSummaryField }
+
+procedure TSDOChangeSummaryField.FreeBuffer(const ABuffer: TSDOFieldBuffer);
+var
+  rawBuffer : PByte;
+  objBuffer : PPSDOChangeSummary;
+begin
+  rawBuffer := PByte(ABuffer);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    Inc(rawBuffer);
+    objBuffer := PPSDOChangeSummary(rawBuffer);
+    objBuffer^^ := nil;
+    FreeMem(objBuffer^,SizeOf(PPSDOChangeSummary));
+    objBuffer^ := nil;
+    Dec(rawBuffer);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,False);
+  end;
+end;
+
+function TSDOChangeSummaryField.getChangeSummary(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+): ISDOChangeSummary;
+var
+  buff : PByte;
+  objBuffer : PPSDOChangeSummary;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := nil;
+  end else begin
+    if IsBitON(buff^,BIT_ORDER_BUFFER) then begin
+      Inc(buff);
+      objBuffer := PPSDOChangeSummary(buff);
+      Result := objBuffer^^;
+    end else begin
+      Result := nil;
+    end;
+  end;
+end;
+
+procedure TSDOChangeSummaryField.setChangeSummary(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: ISDOChangeSummary
+);
+var
+  rawBuffer : PByte;
+  objBuffer : PPSDOChangeSummary;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    Inc(rawBuffer);
+    objBuffer := PPSDOChangeSummary(rawBuffer);
+  end else begin;
+    SetBit(rawBuffer^,BIT_ORDER_SET,True);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,True);
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    Inc(rawBuffer);
+    objBuffer := PPSDOChangeSummary(rawBuffer);
+    GetMem(objBuffer^,SizeOf(PSDOChangeSummary));
+    FillChar(objBuffer^^,SizeOf(ISDOChangeSummary),#0);
+  end;
+  objBuffer^^ := AValue;
+end;
+
+procedure TSDOChangeSummaryField.setNull(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    FreeBuffer(rawBuffer);
+  end;
+  inherited setNull(ABuffer,AOffset);
+end;
+
+procedure TSDOChangeSummaryField.unset(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    FreeBuffer(rawBuffer);
+  end;
+  inherited unset(ABuffer,AOffset);
+end;
+
+{ TSDOByteField }
+
+function TSDOByteField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBoolean;
+begin
+  Result := TSDOConvertHelper.ByteToBool(getByte(ABuffer,AOffset));
+end;
+
+function TSDOByteField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+): TSDOByte;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := 0;
+  end else begin
+    Inc(buff);
+    Result := buff^;
+  end;
+end;
+
+function TSDOByteField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+begin
+  Result := TSDOConvertHelper.ByteToChar(getByte(ABuffer,AOffset));
+end;
+
+function TSDOByteField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+begin
+  Result := getByte(ABuffer,AOffset);
+end;
+
+function TSDOByteField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+begin
+  Result := getByte(ABuffer,AOffset);
+end;
+
+function TSDOByteField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+begin
+  Result := getByte(ABuffer,AOffset);
+end;
+
+function TSDOByteField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.ByteToString(getByte(ABuffer,AOffset));
+end;
+
+function TSDOByteField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getByte(ABuffer,AOffset);
+end;
+
+procedure TSDOByteField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOBoolean
+);
+begin
+  setByte(ABuffer,AOffset,TSDOConvertHelper.BoolToByte(AValue));
+end;
+
+procedure TSDOByteField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  buff^ := AValue;
+end;
+
+procedure TSDOByteField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+begin
+  setByte(ABuffer,AOffset,TSDOConvertHelper.CharToByte(AValue));
+end;
+
+procedure TSDOByteField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOInteger
+);
+begin
+  setByte(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOByteField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+begin
+  setByte(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOByteField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort
+);
+begin
+  setByte(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOByteField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  setByte(ABuffer,AOffset,TSDOConvertHelper.StringToByte(AValue));
+end;
+
+procedure TSDOByteField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setByte(ABuffer,AOffset,AValue);
+end;
+
+{ TSDODateField }
+
+function TSDODateField.getDate(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDODate;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := ZERO_DATE;
+  end else begin
+    Inc(buff);
+    Result := PSDODate(buff)^;
+  end;
+end;
+
+function TSDODateField.getString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.DateToString(getDate(ABuffer,AOffset));
+end;
+
+function TSDODateField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := NormalizeToUTC(getDate(ABuffer,AOffset));
+end;
+
+procedure TSDODateField.setDate(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDODate
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDODate(buff)^ := AValue;
+end;
+
+procedure TSDODateField.setString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOString
+);
+begin
+  setDate(ABuffer,AOffset,TSDOConvertHelper.StringToDate(AValue));
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDODateField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setDate(ABuffer,AOffset,DateTimeToDateTimeRec(AValue));
+end;
+
+{ TSDOCharField }
+
+function TSDOCharField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBoolean;
+begin
+  Result := TSDOConvertHelper.CharToBool(getCharacter(ABuffer,AOffset));
+end;
+
+function TSDOCharField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOByte;
+begin
+  Result := TSDOConvertHelper.CharToByte(getCharacter(ABuffer,AOffset));
+end;
+
+function TSDOCharField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := #0;
+  end else begin
+    Inc(buff);
+    Result := PSDOChar(buff)^;
+  end;
+end;
+
+function TSDOCharField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+begin
+  Result := TSDOConvertHelper.CharToInteger(getCharacter(ABuffer,AOffset));
+end;
+
+function TSDOCharField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+begin
+  Result := TSDOConvertHelper.CharToLong(getCharacter(ABuffer,AOffset));
+end;
+
+function TSDOCharField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+begin
+  Result := TSDOConvertHelper.CharToShort(getCharacter(ABuffer,AOffset));
+end;
+
+function TSDOCharField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOString;
+begin
+  Result := getCharacter(ABuffer,AOffset);
+end;
+
+function TSDOCharField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getCharacter(ABuffer,AOffset);
+end;
+
+procedure TSDOCharField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOBoolean
+);
+begin
+  setCharacter(ABuffer,AOffset,TSDOConvertHelper.BoolToChar(AValue));
+end;
+
+procedure TSDOCharField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  setCharacter(ABuffer,AOffset,TSDOConvertHelper.ByteToChar(AValue));
+end;
+
+procedure TSDOCharField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDOChar(buff)^ := AValue;
+end;
+
+procedure TSDOCharField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOInteger
+);
+begin
+  setCharacter(ABuffer,AOffset,TSDOConvertHelper.IntegerToChar(AValue));
+end;
+
+procedure TSDOCharField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+begin
+  setCharacter(ABuffer,AOffset,TSDOConvertHelper.LongToChar(AValue));
+end;
+
+procedure TSDOCharField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort);
+begin
+  setCharacter(ABuffer,AOffset,TSDOConvertHelper.ShortToChar(AValue));
+end;
+
+procedure TSDOCharField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  setCharacter(ABuffer,AOffset,TSDOConvertHelper.StringToChar(AValue));
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+
+{$IFDEF HAS_SDO_CURRENCY}
+function TSDOCurrencyField.getString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.CurrencyToString(getCurrency(ABuffer,AOffset));
+end;
+
+procedure TSDOCurrencyField.setString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOString
+);
+begin
+  setCurrency(ABuffer,AOffset,TSDOConvertHelper.StringToCurrency(AValue));
+end;
+
+function TSDOCurrencyField.getCurrency(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOCurrency;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := 0;
+  end else begin
+    Inc(buff);
+    Result := PSDOCurrency(buff)^;
+  end;
+end;
+
+procedure TSDOCurrencyField.setCurrency(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOCurrency
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDOCurrency(buff)^ := AValue;
+end;
+
+function TSDOCurrencyField.getDouble(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDODouble;
+begin
+  Result := getCurrency(ABuffer,AOffset);
+end;
+
+procedure TSDOCurrencyField.setDouble(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDODouble
+);
+begin
+  setCurrency(ABuffer,AOffset,AValue);
+end;
+
+function TSDOCurrencyField.getFloat(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOFloat;
+begin
+  Result := getCurrency(ABuffer,AOffset);
+end;
+
+procedure TSDOCurrencyField.setFloat(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOFloat
+);
+begin
+  setCurrency(ABuffer,AOffset,AValue);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOCharField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+var
+  locStr : TSDOString;
+begin
+  if isNull(ABuffer,AOffset) then begin
+    setNull(ABuffer,AOffset)
+  end else begin
+    locStr := AValue;
+    if IsStrEmpty(locStr) then
+      locStr := #0;
+    setCharacter(ABuffer,AOffset,locStr[1]);
+  end;
+end;
+
+{ TSDOLongField }
+
+function TSDOLongField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBoolean;
+begin
+  Result := TSDOConvertHelper.LongToBool(getLong(ABuffer,AOffset));
+end;
+
+function TSDOLongField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOByte;
+begin
+  Result := getLong(ABuffer,AOffset);
+end;
+
+function TSDOLongField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+begin
+  Result := TSDOConvertHelper.LongToChar(getLong(ABuffer,AOffset));
+end;
+
+function TSDOLongField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+begin
+  Result := getLong(ABuffer,AOffset);
+end;
+
+function TSDOLongField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := 0;
+  end else begin
+    Inc(buff);
+    Result := PSDOLong(buff)^;
+  end;
+end;
+
+function TSDOLongField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+begin
+  Result := getLong(ABuffer,AOffset);
+end;
+
+function TSDOLongField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.LongToString(getLong(ABuffer,AOffset));
+end;
+
+function TSDOLongField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getLong(ABuffer,AOffset);
+end;
+
+procedure TSDOLongField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOBoolean
+);
+begin
+  setLong(ABuffer,AOffset,TSDOConvertHelper.BoolToLong(AValue));
+end;
+
+procedure TSDOLongField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  setLong(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOLongField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+begin
+  setLong(ABuffer,AOffset,TSDOConvertHelper.CharToLong(AValue));
+end;
+
+procedure TSDOLongField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOInteger
+);
+begin
+  setLong(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOLongField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDOLong(buff)^ := AValue;
+end;
+
+procedure TSDOLongField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort);
+begin
+  setLong(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOLongField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  setLong(ABuffer,AOffset,TSDOConvertHelper.StringToLong(AValue));
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOLongField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setLong(ABuffer,AOffset,AValue);
+end;
+
+{ TSDOShortField }
+
+function TSDOShortField.getBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBoolean;
+begin
+  Result := TSDOConvertHelper.ShortToBool(getShort(ABuffer,AOffset));
+end;
+
+function TSDOShortField.getByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOByte;
+begin
+  Result := getShort(ABuffer,AOffset);
+end;
+
+function TSDOShortField.getCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOChar;
+begin
+  Result := TSDOConvertHelper.ShortToChar(getShort(ABuffer,AOffset));
+end;
+
+function TSDOShortField.getInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOInteger;
+begin
+  Result := getShort(ABuffer,AOffset);
+end;
+
+function TSDOShortField.getLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOLong;
+begin
+ Result := getShort(ABuffer,AOffset);
+end;
+
+function TSDOShortField.getShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOShort;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := 0;
+  end else begin
+    Inc(buff);
+    Result := PSDOShort(buff)^;
+  end;
+end;
+
+function TSDOShortField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.ShortToString(getShort(ABuffer,AOffset));
+end;
+
+function TSDOShortField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getShort(ABuffer,AOffset);
+end;
+
+procedure TSDOShortField.setBoolean(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOBoolean
+);
+begin
+  setShort(ABuffer,AOffset,TSDOConvertHelper.BooltoShort(AValue));
+end;
+
+procedure TSDOShortField.setByte(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOByte
+);
+begin
+  setShort(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOShortField.setCharacter(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOChar
+);
+begin
+  setShort(ABuffer,AOffset,TSDOConvertHelper.ChartoShort(AValue));
+end;
+
+procedure TSDOShortField.setInteger(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOInteger
+);
+begin
+  setShort(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOShortField.setLong(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOLong
+);
+begin
+  setShort(ABuffer,AOffset,AValue);
+end;
+
+procedure TSDOShortField.setShort(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOShort
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDOShort(buff)^ := AValue;
+end;
+
+procedure TSDOShortField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  setShort(ABuffer,AOffset,TSDOConvertHelper.StringtoShort(AValue));
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOShortField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setShort(ABuffer,AOffset,AValue);
+end;
+
+{ TSDOBytesField }
+
+procedure TSDOBytesField.FreeBuffer(const ABuffer: TSDOFieldBuffer);
+var
+  rawBuffer : PByte;
+  valBuffer : PPSDOBytes;
+begin
+  rawBuffer := PByte(ABuffer);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    Inc(rawBuffer);
+    valBuffer := PPSDOBytes(rawBuffer);
+    SetLength(valBuffer^^,0);
+    FreeMem(valBuffer^,SizeOf(PPSDOBytes));
+    valBuffer^ := nil;
+    Dec(rawBuffer);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,False);
+  end;
+end;
+
+function TSDOBytesField.getBytes(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOBytes;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := nil;
+  end else begin
+    if IsBitON(buff^,BIT_ORDER_BUFFER) then begin
+      Inc(buff);
+      Result := Copy(PPSDOBytes(buff)^^);
+    end else begin
+      Result := nil;
+    end;
+  end;
+end;
+
+function TSDOBytesField.getString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.BytesToString(getBytes(ABuffer,AOffset));
+end;
+
+function TSDOBytesField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getBytes(ABuffer,AOffset);
+end;
+
+procedure TSDOBytesField.setBytes(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+        AValue: TSDOBytes
+);
+var
+  rawBuffer : PByte;
+  valBuffer : PPSDOBytes;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  SetBit(rawBuffer^,BIT_ORDER_SET,True);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    Inc(rawBuffer);
+    valBuffer := PPSDOBytes(rawBuffer);
+  end else begin;
+    SetBit(rawBuffer^,BIT_ORDER_NULL,False);
+    SetBit(rawBuffer^,BIT_ORDER_BUFFER,True);
+    Inc(rawBuffer);
+    valBuffer := PPSDOBytes(rawBuffer);
+    GetMem(valBuffer^,SizeOf(PPSDOBytes));
+    FillChar(valBuffer^^,SizeOf(TSDOBytes),#0);
+  end;
+  valBuffer^^ := Copy(AValue);
+end;
+
+procedure TSDOBytesField.setNull(const ABuffer: TSDOFieldBuffer; const AOffset: PtrUInt);
+var
+  rawBuffer : PByte;
+begin
+  rawBuffer := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(rawBuffer,AOffset);
+  if IsBitON(rawBuffer^,BIT_ORDER_BUFFER) then begin
+    FreeBuffer(rawBuffer);
+  end;
+  inherited setNull(ABuffer,AOffset);
+end;
+
+procedure TSDOBytesField.setString(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOString
+);
+begin
+  setBytes(ABuffer,AOffset,TSDOConvertHelper.StringToBytes(AValue));
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_DOUBLE}
+function TSDODoubleField.getString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.FloatToString(getDouble(ABuffer,AOffset));
+end;
+
+procedure TSDODoubleField.setString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOString
+);
+begin
+  setDouble(ABuffer,AOffset,TSDOConvertHelper.StringToFloat(AValue));
+end;
+
+function TSDODoubleField.getDouble(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDODouble;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := 0;
+  end else begin
+    Inc(buff);
+    Result := PSDODouble(buff)^;
+  end;
+end;
+
+procedure TSDODoubleField.setDouble(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDODouble
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDODouble(buff)^ := AValue;
+end;
+
+function TSDODoubleField.getCurrency(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOCurrency;
+begin
+  Result := getDouble(ABuffer,AOffset);
+end;
+
+procedure TSDODoubleField.setCurrency(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOCurrency
+);
+begin
+  setDouble(ABuffer,AOffset,AValue);
+end;
+
+function TSDODoubleField.getFloat(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOFloat;
+begin
+  Result := getDouble(ABuffer,AOffset);
+end;
+
+procedure TSDODoubleField.setFloat(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOFloat
+);
+begin
+  setDouble(ABuffer,AOffset,AValue);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+function TSDOFloatField.getString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOString;
+begin
+  Result := TSDOConvertHelper.FloatToString(getFloat(ABuffer,AOffset));
+end;
+
+procedure TSDOFloatField.setString(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOString
+);
+begin
+  setFloat(ABuffer,AOffset,TSDOConvertHelper.StringToFloat(AValue));
+end;
+
+function TSDOFloatField.getFloat(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOFloat;
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  if IsBitON(buff^,BIT_ORDER_NULL) then begin
+    Result := 0;
+  end else begin
+    Inc(buff);
+    Result := PSDOFloat(buff)^;
+  end;
+end;
+
+procedure TSDOFloatField.setFloat(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOFloat
+);
+var
+  buff : PByte;
+begin
+  buff := PByte(ABuffer);
+  if ( AOffset <> 0 ) then
+    Inc(buff,AOffset);
+  SetBit(buff^,BIT_ORDER_SET,True);
+  SetBit(buff^,BIT_ORDER_NULL,False);
+  Inc(buff);
+  PSDOFloat(buff)^ := AValue;
+end;
+
+function TSDOFloatField.getCurrency(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDOCurrency;
+begin
+  Result := getFloat(ABuffer,AOffset);
+end;
+
+procedure TSDOFloatField.setCurrency(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDOCurrency
+);
+begin
+  setFloat(ABuffer,AOffset,AValue);
+end;
+
+function TSDOFloatField.getDouble(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt
+) : TSDODouble;
+begin
+  Result := getFloat(ABuffer,AOffset);
+end;
+
+procedure TSDOFloatField.setDouble(
+  const ABuffer : TSDOFieldBuffer;
+  const AOffset : PtrUInt;
+  const AValue : TSDODouble
+);
+begin
+  setFloat(ABuffer,AOffset,AValue);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$WARNINGS OFF}
+function TSDOBaseField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+
+procedure TSDOBaseField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  raise ESDOInvalidConversionException.Create(ClassName);
+end;
+{$WARNINGS ON}
+
+procedure TSDOBytesField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setBytes(ABuffer,AOffset,AValue);
+end;
+
+function TSDOCurrencyField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getCurrency(ABuffer,AOffset);
+end;
+
+procedure TSDOCurrencyField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setCurrency(ABuffer,AOffset,AValue);
+end;
+
+function TSDODoubleField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getDouble(ABuffer,AOffset);
+end;
+
+procedure TSDODoubleField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+ if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setDouble(ABuffer,AOffset,AValue);
+end;
+
+function TSDOFloatField.getVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt
+) : TSDOVariant;
+begin
+  if isNull(ABuffer,AOffset) then
+    Result := Null
+  else
+    Result := getFloat(ABuffer,AOffset);
+end;
+
+procedure TSDOFloatField.setVariant(
+  const ABuffer: TSDOFieldBuffer;
+  const AOffset: PtrUInt;
+  const AValue: TSDOVariant
+);
+begin
+  if isNull(ABuffer,AOffset) then
+    setNull(ABuffer,AOffset)
+  else
+    setFloat(ABuffer,AOffset,AValue);
+end;
+
+initialization
+  PrepareMap();
+
+finalization
+  UnprepareMap();
+  
+end.

+ 188 - 0
packages/fcl-sdo/src/base/sdo_fpc_xml.pas

@@ -0,0 +1,188 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements XML DOM handling utilities
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_fpc_xml;
+
+interface
+
+uses
+  Classes, SysUtils, DOM;
+
+type
+
+  { TDOMNodeSelectListImp }
+
+  TDOMNodeSelectListImp = class(TDOMNodeList)
+  private
+    FFilter: DOMString;
+    FUseFilter: Boolean;
+  protected
+    procedure BuildList(); override;
+  public
+    constructor Create(ANode: TDOMNode; const AFilter: DOMString);
+  end;
+
+  function FilterList(const ANode : TDOMNode; const ANodeName : DOMString) : TDOMNodeList ;
+  function SelectSingleNode(
+    const AXPathExpression : DOMString;
+    const AContextNode     : TDOMNode;
+    const AErrorIfMore     : Boolean
+  ) : TDOMNode;
+
+
+  function GetNodeItemsCount(const ANode : TDOMNode): Integer;
+  function GetNodeListCount(ANodeList : TDOMNodeList) : Integer ;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function GetNodeListCount(ANodeList : TDOMNamedNodeMap) : Integer ;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  procedure ReleaseDomNode(ADomNode : TDOMNode);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  procedure ReleaseDomNode(ADomNode : TDOMNodeList);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  procedure ReleaseDomNode(ADomNode : TDOMNamedNodeMap);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function CreateDoc() : TXMLDocument ;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function FindNode(ANode : TDOMNode;const ANodeName : string) : TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+  function NodeToBuffer(ANode : TDOMNode):string ;
+  
+resourcestring
+  SERR_NoNodeXpathExpression = 'This XPath expression does not correspond to node(s) : %s.';
+  SERR_XpathExpectingOneNode = 'Xpath expression expecting a single node while got %d node : %s.';
+
+implementation
+uses
+  XMLWrite, xpath;
+
+function GetNodeItemsCount(const ANode : TDOMNode): Integer;
+var
+  n: TDOMNode;
+begin
+  n := ANode.FirstChild;
+  Result := 0;
+  while Assigned(n) do
+  begin
+    Inc(Result);
+    n := n.NextSibling;
+  end;
+end;
+
+function GetNodeListCount(ANodeList : TDOMNodeList) : Integer ;overload;
+begin
+  Result := ANodeList.Count;
+end;
+
+function GetNodeListCount(ANodeList : TDOMNamedNodeMap) : Integer ;overload;
+begin
+  Result := ANodeList.Length;
+end;
+
+procedure ReleaseDomNode(ADomNode : TDOMNode);overload;
+begin
+  ADomNode.Free();
+end;
+
+procedure ReleaseDomNode(ADomNode : TDOMNodeList);overload;
+begin
+{ $IFNDEF TDOMNodeList_RELEASE_NOT_FREE}
+  ADomNode.Free();
+{ $ENDIF}
+end;
+
+procedure ReleaseDomNode(ADomNode : TDOMNamedNodeMap);overload;
+begin
+  ADomNode.Free();
+end;
+
+function CreateDoc() : TXMLDocument ;
+begin
+  Result := TXMLDocument.Create();
+{$IF ((FPC_VERSION = 2) and (FPC_RELEASE = 6)) }  
+  Result.Encoding := 'UTF-8';
+{$IFEND}  
+end;
+
+function FindNode(ANode : TDOMNode;const ANodeName : string) : TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  Result := ANode.FindNode(ANodeName);
+end;
+
+function NodeToBuffer(ANode : TDOMNode):string ;
+var
+  locStream : TStringStream;
+begin
+  locStream := TStringStream.Create('');
+  try
+    WriteXML(ANode,locStream);
+    Result := locStream.DataString;
+  finally
+    locStream.Free();
+  end;
+end;
+
+function FilterList(const ANode : TDOMNode; const ANodeName : DOMString) : TDOMNodeList ;
+begin
+  Result := TDOMNodeSelectListImp.Create(ANode,ANodeName);
+end;
+
+function SelectSingleNode(
+  const AXPathExpression : DOMString;
+  const AContextNode     : TDOMNode;
+  const AErrorIfMore     : Boolean
+) : TDOMNode;
+var
+  xp_res : TXPathVariable;
+  ns : TNodeSet;
+begin
+  Result := nil;
+  xp_res := EvaluateXPathExpression(AXPathExpression,AContextNode);
+  if ( xp_res <> nil ) then begin
+    if not xp_res.InheritsFrom(TXPathNodeSetVariable) then
+      raise Exception.CreateFmt(SERR_NoNodeXpathExpression,[AXPathExpression]);
+    ns := xp_res.AsNodeSet;
+    if ( ns <> nil ) and ( ns.Count > 0 ) then begin
+      if AErrorIfMore and ( ns.Count > 1 ) then
+        raise Exception.CreateFmt(SERR_XpathExpectingOneNode,[ns.Count,AXPathExpression]);
+      Result := TDOMNode(ns[0]);
+    end;
+  end;
+end;
+
+{ TDOMNodeSelectListImp }
+
+type
+  TDOMNodeCracked = class(TDOMNode);
+procedure TDOMNodeSelectListImp.BuildList();
+var
+  Child: TDOMNode;
+begin
+  FList.Clear;
+  FRevision := TDOMNodeCracked(FNode).GetRevision();
+
+  Child := FNode.FirstChild;
+  while ( Child <> nil ) do begin
+    if ( Child.NodeType = ELEMENT_NODE ) and
+       ( ( not FUseFilter ) or ( TDOMElement(Child).TagName = FFilter ) )
+    then begin
+      FList.Add(Child);
+    end;
+    Child := Child.NextSibling
+  end;
+end;
+
+constructor TDOMNodeSelectListImp.Create(ANode: TDOMNode; const AFilter: DOMString);
+begin
+  inherited Create(ANode);
+  FFilter := AFilter;
+  FUseFilter := ( FFilter <> '*' );
+end;
+
+end.

+ 63 - 0
packages/fcl-sdo/src/base/sdo_global.inc

@@ -0,0 +1,63 @@
+{$WARNINGS OFF}
+
+  {$IFDEF FPC}
+    {$mode objfpc}{$H+}
+    {$DEFINE HAS_QWORD}
+    {$DEFINE ATT_PROC_ADDRESS}
+    {$DEFINE HAS_UNICODE}  
+    {$IF Defined(FPC_RELEASE) and (FPC_RELEASE > 0) }
+      {$define FCL_HAS_TDOMElementList}
+      {$IF Defined(FPC_VERSION) and (FPC_RELEASE >= 5) }
+        {$DEFINE HAS_CURR_TO_STR_SETTINGS}
+      {$IFEND}
+    {$IFEND}
+    {$DEFINE USE_INLINE}
+  {$ELSE}
+    {$UNDEF HAS_QWORD}
+    {$UNDEF USE_INLINE}
+    {$UNDEF ATT_PROC_ADDRESS}
+    {$DEFINE DELPHI}
+    {$DEFINE INTF_DOM}
+    {$IFDEF VER200}
+      {$DEFINE HAS_UNICODE}
+    {$ENDIF}
+    {$IFDEF VER210}
+      {$DEFINE HAS_UNICODE}
+    {$ENDIF}     
+    {$IFDEF VER220} //DelphiXE
+      {$DEFINE HAS_UNICODE}
+    {$ENDIF}
+    {$IF Defined(CompilerVersion) and (CompilerVersion >= 20)}
+      {$DEFINE HAS_UNICODE}
+    {$IFEND}
+    {$IF Defined(CompilerVersion) and (CompilerVersion < 23)}
+      {$DEFINE WINDOWS}
+    {$IFEND}
+    {$IFDEF MSWINDOWS}
+      {$DEFINE WINDOWS}
+    {$ENDIF}
+    {$IFDEF HAS_UNICODE}
+      {$DEFINE DEFAULT_UNICODE}
+    {$ENDIF}
+  {$ENDIF}
+
+{$WARNINGS ON}
+
+{$UNDEF EQUALITY_USE_SET_NULL}
+{$DEFINE TEST_GENERATE_FILE}
+
+{$DEFINE HAS_SDO_BYTES}
+{$DEFINE HAS_SDO_CHAR}
+{$DEFINE HAS_SDO_DOUBLE}
+{$DEFINE HAS_SDO_FLOAT}
+{$DEFINE HAS_SDO_LONG}
+{$DEFINE HAS_SDO_SHORT}
+{$DEFINE HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_UNICODE}
+  {$DEFINE USE_UNICODE}
+  {$IFDEF DELPHI}
+    {$DEFINE HAS_CP_STRING}
+  {$ENDIF}
+{$ENDIF}
+

+ 358 - 0
packages/fcl-sdo/src/base/sdo_imp_utils.pas

@@ -0,0 +1,358 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit contains some implementation utilities
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_imp_utils;
+
+interface
+uses
+  SysUtils, Classes,
+  sdo_types, sdo;
+
+type
+
+  TBitOrder = 0..7;
+
+  TStringInterfaceItem = class
+  private
+    FIntf : IInterface;
+  public
+    constructor Create(const AIntf : IInterface);
+    destructor Destroy();override;
+    property Intf : IInterface read FIntf write FIntf;
+  end;
+
+  TStringInterfaceList = class
+  private
+    FList : TStringList;
+  private
+    function GetCount: PtrInt;
+    function GetIntf(const AIndex: PtrInt): IInterface;
+    function GetString(const AIndex: PtrInt): string;
+    procedure SetIntf(const AIndex: PtrInt; const Value: IInterface);
+    procedure SetString(const AIndex: PtrInt; const Value: string);
+  public
+    constructor Create();
+    destructor Destroy();override;
+    function Add(const AString : string) : PtrInt;overload;
+    function Add(const AString : string; const AIntf : IInterface) : PtrInt;overload;
+    procedure Delete(const AIndex : PtrInt);
+    procedure Clear();
+    function IndexOf(const AString : string) : PtrInt;overload;
+    function IndexOf(const AIntf : IInterface) : PtrInt;overload;
+    property Count : PtrInt read GetCount;
+    property Strings[const AIndex : PtrInt] : string read GetString write SetString;
+    property Intf[const AIndex : PtrInt] : IInterface read GetIntf write SetIntf;
+  end;
+
+  function IsStrEmpty(const AStr : AnsiString) : Boolean; overload; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function GetNextToken(var AStr : AnsiString; const ASeparator : AnsiChar) : AnsiString;overload;
+{$IFDEF HAS_UNICODE}
+  function IsStrEmpty(const AStr : UnicodeString) : Boolean; overload; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function GetNextToken(var AStr : UnicodeString; const ASeparator : AnsiChar) : UnicodeString;overload; {$IFDEF USE_INLINE}inline;{$ENDIF}
+  function GetNextToken(var AStr : UnicodeString; const ASeparator : UnicodeChar) : UnicodeString;overload;
+{$ENDIF HAS_UNICODE}    
+  function StringToVarBytes(const AValue : string) : TSDOBytes;
+  function StreamToVarBytes(const AValue : TStream) : TSDOBytes; overload;
+  function StreamToVarBytes(const AValue : TMemoryStream) : TSDOBytes; overload;
+  function ExtractLocalName(const AValue : string; const ASeparator : string = ':') : string ;
+  function IsValidName(const AStr : string) : Boolean;
+
+  function IsBitON(const AData : Byte; const ABit : TBitOrder) : Boolean ;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  procedure SetBit(var AData : Byte; const ABit : TBitOrder; const AValue : Boolean);{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+implementation
+
+
+function IsValidName(const AStr : string) : Boolean;
+var
+  i, c : PtrInt;
+begin
+  Result := False;
+  c := Length(AStr);
+  if ( c > 0 ) then begin
+    if ( AStr[1] in ['_', 'a'..'z', 'A'..'Z'] ) then begin
+      Result := True;
+      i := 2;
+      while ( i <= c ) do begin
+        if not ( AStr[i] in ['_', 'a'..'z', 'A'..'Z', '0'..'9'] ) then begin
+          Result := False;
+          Break;
+        end;
+        Inc(i);
+      end;
+    end;
+  end;
+end;
+
+function GetNextToken(var AStr : AnsiString; const ASeparator : AnsiChar) : AnsiString;
+var
+  j, i, l : PtrInt;
+begin
+  l := Length(AStr);
+  i := 1;
+  while ( i <= l ) and ( AStr[i] = ASeparator ) do begin
+    Inc(i);
+  end;
+  j := i;
+  while ( i <= l ) and ( AStr[i] <> ASeparator ) do begin
+    Inc(i);
+  end;
+  Result := Copy(AStr, j, ( i - j ));
+  if ( i = l ) then
+    AStr := ''
+  else
+    Delete(AStr, 1, i);
+end;
+
+function IsStrEmpty(const AStr : AnsiString) : Boolean;
+begin
+  Result := ( Length(Trim(AStr)) = 0 )
+end;
+
+{$IFDEF HAS_UNICODE}
+function IsStrEmpty(const AStr : UnicodeString) : Boolean;
+begin
+  Result := ( Length(Trim(AStr)) = 0 )
+end; 
+
+function GetNextToken(var AStr : UnicodeString; const ASeparator : UnicodeChar) : UnicodeString;
+var
+  j, i, l : PtrInt;
+begin
+  l := Length(AStr);
+  i := 1;
+  while ( i <= l ) and ( AStr[i] = ASeparator ) do begin
+    Inc(i);
+  end;
+  j := i;
+  while ( i <= l ) and ( AStr[i] <> ASeparator ) do begin
+    Inc(i);
+  end;
+  Result := Copy(AStr, j, ( i - j ));
+  if ( i = l ) then
+    AStr := ''
+  else
+    Delete(AStr, 1, i);
+end;           
+
+function GetNextToken(var AStr : UnicodeString; const ASeparator : AnsiChar) : UnicodeString;
+begin
+  Result := GetNextToken(AStr,UnicodeChar(ASeparator));
+end;
+
+{$ENDIF}  
+
+function StringToVarBytes(const AValue : string) : TSDOBytes;
+var
+  c : Integer;
+begin
+  c := Length(AValue) * SizeOf(Char);
+  SetLength(Result,c);
+  if ( c > 0 ) then
+    Move(AValue[1],Result[Low(Result)],c);
+end;
+
+function StreamToVarBytes(const AValue : TStream) : TSDOBytes;
+var
+  locOldPos : Int64;
+begin
+  if (AValue = nil) or (AValue.Size < 1) then begin
+    Result := nil;
+  end else begin
+    SetLength(Result,AValue.Size);
+    locOldPos := AValue.Position;
+    try
+      AValue.Position := 0;
+      AValue.Read(Result[0],AValue.Size);
+    finally
+      AValue.Position := locOldPos;
+    end;
+  end;
+end;
+
+function StreamToVarBytes(const AValue : TMemoryStream) : TSDOBytes;
+begin
+  if (AValue = nil) or (AValue.Size < 1) then begin
+    Result := nil
+  end else begin
+    SetLength(Result,AValue.Size);
+    Move(AValue.Memory^,Result[0],AValue.Size);
+  end;
+end;
+
+function IsBitON(const AData : Byte; const ABit : TBitOrder) : Boolean ;
+begin
+  Result := ( ( AData and ( 1 shl ABit ) ) <> 0 );
+end;
+
+procedure SetBit(var AData : Byte; const ABit : TBitOrder; const AValue : Boolean);
+begin
+  if AValue then
+    AData := AData or (1 shl (ABit mod 8))
+  else
+    AData := AData and ( not ( 1 shl ( ABit mod 8 ) ) );
+end;
+
+{function IntPower(const ABase, AExponent : Byte) : Byte;
+var
+  i : Integer;
+begin
+  if ( AExponent = 0 ) or ( ABase = 1 ) then begin
+    Result := 1
+  end else begin
+    if ( ABase = 0 ) then begin
+      Result := 0;
+    end else begin
+      Result := 1;
+      for i := 0 to Pred(AExponent) do begin
+        Result := Result * ABase;
+      end;
+    end;
+  end;
+end; }
+
+function ExtractLocalName(const AValue : string; const ASeparator : string) : string ;
+var
+  i : PtrInt;
+begin
+  i := AnsiPos(ASeparator,AValue);
+  if ( i < 0 ) then
+    i := 0;
+  Inc(i);
+  Result := Copy(AValue,i,Length(AValue));
+end;
+
+{ TStringInterfaceList }
+
+function TStringInterfaceList.Add(const AString: string): PtrInt;
+begin
+  Result := Add(AString,nil);
+end;
+
+function TStringInterfaceList.Add(const AString: string; const AIntf: IInterface): PtrInt;
+begin
+  Result := IndexOf(AString);
+  if ( Result = -1 ) then
+    Result := FList.AddObject(AString,TStringInterfaceItem.Create(AIntf as IInterface))
+  else
+    TStringInterfaceItem(FList.Objects[Result]).Intf := AIntf as IInterface;
+end;
+
+procedure TStringInterfaceList.Clear();
+var
+  i, c : PtrInt;
+  tmp : TObject;
+begin
+  c := FList.Count;
+  if ( c > 0 ) then begin
+    FList.BeginUpdate();
+    try
+      for i := Pred(c) downto 0 do begin
+        tmp := FList.Objects[i];
+        FList.Delete(i);
+        tmp.Free();
+      end;
+    finally
+      FList.EndUpdate();
+    end;
+  end;
+end;
+
+constructor TStringInterfaceList.Create();
+begin
+  inherited;
+  FList := TStringList.Create();
+  FList.Sorted := True;
+  FList.Duplicates := dupError;
+end;
+
+procedure TStringInterfaceList.Delete(const AIndex: PtrInt);
+var
+  tmp : TObject;
+begin
+  tmp := FList.Objects[AIndex];
+  FList.Delete(AIndex);
+  tmp.Free();
+end;
+
+destructor TStringInterfaceList.Destroy;
+begin
+  if ( FList <> nil ) then
+    Clear();
+  FreeAndNil(FList);
+  inherited;
+end;
+
+function TStringInterfaceList.GetCount: PtrInt;
+begin
+  Result := FList.Count;
+end;
+
+function TStringInterfaceList.GetIntf(const AIndex: PtrInt): IInterface;
+begin
+  Result := TStringInterfaceItem(FList[AIndex]).Intf;
+end;
+
+function TStringInterfaceList.GetString(const AIndex: PtrInt): string;
+begin
+  Result := FList[AIndex];
+end;
+
+function TStringInterfaceList.IndexOf(const AIntf: IInterface): PtrInt;
+var
+  c, i : PtrInt;
+begin
+  Result := -1;
+  c := Count;
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      if ( Intf[i] = AIntf ) then begin
+        Result := i;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+function TStringInterfaceList.IndexOf(const AString: string): PtrInt;
+begin
+  Result := FList.IndexOf(AString);
+end;
+
+procedure TStringInterfaceList.SetIntf(const AIndex: PtrInt; const Value: IInterface);
+begin
+  TStringInterfaceItem(FList.Objects[AIndex]).Intf := Value as IInterface;
+end;
+
+procedure TStringInterfaceList.SetString(const AIndex: PtrInt; const Value: string);
+begin
+  FList.Strings[AIndex] := Value;
+end;
+
+{ TStringInterfaceItem }
+
+constructor TStringInterfaceItem.Create(const AIntf: IInterface);
+begin
+  FIntf := AIntf;
+end;
+
+destructor TStringInterfaceItem.Destroy();
+begin
+  FIntf := nil;
+  inherited;
+end;
+
+end.

+ 593 - 0
packages/fcl-sdo/src/base/sdo_linked_list.pas

@@ -0,0 +1,593 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a doubly linked list.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{$INCLUDE sdo_global.inc}
+{$RANGECHECKS OFF}
+unit sdo_linked_list;
+
+interface
+uses
+  SysUtils, Classes, Types,
+  sdo_types;
+
+type
+
+  EListException = class(Exception);
+
+  PLinkedNode = ^TLinkedNode;
+  TLinkedNode = packed record
+    Previous :PLinkedNode;
+    Next : PLinkedNode;
+    Data : array[0..0] of Byte;
+  end;
+
+  TMoveType = ( mtRelative, mtAbsolute );
+  TLinkedListBookmark = TByteDynArray;//type TStringBufferType;
+  ILinkedListCursor = interface
+    ['{10586C3A-E8C9-4E68-A338-1605ECEB5C31}']
+    function IsPosValid() : Boolean;
+    function Eof() : Boolean;
+    function Bof() : Boolean;
+    function GetCurrent() : PLinkedNode;
+    function MoveNext() : Boolean;
+    function MovePrevious() : Boolean;
+    function MoveFirst() : Boolean;
+    function MoveLast() : Boolean;
+    function GetPosition({the position is zero-based}) : PtrInt;
+    function MoveTo(const APosition{the position is zero-based} : PtrInt) : Boolean;
+    procedure Reset();
+    function GetBookmark() : TLinkedListBookmark;
+    function GotoBookmark(const ABookmark : TLinkedListBookmark) : Boolean;
+    //function Clone() : ILinkedListCursor;
+  end;
+
+  TNotifyReason = ( nrDelete, nrNew, nrDestroy );
+  ILinkedListNotify = interface
+    ['{D53E46B0-8709-4662-B91E-0D746828A27C}']
+    procedure Notify(const AReason : TNotifyReason; const ANode : PLinkedNode);
+  end;
+
+  TDoubleLinkedList = class
+  private
+    FGeneration : PtrUInt;
+    FCount : PtrInt;
+    FDataSize : PtrInt;
+    FItemSize : PtrInt;
+    FFirst : PLinkedNode;
+    FLast : PLinkedNode;
+    FNotifyList : IInterfaceList;
+  private
+    function AllocateBuffer() : PLinkedNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure Notify(const AReason : TNotifyReason; const ANode : PLinkedNode);
+  public
+    constructor Create(const ADataSize : PtrInt);
+    destructor Destroy();override;
+    procedure RegisterForNotification(const AListener : ILinkedListNotify);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure UnregisterForNotification(const AListener : ILinkedListNotify);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure FreeBuffer(const AItem : PLinkedNode);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure Clear();
+    function GetLength() : PtrInt;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function IsEmpty() : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetFirst() : PLinkedNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetLast() : PLinkedNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function InsertFirst() : PLinkedNode;
+    function Append() : PLinkedNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function InsertBefore(const AItem : PLinkedNode) : PLinkedNode;
+    function InsertAfter(const AItem : PLinkedNode) : PLinkedNode;
+    //remove links, do not delete the buffer
+    procedure Remove(const AItem : PLinkedNode);
+    //remove links, delete the buffer
+    procedure Delete(const AItem : PLinkedNode);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    property DataSize : PtrInt read FDataSize;
+    property Generation : PtrUInt read FGeneration;
+  end;
+
+
+  function CreateIterator(AList : TDoubleLinkedList) : ILinkedListCursor;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  function GetData(const ANode : PLinkedNode) : Pointer ;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+implementation
+
+type
+  TLinkedListBookmarkRecord = packed record
+    _Data : TDoubleLinkedList;
+    _Node : PLinkedNode;
+    _Generation : PtrUInt;
+    _Position : PtrInt;
+  end;
+
+const
+  BOOKMARK_SIZE = SizeOf(TLinkedListBookmarkRecord);
+
+type
+
+  TLinkedListIterator = class(
+    TInterfacedObject,
+    IInterface,
+    ILinkedListNotify,
+    ILinkedListCursor
+  )
+  private
+    FData : TDoubleLinkedList;
+    FCurrent : PLinkedNode;
+    FPosition : PtrInt;
+  protected
+    // -- IDoubleLinkedList
+    function IsPosValid() : Boolean;
+    function Eof() : Boolean;
+    function Bof() : Boolean;
+    function GetCurrent() : PLinkedNode;
+    function MoveNext() : Boolean;
+    function MovePrevious() : Boolean;
+    function MoveFirst() : Boolean;
+    function MoveLast() : Boolean;
+    function MoveTo(const APosition{the position is zero-based} : PtrInt) : Boolean;
+    procedure Reset();
+    function GetBookmark() : TLinkedListBookmark;
+    function GotoBookmark(const ABookmark : TLinkedListBookmark) : Boolean;
+    function GetPosition({the position is zero-based}) : PtrInt;
+    function Clone() : ILinkedListCursor;
+    // -- ILinkedListNotify
+    procedure Notify(const AReason : TNotifyReason; const ANode : PLinkedNode);
+  public
+    constructor Create(AData : TDoubleLinkedList);
+    destructor Destroy();override;
+  end;
+
+function CreateIterator(AList : TDoubleLinkedList) : ILinkedListCursor;
+begin
+  Result := TLinkedListIterator.Create(AList) as ILinkedListCursor;
+end;
+
+function GetData(const ANode : PLinkedNode) : Pointer ;
+begin
+  Result := @(ANode^.Data[0]);
+end;
+
+{ TSDOLinkedList }
+
+function TDoubleLinkedList.InsertBefore(const AItem : PLinkedNode): PLinkedNode;
+begin
+  if Assigned(AItem) then begin
+    Result := AllocateBuffer();
+    Result^.Previous := AItem^.Previous;
+    if Assigned(AItem^.Previous) then
+      AItem^.Previous^.Next := Result
+    else
+      FFirst := Result;
+    Result^.Next := AItem;
+    AItem^.Previous := Result;
+    Inc(FCount);
+    Notify(nrNew,Result);
+  end else begin
+    raise EListException.Create('Invalid parameter.');
+  end;
+end;
+
+procedure TDoubleLinkedList.Clear();
+begin
+  while ( FCount > 0 ) do begin
+    Delete(GetFirst());
+  end;
+end;
+
+constructor TDoubleLinkedList.Create(const ADataSize : PtrInt);
+begin
+  if ( ADataSize < 1 ) then
+    raise EListException.CreateFmt('Invalid Data size : %d.',[ADataSize]);
+  inherited Create();
+  FDataSize := ADataSize;
+  FItemSize :=
+    SizeOf(PLinkedNode) + //Previous
+    SizeOf(PLinkedNode) + //Next
+    FDataSize;
+  FNotifyList := TInterfaceList.Create() as IInterfaceList;
+end;
+
+procedure TDoubleLinkedList.Delete(const AItem : PLinkedNode);
+begin
+  Remove(AItem);
+  FreeBuffer(AItem);
+end;
+
+destructor TDoubleLinkedList.Destroy();
+begin
+  if ( FNotifyList <> nil ) then begin
+    Notify(nrDestroy,nil);
+    FNotifyList.Clear();
+  end;
+  Clear();
+  FNotifyList := nil;
+  inherited;
+end;
+
+function TDoubleLinkedList.GetFirst() : PLinkedNode;
+begin
+  if ( GetLength() > 0 ) then
+    Result := FFirst
+  else
+    raise EListException.Create('The list is empty.');
+end;
+
+function TDoubleLinkedList.GetLength(): PtrInt;
+begin
+  Result := FCount;
+end;
+
+function TDoubleLinkedList.IsEmpty() : Boolean;
+begin
+  Result := ( FCount = 0 );
+end;
+
+function TDoubleLinkedList.GetLast() : PLinkedNode;
+begin
+  if ( GetLength() > 0 ) then
+    Result := FLast
+  else
+    raise EListException.Create('The list is empty.');
+end;
+
+procedure TDoubleLinkedList.Remove(const AItem : PLinkedNode);
+begin
+  if ( AItem = nil ) then
+    raise EListException.Create('Invalid parameter.');
+  if Assigned(AItem^.Previous) then begin
+    AItem^.Previous^.Next := AItem^.Next;
+  end else begin
+    FFirst := AItem^.Next;
+    if Assigned(FFirst) then
+      FFirst^.Previous := nil;
+  end;
+
+  if Assigned(AItem^.Next) then begin
+    AItem^.Next^.Previous := AItem^.Previous;
+  end else begin
+    FLast := AItem^.Previous;
+    if Assigned(FLast) then
+      FLast^.Next := nil;
+  end;
+  Dec(FCount);
+  Notify(nrDelete,AItem);
+end;
+
+{ TLinkedListIterator }
+
+function TLinkedListIterator.Bof() : Boolean;
+begin
+  //Result := FData.IsEmpty() or ( FCurrent = FData.GetFirst() );
+  Result := FData.IsEmpty() or ( FPosition = 0 );
+end;
+
+function TLinkedListIterator.Clone() : ILinkedListCursor;
+var
+  bm : TLinkedListBookmark;
+begin
+  Result := TLinkedListIterator.Create(FData);
+  bm := GetBookmark();
+  Result.GotoBookmark(bm);
+end;
+
+constructor TLinkedListIterator.Create(AData: TDoubleLinkedList);
+var
+  selfNotify : ILinkedListNotify;
+begin
+  if ( AData = nil ) then
+    raise EListException.Create('Invalid parameter.');
+  inherited Create();
+  FData := AData;
+  selfNotify := Self as ILinkedListNotify;
+  FData.RegisterForNotification(selfNotify);
+  Reset();
+end;
+
+destructor TLinkedListIterator.Destroy();
+var
+  selfNotify : ILinkedListNotify;
+begin
+  if ( FData <> nil ) then begin
+    selfNotify := Self as ILinkedListNotify;
+    FData.UnregisterForNotification(selfNotify);
+  end;
+  FData := nil;
+  FCurrent := nil;
+  inherited;
+end;
+
+function TLinkedListIterator.Eof() : Boolean;
+begin
+  Result := FData.IsEmpty() or (FPosition = FData.GetLength());
+end;
+
+function TLinkedListIterator.GetBookmark(): TLinkedListBookmark;
+var
+  rec : TLinkedListBookmarkRecord;
+begin
+  rec._Data := FData;
+  rec._Node := FCurrent;
+  rec._Generation := FData.Generation;
+  rec._Position := FPosition;
+  SetLength(Result,BOOKMARK_SIZE);
+  Move(rec,Pointer(Result)^,BOOKMARK_SIZE);
+end;
+
+function TLinkedListIterator.GetCurrent() : PLinkedNode;
+begin
+  Result := FCurrent;
+end;
+
+function TLinkedListIterator.GetPosition() : PtrInt;
+begin
+  if FData.IsEmpty() then begin
+    Result := FPosition
+  end else begin
+    if (FPosition >= FData.GetLength()) then
+      Result := (FPosition - 1)
+    else
+      Result := FPosition;
+  end;
+end;
+
+function TLinkedListIterator.GotoBookmark(const ABookmark: TLinkedListBookmark): Boolean;
+var
+  rec : TLinkedListBookmarkRecord;
+begin
+  Result := False;
+  if ( Length(ABookmark) = BOOKMARK_SIZE ) then begin
+    Move(Pointer(ABookmark)^,rec,BOOKMARK_SIZE);
+    if ( rec._Data = FData ) and ( rec._Generation = FData.Generation ) then begin
+      FCurrent := rec._Node;
+      FPosition := rec._Position;
+      Result := True;
+    end;
+  end;
+end;
+
+function TLinkedListIterator.IsPosValid() : Boolean;
+begin
+  Result := Assigned(FCurrent) and ( not FData.IsEmpty() );
+end;
+
+function TLinkedListIterator.MoveFirst() : Boolean;
+begin
+  Reset();
+  Result := MoveNext();
+end;
+
+function TLinkedListIterator.MoveLast() : Boolean;
+begin
+  if FData.IsEmpty() then begin
+    Result := False;
+  end else begin
+    FCurrent := FData.GetLast();
+    Result := True;
+  end;
+  if Result then
+    FPosition := FData.GetLength()// - 1;
+end;
+
+function TLinkedListIterator.MoveNext() : Boolean;
+begin
+  if ( FCurrent = nil ) then begin
+    if FData.IsEmpty() then begin
+      Result := False;
+    end else begin
+      FCurrent := FData.GetFirst();
+      Result := True;
+    end;
+  end else begin
+    if ( FCurrent = FData.GetLast() ) then begin
+      FPosition := FData.GetLength();
+      Result := False;
+    end else begin
+      FCurrent := FCurrent^.Next;
+      Result := True;
+    end;
+  end;
+  if Result then
+    Inc(FPosition);
+end;
+
+function TLinkedListIterator.MovePrevious() : Boolean;
+begin
+  if ( FCurrent = nil ) or
+     FData.IsEmpty() or
+     ( FCurrent = FData.GetFirst() )
+  then begin
+    Result := False;
+  end else begin
+    FCurrent := FCurrent^.Previous;
+    Result := True;
+  end;
+  if Result then begin
+    if (FPosition = FData.GetLength()) then
+      Dec(FPosition);
+    Dec(FPosition);
+  end;
+end;
+
+function TLinkedListIterator.MoveTo(const APosition: PtrInt): Boolean;
+var
+  oldPos : TLinkedListBookmark;
+  d1, d2, idx : PtrInt;
+  neg : Boolean;
+begin
+  Result := False;
+  if (APosition < 0) then
+    Exit;
+  if FData.IsEmpty() then
+    Exit;
+  if (APosition < FData.GetLength()) then begin
+    d1 := APosition - 0;
+    d2 := APosition - GetPosition();
+    neg := ( d2 < 0 );
+    if neg then
+      d2 := -d2;
+    if ( d1 <= d2 ) then begin
+      idx := 1
+    end else begin
+      d1 := d2;
+      idx := 2;
+    end;
+    d2 := ( Pred(FData.GetLength()) - APosition );
+    if ( d2 < d1 ) then begin
+      d1 := d2;
+      idx := 3;
+    end;
+    if ( d1 = 0 ) and ( idx = 2 ) then begin
+      Result := True;
+    end else begin
+      oldPos := GetBookmark();
+      try
+        case idx of
+          1 :
+            begin
+              if MoveFirst() then begin
+                while ( d1 > 0 ) and MoveNext() do begin
+                  Dec(d1);
+                end;
+              end;
+            end;
+          2 :
+            begin
+              if neg then begin
+                while ( d1 > 0 ) and MovePrevious() do begin
+                  Dec(d1);
+                end;
+              end else begin
+                while ( d1 > 0 ) and MoveNext() do begin
+                  Dec(d1);
+                end;
+              end;
+            end;
+          3 :
+            begin
+              if MoveLast() then begin
+                while ( d1 > 0 ) and MovePrevious() do begin
+                  Dec(d1);
+                end;
+              end;
+            end;
+        end;
+        Result := ( d1 = 0 );
+      except
+        GotoBookmark(oldPos);
+        raise;
+      end;
+    end;
+  end else if (APosition = FData.GetLength()) and (FPosition < APosition ) then begin
+    Inc(FPosition);
+  end;
+end;
+
+procedure TLinkedListIterator.Notify(const AReason: TNotifyReason; const ANode: PLinkedNode);
+begin
+  Reset();
+  if ( AReason = nrDestroy ) then
+    FData := nil;
+end;
+
+procedure TLinkedListIterator.Reset();
+begin
+  FCurrent := nil;
+  FPosition := -1;
+end;
+
+function TDoubleLinkedList.InsertFirst() : PLinkedNode;
+begin
+  if Assigned(FFirst) then begin
+    Result := InsertBefore(FFirst);
+  end else begin
+    Result := AllocateBuffer();
+    FFirst := Result;
+    FLast := FFirst;
+    Inc(FCount);
+    Notify(nrNew,FFirst);
+  end;
+end;
+
+function TDoubleLinkedList.AllocateBuffer() : PLinkedNode;
+begin
+  Inc(FGeneration);
+  GetMem(Result,FItemSize);
+  FillChar(Result^,FItemSize,#0);
+end;
+
+function TDoubleLinkedList.InsertAfter(const AItem: PLinkedNode): PLinkedNode;
+begin
+  if Assigned(AItem) then begin
+    Result := AllocateBuffer();
+    Result^.Previous := AItem;
+    if Assigned(AItem^.Next) then
+      AItem^.Next^.Previous := Result
+    else
+      FLast := Result;
+    Result^.Next := AItem^.Next;
+    AItem^.Next := Result;
+    Inc(FCount);
+    Notify(nrNew,Result);
+  end else begin
+    raise EListException.Create('Invalid parameter.');
+  end;
+end;
+
+procedure TDoubleLinkedList.FreeBuffer(const AItem: PLinkedNode);
+begin
+  Inc(FGeneration);
+  FreeMem(AItem,FItemSize);
+end;
+
+function TDoubleLinkedList.Append() : PLinkedNode;
+begin
+  if IsEmpty() then
+    Result := InsertFirst()
+  else
+    Result := InsertAfter(GetLast());
+end;
+
+procedure TDoubleLinkedList.RegisterForNotification(const AListener: ILinkedListNotify);
+begin
+  if ( FNotifyList.IndexOf(AListener) = -1 ) then
+    FNotifyList.Add(AListener);
+end;
+
+procedure TDoubleLinkedList.UnregisterForNotification(const AListener: ILinkedListNotify);
+begin
+  FNotifyList.Remove(AListener);
+end;
+
+procedure TDoubleLinkedList.Notify(
+  const AReason : TNotifyReason;
+  const ANode : PLinkedNode
+);
+var
+  c, i : PtrInt;
+  ntfy : ILinkedListNotify;
+begin
+  FNotifyList.Lock();
+  try
+    c := FNotifyList.Count;
+    if ( c > 0 ) then begin
+      for i := 0 to Pred(c) do begin
+        ntfy := FNotifyList[i] as ILinkedListNotify;
+        ntfy.Notify(AReason,ANode);
+      end;
+    end;
+  finally
+    FNotifyList.Unlock();
+  end;
+end;
+
+end.

+ 73 - 0
packages/fcl-sdo/src/base/sdo_locators.pas

@@ -0,0 +1,73 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a file locator interface
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_locators;
+
+interface
+
+uses
+  Classes, SysUtils,
+{$IFDEF DELPHI}
+  xmldom, sdo_win_xml,
+{$ENDIF DELPHI}
+{$IFDEF FPC}
+ DOM, XMLRead,
+{$ENDIF FPC}
+ sdo_xsdparser;
+
+type
+
+  { TFileDocumentLocator }
+
+  TFileDocumentLocator = class(TInterfacedObject,IDocumentLocator)
+  private
+    FBasePath : string;
+  protected
+    property BasePath : string read FBasePath;
+  protected
+    function Find(
+      const ADocLocation : string;
+      out   ADoc : TXMLDocument
+    ) : Boolean;
+  public
+    constructor Create(const ABasePath : string);
+  end;
+
+implementation
+
+{ TFileDocumentLocator }
+
+function TFileDocumentLocator.Find(
+  const ADocLocation: string;
+  out   ADoc: TXMLDocument
+) : Boolean;
+var
+  locFileName : string;
+begin
+  locFileName := BasePath + ExtractFileName(ADocLocation);
+  locFileName := ExpandFileName(locFileName);
+  Result := FileExists(locFileName);
+  if Result then
+    ReadXMLFile(ADoc,locFileName);
+end;
+
+constructor TFileDocumentLocator.Create(const ABasePath: string);
+begin
+  FBasePath := IncludeTrailingPathDelimiter(ABasePath);
+end;
+
+end.
+

+ 98 - 0
packages/fcl-sdo/src/base/sdo_logger_intf.pas

@@ -0,0 +1,98 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a basic logger interface
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_logger_intf;
+
+interface
+
+uses
+  SysUtils; 
+
+type
+
+  TMessageType = ( mtInfo, mtError );
+
+const
+  MessageTypeNames : array[TMessageType] of string = ( 'Information', 'Error' );
+
+type
+
+  ILogger = interface
+    ['{158C90B5-BAC3-40A1-B471-C9327692A3BF}']
+    procedure Log(const AMsgType : TMessageType; const AMsg : string);overload;
+    procedure Log(const AMsgType : TMessageType; const AMsg : string; const AArgs : array of const);overload;
+    function GetMessageCount(const AMsgType : TMessageType) : Integer;
+  end;
+
+  { TSimpleConsoleLogger }
+
+  TSimpleConsoleLogger = class(TInterfacedObject,ILogger)
+  private
+    FMessageCount : array[TMessageType] of Integer;
+  protected
+    procedure Log(const AMsgType : TMessageType; const AMsg : string);overload;
+    procedure Log(const AMsgType : TMessageType; const AMsg : string; const AArgs : array of const);overload;
+    function GetMessageCount(const AMsgType : TMessageType) : Integer;
+  end;
+
+
+  function HasLogger() : Boolean;
+  function SetLogger(ALogger : ILogger) : ILogger;
+  function GetLogger() : ILogger;
+  
+implementation
+
+var FLogger : ILogger = nil;
+function SetLogger(ALogger : ILogger) : ILogger;
+begin
+  Result := FLogger;
+  FLogger := ALogger;
+end;
+
+function GetLogger() : ILogger;
+begin
+  Result := FLogger;
+end;
+
+function HasLogger() : Boolean;
+begin
+  Result := Assigned(FLogger);
+end;
+
+{ TSimpleConsoleLogger }
+
+procedure TSimpleConsoleLogger.Log(const AMsgType: TMessageType; const AMsg: string);
+begin
+  Log(AMsgType,AMsg,[]);
+end;
+
+procedure TSimpleConsoleLogger.Log(
+  const AMsgType : TMessageType;
+  const AMsg     : string;
+  const AArgs    : array of const
+);
+begin
+  Inc(FMessageCount[AMsgType]);
+  WriteLn(Format('%s : %s',[MessageTypeNames[AMsgType],Format(AMsg,AArgs)]));
+end;
+
+function TSimpleConsoleLogger.GetMessageCount(const AMsgType: TMessageType): Integer;
+begin
+  Result := FMessageCount[AMsgType];
+end;
+
+end.
+

+ 543 - 0
packages/fcl-sdo/src/base/sdo_parserutils.pas

@@ -0,0 +1,543 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements XSD parser utils
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_parserutils;
+
+interface
+
+uses
+  SysUtils, Classes
+  {$IFNDEF FPC}, xmldom, sdo_win_xml{$ELSE},DOM{$ENDIF},
+  sdo_cursor_intf, sdo_dom_cursors, xsd_consts, sdo_types;
+
+type
+  TNotFoundAction = ( nfaNone, nfaRaiseException );
+
+const
+  sNEW_LINE = sLineBreak;
+
+type
+
+  { TIntfObjectRef }
+
+  TIntfObjectRef = class
+  private
+    FIntf: IInterface;
+  public
+    constructor Create(AIntf : IInterface);
+    destructor Destroy();override;
+    property Intf : IInterface read FIntf;
+  end; 
+  
+  { TQualifiedNameObjectFilter }
+
+  TQualifiedNameObjectFilter = class(TInterfacedObject,IObjectFilter)
+  private
+    FNameSpace : string;
+    FName : string;
+  protected
+    function Evaluate(const AObject : TObject) : Boolean;
+  public
+    constructor Create(const AName,ANameSpace : string);
+  end;
+
+  function IsStrEmpty(Const AStr : String):Boolean;
+  function ExtractIdentifier(const AValue : string) : string ;
+  function GetToken(var ABuffer : string; const ADelimiter : string) : string;
+{$IFDEF SDO_HANDLE_DOC}
+  function EncodeLineBreak(const AInStr : string) : string;
+  function DecodeLineBreak(const AInStr : string) : string;
+{$ENDIF}
+
+  function IsReservedKeyWord(const AValue : string):Boolean ;
+
+  procedure ExtractNameSpaceShortNamesNested(
+          ANode         : TDOMNode;
+          AResList      : TStrings;
+    const ANameSpace    : WideString
+  );
+  function CreateQualifiedNameFilterStr(
+    const AName        : WideString;
+          APrefixList  : TStrings
+  ) : string;
+  function ExtractNameFromQName(const AQName : string):string ;
+  procedure ExtractNameSpaceShortNames(
+          AAttribCursor   : IObjectCursor;
+          AResList        : TStrings;
+    const ANameSpace      : WideString;
+    const ANotFoundAction : TNotFoundAction;
+    const AClearBefore    : Boolean;
+    const AExceptionClass : ExceptClass
+  );
+  function AddNameSpace(const AValue: string; ANameSpaceList : TStrings): TStrings;
+  procedure BuildNameSpaceList(AAttCursor : IObjectCursor; ANameSpaceList : TStrings);
+  procedure ExplodeQName(const AQName : string; out ALocalName, ANameSpace : string) ;
+  
+  function sdo_findCustomAttribute(
+          AWsdlShortNames : TStrings;
+          ANode      : TDOMNode;
+    const AAttribute : string;
+    out   AValue     : string
+  ) : Boolean;
+  function sdo_findCustomAttributeXsd(
+          AXsdShortNames : TStrings;
+          ANode      : TDOMNode;
+    const AAttribute : string;
+    out   AValue     : string
+  ) : Boolean;
+
+implementation
+
+uses StrUtils, sdo_rtti_filters;
+
+const LANGAGE_TOKEN : array[0..127] of string = (
+  'ABSOLUTE', 'ABSTRACT', 'AND', 'ARRAY', 'AS', 'ASM',
+  'BEGIN', 'BOOLEAN', 'BYTE',
+  'CASE', 'CDECL', 'CHAR', 'CLASS', 'COMP', 'CONST', 'CONSTRUCTOR', 'CONTAINS',
+  'CURRENCY', 'DEFAULT', 'DEPRECATED', 'DESTRUCTOR', 'DISPINTERFACE', 'DISPOSE', 'DIV', 'DO',
+  'DOUBLE', 'DOWNTO', 'DYNAMIC', 'END', 'EXCEPT', 'EXIT', 'EXPORT', 'EXPORTS',
+  'EXTERNAL', 'FALSE', 'FAR', 'FILE', 'FINALIZATION', 'FINALLY', 'FOR',
+  'FORWARD', 'FUNCTION', 'GOTO', 'ELSE', 'EXCEPT', 'EXTENDED',
+  'IF', 'IMPLEMENTATION', 'IMPLEMENTS', 'IN', 'INHERITED', 'INLINE', 'INT64',
+  'INITIALIZATION', 'INTEGER', 'INTERFACE', 'IS',
+  'LABEL', 'LIBRARY', 'LOCAL', 'LONGINT', 'LONGWORD',
+  'MOD', 'NEAR', 'NEW', 'NIL', 'NODEFAULT', 'NOT',
+  'OBJECT', 'OF', 'OLEVARIANT', 'ON', 'OPERATOR', 'OR', 'OUT', 'OVERLOAD',
+  'OVERRIDE','PACKAGE', 'PACKED', 'PASCAL', 'PCHAR', 'PRIVATE', 'PROCEDURE',
+  'PROGRAM', 'PROPERTY', 'PROTECTED', 'PUBLIC', 'PUBLISHED',
+  'RAISE', 'READ', 'REAL', 'RECORD', 'REGISTER', 'REINTRODUCE', 'REPEAT',
+  'REQUIRES', 'RESOURCESTRING', 'RESULT', 'SAFECALL', 'SELF', 'SET', 'SHL',
+  'SHORTINT', 'SHR', 'SINGLE', 'SMALLINT', 'STDCALL', 'STORED', 'STRING',
+  'THEN', 'THREADVAR', 'TO', 'TRUE', 'TRY', 'TYPE', 'UNIT', 'UNTIL', 'USES',
+  'VAR', 'VARARGS', 'VARIANT', 'VIRTUAL', 'WHILE', 'WIDECHAR', 'WITH', 'WORD',
+  'WRITE', 'XOR'
+);
+const SDO_RESERVED_TOKEN : array[0..1] of string = ( 'Item', 'Item' );
+function IsReservedKeyWord(const AValue : string):Boolean ;
+begin
+  Result := AnsiMatchText(AValue,LANGAGE_TOKEN) or
+            AnsiMatchText(AValue,SDO_RESERVED_TOKEN);
+end;
+
+function IsStrEmpty(Const AStr : String):Boolean;
+begin
+  Result := ( Length(Trim(AStr)) = 0 );
+end;
+
+function ExtractIdentifier(const AValue : string) : string ;
+var
+  i, c : Integer;
+  s : string;
+begin
+  Result := '';
+  s := Trim(AValue);
+  c := Length(s);
+  if ( c > 0 ) then begin
+    if not ( s[1] in ['A'..'Z', 'a'..'z', '_'] ) then begin
+      Result := '_';
+    end;
+    for i := 1 to c do begin
+      if ( s[i] in ['A'..'Z', 'a'..'z', '0'..'9', '_'] ) then begin
+        Result := Result + s[i];
+      end else begin
+        if ( Length(Result) > 0 ) and ( Result[Length(Result)] <> '_' ) then begin
+          Result := Result + '_';
+        end;
+      end;
+    end;
+    if (Length(Result) > 1) and (Result[Length(Result)] = '_') then
+      Delete(Result,Length(Result),1);
+  end;
+end;
+
+function GetToken(
+  var   ABuffer    : string;
+  const ADelimiter : string
+) : string;
+var
+  locDelPos, locDelLength : Integer;
+begin
+  Result := '';
+  if IsStrEmpty(ABuffer) then begin
+    ABuffer := '';
+  end else begin
+    locDelPos := Pos(ADelimiter,ABuffer);
+    if ( locDelPos < 1 ) then begin
+      Result := ABuffer;
+      ABuffer := '';
+    end else begin
+      locDelLength := Length(ADelimiter);
+      if ( locDelPos = 1 ) then begin
+        ABuffer := Copy(ABuffer,(locDelLength + 1),(Length(ABuffer) - locDelLength));
+      end else begin
+        Result := Copy(ABuffer,1,(locDelPos - 1));
+        ABuffer := Copy(ABuffer,(locDelPos + locDelLength),(Length(ABuffer) - locDelLength));
+      end;
+    end;
+  end;
+end;
+
+{$IFDEF SDO_HANDLE_DOC}
+const
+  REPLACE_CHAR_A = '#';  TARGET_SEQUENCE_A = sLineBreak;
+  REPLACE_CHAR_B = '|';  TARGET_SEQUENCE_B = #10;
+
+function EncodeLineBreak(const AInStr : string) : string;
+begin
+  Result :=
+    StringReplace(
+      StringReplace(AInStr,REPLACE_CHAR_A,(REPLACE_CHAR_A + REPLACE_CHAR_A),[rfReplaceAll]),
+      TARGET_SEQUENCE_A,REPLACE_CHAR_A,[rfIgnoreCase,rfReplaceAll]
+    );
+  Result :=
+    StringReplace(
+      StringReplace(Result,REPLACE_CHAR_B,(REPLACE_CHAR_B + REPLACE_CHAR_B),[rfReplaceAll]),
+      TARGET_SEQUENCE_B,REPLACE_CHAR_B,[rfIgnoreCase,rfReplaceAll]
+    );
+end;
+
+function DecodeLineBreak(const AInStr : string) : string;
+var
+  i, c : PtrInt;
+  pc : PChar;
+  tmp, res : string;
+begin
+  res := '';
+  pc := PChar(AInStr);
+  i := 1;
+  c := Length(AInStr);
+  while ( i <= c ) do begin
+    if ( pc^ = REPLACE_CHAR_B ) then begin
+      if ( i < c ) then begin
+        Inc(pc); Inc(i);
+        if ( pc^ = REPLACE_CHAR_B ) then
+          res := res + REPLACE_CHAR_B
+        else
+          res := res + TARGET_SEQUENCE_B + pc^;
+      end else begin
+        res := res + TARGET_SEQUENCE_B;
+      end;
+    end else begin
+      res := res  + pc^;
+    end;
+    Inc(pc); Inc(i);
+  end;
+
+  tmp := res;
+  res := '';
+  pc := PChar(tmp);
+  i := 1;
+  c := Length(tmp);
+  while ( i <= c ) do begin
+    if ( pc^ = REPLACE_CHAR_A ) then begin
+      if ( i < c ) then begin
+        Inc(pc); Inc(i);
+        if ( pc^ = REPLACE_CHAR_A ) then
+          res := res + REPLACE_CHAR_A
+        else
+          res := res + TARGET_SEQUENCE_A + pc^;
+      end else begin
+        res := res + TARGET_SEQUENCE_A;
+      end;
+    end else begin
+      res := res  + pc^;
+    end;
+    Inc(pc); Inc(i);
+  end;
+
+  Result := res;
+end;
+{$ENDIF SDO_HANDLE_DOC}
+
+function ExtractNameFromQName(const AQName : string):string ;
+var
+  i : Integer;
+begin
+  Result := Trim(AQName);
+  i := Pos(':',Result);
+  if ( i > 0 ) then
+    Result := Copy(Result,( i + 1 ), MaxInt);
+end;
+
+function CreateQualifiedNameFilterStr(
+  const AName        : WideString;
+        APrefixList  : TStrings
+) : string;
+var
+  k : Integer;
+  locStr : string;
+  locWStr : WideString;
+begin
+  Result := '';
+  if ( APrefixList.Count > 0 ) then begin
+    for k := 0 to Pred(APrefixList.Count) do begin
+      if IsStrEmpty(APrefixList[k]) then begin
+        locWStr := ''
+      end else begin
+        locWStr := APrefixList[k] + ':';
+      end;
+      locWStr := locWStr + AName;
+      locStr := s_NODE_NAME;
+      Result := Result + ' or ' + locStr + ' = ' + QuotedStr(locWStr);
+    end;
+    if ( Length(Result) > 0 ) then begin
+      Delete(Result,1,Length(' or'));
+    end;
+  end else begin
+    Result := Format('%s = %s',[s_NODE_NAME,QuotedStr(AName)]);
+  end;
+end;
+
+procedure ExtractNameSpaceShortNamesNested(
+        ANode         : TDOMNode;
+        AResList      : TStrings;
+  const ANameSpace    : WideString
+);
+var
+  nd : TDOMNode;
+begin
+  AResList.Clear();
+  nd := ANode;
+  while Assigned(nd) do begin
+    if Assigned(nd.Attributes) and ( nd.Attributes.Length > 0 ) then begin
+      ExtractNameSpaceShortNames(CreateAttributesCursor(nd,cetRttiNode),AResList,ANameSpace,nfaNone,False,nil);
+    end;
+    nd := nd.ParentNode;
+  end;
+end;
+
+procedure ExtractNameSpaceShortNames(
+        AAttribCursor   : IObjectCursor;
+        AResList        : TStrings;
+  const ANameSpace      : WideString;
+  const ANotFoundAction : TNotFoundAction;
+  const AClearBefore    : Boolean;
+  const AExceptionClass : ExceptClass
+);
+var
+  crs : IObjectCursor;
+  locObj : TDOMNodeRttiExposer;
+  wStr : WideString;
+  i : Integer;
+  ec : ExceptClass;
+begin
+  if AClearBefore then begin
+    AResList.Clear();
+  end;
+  AAttribCursor.Reset();
+  crs := CreateCursorOn(AAttribCursor,ParseFilter(Format('%s=%s',[s_NODE_VALUE,QuotedStr(ANameSpace)]),TDOMNodeRttiExposer));
+  crs.Reset();
+  if crs.MoveNext() then begin
+    repeat
+      locObj := crs.GetCurrent() as TDOMNodeRttiExposer;
+      wStr := Trim(locObj.NodeName);
+      i := AnsiPos(s_xmlns + ':',wStr);
+      if ( i > 0 ) then begin
+        i := AnsiPos(':',wStr);
+        AResList.Add(Copy(wStr,( i + 1 ), MaxInt));
+      end else begin
+        if ( AResList.IndexOf('') = -1 ) then
+          AResList.Add('');
+      end;
+    until not crs.MoveNext();
+  end else begin
+    if ( ANotFoundAction = nfaRaiseException ) then begin
+      if Assigned(AExceptionClass) then
+        ec := AExceptionClass
+      else
+        ec := Exception;
+      raise ec.CreateFmt('Namespace not found : "%s"',[ANameSpace]);
+    end;
+  end;
+end;
+
+function sdo_findCustomAttribute(
+        AWsdlShortNames : TStrings;
+        ANode      : TDOMNode;
+  const AAttribute : string;
+  out   AValue     : string
+) : Boolean;
+var
+  nd : TDOMNode;
+  tmpCrs : IObjectCursor;
+begin
+  Result := False;
+  tmpCrs := CreateCursorOn(
+              CreateChildrenCursor(ANode,cetRttiNode),
+              ParseFilter(CreateQualifiedNameFilterStr(s_document,AWsdlShortNames),TDOMNodeRttiExposer)
+            );
+  tmpCrs.Reset();
+  if tmpCrs.MoveNext() then begin
+    nd := (tmpCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+    if nd.HasChildNodes() then begin
+      tmpCrs := CreateCursorOn(
+                  CreateChildrenCursor(nd,cetRttiNode),
+                  ParseFilter(Format('%s=%s',[s_NODE_NAME,QuotedStr(s_customAttributes)]),TDOMNodeRttiExposer)
+                );
+      tmpCrs.Reset();
+      if tmpCrs.MoveNext() then begin
+        nd := (tmpCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+        if ( nd.Attributes <> nil ) then begin
+          nd := nd.Attributes.GetNamedItem(AAttribute);
+          if Assigned(nd) then begin
+            Result := True;
+            AValue := nd.NodeValue;
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+function sdo_findCustomAttributeXsd(
+        AXsdShortNames : TStrings;
+        ANode      : TDOMNode;
+  const AAttribute : string;
+  out   AValue     : string
+) : Boolean;
+var
+  nd : TDOMNode;
+begin
+  Result := False;
+  if Assigned(ANode) and ( ANode.Attributes <> nil ) then begin
+    nd := ANode.Attributes.GetNamedItem(Format('%s:%s',[s_SDO,AAttribute]));
+    if Assigned(nd) then begin
+      Result := True;
+      AValue := nd.NodeValue;
+    end;
+  end;
+end;
+
+procedure ExplodeQName(const AQName : string; out ALocalName, ANameSpace : string) ;
+var
+  i : PtrInt;
+begin
+  i := Pos(':',AQName);
+  if ( i > 0 ) then begin
+    ANameSpace := Copy(AQName,1,Pred(i));
+    ALocalName := Copy(AQName,Succ(i),Length(AQName));
+  end else begin
+    ANameSpace := '';
+    ALocalName := AQName;
+  end;
+end;
+
+function AddNameSpace(const AValue: string; ANameSpaceList : TStrings): TStrings;
+var
+  i : PtrInt;
+  s : string;
+  ls : TStringList;
+begin
+  s := Trim(AValue);
+  i := ANameSpaceList.IndexOf(s);
+  if ( i < 0 ) then begin
+    i := ANameSpaceList.Add(s);
+    ls := TStringList.Create();
+    ANameSpaceList.Objects[i] := ls;
+    ls.Duplicates := dupIgnore;
+    ls.Sorted := True;
+    Result := ls;
+  end else begin
+    Result := ANameSpaceList.Objects[i] as TStrings;
+  end;
+end;
+
+procedure BuildNameSpaceList(AAttCursor : IObjectCursor; ANameSpaceList : TStrings);
+var
+  locObj : TDOMNodeRttiExposer;
+  locNameSpace, locNameSpaceShort : string;
+  tmpXmlNs : string;
+  found : Boolean;
+begin
+  if Assigned(AAttCursor) then begin
+    tmpXmlNs := s_xmlns + ':';
+    AAttCursor.Reset();
+    while AAttCursor.MoveNext() do begin
+      found := False;
+      locObj := AAttCursor.GetCurrent() as TDOMNodeRttiExposer;
+      if AnsiSameText(s_xmlns,locObj.NodeName) then begin
+        found := True;
+        locNameSpace := locObj.NodeValue;
+        locNameSpaceShort := '';
+      end else if AnsiStartsText(tmpXmlNs,locObj.NodeName) then begin
+        found := True;
+        locNameSpace := locObj.NodeValue;
+        locNameSpaceShort := locObj.NodeName;
+        locNameSpaceShort := Copy(locNameSpaceShort,Pos(':',locNameSpaceShort) + 1, Length(locNameSpaceShort));
+      end;
+      if found then
+        AddNameSpace(locNameSpace,ANameSpaceList).Add(locNameSpaceShort);
+    end;
+  end;
+end;
+
+
+{ TQualifiedNameObjectFilter }
+
+function TQualifiedNameObjectFilter.Evaluate(const AObject: TObject): Boolean;
+var
+  locObj : TDOMNodeRttiExposer;
+  startPos, i : PtrInt;
+  shortNameSpace : string;
+  locContinue : Boolean;
+  tmpNode : TDOMNode;
+begin
+  Result := False;
+  if ( AObject <> nil ) then begin
+    locObj := TDOMNodeRttiExposer(AObject);
+    i := Length(FName);
+    startPos := ( Length(locObj.NodeName) - i + 1 );
+    if ( startPos > 0 ) and ( FName = Copy(locObj.NodeName,startPos,i) ) then begin
+      if ( startPos = 1 ) then begin
+        shortNameSpace := 'xmlns';
+        locContinue := True;
+      end else begin
+        locContinue := ( startPos > 2 ) and ( locObj.NodeName[startPos-1] = ':' );
+        if locContinue then
+          shortNameSpace := 'xmlns:' + Copy(locObj.NodeName,1,( startPos - 2 ));
+      end;
+      if locContinue then begin
+        if ( locObj.InnerObject.Attributes <> nil ) then begin
+          tmpNode := locObj.InnerObject.Attributes.GetNamedItem(shortNameSpace);
+          if ( tmpNode <> nil ) and ( tmpNode.NodeValue = FNameSpace ) then
+            Result := True;
+        end;
+      end;
+    end;
+  end;
+end;
+
+constructor TQualifiedNameObjectFilter.Create(const AName, ANameSpace: string);
+begin
+  FName := AName;
+  FNameSpace := ANameSpace;;
+end;
+
+{ TIntfObjectRef }
+
+constructor TIntfObjectRef.Create(AIntf: IInterface);
+begin
+  Assert(Assigned(AIntf));
+  FIntf := AIntf;
+end;
+
+destructor TIntfObjectRef.Destroy();
+begin
+  FIntf := nil;
+  inherited Destroy();
+end;
+
+end.

+ 920 - 0
packages/fcl-sdo/src/base/sdo_rtti_filters.pas

@@ -0,0 +1,920 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements RTTI filters.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_rtti_filters;
+
+interface
+
+uses
+  Classes, SysUtils, Contnrs, TypInfo,
+  sdo_cursor_intf, sdo_types;
+
+type
+
+  ERttiFilterException = class(Exception)
+  end;
+
+  TNumericFilterOperator = (
+    nfoEqual, nfoGreater, nfoLesser, nfoNotEqual,
+    nfoGreaterOrEqual, nfoLesserOrEqual
+  );
+  TStringFilterOperator = ( sfoEqualCaseSensitive, sfoEqualCaseInsensitive, sfoNotEqual );
+
+  TRttiFilterCreatorTarget = TPersistent;
+  TRttiFilterCreatorTargetClass = class of TRttiFilterCreatorTarget;
+
+  TRttiExpNodeItem = class;
+  TRttiExpNode = class;
+
+  TClearAction = ( clrNone, clrFreeObjects );
+
+  { TRttiFilterCreator }
+  TRttiFilterCreator = class
+  private
+    FRoot : TRttiExpNode;
+    FCurrent : TRttiExpNode;
+    FTargetClass: TRttiFilterCreatorTargetClass;
+    FCurrentStack : TObjectStack;
+  private
+    procedure AddNode(
+      const ANode       : TRttiExpNodeItem;
+      const AConnector  : TFilterConnector
+    );
+    procedure PushCurrent(ACurrent : TRttiExpNode);
+    function PopCurrent() : TRttiExpNode;
+  public
+    constructor Create(const ATargetClass : TRttiFilterCreatorTargetClass);
+    destructor Destroy();override;
+    procedure Clear(const AFreeObjects : TClearAction);
+    function AddCondition(
+      const APropertyName : string;
+      const AOperator     : TNumericFilterOperator;
+      const AValue        : Integer;
+      const AConnector    : TFilterConnector
+    ) : TRttiFilterCreator;overload;
+    function AddCondition(
+      const APropertyName : string;
+      const AOperator     : TNumericFilterOperator;
+      const AEnumValue    : string;
+      const AConnector    : TFilterConnector
+    ) : TRttiFilterCreator;overload;
+
+    function AddCondition(
+      const APropertyName : string;
+      const AOperator     : TStringFilterOperator;
+      const AValue        : AnsiString;
+      const AConnector    : TFilterConnector
+    ) : TRttiFilterCreator;overload;
+    function AddCondition(
+      const APropertyName : string;
+      const AOperator     : TStringFilterOperator;
+      const AValue        : WideString;
+      const AConnector    : TFilterConnector
+    ) : TRttiFilterCreator;overload;
+{$IFDEF USE_UNICODE}
+    function AddCondition(
+      const APropertyName : string;
+      const AOperator     : TStringFilterOperator;
+      const AValue        : UnicodeString;
+      const AConnector    : TFilterConnector
+    ) : TRttiFilterCreator;overload;
+{$ENDIF USE_UNICODE}
+
+    function BeginGroup(const AConnector : TFilterConnector):TRttiFilterCreator;
+    function EndGroup():TRttiFilterCreator;
+    property TargetClass : TRttiFilterCreatorTargetClass read FTargetClass;
+    property Root : TRttiExpNode read FRoot;
+  end;
+
+
+  TRttiExpNodeItem = class
+  public
+    function Evaluate(AInstance : TRttiFilterCreatorTarget):Boolean;virtual;abstract;
+  end;
+
+  { TRttiObjectFilter }
+
+  TRttiObjectFilter = class(TInterfacedObject,IObjectFilter)
+  private
+    FFilterRoot : TRttiExpNodeItem;
+    FOnDestroyFilterAction : TClearAction;
+  protected
+    function Evaluate(const AObject : TObject) : Boolean;
+  public
+    constructor Create(
+            AFilterRoot            : TRttiExpNodeItem;
+      const AOnDestroyFilterAction : TClearAction
+    );
+    destructor Destroy();override;
+  end;
+
+  { TRttiExpNode }
+
+  TRttiExpNode = class(TRttiExpNodeItem)
+  private
+    FConnector: TFilterConnector;
+    FLeft: TRttiExpNodeItem;
+    FRight: TRttiExpNodeItem;
+  private
+    procedure SetConnector(const AValue: TFilterConnector);
+    procedure SetLeft(const AValue: TRttiExpNodeItem);
+    procedure SetRight(const AValue: TRttiExpNodeItem);
+  public
+    destructor Destroy();override;
+    function Evaluate(AInstance : TRttiFilterCreatorTarget):Boolean;override;
+    property Connector : TFilterConnector read FConnector write SetConnector;
+    property Left : TRttiExpNodeItem read FLeft write SetLeft;
+    property Right : TRttiExpNodeItem read FRight write SetRight;
+  end;
+
+  { TRttiExpConcreteNodeItem }
+
+  TRttiExpConcreteNodeItem = class(TRttiExpNodeItem)
+  private
+    FPropInfo: PPropInfo;
+  public
+    constructor Create(const APropInfo : PPropInfo);
+    property PropInfo : PPropInfo read FPropInfo;
+  end;
+
+  { TRttiExpNumericNodeItem }
+
+  TRttiExpNumericNodeItem = class(TRttiExpConcreteNodeItem)
+  private
+    FOperation: TNumericFilterOperator;
+  public
+    constructor Create(
+      const APropInfo      : PPropInfo;
+      const AOperation     : TNumericFilterOperator
+    );
+    property Operation : TNumericFilterOperator read FOperation;
+  end;
+
+  { TRttiExpIntegerNodeItem }
+
+  TRttiExpIntegerNodeItem = class(TRttiExpNumericNodeItem)
+  private
+    FComparedValue: Integer;
+  public
+    constructor Create(
+      const APropInfo      : PPropInfo;
+      const AOperation     : TNumericFilterOperator;
+      const AComparedValue : Integer
+    );
+    function Evaluate(AInstance : TRttiFilterCreatorTarget):Boolean;override;
+    property ComparedValue : Integer read FComparedValue;
+  end;
+
+  { TRttiExpEnumNodeItem }
+
+  TRttiExpEnumNodeItem = class(TRttiExpIntegerNodeItem)
+  public
+    constructor Create(
+      const APropInfo      : PPropInfo;
+      const AOperation     : TNumericFilterOperator;
+      const AComparedValue : string
+    );
+  end;
+
+  { TRttiExpStringNodeItem }
+
+  TRttiExpStringNodeItem = class(TRttiExpConcreteNodeItem)
+  private
+    FOperation: TStringFilterOperator;
+  public
+    constructor Create(
+      const APropInfo      : PPropInfo;
+      const AOperation     : TStringFilterOperator
+    );
+    property Operation : TStringFilterOperator read FOperation;
+  end;
+
+  { TRttiExpAnsiStringNodeItem }
+
+  TRttiExpAnsiStringNodeItem = class(TRttiExpStringNodeItem)
+  private
+    FComparedValue: AnsiString;
+  public
+    constructor Create(
+      const APropInfo      : PPropInfo;
+      const AOperation     : TStringFilterOperator;
+      const AComparedValue : AnsiString
+    );
+    function Evaluate(AInstance : TRttiFilterCreatorTarget):Boolean;override;
+    property ComparedValue : AnsiString read FComparedValue;
+  end;
+
+  { TRttiExpWideStringNodeItem }
+
+  TRttiExpWideStringNodeItem = class(TRttiExpStringNodeItem)
+  private
+    FComparedValue: WideString;
+  public
+    constructor Create(
+      const APropInfo      : PPropInfo;
+      const AOperation     : TStringFilterOperator;
+      const AComparedValue : WideString
+    );
+    function Evaluate(AInstance : TRttiFilterCreatorTarget):Boolean;override;
+    property ComparedValue : WideString read FComparedValue;
+  end;
+
+{$IFDEF USE_UNICODE}
+  { TRttiExpUnicodeStringNodeItem }
+
+  TRttiExpUnicodeStringNodeItem = class(TRttiExpStringNodeItem)
+  private
+    FComparedValue: UnicodeString;
+  public
+    constructor Create(
+      const APropInfo      : PPropInfo;
+      const AOperation     : TStringFilterOperator;
+      const AComparedValue : UnicodeString
+    );
+    function Evaluate(AInstance : TRttiFilterCreatorTarget):Boolean;override;
+    property ComparedValue : UnicodeString read FComparedValue;
+  end;
+{$ENDIF USE_UNICODE}
+
+  procedure ParseFilter(const AFilterText: string; AFltrCrtr : TRttiFilterCreator);overload;
+  function ParseFilter(
+    const AFilterText  : string;
+          ATargetClass : TRttiFilterCreatorTargetClass
+  ) : IObjectFilter;overload;
+
+implementation
+
+function ParseFilter(
+  const AFilterText  : string;
+        ATargetClass : TRttiFilterCreatorTargetClass
+) : IObjectFilter;
+var
+  fltr : TRttiFilterCreator;
+begin
+  Result := nil;
+  fltr := TRttiFilterCreator.Create(ATargetClass);
+  try
+    try
+      ParseFilter(AFilterText,fltr);
+      Result := TRttiObjectFilter.Create(fltr.Root,clrFreeObjects);
+      fltr.Clear(clrNone);
+    except
+      fltr.Clear(clrFreeObjects);
+      raise;
+    end;
+  finally
+    FreeAndNil(fltr);
+  end;
+end;
+
+procedure ParseFilter(const AFilterText: string; AFltrCrtr : TRttiFilterCreator);
+const
+  tkn_LeftParenthesis  = '('; tkn_RigthParenthesis = ')';
+  tkn_Equal = '='; tkn_NotEqual = '<>';
+  tkn_Sup = '>'; tkn_Inf = '<';
+  tkn_And = 'and'; tkn_Or = 'or';
+var
+  strm : TStringStream;
+  prsr : TParser;
+
+  procedure MoveNext();
+  begin
+    prsr.NextToken();
+    if ( prsr.Token = toEOF ) then
+      raise ERttiFilterException.Create('Unexpected end of filter.');
+  end;
+
+var
+  propName : string;
+  propInfo : PPropInfo;
+  lastCntr : TFilterConnector;
+
+  procedure Handle_String();
+  var
+    s : string;
+    ws : WideString;
+{$IFDEF USE_UNICODE}
+    us : UnicodeString;
+{$ENDIF USE_UNICODE}
+    fltrOp : TStringFilterOperator;
+  begin
+    MoveNext();
+    s := prsr.TokenString();
+    if ( s = tkn_Equal ) then
+      fltrOp := sfoEqualCaseInsensitive
+    else if ( s = tkn_NotEqual ) then
+      fltrOp := sfoNotEqual
+    else if ( s = tkn_Inf ) then begin
+      MoveNext();
+      if ( prsr.Token = tkn_Sup ) then
+        fltrOp := sfoNotEqual
+      else
+        raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+    end else begin
+      raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+    end;
+    MoveNext();
+    prsr.CheckToken(toString);
+    case propInfo^.PropType^.Kind of
+      tkString, tkLString :
+        begin
+          AFltrCrtr.AddCondition(propName,fltrOp,AnsiString(prsr.TokenString()),lastCntr);
+        end;
+      tkWString :
+        begin
+          ws := prsr.TokenString();
+          AFltrCrtr.AddCondition(propName,fltrOp,ws,lastCntr);
+        end;
+{$IFDEF USE_UNICODE}
+      tkUString :
+        begin
+          us := prsr.TokenString();
+          AFltrCrtr.AddCondition(propName,fltrOp,us,lastCntr);
+        end;
+{$ENDIF USE_UNICODE}
+      else
+        begin
+          s := prsr.TokenString();
+          AFltrCrtr.AddCondition(propName,fltrOp,s,lastCntr);
+        end;
+    end;
+  end;
+
+  procedure Handle_Integer();
+  var
+    s : string;
+    fltrOp : TNumericFilterOperator;
+  begin
+    MoveNext();
+    s := prsr.TokenString();
+    if ( s = tkn_Equal ) then
+      fltrOp := nfoEqual
+    else if ( s = tkn_NotEqual ) then
+      fltrOp := nfoNotEqual
+    else if ( s = tkn_Inf ) then
+      fltrOp := nfoLesser
+    else if ( s = tkn_Sup ) then
+      fltrOp := nfoGreater
+    else
+      raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+    MoveNext();
+    if ( prsr.Token = tkn_Equal ) then begin
+      case fltrOp of
+        nfoGreater : fltrOp := nfoGreaterOrEqual;
+        nfoLesser  : fltrOp := nfoLesserOrEqual;
+        else
+          raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+      end;
+      MoveNext();
+    end else if ( prsr.Token = tkn_Sup ) then begin
+      if ( fltrOp = nfoLesser ) then
+        fltrOp := nfoNotEqual
+      else
+        raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+      MoveNext();
+    end;
+    prsr.CheckToken(toInteger);
+    AFltrCrtr.AddCondition(propName,fltrOp,prsr.TokenInt(),lastCntr);
+  end;
+
+  procedure Handle_Enum();
+  var
+    s : string;
+    fltrOp : TNumericFilterOperator;
+  begin
+    MoveNext();
+    s := prsr.TokenString();
+    if ( s = tkn_Equal ) then
+      fltrOp := nfoEqual
+    else if ( s = tkn_NotEqual ) then
+      fltrOp := nfoNotEqual
+    else if ( s = tkn_Inf ) then
+      fltrOp := nfoLesser
+    else if ( s = tkn_Sup ) then
+      fltrOp := nfoGreater
+    else
+      raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+    MoveNext();
+    if ( prsr.Token = tkn_Equal ) then begin
+      case fltrOp of
+        nfoGreater : fltrOp := nfoGreaterOrEqual;
+        nfoLesser  : fltrOp := nfoLesserOrEqual;
+        else
+          raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+      end;
+      MoveNext();
+    end else if ( prsr.Token = tkn_Sup ) then begin
+      if ( fltrOp = nfoLesser ) then
+        fltrOp := nfoNotEqual
+      else
+        raise ERttiFilterException.CreateFmt('Unexpected symbol : "%s".',[s]);
+      MoveNext();
+    end;
+    if (prsr.Token = toInteger) then begin
+      AFltrCrtr.AddCondition(propName,fltrOp,prsr.TokenInt,lastCntr)
+    end else begin
+      prsr.CheckToken(toSymbol);
+      AFltrCrtr.AddCondition(propName,fltrOp,prsr.TokenString(),lastCntr);
+    end;
+  end;
+
+var
+  s : string;
+begin
+  lastCntr := fcAnd;
+  AFltrCrtr.Clear(clrFreeObjects);
+  strm := TStringStream.Create(Trim(AFilterText));
+  try
+    prsr := TParser.Create(strm);
+    while ( prsr.Token <> toEOF ) do begin
+      s := prsr.TokenString();
+      if SameText(s,tkn_LeftParenthesis) then
+        AFltrCrtr.BeginGroup(lastCntr)
+      else if SameText(s,tkn_RigthParenthesis) then
+        AFltrCrtr.EndGroup()
+      else if SameText(s,tkn_And) then
+        lastCntr := fcAnd
+      else if SameText(s,tkn_Or) then
+        lastCntr := fcOr
+      else begin
+        prsr.CheckToken(toSymbol);
+        propName := prsr.TokenString();
+        propInfo := GetPropInfo(AFltrCrtr.TargetClass,propName);
+        if ( propInfo = nil ) then
+          raise ERttiFilterException.CreateFmt('Invalid property : "%s"',[propName]);
+        if ( propInfo^.PropType^.Kind in
+             [ {$IFDEF FPC}tkSString,tkAString,{$ENDIF}
+               {$IFDEF USE_UNICODE}tkUString,{$ENDIF}
+               tkLString,tkWString
+             ]
+           )
+        then
+          Handle_String()
+        else if ( propInfo^.PropType^.Kind in [tkInteger,tkInt64{$IFDEF HAS_QWORD},tkQWord{$ENDIF}] ) then
+          Handle_Integer()
+        else if ( propInfo^.PropType^.Kind in [tkEnumeration {$IFDEF HAS_TKBOOL},tkBool{$ENDIF}] ) then
+          Handle_Enum()
+        else
+          raise ERttiFilterException.CreateFmt('Type not handled : "%s"',[GetEnumName(TypeInfo(TTypeKind),Ord(propInfo^.PropType^.Kind))]);
+      end;
+      prsr.NextToken();
+    end;
+  finally
+    FreeAndNil(prsr);
+    FreeAndNil(strm);
+  end;
+end;
+
+procedure ClearObject(ARoot : TRttiExpNodeItem);
+begin
+  if Assigned(ARoot) then begin
+    if ARoot.InheritsFrom(TRttiExpNode) then begin
+      with TRttiExpNode(ARoot) do begin
+        ClearObject(Right);
+        Right := nil;
+        ClearObject(Left);
+        Left := nil;
+      end;
+    end;
+    ARoot.Free();
+  end;
+end;
+
+{ TRttiExpNode }
+
+procedure TRttiExpNode.SetRight(const AValue: TRttiExpNodeItem);
+begin
+  if ( Connector = fcNone ) and ( AValue <> nil ) then
+    raise ERttiFilterException.Create('"Connector" must be set before "Right".');
+  //FreeAndNil(FRight);
+  FRight := AValue;
+end;
+
+procedure TRttiExpNode.SetConnector(const AValue: TFilterConnector);
+begin
+  if ( AValue = fcNone ) and ( FRight <> nil ) then
+    raise ERttiFilterException.Create('"Right" must be set to "nil" before "Connector" can be set to "none".');
+  FConnector := AValue;
+end;
+
+procedure TRttiExpNode.SetLeft(const AValue: TRttiExpNodeItem);
+begin
+  if ( FRight <> nil ) and ( AValue = nil ) then
+    raise ERttiFilterException.Create('"Right" must be set to "nil" before "Left" can be set to "none".');
+  //FreeAndNil(FLeft);
+  FLeft := AValue;
+end;
+
+destructor TRttiExpNode.Destroy();
+begin
+  FreeAndNil(FLeft);
+  FreeAndNil(FRight);
+  inherited Destroy();
+end;
+
+function TRttiExpNode.Evaluate(AInstance: TRttiFilterCreatorTarget): Boolean;
+begin
+  if Assigned(Left) then begin
+    Result := Left.Evaluate(AInstance);
+    if not Assigned(Right) then
+      Exit;
+    if Result and ( Connector = fcOr ) then
+      Exit;
+    if ( not Result ) and ( Connector = fcAnd ) then
+      Exit;
+    Result := Right.Evaluate(AInstance);
+  end else begin
+    Result := False;
+  end;
+end;
+
+{ TRttiExpConcreteNodeItem }
+
+constructor TRttiExpConcreteNodeItem.Create(const APropInfo : PPropInfo);
+begin
+  Assert(Assigned(APropInfo));
+  FPropInfo := APropInfo;
+end;
+
+{ TRttiExpIntegerNodeItem }
+
+constructor TRttiExpIntegerNodeItem.Create(
+  const APropInfo      : PPropInfo;
+  const AOperation     : TNumericFilterOperator;
+  const AComparedValue : Integer
+);
+begin
+  Assert(Assigned(APropInfo));
+  if not ( APropInfo^.PropType^.Kind in [tkInteger,tkInt64,tkEnumeration{$IFDEF HAS_QWORD},tkQWord{$ENDIF}{$IFDEF HAS_TKBOOL},tkBool{$ENDIF}] ) then
+    raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['Integer']);
+  inherited Create(APropInfo,AOperation);
+  FComparedValue := AComparedValue;
+end;
+
+function TRttiExpIntegerNodeItem.Evaluate(AInstance: TRttiFilterCreatorTarget): Boolean;
+begin
+  case Operation of
+    nfoEqual          :  Result := ( GetOrdProp(AInstance,PropInfo) =  ComparedValue );
+    nfoGreater        :  Result := ( GetOrdProp(AInstance,PropInfo) >  ComparedValue );
+    nfoLesser         :  Result := ( GetOrdProp(AInstance,PropInfo) <  ComparedValue );
+    nfoNotEqual       :  Result := ( GetOrdProp(AInstance,PropInfo) <> ComparedValue );
+    nfoGreaterOrEqual :  Result := ( GetOrdProp(AInstance,PropInfo) >=  ComparedValue );
+    nfoLesserOrEqual  :  Result := ( GetOrdProp(AInstance,PropInfo) <=  ComparedValue );
+    else begin
+      Assert(False);
+      Result := False;
+    end;
+  end;
+end;
+
+{ TRttiFilterCreator }
+
+procedure TRttiFilterCreator.AddNode(
+  const ANode       : TRttiExpNodeItem;
+  const AConnector  : TFilterConnector
+);
+var
+  tmpNode : TRttiExpNode;
+begin
+  Assert(Assigned(ANode));
+  if not Assigned(FRoot) then begin
+    FRoot := TRttiExpNode.Create();
+    FCurrent := FRoot;
+  end;
+  if not Assigned(FCurrent.Left) then begin
+    FCurrent.Left := ANode;
+    FCurrent.Connector := AConnector;
+    Exit;
+  end;
+  if ( AConnector <= fcNone ) then
+    raise ERttiFilterException.Create('Invalid connector value.');
+  if not Assigned(FCurrent.Right) then begin
+    FCurrent.Right := ANode;
+    FCurrent.Connector := AConnector;
+    Exit;
+  end;
+  tmpNode := TRttiExpNode.Create();
+  tmpNode.Left := FCurrent.Right;
+  FCurrent.Right := tmpNode;
+  FCurrent := tmpNode;
+  FCurrent.Connector := AConnector;
+  FCurrent.Right := ANode;
+end;
+
+procedure TRttiFilterCreator.PushCurrent(ACurrent: TRttiExpNode);
+begin
+  FCurrentStack.Push(FCurrent);
+  FCurrent := ACurrent;
+end;
+
+function TRttiFilterCreator.PopCurrent(): TRttiExpNode;
+begin
+  if not FCurrentStack.AtLeast(1) then
+    raise ERttiFilterException.Create('"BeginGroup" must be called before "EndGroup".');
+  Result := FCurrentStack.Pop() as TRttiExpNode;
+  FCurrent := Result;
+end;
+
+constructor TRttiFilterCreator.Create(const ATargetClass: TRttiFilterCreatorTargetClass);
+begin
+  Assert(Assigned(ATargetClass));
+  FTargetClass := ATargetClass;
+  FCurrentStack := TObjectStack.Create();
+end;
+
+destructor TRttiFilterCreator.Destroy();
+begin
+  FreeAndNil(FCurrentStack);
+  inherited Destroy();
+end;
+
+procedure TRttiFilterCreator.Clear(const AFreeObjects: TClearAction);
+var
+  i : Integer;
+begin
+  if ( AFreeObjects = clrFreeObjects ) then
+    ClearObject(FRoot);
+  for i := 0 to Pred(FCurrentStack.Count) do
+    FCurrentStack.Pop();
+  FRoot := nil;
+  FCurrent := nil;
+end;
+
+function TRttiFilterCreator.AddCondition(
+  const APropertyName    : string;
+  const AOperator        : TNumericFilterOperator;
+  const AValue           : Integer;
+  const AConnector       : TFilterConnector
+) : TRttiFilterCreator;
+begin
+  AddNode(
+    TRttiExpIntegerNodeItem.Create(GetPropInfo(TargetClass,APropertyName),AOperator,AValue),
+    AConnector
+  );
+  Result := Self;
+end;
+
+function TRttiFilterCreator.AddCondition(
+  const APropertyName : string;
+  const AOperator : TNumericFilterOperator;
+  const AEnumValue : string;
+  const AConnector : TFilterConnector
+) : TRttiFilterCreator;
+begin
+  AddNode(
+    TRttiExpEnumNodeItem.Create(GetPropInfo(TargetClass,APropertyName),AOperator,AEnumValue),
+    AConnector
+  );
+  Result := Self;
+end;
+
+function TRttiFilterCreator.AddCondition(
+  const APropertyName : string;
+  const AOperator     : TStringFilterOperator;
+  const AValue        : AnsiString;
+  const AConnector    : TFilterConnector
+): TRttiFilterCreator;
+begin
+  AddNode(
+    TRttiExpAnsiStringNodeItem.Create(GetPropInfo(TargetClass,APropertyName),AOperator,AValue),
+    AConnector
+  );
+  Result := Self;
+end;
+
+function TRttiFilterCreator.AddCondition(
+  const APropertyName : string;
+  const AOperator     : TStringFilterOperator;
+  const AValue        : WideString;
+  const AConnector    : TFilterConnector
+): TRttiFilterCreator;
+begin
+  AddNode(
+    TRttiExpWideStringNodeItem.Create(GetPropInfo(TargetClass,APropertyName),AOperator,AValue),
+    AConnector
+  );
+  Result := Self;
+end;
+
+{$IFDEF USE_UNICODE}
+function TRttiFilterCreator.AddCondition(
+  const APropertyName: string;
+  const AOperator: TStringFilterOperator;
+  const AValue: UnicodeString;
+  const AConnector: TFilterConnector
+) : TRttiFilterCreator;
+begin
+  AddNode(
+    TRttiExpUnicodeStringNodeItem.Create(GetPropInfo(TargetClass,APropertyName),AOperator,AValue),
+    AConnector
+  );
+  Result := Self;
+end;
+{$ENDIF USE_UNICODE}
+
+function TRttiFilterCreator.BeginGroup(const AConnector: TFilterConnector):TRttiFilterCreator;
+var
+  gn : TRttiExpNode;
+begin
+  {if not Assigned(FCurrent) then
+    AddNode(TRttiExpNode.Create(),fcNone);}
+  gn := TRttiExpNode.Create();
+  AddNode(gn,AConnector);
+  PushCurrent(gn);
+  Result := Self;
+end;
+
+function TRttiFilterCreator.EndGroup(): TRttiFilterCreator;
+begin
+  PopCurrent();
+  Result := Self;
+end;
+
+{ TRttiObjectFilter }
+
+function TRttiObjectFilter.Evaluate(const AObject: TObject): Boolean;
+begin
+  Result := FFilterRoot.Evaluate(TRttiFilterCreatorTarget(AObject));
+end;
+
+constructor TRttiObjectFilter.Create(
+        AFilterRoot              : TRttiExpNodeItem;
+  const AOnDestroyFilterAction   : TClearAction
+);
+begin
+  Assert(Assigned(AFilterRoot));
+  FFilterRoot := AFilterRoot;
+  FOnDestroyFilterAction := AOnDestroyFilterAction;
+end;
+
+destructor TRttiObjectFilter.Destroy();
+begin
+  if ( FOnDestroyFilterAction = clrFreeObjects ) then
+    ClearObject(FFilterRoot);
+  inherited Destroy();
+end;
+
+{ TRttiExpNumericNodeItem }
+
+constructor TRttiExpNumericNodeItem.Create(
+  const APropInfo: PPropInfo;
+  const AOperation: TNumericFilterOperator
+);
+begin
+  Assert(Assigned(APropInfo));
+  inherited Create(APropInfo);
+  FOperation := AOperation;
+end;
+
+{ TRttiExpStringNodeItem }
+
+constructor TRttiExpStringNodeItem.Create(
+  const APropInfo: PPropInfo;
+  const AOperation: TStringFilterOperator
+);
+begin
+  Assert(Assigned(APropInfo));
+  inherited Create(APropInfo);
+  FOperation := AOperation;
+end;
+
+{ TRttiExpAnsiStringNodeItem }
+
+constructor TRttiExpAnsiStringNodeItem.Create(
+  const APropInfo: PPropInfo;
+  const AOperation: TStringFilterOperator;
+  const AComparedValue: AnsiString
+);
+begin
+  Assert(Assigned(APropInfo));
+  if not ( APropInfo^.PropType^.Kind in [{$IFDEF FPC}tkSString,tkAString,{$ENDIF}tkLString] ) then
+    raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['AnsiString']);
+  inherited Create(APropInfo,AOperation);
+  FComparedValue := AComparedValue;
+end;
+
+function TRttiExpAnsiStringNodeItem.Evaluate(AInstance: TRttiFilterCreatorTarget): Boolean;
+begin
+  case Operation of
+    sfoEqualCaseSensitive   :  Result := ( GetStrProp(AInstance,PropInfo) = ComparedValue );
+    sfoEqualCaseInsensitive :  Result := AnsiSameText(GetStrProp(AInstance,PropInfo),ComparedValue);
+    sfoNotEqual             :  Result := ( GetStrProp(AInstance,PropInfo) <> ComparedValue);
+    else begin
+      Assert(False);
+      Result := False;
+    end;
+  end;
+end;
+
+{ TRttiExpWideStringNodeItem }
+
+constructor TRttiExpWideStringNodeItem.Create(
+  const APropInfo: PPropInfo;
+  const AOperation: TStringFilterOperator;
+  const AComparedValue: WideString
+);
+begin
+  Assert(Assigned(APropInfo));
+  if not ( APropInfo^.PropType^.Kind in [tkWString{$IFDEF USE_UNICODE},tkUString{$ENDIF}] ) then
+    raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted, got "%s".',['WideString',GetEnumName(TypeInfo(TTypeKind),Ord(APropInfo^.PropType^.Kind))]);
+  inherited Create(APropInfo,AOperation);
+  FComparedValue := AComparedValue;
+end;
+
+function TRttiExpWideStringNodeItem.Evaluate(AInstance: TRttiFilterCreatorTarget): Boolean;
+begin
+  case Operation of
+    sfoEqualCaseSensitive   :  Result := ( GetWideStrProp(AInstance,PropInfo) = ComparedValue );
+    sfoEqualCaseInsensitive :  Result := ( LowerCase(GetWideStrProp(AInstance,PropInfo)) = LowerCase(ComparedValue) );
+    sfoNotEqual             :  Result := not SameText(GetWideStrProp(AInstance,PropInfo),ComparedValue);
+    else begin
+      Assert(False);
+      Result := False;
+    end;
+  end;
+end;
+
+{$IFDEF USE_UNICODE}
+{ TRttiExpUnicodeStringNodeItem }
+
+constructor TRttiExpUnicodeStringNodeItem.Create(
+  const APropInfo: PPropInfo;
+  const AOperation: TStringFilterOperator;
+  const AComparedValue: UnicodeString
+);
+begin
+  Assert(Assigned(APropInfo));
+  if not ( APropInfo^.PropType^.Kind in [tkUString,tkWString] ) then
+    raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted, got "%s".',['UnicodeString',GetEnumName(TypeInfo(TTypeKind),Ord(APropInfo^.PropType^.Kind))]);
+  inherited Create(APropInfo,AOperation);
+  FComparedValue := AComparedValue;
+end;
+
+function TRttiExpUnicodeStringNodeItem.Evaluate(
+  AInstance: TRttiFilterCreatorTarget
+): Boolean;
+begin
+  case Operation of
+    sfoEqualCaseSensitive   :  Result := ( GetUnicodeStrProp(AInstance,PropInfo) = ComparedValue );
+    sfoEqualCaseInsensitive :  Result := ( LowerCase(GetUnicodeStrProp(AInstance,PropInfo)) = LowerCase(ComparedValue));
+    sfoNotEqual             :  Result := not SameText(GetUnicodeStrProp(AInstance,PropInfo),ComparedValue);
+    else
+      Assert(False);
+  end;
+end;
+{$ENDIF USE_UNICODE}
+
+{ TRttiExpEnumNodeItem }
+
+constructor TRttiExpEnumNodeItem.Create(
+  const APropInfo : PPropInfo;
+  const AOperation : TNumericFilterOperator;
+  const AComparedValue : string
+);
+{$IFDEF HAS_TKBOOL}
+var
+  locEnumOrder : Integer;
+  locBoolVal : Boolean;
+begin
+  Assert(Assigned(APropInfo));
+  if not ( APropInfo^.PropType^.Kind in [tkEnumeration,tkBool] ) then
+    raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['Enumeration']);
+  if ( APropInfo^.PropType^.Kind = tkBool ) then begin
+    if not TryStrToBool(AComparedValue,locBoolVal) then
+      raise ERttiFilterException.CreateFmt('Unknown boolean value : "%s", type : %s .',[AComparedValue,APropInfo^.PropType^.Name]);
+    locEnumOrder := Ord(locBoolVal);
+  end else begin
+    locEnumOrder := GetEnumValue(APropInfo^.PropType,AComparedValue);
+    if ( locEnumOrder < 0 ) then
+      raise ERttiFilterException.CreateFmt('Unknown enumeration value : "%s", type : %s .',[AComparedValue,APropInfo^.PropType^.Name]);
+  end;
+  inherited Create(APropInfo,AOperation,locEnumOrder);
+end;
+{$ELSE}
+var
+  locEnumOrder : Integer;
+begin
+  Assert(Assigned(APropInfo));
+  if not ( APropInfo^.PropType^.Kind = tkEnumeration ) then
+    raise ERttiFilterException.CreateFmt('Invalid property data type. "%s" excpeted.',['Enumeration']);
+  locEnumOrder := GetEnumValue(APropInfo^.PropType{$IFDEF DELPHI}^{$ENDIF},AComparedValue);
+  if ( locEnumOrder < 0 ) then
+    raise ERttiFilterException.CreateFmt('Unknown enumeration value : "%s", type : %s .',[AComparedValue,APropInfo^.PropType^.Name]);
+  inherited Create(APropInfo,AOperation,locEnumOrder);
+end;
+{$ENDIF}
+
+end.

+ 2955 - 0
packages/fcl-sdo/src/base/sdo_serialization.pas

@@ -0,0 +1,2955 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements binary serialization. The payload is architecture free.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_serialization;
+
+interface
+
+uses
+  SysUtils, Classes, Contnrs,
+  sdo, sdo_types,
+  sdo_serialization_utils, sdo_serialization_xml;
+
+const
+  MAX_NESTED_LEVEL = 256;
+    
+type
+
+  TObjectWriteOption = ( owoWriteChangeSummary, owoWriteReference, owoPostRefProperties );
+  TObjectWriteOptions = set of TObjectWriteOption;
+  TObjectReadOption = ( oroDontMake_BeginObjectRead, oroDontMake_EndScopeRead );
+  TObjectReadOptions = set of TObjectReadOption;
+  TReferenceObjectRecallItemType = ( rritPropertyValue, rritSettingItem );
+  TPropListWriterProc = procedure (const AName : string; const AValueList : ISDODataObjectList) of object;
+  TPropWriterProc = procedure (const AProp : ISDOProperty; const AObject : ISDODataObject) of object;
+  TPropListReaderProc = procedure (const AName : string; const AValueList : ISDODataObjectList) of object;
+  TPropReaderProc = procedure (const AProp : ISDOProperty; const AObject : ISDODataObject) of object;
+  TPropHandlerInfo = record
+    PropType : ISDOType;
+    WriterProc     : TPropWriterProc;
+    WriterListProc : TPropListWriterProc;
+    ReaderProc     : TPropReaderProc;
+    ReaderListProc : TPropListReaderProc;
+  end;
+  TSDOSerializer = class(TInterfacedObject, IInterface, ISDOSerializer)
+  private
+    FDataFactory : ISDODataFactory;
+    FStreamer : ISDOSerializerStream;
+    FNamespace : string;
+    FWriteStarted : Boolean;
+    FWriteEnded : Boolean;
+    FProcs : array[TSDOTypeKind] of TPropHandlerInfo;
+  private
+    FSerializationStyleStack : array[0..(MAX_NESTED_LEVEL-1)] of TSerializationStyle;
+    FSerializationStyleStackIndex : PtrInt;
+    FRootName : string;
+    FReferenceWriteRecallList : TObjectList;
+    FReferenceReadRecallList : TObjectList;
+    FChangeSummaryList : ISDODataObject;
+    FChangeSummary : ISDOChangeSummary;
+    FOptions : TSerializerOptions;
+  private
+    procedure Init();
+    procedure PushSerializationStyle(const AValue : TSerializationStyle);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure PopSerializationStyle();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function getType(const AKind : TSDOTypeKind) : ISDOType;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function getSerializationStyle(const AProperty : ISDOProperty) : TSerializationStyle;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+    procedure WriteMetadata();
+    procedure BeginWrite();
+    procedure EndWrite();
+
+    procedure ReadMetadata();
+
+    procedure WriteBoolListProp(const AName : string; const AValueList : ISDODataObjectList);
+    procedure WriteByteListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$IFDEF HAS_SDO_BYTES}
+    procedure WriteBytesListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure WriteCharListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure WriteCurrencyListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure WriteDateListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure WriteDoubleListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure WriteFloatListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_FLOAT}
+    procedure WriteIntegerListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$IFDEF HAS_SDO_LONG}
+    procedure WriteLongListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure WriteShortListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_SHORT}
+    procedure WriteStringListProp(const AName : string; const AValueList : ISDODataObjectList);
+
+    procedure WriteBoolProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+    procedure WriteByteProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$IFDEF HAS_SDO_BYTES}
+    procedure WriteBytesProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure WriteCharProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure WriteCurrencyProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure WriteDateProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure WriteDoubleProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure WriteFloatProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_FLOAT}
+    procedure WriteIntegerProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$IFDEF HAS_SDO_LONG}
+    procedure WriteLongProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure WriteShortProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_SHORT}
+    procedure WriteStringProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+
+    procedure ReadBoolProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+    procedure ReadByteProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$IFDEF HAS_SDO_BYTES}
+    procedure ReadBytesProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure ReadCharProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure ReadCurrencyProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure ReadDateProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure ReadDoubleProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure ReadFloatProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_FLOAT}
+    procedure ReadIntegerProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$IFDEF HAS_SDO_LONG}
+    procedure ReadLongProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure ReadShortProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+{$ENDIF HAS_SDO_SHORT}
+    procedure ReadStringProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+
+    procedure ReadBoolListProp(const AName : string; const AValueList : ISDODataObjectList);
+    procedure ReadByteListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$IFDEF HAS_SDO_BYTES}
+    procedure ReadBytesListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure ReadCharListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure ReadCurrencyListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure ReadDateListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure ReadDoubleListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure ReadFloatListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_FLOAT}
+    procedure ReadIntegerListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$IFDEF HAS_SDO_LONG}
+    procedure ReadLongListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure ReadShortListProp(const AName : string; const AValueList : ISDODataObjectList);
+{$ENDIF HAS_SDO_SHORT}
+    procedure ReadStringListProp(const AName : string; const AValueList : ISDODataObjectList);
+
+    function InternalReadObject(
+      const AName : string;
+      const AType : ISDOType;
+      const AOwner,
+            ADataObject : ISDODataObject;
+      const AOptions : TObjectReadOptions
+    ) : ISDODataObject;
+    procedure InternalWriteObject(
+      const AName : string;
+      const AObject : ISDODataObject;
+      const AOptions : TObjectWriteOptions;
+      const AReference : TSDOString
+    );
+    procedure AddPropertyRefRecallWrite(
+      const ARecallType : TReferenceObjectRecallItemType;
+      const ADataObject : ISDODataObject;
+      const AProperty : ISDOProperty;
+      const AValue : ISDODataObject
+    );
+    function AddToChangeSummaryList(const ADataObject : ISDODataObject) : TSDOString;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure WritePendingRefProps();
+    procedure ReadPendingRefProps();
+    procedure WriteChangeSummaryMultiValueProps(
+      const ACS : ISDOChangeSummary;
+      const ADataObject : ISDODataObject
+    );
+    function getObjectPathInChangeSummary(const AObj : ISDODataObject) : TSDOString;
+  protected
+    function  GetDataFactory() : ISDODataFactory;
+    function  GetStreamer() : ISDOSerializerStream;
+    procedure WriteObject(
+      const AName : string;
+      const AObject : ISDODataObject;
+      const AOptions : TObjectWriteOptions;
+      const AReference : string
+    );
+    function ReadObject(
+      const AName : string;
+      const AType : ISDOType;
+      const AOwner : ISDODataObject
+    ) : ISDODataObject;
+    procedure WriteChangeSummary(
+      const AValue : ISDOChangeSummary;
+      const ARootObjectName : string
+    );
+    procedure ReadChangeSummary(
+      const AValue : ISDOChangeSummary;
+      const ARootObjectName : string;
+      const ARootObject : ISDODataObject
+    );
+
+    // ISDOSerializer implementation
+    procedure save(
+      const AName : string;
+            AObject : ISDODataObject;
+      const ADestStream : TStream
+    );overload;
+    procedure save(
+            AObject : ISDODataObject;
+      const ADestStream : TStream
+    );overload;
+    procedure save(
+      const AName : string;
+            AObject : ISDODataObject;
+      const AFileName : string
+    );overload;
+    procedure save(
+            AObject : ISDODataObject;
+      const AFileName : string
+    );overload;
+
+    procedure load(
+      const AStream : TStream;
+            ADestList : ISDODataObjectList
+    );overload;
+    procedure load(
+      const AFileName : string;
+            ADestList : ISDODataObjectList
+    );overload;
+    function load(const AStream : TStream) : ISDODataObject;overload;
+    function load(const AFileName : string) : ISDODataObject;overload;
+
+    // these are the implementation's extensions
+    function getOptions() : TSerializerOptions;
+    procedure setOptions(const AValue : TSerializerOptions);
+  public
+    constructor Create(
+      ADataFactory : ISDODataFactory;
+      AStreamer    : ISDOSerializerStream
+    );
+    destructor Destroy();override;
+  end;
+
+
+implementation
+
+uses
+  TypInfo, sdo_consts, sdo_xsd_helper,
+  StrUtils, sdo_imp_utils, sdo_xpath_helper, sdo_changesummary,
+  sdo_utils, sdo_dataobject;
+
+const
+  //TManyValuePropAction = ( mvpaAppend, mvpaInsert, mvpaChange, mvpaDelete );
+  PROP_ACTION_STRING : array[TManyValuePropAction] of TSDOString = (
+                         s_append, s_insert, s_change, s_delete
+                       );
+
+function FindAction(const AString : string; out ARes : TManyValuePropAction) : Boolean;
+var
+  k : TManyValuePropAction;
+begin
+  Result := False;
+  for k := Low(TManyValuePropAction) to High(TManyValuePropAction) do begin
+    if AnsiSameText(AString,PROP_ACTION_STRING[k]) then begin
+      ARes := k;
+      Result := True;
+      Break;
+    end;
+  end;
+end;
+
+function getObjectPath(
+  const ADataObject : ISDODataObject;
+  const ARootObjectName : string
+) : TSDOString ;
+var
+  locStrBuffer : TSDOString;
+begin
+  locStrBuffer := Trim(getXpath(ADataObject));
+  if IsStrEmpty(locStrBuffer) then
+    locStrBuffer := Format('#/%s',[ARootObjectName])
+  else
+    locStrBuffer := Format('#/%s/%s',[ARootObjectName,locStrBuffer]);
+  Result := locStrBuffer;
+end;
+
+type
+  TReferenceObjectWriteRecall = class
+  private
+    FValue: ISDODataObject;
+    FDataObject: ISDODataObject;
+    FProp: ISDOProperty;
+    FStreamPos: TStreamBookmark;
+    FRecallType: TReferenceObjectRecallItemType;
+  public
+    destructor Destroy();override;
+    property StreamPos : TStreamBookmark read FStreamPos;
+    property RecallType : TReferenceObjectRecallItemType read FRecallType;
+    property DataObject : ISDODataObject read FDataObject;
+    property Prop : ISDOProperty read FProp;
+    property Value : ISDODataObject read FValue;
+  end;
+
+{ TReferenceObjectWriteRecall }
+
+destructor TReferenceObjectWriteRecall.Destroy();
+begin
+  FreeAndNil(FStreamPos);
+  inherited;
+end;
+
+{ TSDOSerializer }
+
+procedure TSDOSerializer.BeginWrite();
+begin
+  if not FWriteStarted then begin
+    FWriteStarted := True;
+
+    FStreamer.SetSerializationStyle(ssAttibuteSerialization);
+    FStreamer.SetNameStyle(nsQualified);
+    try
+      FStreamer.BeginObject(s_datagraph,FDataFactory.getType(sdo_namespace,s_datagraph));
+    finally
+      FStreamer.SetNameStyle(nsUnqualified);
+    end;
+    if not (soExcludeSchema in FOptions) then
+      WriteMetadata();
+  end;
+end;
+
+constructor TSDOSerializer.Create(
+  ADataFactory : ISDODataFactory;
+  AStreamer    : ISDOSerializerStream
+);
+begin
+  if ( ADataFactory = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADataFactory');
+  if ( AStreamer = nil ) then
+    raise ESDOIllegalArgumentException.Create('AStreamer');
+  FDataFactory := ADataFactory;
+  FStreamer := AStreamer;
+  FReferenceWriteRecallList := TObjectList.Create(True);
+  FReferenceReadRecallList := TObjectList.Create(True);
+  
+  FProcs[BooleanType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]);
+  FProcs[BooleanType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteBoolProp;
+  FProcs[BooleanType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteBoolListProp;
+  FProcs[BooleanType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadBoolProp;
+  FProcs[BooleanType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadBoolListProp;
+
+  FProcs[ByteType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ByteType]);
+  FProcs[ByteType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteByteProp;
+  FProcs[ByteType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteByteListProp;
+  FProcs[ByteType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadByteProp;
+  FProcs[ByteType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadByteListProp;
+
+{$IFDEF HAS_SDO_BYTES}
+  FProcs[BytesType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BytesType]);
+  FProcs[BytesType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteBytesProp;
+  FProcs[BytesType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteBytesListProp;
+  FProcs[BytesType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadBytesProp;
+  FProcs[BytesType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadBytesListProp;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  FProcs[CharacterType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[CharacterType]);
+  FProcs[CharacterType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteCharProp;
+  FProcs[CharacterType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteCharListProp;
+  FProcs[CharacterType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadCharProp;
+  FProcs[CharacterType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadCharListProp;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  FProcs[CurrencyType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType]);
+  FProcs[CurrencyType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteCurrencyProp;
+  FProcs[CurrencyType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteCurrencyListProp;
+  FProcs[CurrencyType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadCurrencyProp;
+  FProcs[CurrencyType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadCurrencyListProp;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+  FProcs[DoubleType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[DoubleType]);
+  FProcs[DoubleType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteDoubleProp;
+  FProcs[DoubleType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteDoubleListProp;
+  FProcs[DoubleType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadDoubleProp;
+  FProcs[DoubleType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadDoubleListProp;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  FProcs[FloatType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[FloatType]);
+  FProcs[FloatType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteFloatProp;
+  FProcs[FloatType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteFloatListProp;
+  FProcs[FloatType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadFloatProp;
+  FProcs[FloatType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadFloatListProp;
+{$ENDIF HAS_SDO_FLOAT}
+
+  FProcs[DateTimeType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType]);
+  FProcs[DateTimeType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteDateProp;
+  FProcs[DateTimeType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteDateListProp;
+  FProcs[DateTimeType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadDateProp;
+  FProcs[DateTimeType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadDateListProp;
+
+  FProcs[IntegerType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]);
+  FProcs[IntegerType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteIntegerProp;
+  FProcs[IntegerType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteIntegerListProp;
+  FProcs[IntegerType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadIntegerProp;
+  FProcs[IntegerType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadIntegerListProp;
+
+{$IFDEF HAS_SDO_LONG}
+  FProcs[LongType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[LongType]);
+  FProcs[LongType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteLongProp;
+  FProcs[LongType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteLongListProp;
+  FProcs[LongType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadLongProp;
+  FProcs[LongType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadLongListProp;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  FProcs[ShortType].PropType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ShortType]);
+  FProcs[ShortType].WriterProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteShortProp;
+  FProcs[ShortType].WriterListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteShortListProp;
+  FProcs[ShortType].ReaderProc     := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadShortProp;
+  FProcs[ShortType].ReaderListProc := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadShortListProp;
+{$ENDIF HAS_SDO_SHORT}
+
+  FProcs[StringType].PropType  := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]);
+  FProcs[StringType].WriterProc      := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteStringProp;
+  FProcs[StringType].WriterListProc  := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}WriteStringListProp;
+  FProcs[StringType].ReaderProc      := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadStringProp;
+  FProcs[StringType].ReaderListProc  := {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}ReadStringListProp;
+end;
+
+destructor TSDOSerializer.Destroy();
+begin
+  try
+    EndWrite();
+  finally
+    FreeAndNil(FReferenceWriteRecallList);
+    FreeAndNil(FReferenceReadRecallList);
+  end;
+  inherited;
+end;
+
+procedure TSDOSerializer.EndWrite();
+begin
+  if FWriteStarted then begin
+    if not FWriteEnded then begin
+      FWriteEnded := True;
+      FStreamer.EndScope();
+    end;
+  end;
+end;
+
+function TSDOSerializer.GetDataFactory() : ISDODataFactory;
+begin
+  Result := FDataFactory;
+end;
+
+function TSDOSerializer.GetStreamer() : ISDOSerializerStream;
+begin
+  Result := FStreamer;
+end;
+
+function TSDOSerializer.getType(const AKind: TSDOTypeKind): ISDOType;
+begin
+  Result := FProcs[AKind].PropType;
+end;
+
+procedure TSDOSerializer.Init();
+  procedure ClearChangeSummaryList();
+  var
+    pl : ISDOPropertyList;
+    p : ISDOProperty;
+    ls : ISDODataObjectList;
+    k, kx : PtrInt;
+  begin
+    pl := FChangeSummaryList.getInstanceProperties();
+    for k := 0 to Pred(pl.getCount()) do begin
+      p := pl.getItem(k);
+      if p.getType().isDataObjectType() then begin
+        if not p.isMany() then begin
+          FChangeSummaryList.setDataObject(p,nil);
+        end else begin
+          ls := FChangeSummaryList.getList(p);
+          kx := ls.size();
+          if ( kx > 0 ) then begin
+            for kx := 1 to kx do
+              ls.delete(0);
+          end;
+        end;
+      end;
+    end;
+  end;
+
+begin
+  if ( FChangeSummaryList <> nil ) then begin
+    ClearChangeSummaryList();
+    FChangeSummaryList := nil;
+  end;
+  FWriteStarted := False;
+  FWriteEnded := False;
+  FSerializationStyleStackIndex := -1;
+  FNamespace := '';
+  if Assigned(FStreamer) then
+    FStreamer.Clear();
+  FReferenceWriteRecallList.Clear();
+  FReferenceReadRecallList.Clear();
+end;
+
+procedure TSDOSerializer.load(const AStream: TStream; ADestList: ISDODataObjectList);
+var
+  i, c : PtrInt;
+  scopeList : TStringList;
+  s : string;
+  obj : ISDODataObject;
+begin
+  Init();
+  try
+    FStreamer.LoadFromStream(AStream);
+    scopeList := TStringList.Create();
+    try
+      if ( FStreamer.GetScopeItemNames(ssNodeSerialization,scopeList) > 0 ) then begin
+        if ( scopeList.IndexOf(s_xsd) >= 0 ) then
+          ReadMetadata();
+        c := scopeList.Count;
+        if ( c > 0 ) then begin
+          FStreamer.SetSerializationStyle(ssAttibuteSerialization);
+          for i := 0 to Pred(c) do begin
+            s := scopeList[i];
+            if ( AnsiIndexStr(s,[s_xsd,s_changesummary]) < 0 ) then begin
+              FStreamer.SetNameStyle(nsQualified);
+              obj := ReadObject(s, nil, nil);
+              ADestList.append(obj);
+              scopeList.Objects[i] := TObject(obj);
+            end;
+          end;
+          ReadPendingRefProps();
+          if ( scopeList.IndexOf(s_changesummary) > -1 ) then begin
+            c := ADestList.size();
+            obj := nil;
+            for i := 0 to Pred(c) do begin
+              if ( ADestList.getDataObject(i).getChangeSummary() <> nil ) then begin
+                obj := ADestList.getDataObject(i);
+                Break;
+              end;
+            end;
+            if ( obj = nil ) then
+              raise ESDOSerializationException.Create('Invalid data stream : the stream contains a changes summary and no object to hold it.');
+            i := scopeList.IndexOfObject(TObject(obj));
+            ReadChangeSummary(obj.getChangeSummary(),scopeList[i],obj);
+          end;
+        end;
+      end;
+    finally
+      scopeList.Free();
+    end;
+  finally
+    Init();
+  end;
+end;
+
+procedure TSDOSerializer.load(const AFileName : string; ADestList : ISDODataObjectList);
+var
+  flStream : TStream;
+begin
+  if not FileExists(AFileName) then
+    raise ESDOSerializationException.CreateFmt(SMSG_FileNotFound,[AFileName]);
+  flStream := TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
+  try
+    load(flStream,ADestList);
+  finally
+    flStream.Free();
+  end;
+end;
+
+function TSDOSerializer.load(const AStream: TStream) : ISDODataObject;
+var
+  ls : ISDODataObjectList;
+begin
+  ls := TSDODataObjectList.Create(FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType])) as ISDODataObjectList;
+  load(AStream,ls);
+  if ( ls.size() > 0 ) then
+    Result := ls.getDataObject(0)
+  else
+    raise ESDOSerializationException.Create('No object found in this stream.');
+end;
+
+type
+  TMultiValueRecallData = packed record
+    Action : TManyValuePropAction;
+    ActionIndex : PtrInt;
+    Index : PtrInt;
+  end;
+
+  TReferenceObjectReadRecall = class
+  private
+    FDataObject: ISDODataObject;
+    FRoot: ISDODataObject;
+    FReferenceProperty: ISDOProperty;
+    FAccessPath: string;
+    FRecallType: TReferenceObjectRecallItemType;
+    FIsSet: Boolean;
+    FMultiValueData: TMultiValueRecallData;
+  public
+    constructor Create(
+      const ARecallType : TReferenceObjectRecallItemType;
+      const ARoot : ISDODataObject;
+      const ADataObject : ISDODataObject;
+      const AReferenceProperty : ISDOProperty;
+      const AAccessPath : string;
+      const AIsSet : Boolean
+    );
+    property IsSet : Boolean read FIsSet;
+    property RecallType : TReferenceObjectRecallItemType read FRecallType;
+    property Root : ISDODataObject read FRoot;
+    property DataObject : ISDODataObject read FDataObject;
+    property ReferenceProperty : ISDOProperty read FReferenceProperty;
+    property AccessPath : string read FAccessPath;
+    property MultiValueData : TMultiValueRecallData read FMultiValueData;
+  end;
+
+procedure TSDOSerializer.AddPropertyRefRecallWrite(
+  const ARecallType : TReferenceObjectRecallItemType;
+  const ADataObject: ISDODataObject;
+  const AProperty: ISDOProperty;
+  const AValue: ISDODataObject
+);
+var
+  locRecall : TReferenceObjectWriteRecall;
+begin
+  locRecall := TReferenceObjectWriteRecall.Create();
+  try
+    locRecall.FRecallType := ARecallType;
+    locRecall.FDataObject := ADataObject;
+    locRecall.FProp := AProperty;
+    locRecall.FStreamPos := FStreamer.GetBookMark();
+    locRecall.FValue := AValue
+  except
+    FreeAndNil(locRecall);
+    raise;
+  end;
+  FReferenceWriteRecallList.Add(locRecall);
+end;
+
+procedure TSDOSerializer.ReadPendingRefProps();
+
+  function FindDataObject(
+    const AItem : TReferenceObjectReadRecall;
+    const APath : string;
+    out AIndex : PtrInt;
+    const AContainingRoot : ISDODataObject = nil
+  ) : ISDODataObject;
+  var
+    locExpr : TXPathExpression;
+    locProc : TXPathProcessor;
+    locCtx : TXPathExecContext;
+  begin
+    locProc := nil;
+    locExpr := TXPathExpression.Create();
+    try
+      locExpr.SetRoot(ParseXPath(APath));
+      locProc := TXPathProcessor.Create();
+      if ( AContainingRoot = nil ) then
+        locProc.Context.SetObject(AItem.Root,nil)
+      else
+        locProc.Context.SetObject(AContainingRoot,nil);
+      locProc.Execute(locExpr);
+      locCtx := locProc.Context;
+      if ( locCtx.PropertyOwner = nil ) or ( locCtx.CurrentProperty = nil ) then
+        raise ESDOInvalidPathException.Create(APath);
+      if locCtx.CurrentProperty.isMany() then begin
+        Result := locCtx.ListItem.getDataObject();
+        AIndex := locCtx.ListItem.getCursor().GetPosition();
+      end else begin
+        Result := locCtx.PropertyOwner.getDataObject(locCtx.CurrentProperty);
+        AIndex := 0;
+      end;
+    finally
+      locProc.Free();
+      locExpr.Free();
+    end;
+  end;
+
+  procedure InternalReadPendingRefProps_Properties();
+  var
+    k : PtrInt;
+    itm : TReferenceObjectReadRecall;
+    tmpBuffer : string;
+    tmpObject : ISDODataObject;
+    i : PtrInt;
+  begin
+    if ( FReferenceReadRecallList.Count > 0 ) then begin
+      for k := 0 to Pred(FReferenceReadRecallList.Count) do begin
+        itm := TReferenceObjectReadRecall(FReferenceReadRecallList[k]);
+        if ( itm.RecallType = rritPropertyValue ) then begin
+          tmpBuffer := xpath_ExcludeRootElement(itm.AccessPath,FRootName);
+          if ( Pos(s_changeSummary + '/',tmpBuffer) = 1 ) then
+            tmpObject := FChangeSummaryList.getDataObject(Copy(tmpBuffer, ( Length(s_changeSummary) + 1 {/} ), MaxInt))
+          else
+            tmpObject := FindDataObject(itm,tmpBuffer,i);
+          itm.DataObject.setDataObject(itm.ReferenceProperty,tmpObject)
+        end;
+      end;
+    end;
+  end;
+
+  procedure InternalReadPendingRefProps_Settings();
+  var
+    k : PtrInt;
+    itm : TReferenceObjectReadRecall;
+    tmpBuffer : string;
+    tmpObject : ISDODataObject;
+    ls : ISDOChangedDataObjectList;
+    lsX : ISDOChangedDataObjectListEx;
+    i, q, loc_index : PtrInt;
+  begin
+    if ( FReferenceReadRecallList.Count > 0 ) then begin
+      for k := 0 to Pred(FReferenceReadRecallList.Count) do begin
+        itm := TReferenceObjectReadRecall(FReferenceReadRecallList[k]);
+        if ( itm.RecallType = rritSettingItem ) then begin
+          tmpBuffer := xpath_ExcludeRootElement(itm.AccessPath,FRootName);
+          if ( Pos(s_changeSummary + '/',tmpBuffer) = 1 ) then begin
+            tmpBuffer := Copy(tmpBuffer, ( Length(s_changeSummary) + 1 {/} + 1 ), MaxInt);
+            tmpObject := FindDataObject(itm,tmpBuffer,loc_index,FChangeSummaryList);
+            loc_index := 0;
+          end else begin
+            tmpObject := FindDataObject(itm,tmpBuffer,loc_index);
+          end;
+          ls := itm.Root.getChangeSummary.getChangedDataObjects();
+          if ( ls = nil ) then
+            raise ESDOSerializationException.Create('Unable to find ChangeSummary.');
+          lsX := ls as ISDOChangedDataObjectListEx;
+          if not lsX.find(itm.DataObject,i) then
+            raise ESDOSerializationException.Create('Invalid ChangeSummary stream.');
+          if ( tmpObject <> nil ) and itm.ReferenceProperty.isContainment() then begin
+            (tmpObject as ISDODataObjectEx).setContainer(itm.DataObject, itm.ReferenceProperty);
+            if lsX.find(tmpObject,q) then
+              lsX.getInfo(q).CaptureOldContainment();
+          end;
+          if itm.ReferenceProperty.isMany() then
+            lsX.getInfo(i).GetChanges(itm.ReferenceProperty).AddAt(itm.MultiValueData.Index,itm.MultiValueData.Action,itm.MultiValueData.ActionIndex,tmpObject)
+          else
+            lsX.getInfo(i).ChangeList.append(TValueSetting.Create(itm.IsSet, (tmpObject = nil), tmpObject, itm.ReferenceProperty,loc_index));
+        end;
+      end;
+    end;
+  end;
+
+begin
+  InternalReadPendingRefProps_Properties();
+  InternalReadPendingRefProps_Settings();
+  FReferenceReadRecallList.Clear();
+end;
+
+function TSDOSerializer.AddToChangeSummaryList(const ADataObject: ISDODataObject): TSDOString;
+var
+  objTypeName : TSDOString;
+  pls : ISDODataObjectList;
+begin
+  objTypeName := ADataObject.getType().getName();
+  if ( FChangeSummaryList.getInstanceProperties().find(objTypeName) = nil ) then
+    FDataFactory.addProperty(FChangeSummaryList,objTypeName,ADataObject.getType(),[pfIsMany]);
+  pls := FChangeSummaryList.getList(objTypeName);
+  pls.append(ADataObject);
+  Result := Format('#/%s/%s[%d]',[s_changeSummary,objTypeName,pls.getCursor().GetPosition()]);
+end;
+
+procedure TSDOSerializer.WriteChangeSummaryMultiValueProps(
+  const ACS: ISDOChangeSummary;
+  const ADataObject: ISDODataObject
+);
+var
+  locIntType, locStringType : ISDOType;
+
+  procedure WriteItem_non_ref_type(const AItem : TManyValuePropChanges);
+  var
+    q, k : PtrInt;
+    ch : TManyValuePropRecordData;
+    pt : ISDOType;
+  begin
+    q := AItem.Count;
+    if ( q > 0 ) then begin
+      pt := AItem.Prop.getType();
+      FStreamer.BeginObject(AItem.Prop.getName(), pt);
+        for k := 0 to Pred(q) do begin
+          FStreamer.BeginObject(s_listChanges, pt);
+            ch := AItem.GetItem(k);
+            PushSerializationStyle(ssAttibuteSerialization);
+              FStreamer.Put(s_index, locIntType, ch.Index);
+              FStreamer.Put(s_kind, locStringType, PROP_ACTION_STRING[ch.Action]);
+            PopSerializationStyle();
+            if ( ch.Action in [mvpaChange, mvpaDelete] ) then
+              FStreamer.Put(s_dataValues, pt, ch.Value);
+          FStreamer.EndScope();
+        end;
+      FStreamer.EndScope();
+    end;
+  end;
+
+  procedure WriteItem_object_type(const AItem : TManyValuePropChanges);
+  var
+    q, k : PtrInt;
+    ch : TManyValuePropRecordData;
+    pt : ISDOType;
+  begin
+    q := AItem.Count;
+    if ( q > 0 ) then begin
+      pt := AItem.Prop.getType();
+      FStreamer.BeginObject(AItem.Prop.getName(), pt);
+        for k := 0 to Pred(q) do begin
+          FStreamer.BeginObject(s_listChanges, pt);
+            ch := AItem.GetItem(k);
+            PushSerializationStyle(ssAttibuteSerialization);
+              FStreamer.Put(s_index, locIntType, ch.Index);
+              FStreamer.Put(s_kind, locStringType, PROP_ACTION_STRING[ch.Action]);
+            PopSerializationStyle();
+            if ( ch.Action in [mvpaChange, mvpaDelete] ) then
+              AddPropertyRefRecallWrite(rritSettingItem,ADataObject,AItem.Prop,ch.Value.ObjectValue^);
+          FStreamer.EndScope();
+        end;
+      FStreamer.EndScope();
+    end;
+  end;
+
+  procedure WriteItem_simple_ref_type(const AItem : TManyValuePropChanges);
+  var
+    q, k : PtrInt;
+    ch : TManyValuePropRecordData;
+    pt : ISDOType;
+  begin
+    q := AItem.Count;
+    if ( q > 0 ) then begin
+      pt := AItem.Prop.getType();
+      FStreamer.BeginObject(AItem.Prop.getName(), pt);
+        for k := 0 to Pred(q) do begin
+          FStreamer.BeginObject(s_listChanges, pt);
+            ch := AItem.GetItem(k);
+            PushSerializationStyle(ssAttibuteSerialization);
+              FStreamer.Put(s_index, locIntType, ch.Index);
+              FStreamer.Put(s_kind, locStringType, PROP_ACTION_STRING[ch.Action]);
+            PopSerializationStyle();
+            if ( ch.Action in [mvpaChange, mvpaDelete] ) then begin
+              case pt.getTypeEnum() of
+                StringType   :  FStreamer.Put(s_dataValues, pt, ch.Value.StringValue^);
+{$IFDEF HAS_SDO_BYTES}
+                BytesType    :  FStreamer.Put(s_dataValues, pt, ch.Value.BytesValue^);
+{$ENDIF HAS_SDO_BYTES}
+              end;
+            end;
+          FStreamer.EndScope();
+        end;
+      FStreamer.EndScope();
+    end;
+  end;
+
+var
+  i, c : PtrInt;
+  ls : TManyValuePropChangesList;
+  itm : TManyValuePropChanges;
+begin
+  ls := (ACS as ISDOChangeSummaryEx).FindManyValueChanges(ADataObject);
+  if ( ls <> nil ) and ( ls.Count > 0 ) then begin
+    locIntType := getType(IntegerType);
+    locStringType := getType(StringType);
+    c := ls.Count;
+    for i := 0 to ( c - 1 ) do begin
+      itm := ls[i];
+      case itm.Prop.getTypeEnum() of
+        BooleanType, ByteType
+        {$IFDEF HAS_SDO_CHAR}, CharacterType{$ENDIF}
+        {$IFDEF HAS_SDO_CURRENCY}, CurrencyType{$ENDIF}
+        ,DateTimeType
+        {$IFDEF HAS_SDO_DOUBLE},DoubleType{$ENDIF}
+        {$IFDEF HAS_SDO_FLOAT},FloatType{$ENDIF}
+        ,IntegerType
+        {$IFDEF HAS_SDO_LONG},LongType{$ENDIF}
+        {$IFDEF HAS_SDO_SHORT},ShortType{$ENDIF} :
+          begin
+            WriteItem_non_ref_type(itm);
+          end;
+        ObjectType : WriteItem_object_type(itm);
+{$IFDEF HAS_SDO_BYTES}
+        BytesType,
+{$ENDIF HAS_SDO_BYTES}
+        StringType :
+          begin
+            WriteItem_simple_ref_type(itm);
+          end;
+        else
+          Assert(False, 'NOT IMPLEMENTED YET!');
+      end;
+    end;
+  end;
+end;
+
+function TSDOSerializer.getSerializationStyle(const AProperty: ISDOProperty): TSerializationStyle;
+begin
+  //Result := ssAttibuteSerialization;
+  if AProperty.isAttribute() then
+    Result := ssAttibuteSerialization
+  else
+    Result := ssNodeSerialization;
+end;
+
+procedure TSDOSerializer.WriteObject(
+  const AName: string;
+  const AObject: ISDODataObject;
+  const AOptions: TObjectWriteOptions;
+  const AReference: string
+);
+begin
+  FRootName := AName;
+  InternalWriteObject(AName,AObject,AOptions,AReference);
+end;
+
+function TSDOSerializer.getObjectPathInChangeSummary(const AObj: ISDODataObject): TSDOString;
+var
+  r : TSDOString;
+  x, p : ISDODataObject;
+  prp : ISDOProperty;
+  ls : ISDODataObjectList;
+  locPos : PtrInt;
+begin
+  r := '';
+  x := AObj;
+  p := x.getContainer();
+  while ( p <> nil ) do begin
+    prp := x.getContainmentProperty();
+    if prp.isMany() then
+      r := Format('%s[%d]/%s',[prp.getName(),indexOf(x,p.getList(prp)),r])
+    else
+      r := prp.getName() + '/' + r;
+    x := p;
+    p := x.getContainer();
+  end;
+  prp := FChangeSummaryList.getInstanceProperties().find(x.getType().getName());
+  if ( prp <> nil ) then begin
+    ls := FChangeSummaryList.getList(prp);
+    locPos := indexOf(x,ls) ;
+    if ( locPos > -1 ) then begin
+      if ( r = '' ) then
+        r := Format('#/%s/%s[%d]',[s_changeSummary,x.getType().getName(),locPos])
+      else
+        r := Format('#/%s/%s[%d]/%s',[s_changeSummary,x.getType().getName(),locPos,r]);
+    end;
+  end;
+  Result := r;
+end;
+
+function TSDOSerializer.getOptions() : TSerializerOptions;
+begin
+  Result := FOptions;
+end;
+
+procedure TSDOSerializer.WriteByteListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOByte;
+begin
+  tmpVal := AValueList.getByte();
+  FStreamer.Put(AName,FProcs[ByteType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteByteProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOByte;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getByte(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[ByteType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadByteProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOByte;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[ByteType].PropType,localName,tmpVal) then
+    AObject.setByte(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadByteListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOByte;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[ByteType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+
+procedure TSDOSerializer.WriteDateProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDODateTime;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getDate(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[DateTimeType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.WriteDateListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDODateTime;
+begin
+  tmpVal := AValueList.getDate();
+  FStreamer.Put(AName,FProcs[DateTimeType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.ReadDateProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDODateTime;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[DateTimeType].PropType,localName,tmpVal) then
+    AObject.setDate(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadDateListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDODateTime;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[DateTimeType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOSerializer.WriteBytesListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOBytes;
+begin
+  tmpVal := AValueList.getBytes();
+  FStreamer.Put(AName,FProcs[BytesType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteBytesProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOBytes;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getBytes(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[BytesType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadBytesProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOBytes;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[BytesType].PropType,localName,tmpVal) then
+    AObject.setBytes(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadBytesListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOBytes;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[BytesType].PropType,localName,tmpVal) then
+    AValueList.appendBytes(tmpVal);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOSerializer.WriteCharListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOChar;
+begin
+  tmpVal := AValueList.getCharacter();
+  FStreamer.Put(AName,FProcs[CharacterType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteCharProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOChar;
+begin
+  if not AObject.isNull(AProp) then begin
+    tmpVal := AObject.getCharacter(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[CharacterType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadCharProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOChar;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[CharacterType].PropType,localName,tmpVal) then
+    AObject.setCharacter(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);            
+end;
+
+procedure TSDOSerializer.ReadCharListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOChar;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[CharacterType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOSerializer.WriteCurrencyListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOCurrency;
+begin
+  tmpVal := AValueList.getCurrency();
+  FStreamer.Put(AName,FProcs[CurrencyType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteCurrencyProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOCurrency;
+begin                   
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getCurrency(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[CurrencyType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadCurrencyProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOCurrency;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[CurrencyType].PropType,localName,tmpVal) then
+    AObject.setCurrency(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadCurrencyListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOCurrency;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[CurrencyType].PropType,localName,tmpVal) then
+    AValueList.appendCurrency(tmpVal);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOSerializer.WriteDoubleListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDODouble;
+begin
+  tmpVal := AValueList.getDouble();
+  FStreamer.Put(AName,FProcs[DoubleType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteDoubleProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDODouble;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getDouble(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[DoubleType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadDoubleProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDODouble;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[DoubleType].PropType,localName,tmpVal) then
+    AObject.setDouble(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadDoubleListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDODouble;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[DoubleType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOSerializer.WriteFloatListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOFloat;
+begin
+  tmpVal := AValueList.getFloat();
+  FStreamer.Put(AName,FProcs[FloatType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteFloatProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOFloat;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getFloat(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[FloatType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadFloatProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOFloat;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[FloatType].PropType,localName,tmpVal) then
+    AObject.setFloat(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadFloatListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOFloat;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[FloatType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOSerializer.WriteLongListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOLong;
+begin
+  tmpVal := AValueList.getLong();
+  FStreamer.Put(AName,FProcs[LongType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteLongProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOLong;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getLong(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[LongType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadLongProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOLong;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[LongType].PropType,localName,tmpVal) then
+    AObject.setLong(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadLongListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOLong;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[LongType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOSerializer.WriteShortListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOShort;
+begin
+  tmpVal := AValueList.getShort();
+  FStreamer.Put(AName,FProcs[ShortType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteShortProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOShort;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getShort(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[ShortType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.ReadShortProp(
+  const AProp: ISDOProperty;
+  const AObject: ISDODataObject
+);
+var
+  tmpVal : TSDOShort;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[ShortType].PropType,localName,tmpVal) then
+    AObject.setShort(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadShortListProp(
+  const AName: string;
+  const AValueList: ISDODataObjectList
+);
+var
+  tmpVal : TSDOShort;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[ShortType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+{ TReferenceObjectReadRecall }
+
+constructor TReferenceObjectReadRecall.Create(
+  const ARecallType : TReferenceObjectRecallItemType;
+  const ARoot,
+        ADataObject: ISDODataObject;
+  const AReferenceProperty: ISDOProperty;
+  const AAccessPath: string;
+  const AIsSet : Boolean
+);
+begin
+  FRecallType := ARecallType;
+  FRoot := ARoot;
+  FDataObject := ADataObject;
+  FReferenceProperty := AReferenceProperty;
+  FAccessPath := AAccessPath;
+  FIsSet := AIsSet;
+end;
+
+procedure TSDOSerializer.WritePendingRefProps();
+var
+  i, c : PtrInt;
+  locItem : TReferenceObjectWriteRecall;
+  locStrBuffer : TSDOString;
+  oldPos : TStreamBookmark;
+begin
+  c := FReferenceWriteRecallList.Count;
+  if ( c > 0 ) then begin
+    oldPos := FStreamer.GetBookMark();
+    try
+      for i := 0 to Pred(c) do begin
+        locItem := TReferenceObjectWriteRecall(FReferenceWriteRecallList[i]);
+        if not FStreamer.GotoBookmark(locItem.StreamPos) then
+          raise ESDOSerializationException.Create('FStreamer seems to be corrupted, writing ChangeSummary reference properties.');
+        if ( locItem.RecallType = rritPropertyValue ) or ( not locItem.Prop.isMany() ) then
+          locStrBuffer := locItem.Prop.getName()
+        else
+          locStrBuffer := s_dataValues;
+        FStreamer.BeginObject(locStrBuffer,locItem.Prop.getType());
+        try
+          if ( locItem.Value = nil ) then begin
+            FStreamer.NilCurrentScope()
+          end else begin
+            locStrBuffer := getObjectPathInChangeSummary(locItem.Value);
+            if locItem.Prop.isContainment() then begin
+              if IsStrEmpty(locStrBuffer) then begin
+                FStreamer.NilCurrentScope();
+              end else begin
+                FStreamer.SetNameStyle(nsQualified);
+                  FStreamer.Put(sdo_namespace,s_ref,getType(StringType),locStrBuffer);
+                FStreamer.SetNameStyle(nsUnqualified);
+              end;
+            end else begin
+              FStreamer.PutScopeInnerValue(getType(StringType),locStrBuffer);
+            end;
+          end;
+        finally
+          FStreamer.EndScope();
+        end;
+      end;
+    finally
+      try
+        FStreamer.GotoBookmark(oldPos);
+      finally
+        FreeAndNil(oldPos);
+      end;
+    end;
+  end;
+end;
+
+function TSDOSerializer.InternalReadObject(
+  const AName : string;
+  const AType : ISDOType;
+  const AOwner,
+        ADataObject : ISDODataObject;
+  const AOptions : TObjectReadOptions
+): ISDODataObject;
+
+  procedure ReadArrayProp(const AProp : ISDOProperty; const AObject : ISDODataObject);
+  var
+    ls : ISDODataObjectList;
+    k, itemCount : PtrInt;
+    rdrProc : TPropListReaderProc;
+    itemName : string;
+    typ : ISDOType;
+  begin
+    ls := AObject.getList(AProp);
+    itemName := AProp.getName();
+    typ := AProp.getType();
+    itemCount := FStreamer.BeginArrayRead(itemName,typ,itemName);
+    if (itemCount > -1) then begin
+      try
+        if typ.isDataObjectType() then begin
+          if AProp.isContainment() then begin
+            for k := 0 to Pred(itemCount) do begin
+              InternalReadObject(itemName,typ,AObject,nil,[]);
+            end;
+          end else begin
+            for k := 0 to Pred(itemCount) do begin
+              ls.append(InternalReadObject(itemName,typ,AObject,nil,[]));
+            end;
+          end;
+        end else begin
+          rdrProc := FProcs[typ.getTypeEnum()].ReaderListProc;
+          if Assigned(rdrProc) then begin
+            PushSerializationStyle(ssNodeSerialization);
+              for k := 0 to Pred(itemCount) do begin
+                rdrProc(itemName,ls);
+              end;
+            PopSerializationStyle();
+          end;
+        end;
+      finally
+        FStreamer.EndScopeRead();
+      end;
+    end;
+  end;
+
+var
+  resObject : ISDODataObject;
+
+  procedure PushReferenceRecall(const AProp : ISDOProperty);
+  var
+    tmpNameBuffer : string;
+    tmpBuffer : TSDOString;
+  begin
+    tmpNameBuffer := AProp.getName();
+    if (FStreamer.BeginObjectRead(tmpNameBuffer,AProp.getType()) > -1) then begin
+      try
+        if not FStreamer.IsCurrentScopeNil() then begin
+          tmpBuffer := '';
+          if FStreamer.GetScopeInnerValue(getType(StringType),tmpBuffer) then begin
+            FReferenceReadRecallList.Add(TReferenceObjectReadRecall.Create(rritPropertyValue,getRoot(resObject),resObject,AProp,tmpBuffer,True));
+          end else begin
+            resObject.unset(AProp);
+          end;
+        end;
+      finally
+        FStreamer.EndScopeRead();
+      end;
+    end;
+  end;
+
+  procedure ReadClosedObject();
+  var
+    pl : ISDOPropertyList;
+    p : ISDOProperty;
+    pt : ISDOType;
+    propCount : PtrInt;
+    k : PtrInt;
+    prpProc : TPropReaderProc;
+    locSerializationStyle : TSerializationStyle;
+  begin
+    pl := resObject.getType().getProperties();
+    propCount := pl.getCount();
+    if ( propCount > 0 ) then begin
+      for k := 0 to Pred(propCount) do begin
+        p := pl.getItem(k);
+        if p.isMany() then begin
+          ReadArrayProp(p,resObject);
+        end else begin
+          pt := p.getType();
+          if pt.isDataObjectType() then begin
+            if p.isContainment() then begin
+              InternalReadObject(p.getName(),pt,resObject,nil,[]);
+            end else begin
+              //do not forget that the referencee may not be read at this moment!
+              PushReferenceRecall(p);
+            end;
+          end else begin
+            prpProc := FProcs[pt.getTypeEnum()].ReaderProc;
+            if Assigned(prpProc) then begin
+              if p.isAttribute() then
+                locSerializationStyle := ssAttibuteSerialization
+              else
+                locSerializationStyle := ssNodeSerialization;
+              PushSerializationStyle(locSerializationStyle);
+                prpProc(p,resObject);
+              PopSerializationStyle();
+            end;
+          end;
+        end;
+      end;
+    end;
+  end;
+
+  procedure ReadOpenedObject();
+  var
+    pl : ISDOPropertyList;
+    p : ISDOProperty;
+    pt : ISDOType;
+    propCount : PtrInt;
+    k : PtrInt;
+    prpProc : TPropReaderProc;
+    ls : TStringList;
+    ss : string; 
+    strBuffer : TSDOString;
+    locSerializationStyle : TSerializationStyle;
+  begin
+    pl := resObject.getInstanceProperties();
+    propCount := pl.getCount();
+    if ( propCount > 0 ) then begin
+      for k := 0 to Pred(propCount) do begin
+        p := pl.getItem(k);
+        if p.isMany() then begin
+          ReadArrayProp(p,resObject);
+        end else begin
+          pt := p.getType();
+          if pt.isDataObjectType() then begin
+            if p.isContainment() then begin
+              InternalReadObject(p.getName(),pt,resObject,nil,[]);
+            end else begin
+              //do not forget that the referencee may not be read at this moment!
+              PushReferenceRecall(p);
+            end;
+          end else begin
+            prpProc := FProcs[pt.getTypeEnum()].ReaderProc;
+            if Assigned(prpProc) then begin
+              if p.isAttribute() then
+                locSerializationStyle := ssAttibuteSerialization
+              else
+                locSerializationStyle := ssNodeSerialization;
+              PushSerializationStyle(locSerializationStyle);
+                prpProc(p,resObject);
+              PopSerializationStyle();
+            end;
+          end;
+        end;
+      end;
+    end;
+    ls := TStringList.Create();
+    try
+      ls.Duplicates := dupAccept;
+      if ( FStreamer.GetScopeItemNames(ssAttibuteSerialization,ls) > 0 ) then begin
+        for k := 0 to Pred(ls.Count) do begin
+          ss := ls[k];
+          if ( pl.find(ss) = nil ) then begin
+            strBuffer := '';
+            if FStreamer.Get(FProcs[StringType].PropType,ss,strBuffer) then
+              resObject.setString(ss,strBuffer);
+          end;
+        end;
+      end;
+    finally
+      ls.Free();
+    end;
+  end;
+
+var
+  space, localName : string;
+  localType : ISDOType;
+  locProp : ISDOProperty;
+begin
+  localType := AType;
+  if ( localType = nil ) then
+    raise ESDOTypeNotFoundException.Create(AName);
+  localName := AName;
+  space := localType.getURI();
+  if (oroDontMake_BeginObjectRead in AOptions) or
+     (FStreamer.BeginObjectRead(localName,localType) > -1)
+  then begin
+    try
+      if not FStreamer.IsCurrentScopeNil() then begin
+        if ( ADataObject = nil ) then begin
+          if ( AOwner <> nil ) then begin
+            //resObject := AOwner.createDataObject(AName);
+            locProp := AOwner.getProperty(AName);
+            resObject := AOwner.createDataObject(locProp);
+            if locProp.isMany() and locProp.isContainment() then
+              AOwner.getList(locProp).append(resObject);
+          end else begin
+            resObject := FDataFactory.createNew(localType);
+          end;
+        end else begin
+          resObject := ADataObject
+        end;
+        FStreamer.SetNameStyle(nsUnqualified);
+        if localType.isOpenType() then
+          ReadOpenedObject()
+        else
+          ReadClosedObject();
+      end;
+      Result := resObject;
+    finally
+      if not (oroDontMake_EndScopeRead in AOptions) then
+        FStreamer.EndScopeRead();
+    end;
+  end;
+end;
+
+function TSDOSerializer.load(const AFileName: string) : ISDODataObject;
+var
+  ls : ISDODataObjectList;
+begin
+  ls := TSDODataObjectList.Create(FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType])) as ISDODataObjectList;
+  load(AFileName,ls);
+  if ( ls.size() > 0 ) then
+    Result := ls.getDataObject(0)
+  else
+    raise ESDOSerializationException.CreateFmt('No object found in this file : "%s".',[AFileName]);
+end;
+
+procedure TSDOSerializer.PopSerializationStyle();
+begin
+  Assert( ( FSerializationStyleStackIndex >= 0 ) );
+  FStreamer.SetSerializationStyle(FSerializationStyleStack[FSerializationStyleStackIndex]);
+  Dec(FSerializationStyleStackIndex);
+end;
+
+procedure TSDOSerializer.PushSerializationStyle(const AValue: TSerializationStyle);
+begin
+  Inc(FSerializationStyleStackIndex);
+  Assert( ( FSerializationStyleStackIndex >= 0 ) and ( FSerializationStyleStackIndex < MAX_NESTED_LEVEL ) );
+  FSerializationStyleStack[FSerializationStyleStackIndex] := FStreamer.GetSerializationStyle();
+  FStreamer.SetSerializationStyle(AValue);
+end;
+
+procedure TSDOSerializer.ReadBoolListProp(const AName: string; const AValueList: ISDODataObjectList);
+var
+  tmpVal : TSDOBoolean;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[BooleanType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+
+procedure TSDOSerializer.ReadBoolProp(const AProp: ISDOProperty; const AObject: ISDODataObject);
+var
+  tmpVal : TSDOBoolean;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[BooleanType].PropType,localName,tmpVal) then
+    AObject.setBoolean(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadChangeSummary(
+  const AValue: ISDOChangeSummary;
+  const ARootObjectName : string;
+  const ARootObject : ISDODataObject
+);
+var
+  stringTypeObj : ISDOType;
+  changedObjList : ISDOChangedDataObjectListEx;
+  rootNameSpace, rootlocaName : string;
+  recorder : TChangeRecorder;
+
+  function FindObject(const APath : string) : ISDODataObject;
+  var
+    locPath : string;
+  begin
+    Result := nil;
+    locPath := Trim(APath);
+    if ( Length(locPath) > 0 ) then begin
+      locPath := xpath_ExcludeRootElement(locPath,rootlocaName);
+      if ( Length(locPath) = 0 ) then
+        Result := ARootObject
+      else
+        Result := ARootObject.getDataObject(locPath);
+    end;
+  end;
+
+  procedure ReadPropMultiValueChange(
+    const AObject : ISDODataObject;
+    const AProp : ISDOProperty;
+    const AChangeInfo : TDataObjectChangeInfo
+  );
+  var
+    locIntType, locStringType : ISDOType;
+    itemType : ISDOType;
+    nameBuffer : string; 
+    stringBuffer : TSDOString;
+    buffer : TValueBuffer;
+    pbuffer : Pointer;
+    oldNameStyle : TNameStyle;
+    ls : TManyValuePropChanges;
+    locIndex : TSDOInteger;
+    locKind : TManyValuePropAction;
+    locCount, locArrayReadIDX : PtrInt;
+    locIsObjectProp : Boolean;
+    locRecall : TReferenceObjectReadRecall;
+  begin
+    nameBuffer := AProp.getName();
+    itemType := AProp.getType();
+    if ( FStreamer.BeginObjectRead(nameBuffer, itemType) >= 0 ) then begin
+      nameBuffer := s_listChanges;
+      locCount := FStreamer.BeginArrayRead(nameBuffer, itemType, s_listChanges);
+      if ( locCount >= 0 ) then begin
+        nameBuffer := s_listChanges;
+        ls := AChangeInfo.GetChanges(AProp);
+        locIntType := getType(IntegerType);
+        locStringType := getType(StringType);
+        InitBufferResources(itemType.getTypeEnum(), buffer);
+        try
+          PushSerializationStyle(ssAttibuteSerialization);
+            locArrayReadIDX := 0;
+            locIsObjectProp := AProp.getType().isDataObjectType();
+            if not locIsObjectProp then begin
+              case AProp.getTypeEnum() of
+                BooleanType,
+                ByteType,
+{$IFDEF HAS_SDO_CHAR}
+                CharacterType,
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+                CurrencyType,
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+                DoubleType,
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+                FloatType,
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+                LongType,
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+                ShortType,
+{$ENDIF HAS_SDO_SHORT}
+                DateTimeType,
+                IntegerType :
+                  begin
+                    pbuffer := @buffer;
+                  end;
+{$IFDEF HAS_SDO_BYTES}
+                BytesType  : pbuffer := buffer.BytesValue;
+{$ENDIF HAS_SDO_BYTES}
+                StringType : pbuffer := buffer.StringValue;
+                else 
+                  Assert(False, 'NON IMPLEMENTED YET!');
+              end;
+            end;
+            oldNameStyle := FStreamer.GetNameStyle();
+            FStreamer.SetNameStyle(nsUnqualified);
+              while ( locArrayReadIDX < locCount ) and ( FStreamer.BeginObjectRead(nameBuffer, itemType) > 0 ) do begin
+                nameBuffer := s_index;
+                if not FStreamer.Get(locIntType, nameBuffer, locIndex) then
+                  raise ESDOSerializationException.CreateFmt('Invalid "%s" stream : unable to find "%s" attribute.',[s_listChanges,s_index]);
+                nameBuffer := s_kind;
+                if not FStreamer.Get(locStringType, nameBuffer, stringBuffer) then
+                  raise ESDOSerializationException.CreateFmt('Invalid "%s" stream : unable to find "%s" attribute.',[s_listChanges,s_kind]);
+                if not FindAction(stringBuffer,locKind) then
+                  raise ESDOSerializationException.CreateFmt('Invalid "%s" stream : invalid "%s" value ( "%s" ).',[s_listChanges,s_kind,stringBuffer]);
+                case locKind of
+                  mvpaAppend, mvpaInsert : ls.Add(locKind,locIndex);
+                  mvpaChange, mvpaDelete :
+                    begin
+                      nameBuffer := s_dataValues;
+                      if locIsObjectProp then begin
+                        nameBuffer := s_dataValues;
+                        if ( FStreamer.BeginObjectRead(nameBuffer,stringTypeObj) < 0 ) then begin
+                          raise ESDOSerializationException.CreateFmt('Invalid "%s" stream : "%s" not found.',[s_listChanges,s_dataValues]);
+                        end;
+                          if FStreamer.IsCurrentScopeNil() then begin
+                            buffer.ObjectValue^ := nil;
+                            ls.Add(locKind,locIndex,buffer);
+                          end else begin
+                            nameBuffer := s_ref;
+                            PushSerializationStyle(ssAttibuteSerialization);
+                              oldNameStyle := FStreamer.GetNameStyle();
+                              FStreamer.SetNameStyle(nsQualified);
+                                if not FStreamer.Get(sdo_namespace,stringTypeObj,nameBuffer,stringBuffer) then
+                                  raise ESDOSerializationException.CreateFmt('Invalid "%s" stream : "%s" not found.',[s_listChanges,s_dataValues]);
+                              FStreamer.SetNameStyle(oldNameStyle);
+                            PopSerializationStyle();
+                            stringBuffer := xpath_ExcludeRootElement(stringBuffer,ARootObjectName);
+                            locRecall := TReferenceObjectReadRecall.Create(rritSettingItem,ARootObject,AObject,AProp,stringBuffer,True);
+                            FReferenceReadRecallList.Add(locRecall);
+                            locRecall.FMultiValueData.Action := locKind;
+                            locRecall.FMultiValueData.ActionIndex := locIndex;
+                            locRecall.FMultiValueData.Index := locArrayReadIDX;
+                          end;
+                        FStreamer.EndScopeRead();
+                      end else begin
+                        PushSerializationStyle(ssAttibuteSerialization);//PushSerializationStyle(getSerializationStyle(AProp));
+                          if not FStreamer.Get(itemType,nameBuffer,pbuffer^) then
+                            raise ESDOSerializationException.CreateFmt('Invalid "%s" stream : "%s" not found.',[s_listChanges,s_dataValues]);
+                        PopSerializationStyle();
+                        ls.Add(locKind,locIndex,buffer);
+                      end;
+                    end;
+                  else
+                    raise ESDONotImplementedException.CreateFmt('Reading this kind of data change : Type = TManyValuePropAction, Ord = %d',[Ord(locKind)]);
+                end;
+                FStreamer.EndScopeRead();
+                Inc(locArrayReadIDX);
+              end;
+            FStreamer.SetNameStyle(oldNameStyle);
+          PopSerializationStyle();
+        finally
+          FreeBufferResources(itemType.getTypeEnum(), buffer);
+        end;
+        FStreamer.EndScopeRead();
+      end;
+      FStreamer.EndScopeRead();
+    end;
+  end;
+
+  procedure ReadPropSingleValueChange(
+    const AObject : ISDODataObject;
+    const AProp : ISDOProperty;
+    const AChangeInfo : TDataObjectChangeInfo
+  );
+  const
+    NIL_OBJ_BUFFER : ISDODataObject = nil;
+  var
+    nameBuffer : string;
+    stringBuffer : TSDOString;
+    bytesBuffer : TSDOBytes;
+    buffer : TValueBuffer;
+    oldNameStyle : TNameStyle;
+  begin
+    nameBuffer := AProp.getName();
+    case AProp.getTypeEnum() of
+      ChangeSummaryType : { nothing };
+      BooleanType, ByteType,
+      {$IFDEF HAS_SDO_CHAR}CharacterType,{$ENDIF}
+      {$IFDEF HAS_SDO_CURRENCY}CurrencyType,{$ENDIF}
+      DateTimeType,
+      {$IFDEF HAS_SDO_DOUBLE}DoubleType,{$ENDIF}
+      {$IFDEF HAS_SDO_FLOAT}FloatType,{$ENDIF}
+      {$IFDEF HAS_SDO_LONG}LongType,{$ENDIF}
+      {$IFDEF HAS_SDO_SHORT}ShortType,{$ENDIF}
+      IntegerType :
+        begin
+          PushSerializationStyle(getSerializationStyle(AProp));
+            if FStreamer.Get(AProp.getType(),nameBuffer,buffer) then
+              AChangeInfo.ChangeList.append(TValueSetting.Create(True,False,buffer,AProp,0));
+          PopSerializationStyle();
+        end;
+      StringType :
+        begin
+          PushSerializationStyle(getSerializationStyle(AProp));
+            if FStreamer.Get(AProp.getType(),nameBuffer,stringBuffer) then
+              AChangeInfo.ChangeList.append(TValueSetting.Create(True,False,stringBuffer,AProp,0));
+          PopSerializationStyle();
+        end;
+{$IFDEF HAS_SDO_BYTES}
+      BytesType :
+        begin
+          PushSerializationStyle(getSerializationStyle(AProp));
+            if FStreamer.Get(AProp.getType(),nameBuffer,bytesBuffer) then
+              AChangeInfo.ChangeList.append(TValueSetting.Create(True,False,bytesBuffer,AProp,0));
+          PopSerializationStyle();
+        end;
+{$ENDIF HAS_SDO_BYTES}
+      ObjectType :
+        begin
+          if AProp.isContainment() then begin
+            if ( FStreamer.BeginObjectRead(nameBuffer,AProp.getType()) > -1 ) then begin
+              oldNameStyle := FStreamer.GetNameStyle();
+              FStreamer.SetNameStyle(nsQualified);
+                nameBuffer := s_ref;
+                if FStreamer.Get(sdo_namespace,stringTypeObj,nameBuffer,stringBuffer) then begin
+                  if not IsStrEmpty(stringBuffer) then
+                    FReferenceReadRecallList.Add(TReferenceObjectReadRecall.Create(rritSettingItem, ARootObject,AObject,AProp,stringBuffer,True));
+                end;
+              FStreamer.SetNameStyle(oldNameStyle);
+              FStreamer.EndScopeRead();
+            end;
+          end else if AProp.isReference() then begin
+            if ( FStreamer.BeginObjectRead(nameBuffer,AProp.getType()) > -1 ) then begin
+              if FStreamer.IsCurrentScopeNil() then begin
+                AChangeInfo.ChangeList.append(TValueSetting.Create(True,True,NIL_OBJ_BUFFER,AProp,0));
+              end else begin
+                if FStreamer.GetScopeInnerValue(stringTypeObj,stringBuffer) then begin
+                  if not IsStrEmpty(stringBuffer) then
+                    FReferenceReadRecallList.Add(TReferenceObjectReadRecall.Create(rritSettingItem, ARootObject,AObject,AProp,stringBuffer,True));
+                end;
+              end;
+              FStreamer.EndScopeRead();
+            end;
+          end;
+        end;
+      else
+        begin
+          raise Exception.Create('NOT-IMPLEMENTED');
+        end;
+    end;
+  end;
+
+  procedure ReadPropChange(
+    const AObject : ISDODataObject;
+    const AProp : ISDOProperty;
+    const AChangeInfo : TDataObjectChangeInfo;
+    const AUnsetList : TStrings
+  );
+  const
+    NIL_OBJ_BUFFER : ISDODataObject = nil;
+  var
+    buffer : TValueBuffer;
+  begin
+    if ( AUnsetList.IndexOf(AProp.getName()) > -1 ) then begin
+      FillChar(buffer,SizeOf(buffer),#0);
+      AChangeInfo.ChangeList.append(TValueSetting.Create(False,False,buffer,AProp,0));
+    end else begin
+      if AProp.isMany() then begin
+        ReadPropMultiValueChange(AObject,AProp,AChangeInfo);
+      end else begin
+        ReadPropSingleValueChange(AObject,AProp,AChangeInfo);
+      end;
+    end;
+  end;
+
+  procedure ReadDeletedObject(const AName : string; const AType : ISDOType);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  var
+    locO : ISDODataObject;
+  begin
+    locO := InternalReadObject(AName,AType,nil,nil,[oroDontMake_BeginObjectRead,oroDontMake_EndScopeRead]);
+    recorder.recordDeletion(locO);
+    AddToChangeSummaryList(locO);
+  end;
+
+  procedure ReadCSObject(const AName : string);
+  var
+    nameBuffer, uriBuffer, tmpNameBuffer : string;
+    objectRef, strBuffer : TSDOString;
+    objType : ISDOType;
+    obj : ISDODataObject;
+    pls : ISDOPropertyList;
+    q, k : PtrInt;
+    objChangeInfo : TDataObjectChangeInfo;
+    oldNameStyle : TNameStyle;
+    locDeleted : Boolean;
+    unsetList : TStringList;
+  begin
+    k := Pos('#',AName);
+    if ( k = 0 ) then begin
+      uriBuffer := ARootObject.getType().getURI();
+      nameBuffer := AName;
+    end else begin
+      uriBuffer := Copy(AName,1,( k - 1 ));
+      nameBuffer := Copy(AName,( k + 1 ),Length(AName));
+    end;
+    objType := FDataFactory.getType(uriBuffer,nameBuffer);
+    pls := nil;
+    FStreamer.BeginObjectRead(nameBuffer,objType);
+    tmpNameBuffer := s_ref;
+    oldNameStyle := FStreamer.GetNameStyle();
+    FStreamer.SetNameStyle(nsQualified);
+    locDeleted := not FStreamer.Get(sdo_namespace,stringTypeObj,tmpNameBuffer,objectRef);
+    FStreamer.SetNameStyle(oldNameStyle);
+    if locDeleted then begin
+      ReadDeletedObject(nameBuffer,objType);
+    end else begin
+      obj := FindObject(objectRef);
+      if ( obj = nil ) then
+        raise ESDOSerializationException.CreateFmt('Object not found : "%s".',[objectRef]);
+      AddToChangeSummaryList(obj);
+      pls := objType.getProperties();
+      q := pls.getCount();
+      if ( q > 0 ) then begin
+        oldNameStyle := FStreamer.GetNameStyle();
+        FStreamer.SetNameStyle(nsQualified);
+          nameBuffer := s_unset;
+          strBuffer := '';
+          FStreamer.Get(sdo_namespace,stringTypeObj,nameBuffer,strBuffer);
+        FStreamer.SetNameStyle(oldNameStyle);
+        unsetList := TStringList.Create();
+        try
+          unsetList.Duplicates := dupIgnore;
+          unsetList.Sorted := True;
+          unsetList.Delimiter := ' ';
+          unsetList.DelimitedText := strBuffer;
+          if changedObjList.find(obj,k) then
+            objChangeInfo := changedObjList.getInfo(k)
+          else
+            objChangeInfo := recorder.recordUpdate(obj);
+          for k := 0 to Pred(q) do begin
+            ReadPropChange(obj,pls.getItem(k),objChangeInfo,unsetList);
+          end;
+          objChangeInfo.ExtractPendingOldValues();
+        finally
+          unsetList.Free();
+        end;
+      end;
+    end;
+    FStreamer.EndScopeRead();
+  end;
+
+  procedure ReadObjects();
+  var
+    ls, lsReaded : TStringList;
+    c, i, k, locArrayLength : PtrInt;
+    itm, nameBuffer, uriBuffer : string;
+    objType : ISDOType;
+  begin
+    lsReaded := nil;
+    ls := TStringList.Create();
+    try
+      if ( FStreamer.GetScopeItemNames(ssNodeSerialization,ls) > 0 ) then begin
+        lsReaded := TStringList.Create();
+        lsReaded.Duplicates := dupIgnore;
+        lsReaded.Sorted := True;
+        changedObjList := AValue.getChangedDataObjects() as ISDOChangedDataObjectListEx;
+        c := ls.Count;
+        for i := 0 to Pred(c) do begin
+          itm := ls[i];
+          if ( lsReaded.IndexOf(itm) = -1 ) then begin
+            lsReaded.Add(itm);
+            nameBuffer := itm;
+            k := Pos('#',itm);
+            if ( k = 0 ) then begin
+              uriBuffer := ARootObject.getType().getURI();
+              nameBuffer := itm;
+            end else begin
+              uriBuffer := Copy(itm,1,( k - 1 ));
+              nameBuffer := Copy(itm,( k + 1 ),Length(itm));
+            end;
+            objType := FDataFactory.getType(uriBuffer,nameBuffer);
+            locArrayLength := FStreamer.BeginArrayRead(nameBuffer,objType,itm);
+            if (locArrayLength > -1) then begin
+              for k := 0 to ( locArrayLength - 1 ) do
+                ReadCSObject(itm);
+              FStreamer.EndScopeRead();
+            end;
+          end;
+        end;
+      end;
+    finally
+      lsReaded.Free();
+      ls.Free();
+    end;
+  end;
+
+  procedure ReadCreatedObjects();
+  var
+    tmpStr : TSDOString; 
+    tmpBuffer : string;
+    tmpObj : ISDODataObject;
+  begin
+    PushSerializationStyle(ssAttibuteSerialization);
+    try
+      tmpBuffer := s_create;
+      if FStreamer.Get(getType(StringType),tmpBuffer,tmpStr) then begin
+        repeat
+          tmpBuffer := GetNextToken(tmpStr,' ');
+          if ( Length(tmpBuffer) = 0 ) then
+            Break;
+          tmpBuffer := xpath_ExcludeRootElement(tmpBuffer,FRootName);
+          tmpObj := ARootObject.getDataObject(tmpBuffer);
+          if ( tmpObj <> nil ) then
+            recorder.recordCreation(tmpObj);
+        until False;
+      end;
+    finally
+      PopSerializationStyle();
+    end;
+  end;
+
+var
+  tmpType : ISDOType;
+  locName : string;
+  i : PtrInt;
+begin
+  FStreamer.Initialize();
+  FReferenceReadRecallList.Clear();
+  FChangeSummaryList := FDataFactory.createNew(sdo_namespace,s_changeSummaryListObject);
+  i := Pos('#',ARootObjectName);
+  if ( i > 0 ) then begin
+    rootNameSpace := Copy(ARootObjectName,1,( i - 1 ));
+    rootlocaName := Copy(ARootObjectName,( i + 1 ), MaxInt);
+  end else begin
+    rootNameSpace := ARootObject.getType().getURI();
+    rootlocaName := ARootObjectName;
+  end;
+  stringTypeObj := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]);
+  tmpType := FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType]);
+  locName := s_changeSummary;
+  recorder := (ARootObject.getChangeSummary() as ISDOChangeSummaryEx).getRecorder();
+  recorder.Deserializing := True;
+  try
+    if (FStreamer.BeginObjectRead(locName,tmpType) > -1) then begin
+      try
+        ReadCreatedObjects();
+        ReadObjects();
+        ReadPendingRefProps();
+      finally
+        FStreamer.EndScopeRead();
+      end;
+    end;
+  finally
+    recorder.Deserializing := False;
+  end;
+end;
+
+procedure TSDOSerializer.ReadIntegerListProp(const AName: string; const AValueList: ISDODataObjectList);
+var
+  tmpVal : TSDOInteger;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[IntegerType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+
+procedure TSDOSerializer.ReadIntegerProp(const AProp: ISDOProperty; const AObject: ISDODataObject);
+var
+  tmpVal : TSDOInteger;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[IntegerType].PropType,localName,tmpVal) then
+    AObject.setInteger(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.ReadMetadata();
+var
+  s : string; 
+  locXdsBuffer : TSDOString;
+  locXsd : IXSDHelper;
+begin
+  s := s_xsd;
+  if (FStreamer.BeginObjectRead(s,FDataFactory.getType(sdo_namespace,s_xsd)) > -1) then begin
+    try
+      locXdsBuffer := '';
+      if AnsiSameText(s_xml,FStreamer.GetFormatName()) then begin
+        locXdsBuffer := FStreamer.ReadBuffer(s_schema)
+      end else begin
+        s := s_xsd;
+        FStreamer.Get(FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),s,locXdsBuffer);
+      end;
+      if not IsStrEmpty(locXdsBuffer) then begin
+        locXsd := TXSDHelper.Create(FDataFactory);
+        locXsd.LoadFromString(locXdsBuffer);
+      end;
+    finally
+      FStreamer.EndScopeRead();
+    end;
+  end;
+end;
+
+function TSDOSerializer.ReadObject(
+  const AName: string;
+  const AType : ISDOType;
+  const AOwner : ISDODataObject
+) : ISDODataObject;
+
+  function findType(const AUri, ALocalName : string) : ISDOType;
+  var
+    k, cc : PtrInt;
+    tl : ISDOTypeList;
+    typ : ISDOType;
+  begin
+    if not IsStrEmpty(AUri) then begin
+      Result := FDataFactory.getTypes().find(AUri,ALocalName);
+    end else begin
+      Result := nil;
+      tl := FDataFactory.getTypes();
+      cc := tl.getCount();
+      if ( cc > 0 ) then begin
+        for k := 0 to Pred(cc) do begin
+          typ := tl.getItem(k);
+          if AnsiSameStr(ALocalName,typ.getName()) then begin
+            Result := typ;
+            Break;
+          end;
+        end;
+        if not Assigned(Result) then begin
+          for k := 0 to Pred(cc) do begin
+            typ := tl.getItem(k);
+            if AnsiSameText(ALocalName,typ.getName()) then begin
+              Result := typ;
+              Break;
+            end;
+          end;
+        end;
+      end;
+    end;
+  end;
+
+  procedure DisableChangeSummary(const AObj : ISDODataObject);
+  var
+    locCS : ISDOChangeSummary;
+  begin
+    locCS := AObj.getChangeSummary();
+    if ( locCS <> nil ) and locCS.isLogging() then
+      locCS.endLogging();
+  end;
+
+var
+  space, localName : string;
+  i : PtrInt;
+  localType : ISDOType;
+  resObject : ISDODataObject;
+begin
+  if Assigned(AType) then begin
+    localType := AType;
+    localName := AName;
+    space := localType.getURI();
+  end else begin
+    i := Pos('#',AName);
+    if ( i > 0 ) then begin
+      space := Copy(AName,1,Pred(i));
+      localName := Copy(AName,Succ(i),Length(AName));
+    end else begin
+      space := '';
+      localName := AName;
+    end;
+    localType := findType(space,localName);
+    if ( localType = nil ) then
+      raise ESDOTypeNotFoundException.Create(AName);
+  end;
+  FRootName := localName;
+  if ( AOwner = nil ) then begin
+    resObject := FDataFactory.createNew(localType);
+  end else begin
+    resObject := AOwner.createDataObject(AName);
+  end;
+  DisableChangeSummary(resObject);
+  Result := InternalReadObject(localName,localType,AOwner,resObject,[]);
+end;
+
+procedure TSDOSerializer.ReadStringListProp(const AName: string; const AValueList: ISDODataObjectList);
+var
+  tmpVal : TSDOString;
+  localName : string;
+begin
+  localName := AName;
+  if FStreamer.Get(FProcs[StringType].PropType,localName,tmpVal) then
+    AValueList.append(tmpVal);
+end;
+
+procedure TSDOSerializer.ReadStringProp(const AProp: ISDOProperty; const AObject: ISDODataObject);
+var
+  tmpVal : TSDOString;
+  localName : string;
+begin
+  localName := AProp.getName();
+  if FStreamer.Get(FProcs[StringType].PropType,localName,tmpVal) then
+    AObject.setString(localName,tmpVal)
+  else if AProp.isNullable() then
+    AObject.setNull(AProp);
+end;
+
+procedure TSDOSerializer.save(
+  const AName : string;
+        AObject : ISDODataObject;
+  const ADestStream : TStream
+);
+begin
+  if ( AObject = nil ) then
+    raise ESDOIllegalArgumentException.Create('AObject');
+  Init();
+  try
+    FNamespace := AObject.getType().getURI();
+    BeginWrite();
+    try
+      FStreamer.SetNameStyle(nsQualified);
+      WriteObject(AName, AObject,[owoWriteChangeSummary],'');
+    finally
+      EndWrite();
+    end;
+    FStreamer.SaveToStream(ADestStream);
+  finally
+    Init();
+  end;
+end;
+
+procedure TSDOSerializer.save(AObject: ISDODataObject; const ADestStream: TStream);
+begin
+  if ( AObject = nil ) then
+    raise ESDOIllegalArgumentException.Create('AObject');
+  save(AObject.getType().getName(),AObject,ADestStream);
+end;
+
+procedure TSDOSerializer.save(
+  const AName: string;
+        AObject: ISDODataObject;
+  const AFileName: string
+);
+var
+  flStream : TStream;
+begin
+  flStream := TFileStream.Create(AFileName,fmCreate);
+  try
+    save(AName,AObject,flStream);
+  finally
+    flStream.Free();
+  end;
+end;
+
+procedure TSDOSerializer.save(AObject: ISDODataObject;  const AFileName: string);
+begin
+  if ( AObject = nil ) then
+    raise ESDOIllegalArgumentException.Create('AObject');
+  save(AObject.getType().getName(),AObject,AFileName);
+end;
+
+procedure TSDOSerializer.setOptions(const AValue: TSerializerOptions);
+begin
+  if (AValue <> FOptions) then
+    FOptions := AValue;
+end;
+
+procedure TSDOSerializer.WriteBoolListProp(const AName: string; const AValueList : ISDODataObjectList);
+var
+  tmpVal : TSDOBoolean;
+begin
+  tmpVal := AValueList.getBoolean();
+  FStreamer.Put(AName,FProcs[BooleanType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteBoolProp(const AProp : ISDOProperty; const AObject: ISDODataObject);
+var
+  tmpVal : TSDOBoolean;
+begin
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getBoolean(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[BooleanType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.WriteChangeSummary(
+  const AValue : ISDOChangeSummary;
+  const ARootObjectName : string
+);
+
+  procedure WriteChange(const ADataObject : ISDODataObject);
+  var
+    unsetList : TSDOString;
+
+    procedure WriteSetting(const ASetting : TValueSetting);
+    var
+      p : ISDOProperty;
+      v : TValueBuffer;
+      vstr : TSDOString;
+      vbytes : TSDOBytes;
+    begin
+      p := ASetting.getProperty();
+      if ASetting.isSet() then begin
+        if p.getType().isDataType() then begin
+          case p.getTypeEnum() of
+            BooleanType :
+              begin
+                v.BooleanValue := ASetting.getBooleanValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+            ByteType :
+              begin
+                v.ByteValue := ASetting.getByteValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$IFDEF HAS_SDO_BYTES}
+            BytesType  :
+              begin
+                vbytes := ASetting.getBytesValue();
+                FStreamer.Put(p.getName(),p.getType(),vbytes);
+              end;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+            CharacterType :
+              begin
+                v.CharValue := ASetting.getCharacterValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+            CurrencyType :
+              begin
+                v.CurrencyValue := ASetting.getCurrencyValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$ENDIF HAS_SDO_CURRENCY}
+            DateTimeType :
+              begin
+                v.DateValue := ASetting.getDateValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$IFDEF HAS_SDO_DOUBLE}
+            DoubleType :
+              begin
+                v.DoubleValue := ASetting.getDoubleValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+            FloatType :
+              begin
+                v.FloatValue := ASetting.getFloatValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$ENDIF HAS_SDO_FLOAT}
+            IntegerType :
+              begin
+                v.IntegerValue := ASetting.getIntegerValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$IFDEF HAS_SDO_LONG}
+            LongType :
+              begin
+                v.LongValue := ASetting.getLongValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+            ShortType :
+              begin
+                v.ShortValue := ASetting.getShortValue();
+                FStreamer.Put(p.getName(),p.getType(),v);
+              end;
+{$ENDIF HAS_SDO_SHORT}
+            StringType  :
+              begin
+                vstr := ASetting.getStringValue();
+                FStreamer.Put(p.getName(),p.getType(),vstr);
+              end;
+            else
+              raise Exception.Create('NOT-IMPLEMENTED');
+          end;
+        end else if p.getType().isDataObjectType() then begin
+          if p.isContainment() then begin
+            if ( ASetting.getDataObjectValue() = nil ) then begin
+              FStreamer.BeginObject(p.getName(),p.getType());
+                FStreamer.NilCurrentScope();
+              FStreamer.EndScope();
+            end else begin
+              AddPropertyRefRecallWrite(rritSettingItem,ADataObject,p,ASetting.getDataObjectValue());
+            end;
+          end else if p.isReference() then begin
+            if ( ASetting.getDataObjectValue() = nil ) then begin
+              FStreamer.BeginObject(p.getName(),p.getType());
+                FStreamer.NilCurrentScope();
+              FStreamer.EndScope();
+            end else begin
+              if AValue.isDeleted(ASetting.getDataObjectValue()) then begin
+                AddPropertyRefRecallWrite(rritSettingItem,ADataObject,p,ASetting.getDataObjectValue());
+              end else begin
+                vstr := Format('%s/%s',[ARootObjectName, AValue.getOldXpath(ASetting.getDataObjectValue())]);
+                if AValue.isDeleted(ASetting.getDataObjectValue()) then
+                  vstr := Format('#/%s/%s',[s_changeSummary,vstr]);
+                FStreamer.BeginObject(p.getName(),p.getType());
+                  FStreamer.SetNameStyle(nsQualified);
+                    FStreamer.Put(sdo_namespace,s_ref,getType(StringType),vstr);
+                  FStreamer.SetNameStyle(nsUnqualified);
+                FStreamer.EndScope();
+              end;
+            end;
+          end;
+        end;
+      end else begin
+        unsetList := Format('%s %s',[unsetList,p.getName()]);
+      end;
+    end;
+
+  var
+    locType : ISDOType;
+    locStrBuffer : TSDOString;
+    ls : ISDOSettingList;
+    c, i : PtrInt;
+    locSetting : TValueSetting;
+  begin
+    AddToChangeSummaryList(ADataObject);
+    locType := ADataObject.getType();
+    FStreamer.BeginObject(locType.getName(),locType);
+    try
+      PushSerializationStyle(ssAttibuteSerialization);
+      try
+        locStrBuffer := getObjectPath(ADataObject,ARootObjectName);
+        FStreamer.SetNameStyle(nsQualified);
+          FStreamer.Put(sdo_namespace, s_ref,getType(StringType),locStrBuffer);
+        FStreamer.SetNameStyle(nsUnqualified);
+        ls := AValue.getOldValues(ADataObject);
+        c := ls.size();
+        if ( c > 0 ) then begin
+          for i := 0 to Pred(c) do begin
+            locSetting := ls.getItem(i);
+            if not locSetting.getProperty().isMany() then
+              WriteSetting(locSetting);
+          end;
+        end;
+        unsetList := Trim(unsetList);
+        if ( Length(unsetList) > 0 ) then begin
+          FStreamer.SetNameStyle(nsQualified);
+            FStreamer.Put(sdo_namespace,s_unset,getType(StringType),unsetList);
+          FStreamer.SetNameStyle(nsUnqualified);
+        end;
+        WriteChangeSummaryMultiValueProps(AValue,ADataObject);
+      finally
+        PopSerializationStyle();
+      end;
+    finally
+      FStreamer.EndScope();
+    end;
+  end;
+
+var
+  oldNameStyle : TNameStyle;
+  ls : ISDOChangedDataObjectListEx;
+  lsCreate, lsDelete, strBuffer : TSDOString;
+  c, i : PtrInt;
+  tmpObj : ISDODataObject;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  if ( AValue <> nil ) then begin
+    FChangeSummary := AValue;
+    try
+      FChangeSummaryList := FDataFactory.createNew(sdo_namespace,s_changeSummaryListObject);
+      ls := AValue.getChangedDataObjects() as ISDOChangedDataObjectListEx;
+      oldNameStyle := FStreamer.GetNameStyle();
+      FStreamer.SetNameStyle(nsUnqualified);
+      try
+        FStreamer.BeginObject(s_changeSummary,FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType]));
+        try
+          c := ls.size();
+          if ( c > 0 ) then begin
+            lsCreate := '';
+            lsDelete := '';
+            FStreamer.SetNameStyle(nsUnqualified);
+            for i := 0 to Pred(c) do begin
+              //if ( ls.getInfo(i).Index = 0 ) then begin
+                case ls.getType(i) of
+                  ctCreate :
+                    begin
+                      locChangeInfo := ls.getInfo(i);
+                      locChangeInfo.CaptureOldContainment();
+                      tmpObj := locChangeInfo.DataObject;
+                      lsCreate := Format('%s %s',[lsCreate,getObjectPath(tmpObj,ARootObjectName)]);
+                      {if locChangeInfo.OldContainmentProperty.isMany() then
+                        lsCreate := Format('%s[%d]',[lsCreate,locChangeInfo.Index]);}
+                    end;
+                  ctChange : WriteChange(ls.getDataObject(i));
+                  ctDelete :
+                    begin
+                      tmpObj := ls.getDataObject(i);
+                      strBuffer := Format('#/%s/%s/%s',[s_changeSummary, ARootObjectName, AValue.getOldXpath(tmpObj)]);
+                      lsDelete := Format('%s %s',[lsDelete, AddToChangeSummaryList(tmpObj)]);
+                      InternalWriteObject(
+                        tmpObj.getType().getName(),tmpObj,
+                        [{owoWriteReference : set the ref only objects represented both in the CS and and the final doc}],
+                        strBuffer
+                      );
+                    end;
+                end;
+              //end;
+            end;
+            lsCreate := Trim(lsCreate);
+            if ( Length(lsCreate) > 0 ) then
+              FStreamer.Put(s_create,getType(StringType),lsCreate);
+            lsCreate := '';
+            lsDelete := Trim(lsDelete);
+            if ( Length(lsDelete) > 0 ) then
+              FStreamer.Put(s_delete,getType(StringType),lsDelete);
+            WritePendingRefProps();
+            FReferenceWriteRecallList.Clear();
+          end;
+        finally
+          FStreamer.EndScope();
+        end;
+      finally
+        FStreamer.SetNameStyle(oldNameStyle);
+        //FChangeSummaryList := nil;
+      end;
+    finally
+      FChangeSummary := nil;
+    end;
+  end;
+end;
+
+procedure TSDOSerializer.WriteIntegerListProp(const AName: string; const AValueList: ISDODataObjectList);
+var
+  tmpVal : TSDOInteger;
+begin
+  tmpVal := AValueList.getInteger();
+  FStreamer.Put(AName,FProcs[IntegerType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteIntegerProp(const AProp: ISDOProperty; const AObject : ISDODataObject);
+var
+  tmpVal : TSDOInteger;
+begin            
+  if not AObject.isNull(AProp) then begin 
+    tmpVal := AObject.getInteger(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[IntegerType].PropType,tmpVal);
+  end;
+end;
+
+procedure TSDOSerializer.WriteMetadata();
+var
+  locXdsBuffer : TSDOString;
+  locXsd : IXSDHelper;
+begin
+  locXsd := TXSDHelper.Create(FDataFactory);
+  locXdsBuffer := locXsd.Generate(FDataFactory.getTypes(),FNamespace);
+  FStreamer.BeginObject(s_xsd,FDataFactory.getType(sdo_namespace,s_xsd));
+  try
+    if AnsiSameText(s_xml,FStreamer.GetFormatName()) then
+      FStreamer.WriteBuffer(locXdsBuffer)
+    else
+      FStreamer.Put(s_xsd,FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),locXdsBuffer);
+  finally
+    FStreamer.EndScope();
+  end;
+end;
+
+procedure TSDOSerializer.InternalWriteObject(
+  const AName : string;
+  const AObject: ISDODataObject;
+  const AOptions : TObjectWriteOptions;
+  const AReference : TSDOString
+);
+
+  procedure WriteArrayProp(const AProp : ISDOProperty);
+  var
+    ls : ISDODataObjectList;
+    k, lsCount : PtrInt;
+    crsr : ISDOCursor;
+    wrtProc : TPropListWriterProc;
+    bmk : ISDOCursorBookmark;
+  begin
+    ls := AObject.getList(AProp);
+    lsCount := ls.size();
+    if ( lsCount > 0 ) then
+      k := lsCount - 1
+    else
+      k := 0;
+    crsr := ls.getCursor();
+    FStreamer.BeginArray(AProp.getName(),AProp.getType(),[0,k]);
+    try
+      PushSerializationStyle(ssNodeSerialization);
+      try
+        bmk := crsr.GetBookmark();
+        try
+          if AProp.getType().isDataObjectType() then begin
+            crsr.Reset();
+            while crsr.MoveNext() do begin
+              InternalWriteObject(AProp.getName(),ls.getDataObject(),[],'');
+            end;
+          end else begin
+            wrtProc := FProcs[AProp.getType().getTypeEnum()].WriterListProc;
+            if Assigned(wrtProc) then begin
+              crsr.Reset();
+              while crsr.MoveNext() do begin
+                wrtProc(AProp.getName(),ls);
+              end;
+            end;
+          end;
+        finally
+          crsr.GotoBookmark(bmk);
+        end;
+      finally
+        PopSerializationStyle();
+      end;
+    finally
+      FStreamer.EndScope();
+    end;
+  end;
+
+  procedure WriteRefObjectProp(const ADataObject : ISDODataObject; const AProp : ISDOProperty);
+  var
+    locStrBuffer : TSDOString;
+    locObjBuffer : ISDODataObject;
+  begin
+    locObjBuffer := AObject.getDataObject(AProp);
+    if ( locObjBuffer <> nil ) and ( owoPostRefProperties in AOptions ) then begin
+      AddPropertyRefRecallWrite(rritPropertyValue,ADataObject,AProp,locObjBuffer);
+    end else begin
+      FStreamer.BeginObject(AProp.getName(),AProp.getType());
+      try
+        if ( locObjBuffer = nil ) then begin
+          FStreamer.NilCurrentScope()
+        end else begin
+          if ( FChangeSummary <> nil ) and FChangeSummary.isDeleted(locObjBuffer) then
+            locStrBuffer := getObjectPathInChangeSummary(locObjBuffer)
+          else
+            locStrBuffer := getObjectPath(locObjBuffer,FRootName);
+          FStreamer.PutScopeInnerValue(getType(StringType),locStrBuffer);
+        end;
+      finally
+        FStreamer.EndScope();
+      end;
+    end;
+  end;
+
+  procedure WriteReference();{$IFDEF USE_INLINE}inline;{$ENDIF}
+  begin
+    FStreamer.SetNameStyle(nsQualified);
+      FStreamer.Put(sdo_namespace, s_ref,getType(StringType),AReference);
+    FStreamer.SetNameStyle(nsUnqualified);
+  end;
+
+  procedure Local_WriteNilObject();{$IFDEF USE_INLINE}inline;{$ENDIF}
+  begin
+    FStreamer.BeginObject(AName,FDataFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+    try
+      FStreamer.NilCurrentScope();
+      if ( owoWriteReference in AOptions ) then
+        WriteReference();
+    finally
+      FStreamer.SetNameStyle(nsUnqualified);
+      FStreamer.EndScope();
+    end;
+  end;
+
+  procedure Local_WriteChangeSummary();{$IFDEF USE_INLINE}inline;{$ENDIF}
+  var
+    locChangeSummary : ISDOChangeSummary;
+  begin
+    locChangeSummary := AObject.getChangeSummary();
+    if ( locChangeSummary <> nil ) then
+      WriteChangeSummary(locChangeSummary,AName);
+  end;
+
+var
+  locType : ISDOType;
+  locPropList : ISDOPropertyList;
+  locProp : ISDOProperty;
+  i, c : PtrInt;
+  prpProc : TPropWriterProc;
+  locSerializationStyle : TSerializationStyle;
+begin
+  if ( AObject = nil ) then begin
+    Local_WriteNilObject();
+  end else begin
+    if ( owoWriteChangeSummary in AOptions ) then
+      Local_WriteChangeSummary();
+    FStreamer.BeginObject(AName,AObject.getType());
+    try
+      if ( owoWriteReference in AOptions ) then
+        WriteReference();
+      FStreamer.SetNameStyle(nsUnqualified);
+      { TODO : The Serialization style should be a Property based option! }
+//    PushSerializationStyle(ssAttibuteSerialization);
+  //  try
+        locPropList := AObject.getInstanceProperties();
+        c := locPropList.getCount();
+        for i := 0 to Pred(c) do begin
+          locProp := locPropList.getItem(i);
+          if locProp.isMany() then begin
+            WriteArrayProp(locProp);
+          end else begin
+            if locProp.isAttribute() then
+              locSerializationStyle := ssAttibuteSerialization
+            else
+              locSerializationStyle := ssNodeSerialization;
+            PushSerializationStyle(locSerializationStyle);
+              locType := locProp.getType();
+              if locType.isDataObjectType() then begin
+                if locProp.isContainment() then begin
+                  InternalWriteObject(locProp.getName(),AObject.getDataObject(locProp),[],'');
+                end else if locProp.isReference() then begin
+                  WriteRefObjectProp(AObject,locProp);
+                end;
+              end else begin
+                prpProc := FProcs[locType.getTypeEnum()].WriterProc;
+                if Assigned(prpProc) then
+                  prpProc(locProp,AObject);
+              end;
+            PopSerializationStyle();
+          end;
+        end;
+//    finally
+//      PopSerializationStyle();
+//    end;
+    finally
+      FStreamer.EndScope();
+    end;
+  end;
+end;
+
+procedure TSDOSerializer.WriteStringListProp(const AName: string; const AValueList: ISDODataObjectList);
+var
+  tmpVal : TSDOString;
+begin
+  tmpVal := AValueList.getString();
+  FStreamer.Put(AName,FProcs[StringType].PropType,tmpVal);
+end;
+
+procedure TSDOSerializer.WriteStringProp(const AProp: ISDOProperty; const AObject: ISDODataObject);
+var
+  tmpVal : TSDOString;
+begin
+  if not AObject.isNull(AProp) then begin
+    tmpVal := AObject.getString(AProp);
+    FStreamer.Put(AProp.getName(),FProcs[StringType].PropType,tmpVal);
+  end;
+end;
+
+
+
+end.

+ 1997 - 0
packages/fcl-sdo/src/base/sdo_serialization_binary.pas

@@ -0,0 +1,1997 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements streaming to binary file.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_serialization_binary;
+
+interface
+
+uses
+  Classes, SysUtils, Contnrs,
+  sdo_binary_streamer,
+  sdo_types, sdo, sdo_consts, sdo_serialization_utils;
+
+{$DEFINE sdo_binary_header}
+  
+const
+  sBINARY_FORMAT_NAME = 'sdo-binary';
+  sROOT   = 'ROOT';
+  sSCOPE_INNER_NAME = 'INNER_VAL';
+  sFORMAT = 'format';
+
+type
+
+  TDataName = String;
+  TDataType = (
+    dtInt8U  = 1,    dtInt8S = 2,
+    dtInt16U = 3,   dtInt16S = 4,
+    dtInt32U = 5,   dtInt32S = 6,
+    dtInt64U = 7,   dtInt64S = 8,
+    dtBool   = 9,
+    dtAnsiChar   = 10, dtWideChar   = 11, dtEnum     = 12,
+    dtSingle     = 13, dtDouble     = 14, dtExtended = 15, dtCurrency = 16,
+    dtAnsiString = 17, dtWideString = 18,
+{$IFDEF USE_UNICODE}
+    dtUnicodeString = 19,
+{$ENDIF USE_UNICODE}
+    dtObject = 30, dtArray = 31,
+    dtByteDynArray = 32
+  );
+const
+  dtDefaultString =
+    {$IFDEF USE_UNICODE}
+      {$IFDEF DELPHI}
+        dtUnicodeString
+      {$ENDIF DELPHI}
+      {$IFDEF FPC}
+        dtAnsiString
+      {$ENDIF FPC}
+    {$ELSE USE_UNICODE}
+      dtAnsiString
+    {$ENDIF USE_UNICODE}
+    ;
+
+type
+
+  PAnsiStringBuffer = ^TAnsiStringBuffer;
+  PWideStringBuffer = ^TWideStringBuffer;
+{$IFDEF USE_UNICODE}
+  PUnicodeStringBuffer = ^TUnicodeStringBuffer;
+{$ENDIF USE_UNICODE}
+  PObjectBuffer = ^TObjectBuffer;
+  PArrayBuffer = ^TArrayBuffer;
+  PByteDynArrayBuffer = ^TByteDynArrayBuffer;
+  PDataBuffer = ^TDataBuffer;
+
+  TDataBuffer = Record
+    Name : TDataName;
+    Case DataType : TDataType of
+      dtInt8S    : ( Int8S : TInt8S );
+      dtInt8U    : ( Int8U : TInt8U );
+      dtInt16U   : ( Int16U : TInt16U );
+      dtInt16S   : ( Int16S : TInt16S );
+      dtInt32U   : ( Int32U : TInt32U );
+      dtInt32S   : ( Int32S : TInt32S );
+      dtInt64U   : ( Int64U : TInt64U );
+      dtInt64S   : ( Int64S : TInt64S );
+      dtBool     : ( BoolData : TBoolData );
+      dtAnsiChar : ( AnsiCharData : TAnsiCharacter; );
+      dtWideChar : ( WideCharData : TWideCharacter; );
+      dtEnum     : ( EnumData : TEnumData );
+      dtSingle   : ( SingleData : TFloat_Single_4 );
+      dtDouble   : ( DoubleData : TFloat_Double_8 );
+      dtExtended   : ( ExtendedData : TFloat_Extended_10 );
+      dtCurrency   : ( CurrencyData : TFloat_Currency_8 );
+      
+      dtAnsiString : ( AnsiStrData : PAnsiStringBuffer );
+      dtWideString : ( WideStrData : PWideStringBuffer );
+{$IFDEF USE_UNICODE}
+      dtUnicodeString : ( UnicodeStrData : PUnicodeStringBuffer );
+{$ENDIF USE_UNICODE}
+      dtObject   : ( ObjectData : PObjectBuffer );
+      dtArray    : ( ArrayData : PArrayBuffer );
+      dtByteDynArray : ( ByteDynArrayData : PByteDynArrayBuffer );
+  End;
+
+  TAnsiStringBuffer = record
+    Data : TAnsiStringData;
+  end;
+
+  TWideStringBuffer = record
+    Data : TWideStringData;
+  end;
+
+{$IFDEF USE_UNICODE}
+  TUnicodeStringBuffer = record
+    Data : TUnicodeStringData;
+  end;
+{$ENDIF USE_UNICODE}
+
+
+
+  PObjectBufferItem = ^TObjectBufferItem;
+  TObjectBufferItem = Record
+    Data : PDataBuffer;
+    Next : PObjectBufferItem;
+  End;
+
+  TObjectBuffer = Record
+    NilObject   : TBoolData;
+    Count       : Integer;
+    Head        : PObjectBufferItem;
+    Last        : PObjectBufferItem;
+    Attributes  : PObjectBuffer;
+    InnerData   : PDataBuffer;
+  End;
+
+  PDataBufferList = ^TDataBufferList;
+  TDataBufferList = array[0..MAX_ARRAY_LENGTH] of PDataBuffer;
+  TArrayBuffer = Record
+    Count : Integer;
+    Items : PDataBufferList;
+    Attributes  : PObjectBuffer;
+  End;
+
+  TByteDynArrayBuffer = record
+    Data : TByteDynArray;
+  end;
+
+  { TStackItem }
+
+  TStackItem = class
+  private
+    FScopeObject: PDataBuffer;
+    FScopeType: TScopeType;
+  protected
+    procedure CopyTo(const AClone : TStackItem);virtual;
+  Public
+    constructor Create(const AScopeObject : PDataBuffer;AScopeType : TScopeType);
+    function Clone() : TStackItem;virtual; abstract;
+    function GetItemCount():Integer;virtual;abstract;
+    function Find(var AName : TDataName):PDataBuffer;virtual;abstract;
+    function GetByIndex(const AIndex : Integer):PDataBuffer;virtual;abstract;
+    function CreateBuffer(
+      Const AName     : String;
+      const ADataType : TDataType
+    ):PDataBuffer;virtual;abstract;
+    function CreateInnerBuffer(const ADataType : TDataType):PDataBuffer;virtual;abstract;
+    function GetInnerBuffer():PDataBuffer;virtual;abstract;
+    procedure NilCurrentScope();virtual;abstract;
+    function IsCurrentScopeNil():Boolean;virtual;abstract;
+    property ScopeObject : PDataBuffer Read FScopeObject;
+    property ScopeType : TScopeType Read FScopeType;
+
+    function GetScopeItemNames(const AReturnList : TStrings) : Integer;virtual;abstract;
+  End;
+
+  { TObjectStackItem }
+
+  TObjectStackItem = class(TStackItem)
+  Public
+    constructor Create(const AScopeObject : PDataBuffer);
+    function Clone() : TStackItem; override;
+    function GetItemCount():Integer;override;
+    function Find(var AName : TDataName):PDataBuffer;override;
+    function GetByIndex(const AIndex : Integer):PDataBuffer;override;
+    function CreateBuffer(
+      Const AName     : String;
+      const ADataType : TDataType
+    ):PDataBuffer;override;
+    function CreateInnerBuffer(const ADataType : TDataType):PDataBuffer;override;
+    function GetInnerBuffer():PDataBuffer;override;
+    procedure NilCurrentScope();override;
+    function IsCurrentScopeNil():Boolean;override;
+    function GetScopeItemNames(const AReturnList : TStrings) : Integer;override;
+  End;
+  TObjectStackItemClass = class of TObjectStackItem;
+
+  { TArrayStackItem }
+
+  TArrayStackItem = class(TStackItem)
+  Private
+    FIndex : Integer;
+  protected
+    procedure CopyTo(const AClone : TStackItem);override;
+  Public
+    constructor Create(const AScopeObject : PDataBuffer);
+    function Clone() : TStackItem; override;
+    function GetItemCount():Integer;override;
+    function Find(var AName : TDataName):PDataBuffer;override;
+    function GetByIndex(const AIndex : Integer):PDataBuffer;override;
+    function CreateBuffer(
+      Const AName     : String;
+      const ADataType : TDataType
+    ):PDataBuffer;override;
+    function CreateInnerBuffer(const ADataType : TDataType):PDataBuffer;override;
+    function GetInnerBuffer():PDataBuffer;overload;override;
+    procedure NilCurrentScope();override;
+    function IsCurrentScopeNil():Boolean;override;
+    function GetScopeItemNames(const AReturnList : TStrings) : Integer;override;
+  End;
+  TArrayStackItemClass = class of TArrayStackItem;
+
+  TStreamBinaryBookmark = class(TStreamBookmark)
+  private
+    FNameStyle: TNameStyle;
+    FStack: TObjectStackEx;
+    FRootData : PDataBuffer;
+    FSerializationStyle: TSerializationStyle;
+  public
+    destructor Destroy();override;
+    property SerializationStyle : TSerializationStyle read FSerializationStyle;
+    property NameStyle : TNameStyle read FNameStyle;
+    property RootData : PDataBuffer read FRootData;
+    property Stack : TObjectStackEx read FStack;
+  end;
+
+  { TSDOSerializationStreamBinary }
+
+  TSDOSerializationStreamBinary = class(TInterfacedObject,IInterface,ISDOSerializerStream)
+  private
+    FRootData : PDataBuffer;
+    FStack : TObjectStackEx;
+    FSerializationStyle : TSerializationStyle;
+    FNameStyle : TNameStyle;
+  protected
+    function GetCurrentScopeObject():PDataBuffer;
+  protected
+    function HasScope():Boolean;
+    procedure CheckScope();
+    procedure ClearStack();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure PushStack(AScopeObject : PDataBuffer;Const AScopeType : TScopeType = stObject);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function StackTop():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function PopStack():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetRootData() : PDataBuffer;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    procedure PutBoolean(const AName : string; const AData : TSDOBoolean);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure PutByte(const AName : string; const AData : TSDOByte);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_BYTES}
+    procedure PutBytes(const AName : string; const AData : TSDOBytes);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure PutChar(const AName : string; const AData : TSDOChar);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure PutCurrency(const AName : string; const AData : TSDOCurrency);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure PutDate(const AName : string; const AData : TSDODateTime);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure PutDouble(const AName : string; const AData : TSDODouble);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure PutFloat(const AName : string; const AData : TSDOFloat);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_FLOAT}
+    procedure PutInteger(const AName : string; const AData : TSDOInteger);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_LONG}
+    procedure PutLong(const AName : string; const AData : TSDOLong);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure PutShort(const AName : string; const AData : TSDOShort);{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+    procedure PutString(const AName : string; const AData : TSDOString);{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+    function GetDataBuffer(
+      var AName : string;
+      out AResultBuffer : PDataBuffer
+    ) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetBoolean(var AName : string;var AData : TSDOBoolean) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetByte(var AName : string;var AData : TSDOByte) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_BYTES}
+    function GetBytes(var AName : string;var AData : TSDOBytes) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    function GetChar(var AName : string;var AData : TSDOChar) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function GetCurrency(var AName : string;var AData : TSDOCurrency) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CURRENCY}
+    function GetDate(var AName : string;var AData : TSDODateTime) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_DOUBLE}
+    function GetDouble(var AName : string;var AData : TSDODouble) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function GetFloat(var AName : string;var AData : TSDOFloat) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_FLOAT}
+    function GetInteger(var AName : string;var AData : TSDOInteger) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_LONG}
+    function GetLong(var AName : string;var AData : TSDOLong) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function GetShort(var AName : string;var AData : TSDOShort) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+    function GetString(var AName : string;var AData : TSDOString) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+  protected // ISDOSerializerStream
+    function GetFormatName() : string;
+    procedure SetSerializationStyle(const ASerializationStyle : TSerializationStyle);
+    function GetSerializationStyle():TSerializationStyle;
+    procedure SetNameStyle(const AValue : TNameStyle);
+    function GetNameStyle() : TNameStyle;
+    function GetCurrentScope():string;
+    procedure Clear();
+    procedure Initialize();
+
+    procedure BeginObject(
+      Const AName      : string;
+      Const ATypeInfo  : ISDOType
+    );
+    procedure BeginArray(
+      const AName         : string;
+      const AItemTypeInfo : ISDOType;
+      const ABounds       : array of Integer
+    );
+    procedure NilCurrentScope();
+    function IsCurrentScopeNil():Boolean;
+    procedure EndScope();
+    function BeginObjectRead(
+      var   AScopeName : string;
+      const ATypeInfo  : ISDOType
+    ) : Integer;
+    function BeginArrayRead(
+      var   AScopeName : string;
+      const ATypeInfo  : ISDOType;
+      const AItemName  : string
+    ):Integer;
+    function GetScopeItemNames(
+      const AItemStyle : TSerializationStyle;
+      const AReturnList : TStrings
+    ) : Integer;
+    procedure EndScopeRead();
+
+    procedure Put(
+      const AName     : string;
+      const ATypeInfo : ISDOType;
+      const AData
+    );overload;
+    procedure Put(
+      const ANameSpace,
+            AName     : string;
+      const ATypeInfo : ISDOType;
+      const AData
+    );overload;
+    procedure PutScopeInnerValue(
+      const ATypeInfo : ISDOType;
+      const AData
+    );
+    function Get(
+      const ATypeInfo : ISDOType;
+      var   AName     : string;
+      var   AData
+    ) : Boolean;overload;
+    function Get(
+      const ANameSpace : string;
+      const ATypeInfo  : ISDOType;
+      var   AName      : string;
+      var   AData
+    ) : Boolean;overload;
+    function GetScopeInnerValue(
+      const ATypeInfo : ISDOType;
+      var   AData
+    ) : Boolean;
+    function ReadBuffer(const AName : string) : string;
+    //Please use this method if and _only_ if you do not have another way to achieve your aim!
+    procedure WriteBuffer(const AValue : string);
+
+    procedure SaveToStream(AStream : TStream);overload;
+    procedure SaveToFile(const AFileName : string);overload;
+    procedure LoadFromStream(AStream : TStream);overload;
+    procedure LoadFromFile(const AFileName : string);overload;
+
+    function GetBookMark() : TStreamBookmark;
+    function GotoBookmark(const AValue : TStreamBookmark) : Boolean;
+    // This procedures will raise exceptions!!!
+    procedure Error(Const AMsg:string);overload;
+    procedure Error(Const AMsg:string; Const AArgs : array of const);overload;
+  public
+    constructor Create();
+    destructor Destroy();override;
+  end;
+
+  TDBGPinterProc = procedure(const AMsg:string);
+
+  procedure ClearObj(const AOwner: PDataBuffer);
+  procedure FreeObjectBuffer(var ABuffer : PDataBuffer); overload;
+  function LoadObjectFromStream(const AStoreRdr : IDataStoreReader):PDataBuffer;
+  procedure SaveObjectToStream(const ARoot: PDataBuffer; const ADest : IDataStore);
+  function CreateArrayBuffer(
+    const ALength   : Integer;
+    const AName     : TDataName;
+    const AOwner    : PDataBuffer = nil
+  ):PDataBuffer;
+  function CreateObjBuffer(
+    const ADataType : TDataType;
+    const AName     : TDataName;
+    const AOwner    : PDataBuffer = nil
+  ):PDataBuffer;
+
+  function ToStr(const ABuffer : PDataBuffer) : TSDOString;
+  procedure PrintObj(const ARoot: PDataBuffer; const ALevel : Integer; const APrinterProc : TDBGPinterProc);
+
+
+implementation
+
+function sdo_GetMem(Size : PtrInt) : Pointer;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  {$IFDEF FPC}
+  Result := GetMem(Size);
+  {$ELSE}
+  GetMem(Result,Size);
+  {$ENDIF}
+end;
+
+function ToStr(const ABuffer : PDataBuffer) : TSDOString;
+begin
+  Result := '';
+  if ( ABuffer <> nil ) then begin
+    case ABuffer^.DataType of
+      dtInt8U     : Result := TSDOConvertHelper.ByteToString(ABuffer^.Int8U);
+      dtInt8S     : Result := TSDOConvertHelper.ShortToString(ABuffer^.Int8S);
+      dtInt16U    : Result := TSDOConvertHelper.IntegerToString(ABuffer^.Int16U);
+      dtInt16S    : Result := TSDOConvertHelper.ShortToString(ABuffer^.Int16S);
+      dtInt32U    : Result := TSDOConvertHelper.LongToString(ABuffer^.Int32U);
+      dtInt32S    : Result := TSDOConvertHelper.IntegerToString(ABuffer^.Int32S);
+      dtInt64U    : Result := IntToStr(ABuffer^.Int64U);
+      dtInt64S    : Result := IntToStr(ABuffer^.Int64S);
+
+      dtBool      : Result := TSDOConvertHelper.BoolToString(ABuffer^.BoolData);
+      dtAnsiChar  : Result := String(ABuffer^.AnsiCharData);
+      dtWideChar  : Result := ABuffer^.WideCharData;
+      dtEnum      : Result := IntToStr(ABuffer^.EnumData);
+      dtSingle    : Result := TSDOConvertHelper.FloatToString(ABuffer^.SingleData);
+      dtDouble    : Result := TSDOConvertHelper.FloatToString(ABuffer^.DoubleData);
+      dtExtended  : Result := TSDOConvertHelper.FloatToString(ABuffer^.ExtendedData);
+      dtCurrency  : Result := TSDOConvertHelper.CurrencyToString(ABuffer^.CurrencyData);
+      dtAnsiString: Result := String(ABuffer^.AnsiStrData^.Data);
+      dtWideString: Result := ABuffer^.WideStrData^.Data;
+{$IFDEF USE_UNICODE}
+      dtUnicodeString : Result := ABuffer^.UnicodeStrData^.Data;
+{$ENDIF USE_UNICODE}
+    end;
+  end;
+end;
+
+{var FFile : TMemoryStream = nil;
+procedure DBG_Write(const AMsg:string);
+var
+  s : string;
+begin
+  if ( FFile = nil ) then
+    FFile := TMemoryStream.Create();
+  s := AMsg + sLineBreak;
+  FFile.Write(s[1],Length(s));
+end;}
+
+procedure PrintObj(const ARoot: PDataBuffer; const ALevel : Integer; const APrinterProc : TDBGPinterProc);
+Var
+  p : PObjectBufferItem;
+  s : string;
+  i ,j: Integer;
+  da : TByteDynArray;
+Begin
+  If Not Assigned(ARoot) Then
+    Exit;
+  s := StringOfChar(' ',ALevel);
+  Case ARoot^.DataType Of
+    dtInt8S   : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int8S) );
+    dtInt8U   : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int8U) );
+    dtInt32U  : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int32U) );
+    dtInt32S  : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int32S) );
+    dtInt64U  : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int64U) );
+    dtInt64S  : APrinterProc( s + ARoot^.Name + ' = ' + IntToStr(ARoot^.Int64S) );
+
+    dtSingle  : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.SingleData) );
+    dtDouble  : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.DoubleData) );
+    dtExtended  : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.ExtendedData) );
+    dtCurrency  : APrinterProc( s + ARoot^.Name + ' = ' + FloatToStr(ARoot^.CurrencyData) );
+
+    dtAnsiString  : APrinterProc( s + ARoot^.Name + ' = ' + String(ARoot^.AnsiStrData^.Data) );
+    dtWideString  : APrinterProc( s + ARoot^.Name + ' = ' + ARoot^.WideStrData^.Data );
+{$IFDEF USE_UNICODE}
+    dtUnicodeString  : APrinterProc( s + ARoot^.Name + ' = ' + ARoot^.UnicodeStrData^.Data );
+{$ENDIF USE_UNICODE}
+    dtObject  :
+      Begin
+        APrinterProc( s + ARoot^.Name + ' = ');
+        If Not Assigned(ARoot^.ObjectData) Then Begin
+          APrinterProc(s + '  <Vide>');
+        End Else Begin
+          APrinterProc('( ' + IntToStr(ARoot^.ObjectData^.Count) + ' Objects )');
+          p := ARoot^.ObjectData^.Head;
+          i := ALevel + 1;
+          While Assigned(p) Do Begin
+            PrintObj(p^.Data,i,APrinterProc);
+            p := p^.Next;
+          End;
+        End;
+      End;
+    dtArray :
+      Begin
+        APrinterProc( s + ARoot^.Name + ' = ');
+        If Not Assigned(ARoot^.ArrayData) Then Begin
+          APrinterProc(s + '  <Vide>');
+        End Else Begin
+          j := ARoot^.ArrayData^.Count;
+          APrinterProc('( Objects[ '+ IntToStr(j)+ '] )');
+          i := ALevel + 1;
+          For j := 0 To Pred(j) Do Begin
+            PrintObj(ARoot^.ArrayData^.Items^[j],i,APrinterProc);
+          End;
+        End;
+      End;
+    dtByteDynArray :
+      begin
+        APrinterProc( s + ARoot^.Name + ' = ');
+        if ( ARoot^.ByteDynArrayData = nil ) then begin
+          APrinterProc(s + '  <Vide>');
+        end else begin
+          i := Length(ARoot^.ByteDynArrayData^.Data);
+          j := i;
+          da := ARoot^.ByteDynArrayData^.Data;
+          for j := 1 to j do
+            s := s + Format(' %d',[da[Pred(j)]]);
+          APrinterProc('( Bytes[ '+ IntToStr(i)+ '] )' + s);
+        end;
+      end;
+  End;
+End;
+
+function FindObj(const AOwner: PDataBuffer; const AName : TDataName) : PDataBuffer;
+Var
+  p : PObjectBufferItem;
+Begin
+  Assert(AOwner^.DataType >= dtObject);
+  Result := Nil;
+   p:= AOwner^.ObjectData^.Head;
+  While Assigned(p) Do Begin
+    If AnsiSameText(AName,p^.Data^.Name) Then Begin
+      Result := p^.Data;
+      Exit;
+    End;
+    p := p^.Next;
+  End;
+End;
+
+procedure AddObj(
+  const AOwner, AChildData: PDataBuffer;
+  const AIndex : Integer = -1
+);
+Var
+  p : PObjectBufferItem;
+Begin
+  If ( AOwner^.DataType = dtObject ) Then Begin
+    p := sdo_GetMem(SizeOf(TObjectBufferItem));
+    p^.Data := AChildData;
+    p^.Next := Nil;
+    If Assigned(AOwner^.ObjectData^.Head) Then Begin
+      AOwner^.ObjectData^.Last^.Next := p;
+    End Else Begin
+      AOwner^.ObjectData^.Head := p;
+    End;
+    AOwner^.ObjectData^.Last := p;
+    Inc(AOwner^.ObjectData^.Count);
+  End Else If ( AOwner^.DataType = dtArray ) Then Begin
+    If ( AIndex >= 0 ) And ( AIndex < AOwner^.ArrayData^.Count ) Then
+      AOwner^.ArrayData^.Items^[AIndex] := AChildData
+    Else
+      raise ESDOSerializationException.CreateFmt(SERR_IndexOutOfBound,[AIndex])
+  End Else Begin
+    Raise ESDOSerializationException.CreateFmt(SERR_InvalidDataTypeInContext,[IntToStr(Ord(AOwner^.DataType))])
+  End;
+End;
+
+function CreateObjBuffer(
+  const ADataType : TDataType;
+  const AName     : TDataName;
+  const AOwner    : PDataBuffer = nil
+):PDataBuffer;
+var
+  resLen, i : Integer;
+begin
+  resLen := SizeOf(TDataBuffer);
+  Result := sdo_GetMem(resLen);
+  Try
+    FillChar(Result^,resLen,#0);
+    Result^.Name := AName;
+    Result^.DataType := ADataType;
+    Case Result^.DataType Of
+      dtAnsiString :
+        Begin
+          i := SizeOf(TAnsiStringBuffer);
+          Result^.AnsiStrData := sdo_GetMem(i);
+          FillChar(Result^.AnsiStrData^,i,#0);
+          Result^.AnsiStrData^.Data := '';
+        End;
+      dtWideString :
+        begin
+          i := SizeOf(TWideStringBuffer);
+          Result^.WideStrData := sdo_GetMem(i);
+          FillChar(Result^.WideStrData^,i,#0);
+          Result^.WideStrData^.Data := '';
+        end;
+{$IFDEF USE_UNICODE}
+      dtUnicodeString :
+        begin
+          i := SizeOf(TUnicodeStringBuffer);
+          Result^.UnicodeStrData := sdo_GetMem(i);
+          FillChar(Result^.UnicodeStrData^,i,#0);
+          Result^.UnicodeStrData^.Data := '';
+        end;
+{$ENDIF USE_UNICODE}
+      dtObject :
+        Begin
+          Result^.ObjectData := sdo_GetMem(SizeOf(TObjectBuffer));
+          FillChar(Result^.ObjectData^,SizeOf(TObjectBuffer),#0);
+        End;
+      dtByteDynArray :
+        begin
+          i := SizeOf(TByteDynArrayBuffer);
+          Result^.ByteDynArrayData := sdo_GetMem(i);
+          FillChar(Result^.ByteDynArrayData^,i,#0);
+          Result^.ByteDynArrayData^.Data := nil;
+        end;
+    End;
+    If Assigned(AOwner) Then
+      AddObj(AOwner,Result);
+  Except
+    Freemem(Result,resLen);
+    Result := nil;
+    Raise;
+  End;
+end;
+
+function CreateArrayBuffer(
+  const ALength   : Integer;
+  const AName     : TDataName;
+  const AOwner    : PDataBuffer = nil
+):PDataBuffer;
+Var
+  i, resLen : Integer;
+begin
+  Assert(ALength>=0);
+  resLen := SizeOf(TDataBuffer);
+  Result := sdo_GetMem(resLen);
+  Try
+    FillChar(Result^,resLen,#0);
+    Result^.Name := AName;
+    Result^.DataType := dtArray;
+    Result^.ArrayData := sdo_GetMem(SizeOf(TArrayBuffer));
+    FillChar(Result^.ArrayData^,SizeOf(TArrayBuffer),#0);
+    Result^.ArrayData^.Count := ALength;
+    If ( ALength > 0 ) Then Begin
+      i := ALength*SizeOf(PDataBuffer);
+      Result^.ArrayData^.Items := sdo_GetMem(i);
+      FillChar(Result^.ArrayData^.Items^[0],i,#0);
+    End Else Begin
+      Result^.ArrayData^.Items := Nil;
+    End;
+    If Assigned(AOwner) Then
+      AddObj(AOwner,Result);
+  Except
+    Freemem(Result,resLen);
+    Result := nil;
+    Raise;
+  End;
+end;
+
+procedure SaveObjectToStream(const ARoot: PDataBuffer; const ADest : IDataStore);
+Var
+  p : PObjectBufferItem;
+  i : TInt32S;
+Begin
+  If Not Assigned(ARoot) Then
+    Exit;
+  i := Ord(ARoot^.DataType);
+  ADest.WriteInt32S(i);
+  ADest.WriteAnsiStr(ARoot^.Name);
+  Case ARoot^.DataType Of
+    dtInt8S  : ADest.WriteInt8S(ARoot^.Int8S);
+      dtInt8U  : ADest.WriteInt8U(ARoot^.Int8U);
+    dtInt16U  : ADest.WriteInt16U(ARoot^.Int16U);
+      dtInt16S  : ADest.WriteInt16S(ARoot^.Int16S);
+    dtInt32U  : ADest.WriteInt32U(ARoot^.Int32U);
+      dtInt32S  : ADest.WriteInt32S(ARoot^.Int32S);
+    dtInt64U  : ADest.WriteInt64U(ARoot^.Int64U);
+      dtInt64S  : ADest.WriteInt64S(ARoot^.Int64S);
+      
+    dtSingle  : ADest.WriteSingle(ARoot^.SingleData);
+    dtDouble  : ADest.WriteDouble(ARoot^.DoubleData);
+    dtExtended  : ADest.WriteExtended(ARoot^.ExtendedData);
+    dtCurrency  : ADest.WriteCurrency(ARoot^.CurrencyData);
+    
+    dtAnsiString  : ADest.WriteAnsiStr(ARoot^.AnsiStrData^.Data);
+    dtWideString  : ADest.WriteWideStr(ARoot^.WideStrData^.Data);
+{$IFDEF USE_UNICODE}
+    dtUnicodeString  : ADest.WriteUnicodeStr(ARoot^.UnicodeStrData^.Data);
+{$ENDIF USE_UNICODE}
+    dtBool    : ADest.WriteBool(ARoot^.BoolData);
+    dtAnsiChar    : ADest.WriteAnsiChar(ARoot^.AnsiCharData);
+    dtWideChar    : ADest.WriteWideChar(ARoot^.WideCharData);
+    dtEnum    : ADest.WriteEnum(ARoot^.EnumData);
+    dtObject :
+      Begin
+        ADest.WriteBool(ARoot^.ObjectData^.NilObject) ;
+        if not ARoot^.ObjectData^.NilObject then begin
+          i := ARoot^.ObjectData^.Count;
+          ADest.WriteInt32S(i);
+
+          If ( i > 0 ) Then Begin
+            p := ARoot^.ObjectData^.Head;
+            For i := 1 To i Do Begin
+              SaveObjectToStream(p^.Data,ADest);
+              p := p^.Next;
+            End;
+          End;
+          ADest.WriteBool(Assigned(ARoot^.ObjectData^.InnerData));
+          if Assigned(ARoot^.ObjectData^.InnerData) then
+            SaveObjectToStream(ARoot^.ObjectData^.InnerData,ADest);
+        end;
+      End;
+    dtArray :
+      Begin
+        i := ARoot^.ArrayData^.Count;
+        ADest.WriteInt32S(i);
+
+        If ( i > 0 ) Then Begin
+          For i := 0 To Pred(i) Do Begin
+            SaveObjectToStream(ARoot^.ArrayData^.Items^[i],ADest);
+          End;
+        End;
+      End;
+    dtByteDynArray : ADest.WriteBinary(ARoot^.ByteDynArrayData^.Data);
+  End;
+End;
+
+function LoadObjectFromStream(const AStoreRdr : IDataStoreReader):PDataBuffer;
+Var
+  i : TInt32S;
+  s : string;
+Begin
+  Result := Nil;
+  If AStoreRdr.IsAtEof() Then
+    Exit;
+  i := AStoreRdr.ReadInt32S();
+  s := AStoreRdr.ReadAnsiStr();
+  If ( TDataType(i) < dtArray ) Then
+    Result := CreateObjBuffer(TDataType(i),s);
+  Case TDataType(i) Of
+    dtInt8S   : Result^.Int8S := AStoreRdr.ReadInt8S();
+    dtInt8U   : Result^.Int8U := AStoreRdr.ReadInt8U();
+    dtInt16U  : Result^.Int16U := AStoreRdr.ReadInt16U();
+    dtInt16S  : Result^.Int16S := AStoreRdr.ReadInt16S();
+    dtInt32U  : Result^.Int32U := AStoreRdr.ReadInt32U();
+    dtInt32S  : Result^.Int32S := AStoreRdr.ReadInt32S();
+    dtInt64U  : Result^.Int64U := AStoreRdr.ReadInt64U();
+    dtInt64S  : Result^.Int64S := AStoreRdr.ReadInt64S();
+
+    dtSingle  : Result^.SingleData := AStoreRdr.ReadSingle();
+    dtDouble  : Result^.DoubleData := AStoreRdr.ReadDouble();
+    dtExtended  : Result^.ExtendedData := AStoreRdr.ReadExtended();
+    dtCurrency  : Result^.CurrencyData := AStoreRdr.ReadCurrency();
+
+    dtAnsiString  : Result^.AnsiStrData^.Data := AStoreRdr.ReadAnsiStr();
+    dtWideString  : Result^.WideStrData^.Data := AStoreRdr.ReadWideStr();
+{$IFDEF USE_UNICODE}
+    dtUnicodeString  : Result^.UnicodeStrData^.Data := AStoreRdr.ReadUnicodeStr();
+{$ENDIF USE_UNICODE}
+    dtBool    : Result^.BoolData := AStoreRdr.ReadBool();
+    dtAnsiChar    : Result^.AnsiCharData := AStoreRdr.ReadAnsiChar();
+    dtWideChar    : Result^.WideCharData := AStoreRdr.ReadWideChar();
+    dtEnum    : Result^.EnumData := AStoreRdr.ReadEnum();
+    dtObject  :
+      Begin
+        Result^.ObjectData^.NilObject := AStoreRdr.ReadBool();
+        if not Result^.ObjectData^.NilObject then begin
+          i := AStoreRdr.ReadInt32S();
+          For i := 1 To i Do Begin
+            AddObj(Result,LoadObjectFromStream(AStoreRdr));
+          End;
+          if AStoreRdr.ReadBool() then
+            Result^.ObjectData^.InnerData := LoadObjectFromStream(AStoreRdr);
+        end;
+      end;
+    dtArray  :
+      Begin
+        i := AStoreRdr.ReadInt32S();
+        Result := CreateArrayBuffer(i,s);
+        For i := 0 To Pred(i) Do Begin
+          AddObj(Result,LoadObjectFromStream(AStoreRdr),i);
+        End;
+      End;
+    dtByteDynArray  : Result^.ByteDynArrayData^.Data := AStoreRdr.ReadBinary();
+  End;
+End;
+
+procedure FreeObjectBuffer(var ABuffer : PObjectBuffer);overload;
+var
+  p,q : PObjectBufferItem;
+begin
+  if Assigned(ABuffer) then begin
+    if Assigned(ABuffer^.Attributes) then
+      FreeObjectBuffer(ABuffer^.Attributes);
+    p := ABuffer^.Head;
+    while Assigned(p) do begin
+      q := p;
+      p := p^.Next;
+      ClearObj(q^.Data);
+      Freemem(q^.Data);
+      q^.Data := Nil;
+      Freemem(q);
+    end;
+    if Assigned(ABuffer^.InnerData) then begin
+      ClearObj(ABuffer^.InnerData);
+      Freemem(ABuffer^.InnerData);
+      ABuffer^.InnerData := nil;
+    end;
+    //ABuffer^.Head := nil;
+    //ABuffer^.Last := nil;
+    Freemem(ABuffer);
+    ABuffer := nil;
+  end;
+end;
+
+procedure FreeObjectBuffer(var ABuffer : PDataBuffer);
+var
+  tmpBuffer : PDataBuffer;
+begin
+  if ( ABuffer <> nil ) then begin
+    tmpBuffer := ABuffer;
+    ABuffer := nil;
+    ClearObj(tmpBuffer);
+    FreeMem(tmpBuffer)
+  end;
+end;
+
+procedure ClearObj(const AOwner: PDataBuffer);
+Var
+  i , j: Integer;
+  eltLen : Integer;
+Begin
+  AOwner^.Name := '';
+  Case AOwner^.DataType Of
+    dtAnsiString :
+      Begin
+        AOwner^.AnsiStrData^.Data := '';
+        Freemem(AOwner^.AnsiStrData);
+        AOwner^.AnsiStrData := Nil;
+      End;
+    dtWideString :
+      begin
+        AOwner^.WideStrData^.Data := '';
+        Freemem(AOwner^.WideStrData);
+        AOwner^.WideStrData := Nil;
+      end;
+{$IFDEF USE_UNICODE}
+    dtUnicodeString :
+      begin
+        AOwner^.UnicodeStrData^.Data := '';
+        Freemem(AOwner^.UnicodeStrData);
+        AOwner^.UnicodeStrData := Nil;
+      end;
+{$ENDIF USE_UNICODE}
+    dtObject :
+      Begin
+        FreeObjectBuffer(AOwner^.ObjectData);
+      End;
+    dtArray :
+      Begin
+        eltLen := SizeOf(TDataBuffer);
+        For j := 0 to Pred(AOwner^.ArrayData^.Count) Do Begin
+          ClearObj(AOwner^.ArrayData^.Items^[j]);
+          Freemem(AOwner^.ArrayData^.Items^[j],eltLen);
+          AOwner^.ArrayData^.Items^[j] := Nil;
+        End;
+        i := AOwner^.ArrayData^.Count * SizeOf(PDataBuffer);
+        Freemem(AOwner^.ArrayData^.Items,i);
+        AOwner^.ArrayData^.Items := Nil;
+        FreeObjectBuffer(AOwner^.ArrayData^.Attributes);
+        i := SizeOf(TArrayBuffer);
+        Freemem(AOwner^.ArrayData,i);
+        AOwner^.ArrayData := Nil;
+      End;
+    dtByteDynArray :
+      begin
+        SetLength(AOwner^.ByteDynArrayData^.Data,0);
+        AOwner^.ByteDynArrayData^.Data := nil;
+        Freemem(AOwner^.ByteDynArrayData);
+        AOwner^.ByteDynArrayData := Nil;
+      end;
+  End;
+End;
+
+
+{ TStackItem }
+
+procedure TStackItem.CopyTo(const AClone: TStackItem);
+begin
+  AClone.FScopeObject := Self.FScopeObject;
+  AClone.FScopeType := Self.FScopeType;
+end;
+
+constructor TStackItem.Create(const AScopeObject: PDataBuffer; AScopeType: TScopeType);
+begin
+  Assert(Assigned(AScopeObject));
+  FScopeObject := AScopeObject;
+  FScopeType := AScopeType;
+end;
+
+{ TObjectStackItem }
+
+constructor TObjectStackItem.Create(const AScopeObject: PDataBuffer);
+begin
+  Inherited Create(AScopeObject,stObject);
+end;
+
+function TObjectStackItem.GetItemCount(): Integer;
+begin
+  Result := ScopeObject^.ObjectData^.Count;
+end;
+
+function TObjectStackItem.Find(var AName: TDataName): PDataBuffer;
+begin
+  Result := FindObj(ScopeObject,AName);
+end;
+
+function TObjectStackItem.GetByIndex(const AIndex: Integer): PDataBuffer;
+Var
+  p : PObjectBufferItem;
+  i : Integer;
+begin
+  If ( AIndex >=0 ) And ( AIndex < ScopeObject^.ObjectData^.Count) Then Begin
+    p := ScopeObject^.ObjectData^.Head;
+    For i := 1 To AIndex Do
+      p := p^.Next;
+    Result := p^.Data;
+  End Else
+    Raise ESDOSerializationException.CreateFmt(SERR_IndexOutOfBound,[AIndex]);
+end;
+
+function TObjectStackItem.CreateBuffer(
+  Const AName     : String;
+  const ADataType : TDataType
+):PDataBuffer;
+begin
+  Result := CreateObjBuffer(ADataType,AName,ScopeObject);
+end;
+
+function TObjectStackItem.CreateInnerBuffer(const ADataType: TDataType): PDataBuffer;
+begin
+  Result := CreateObjBuffer(ADataType,sSCOPE_INNER_NAME,nil);
+  ScopeObject^.ObjectData^.InnerData := Result;
+end;
+
+function TObjectStackItem.GetInnerBuffer(): PDataBuffer;
+begin
+  Result := ScopeObject^.ObjectData^.InnerData;
+end;
+
+procedure TObjectStackItem.NilCurrentScope();
+begin
+  Assert(ScopeObject^.ObjectData^.Count = 0);
+  ScopeObject^.ObjectData^.NilObject := True;
+end;
+
+function TObjectStackItem.IsCurrentScopeNil(): Boolean;
+begin
+  Result := ScopeObject^.ObjectData^.NilObject;
+end;
+
+//----------------------------------------------------------------
+function TObjectStackItem.GetScopeItemNames(const AReturnList: TStrings): Integer;
+var
+  locBuffer : PObjectBufferItem;
+begin
+  AReturnList.Clear();
+  if Assigned(ScopeObject) and ( ScopeObject^.ObjectData^.Count > 0 ) then begin
+    locBuffer := ScopeObject^.ObjectData^.Head;
+    while Assigned(locBuffer) do begin
+      AReturnList.Add(locBuffer^.Data^.Name);
+      locBuffer := locBuffer^.Next;
+    end;
+  end;
+  Result := AReturnList.Count;
+end;
+
+function TObjectStackItem.Clone() : TStackItem;
+begin
+  Result := TObjectStackItemClass(Self.ClassType).Create(FScopeObject);
+  try
+    CopyTo(Result);
+  except
+    FreeAndNil(Result);
+    raise;
+  end;
+end;
+
+{ TSDOSerializationStreamBinary }
+
+procedure TSDOSerializationStreamBinary.ClearStack();
+Var
+  i, c : Integer;
+begin
+  c := FStack.Count;
+  For I := 1 To c Do
+    FStack.Pop().Free();
+end;
+
+procedure TSDOSerializationStreamBinary.PushStack(AScopeObject: PDataBuffer;const AScopeType: TScopeType);
+begin
+  If ( AScopeType = stObject ) Then
+    FStack.Push(TObjectStackItem.Create(AScopeObject))
+  Else If ( AScopeType = stArray ) Then
+    FStack.Push(TArrayStackItem.Create(AScopeObject))
+  Else
+    Assert(False);
+end;
+
+function TSDOSerializationStreamBinary.StackTop(): TStackItem;
+begin
+  Result := FStack.Peek() as TStackItem;
+end;
+
+function TSDOSerializationStreamBinary.PopStack(): TStackItem;
+begin
+  Result := FStack.Pop() as TStackItem;
+end;
+
+function TSDOSerializationStreamBinary.GetRootData(): PDataBuffer;
+begin
+  Result := FRootData;
+end;
+
+function TSDOSerializationStreamBinary.GetCurrentScopeObject(): PDataBuffer;
+begin
+  Result := StackTop().ScopeObject;
+end;
+
+procedure TSDOSerializationStreamBinary.SetSerializationStyle(
+  const ASerializationStyle: TSerializationStyle
+);
+begin
+  FSerializationStyle := ASerializationStyle;
+end;
+
+function TSDOSerializationStreamBinary.GetSerializationStyle(): TSerializationStyle;
+begin
+  Result := FSerializationStyle;
+end;
+
+function TSDOSerializationStreamBinary.HasScope(): Boolean;
+begin
+  Result := ( FStack.Count > 0 );
+end;
+
+procedure TSDOSerializationStreamBinary.CheckScope();
+begin
+  If Not HasScope() Then
+    Error(SERR_NoScope);
+end;
+
+function TSDOSerializationStreamBinary.GetCurrentScope: String;
+begin
+  Result := GetCurrentScopeObject()^.Name;
+end;
+
+function TSDOSerializationStreamBinary.GetDataBuffer(
+  var AName: string;
+  out AResultBuffer : PDataBuffer
+) : Boolean;
+begin
+  AResultBuffer := StackTop().Find(AName);
+  Result := ( AResultBuffer <> nil );
+end;
+
+procedure TSDOSerializationStreamBinary.Clear();
+begin
+  ClearStack();
+  if ( FRootData <> nil ) then begin
+    ClearObj(FRootData);
+    Freemem(FRootData);
+  end;
+  //FRootData := CreateObjBuffer(dtObject,sROOT);
+  //PushStack(FRootData,stObject);
+  FRootData := nil;
+end;
+
+procedure TSDOSerializationStreamBinary.BeginArray(
+  const AName         : string;
+  const AItemTypeInfo : ISDOType;
+  const ABounds       : array of Integer
+);
+var
+  i, j, k : Integer;
+begin
+  if ( Length(ABounds) < 2 ) then
+    Error(SERR_InvalidArrayBounds);
+  i := ABounds[0];
+  j := ABounds[1];
+  k := ( j - i + 1 );
+  if ( k < 0 ) then
+    Error(SERR_InvalidArrayBounds);
+  PushStack(CreateArrayBuffer(k,AName,StackTop().ScopeObject),stArray);
+end;
+
+procedure TSDOSerializationStreamBinary.NilCurrentScope();
+begin
+  CheckScope();
+  StackTop().NilCurrentScope();
+end;
+
+function TSDOSerializationStreamBinary.IsCurrentScopeNil(): Boolean;
+begin
+  Result := StackTop().IsCurrentScopeNil();
+end;
+
+procedure TSDOSerializationStreamBinary.BeginObject(
+  const AName: string;
+  const ATypeInfo: ISDOType
+);
+begin
+  if HasScope() then begin
+    PushStack(StackTop().CreateBuffer(AName,dtObject));
+  end else begin
+    FRootData := CreateObjBuffer(dtObject,AName);
+    PushStack(FRootData,stObject);
+  end;
+end;
+
+procedure TSDOSerializationStreamBinary.EndScope();
+begin
+  FStack.Pop().Free();
+end;
+
+function TSDOSerializationStreamBinary.BeginObjectRead(
+  var   AScopeName : string;
+  const ATypeInfo  : ISDOType
+): Integer;
+var
+  locNode : PDataBuffer;
+  stk : TStackItem;
+begin
+  stk := StackTop();
+  locNode := stk.Find(AScopeName);
+  if not Assigned(locNode) then
+    Error(SERR_ScopeNotFound,[AScopeName]);
+  PushStack(locNode,stObject);
+  Result := StackTop().GetItemCount();
+end;
+
+function TSDOSerializationStreamBinary.BeginArrayRead(
+  var   AScopeName : string;
+  const ATypeInfo  : ISDOType;
+  const AItemName  : string
+): Integer;
+var
+  locNode : PDataBuffer;
+  stk : TStackItem;
+begin
+  stk := StackTop();
+  locNode := stk.Find(AScopeName);
+  if ( locNode <> nil ) then begin
+    PushStack(locNode,stArray);
+    Result := StackTop().GetItemCount();
+  end else begin
+    Result := -1;
+  end;
+end;
+
+function TSDOSerializationStreamBinary.GetScopeItemNames(
+  const AItemStyle : TSerializationStyle;
+  const AReturnList : TStrings
+) : Integer;
+begin
+  CheckScope();
+  Result := StackTop.GetScopeItemNames(AReturnList);
+end;
+
+procedure TSDOSerializationStreamBinary.EndScopeRead();
+begin
+  PopStack().Free();
+end;
+
+procedure TSDOSerializationStreamBinary.Put(
+  const AName     : string;
+  const ATypeInfo : ISDOType;
+  const AData
+);
+var
+  valBuffer : TValueBuffer;
+  strData : TSDOString;
+  bytesData : TSDOBytes;
+begin
+  case ATypeInfo.getTypeEnum() Of
+    BooleanType :
+      begin
+        valBuffer.BooleanValue := TSDOBoolean(AData);
+        PutBoolean(AName,valBuffer.BooleanValue);
+      end;
+    ByteType :
+      begin
+        valBuffer.ByteValue := TSDOByte(AData);
+        PutByte(AName,valBuffer.ByteValue);
+      end;
+{$IFDEF HAS_SDO_BYTES}
+     BytesType :
+      begin
+        bytesData := TSDOBytes(AData);
+        PutBytes(AName,bytesData);
+      end;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType :
+      begin
+        valBuffer.CharValue := TSDOChar(AData);
+        PutChar(AName,valBuffer.CharValue);
+      end;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType :
+      begin
+        valBuffer.CurrencyValue := TSDOCurrency(AData);
+        PutCurrency(AName,valBuffer.CurrencyValue);
+      end;
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType :
+      begin
+        valBuffer.DateValue := TSDODateTime(AData);
+        PutDate(AName,valBuffer.DateValue);
+      end;
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType :
+      begin
+        valBuffer.DoubleValue := TSDODouble(AData);
+        PutDouble(AName,valBuffer.DoubleValue);
+      end;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType :
+      begin
+        valBuffer.FloatValue := TSDOFloat(AData);
+        PutFloat(AName,valBuffer.FloatValue);
+      end;
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType :
+      begin
+        valBuffer.IntegerValue := TSDOInteger(AData);
+        PutInteger(AName,valBuffer.IntegerValue);
+      end;
+{$IFDEF HAS_SDO_LONG}
+    LongType :
+      begin
+        valBuffer.LongValue := TSDOLong(AData);
+        PutLong(AName,valBuffer.LongValue);
+      end;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType :
+      begin
+        valBuffer.ShortValue := TSDOShort(AData);
+        PutShort(AName,valBuffer.ShortValue);
+      end;
+{$ENDIF HAS_SDO_SHORT}
+    StringType  :
+      begin
+        strData := TSDOString(AData);
+        PutString(AName,strData);
+      end;
+    else
+      Assert(False);
+  end;
+end;
+
+procedure TSDOSerializationStreamBinary.Put(
+  const ANameSpace,
+        AName     : string;
+  const ATypeInfo : ISDOType;
+  const AData
+);
+begin
+  Put(AName,ATypeInfo,AData);
+end;
+
+procedure TSDOSerializationStreamBinary.PutScopeInnerValue(
+  const ATypeInfo : ISDOType;
+  const AData
+);
+
+
+  procedure doPutDate();
+  var
+    locBuffer : TByteDynArray;
+    locDate : TSDODateTime;
+  begin
+    locDate := TSDODateTime(AData);
+    SetLength(locBuffer,SizeOf(TSDODateTime));
+    Move(locDate,locBuffer[0],SizeOf(TSDODateTime));
+    ReverseBytes(locBuffer[0],SizeOf(TSDODateTime));
+    StackTop().CreateInnerBuffer(dtByteDynArray)^.ByteDynArrayData^.Data := locBuffer;
+  end;
+
+
+begin
+  CheckScope();
+  case ATypeInfo.getTypeEnum() Of
+    BooleanType : StackTop().CreateInnerBuffer(dtBool)^.BoolData := TSDOBoolean(AData);
+{$IFDEF HAS_SDO_BYTES}
+    BytesType   : StackTop().CreateInnerBuffer(dtByteDynArray)^.ByteDynArrayData^.Data := Copy(TSDOBytes(AData));
+{$ENDIF HAS_SDO_BYTES}
+    ByteType    : StackTop().CreateInnerBuffer(dtInt8U)^.Int8U := TSDOByte(AData);
+{$IFDEF HAS_SDO_CHAR}
+  {$IFDEF USE_UNICODE}
+    CharacterType : StackTop().CreateInnerBuffer(dtWideChar)^.WideCharData := TSDOChar(AData);
+  {$ELSE USE_UNICODE}
+    CharacterType : StackTop().CreateInnerBuffer(dtAnsiChar)^.AnsiCharData := TSDOChar(AData);
+  {$ENDIF USE_UNICODE}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType : StackTop().CreateInnerBuffer(dtCurrency)^.CurrencyData := TSDOCurrency(AData);
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType: doPutDate();
+    IntegerType : StackTop().CreateInnerBuffer(dtInt32S)^.Int32S := TSDOInteger(AData);
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType  : StackTop().CreateInnerBuffer(dtDouble)^.DoubleData := TSDODouble(AData);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType   : StackTop().CreateInnerBuffer(dtSingle)^.SingleData := TSDOFloat(AData);
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    LongType    : StackTop().CreateInnerBuffer(dtInt64S)^.Int64S := TSDOLong(AData);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType   : StackTop().CreateInnerBuffer(dtInt16S)^.Int16S := TSDOShort(AData);
+{$ENDIF HAS_SDO_SHORT}
+    StringType  :
+{$IFDEF USE_UNICODE}
+      StackTop().CreateInnerBuffer(dtUnicodeString)^.UnicodeStrData^.Data := TSDOString(AData);
+{$ELSE USE_UNICODE}
+      StackTop().CreateInnerBuffer(dtAnsiString)^.AnsiStrData^.Data := TSDOString(AData);
+{$ENDIF USE_UNICODE}
+    else
+      Assert(False);
+  end;
+end;
+
+function TSDOSerializationStreamBinary.Get(
+  const ATypeInfo: ISDOType;
+  var AName: String;
+  var AData
+) : Boolean;
+var
+  valBuffer : TValueBuffer;
+  strData : TSDOString;
+  bytesData : TSDOBytes;
+begin
+  FillChar(valBuffer,SizeOf(valBuffer),#0);
+  case ATypeInfo.getTypeEnum() of
+    BooleanType :
+      begin
+        Result := GetBoolean(AName,valBuffer.BooleanValue);
+        if Result then
+          TSDOBoolean(AData) := valBuffer.BooleanValue;
+      end;
+    ByteType :
+      begin
+        Result := GetByte(AName,valBuffer.ByteValue);
+        if Result then
+          TSDOByte(AData) := valBuffer.ByteValue;
+      end;
+{$IFDEF HAS_SDO_BYTES}
+    BytesType :
+      begin
+        Result := GetBytes(AName,bytesData);
+        if Result then
+          TSDOBytes(AData) := bytesData;
+      end;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType :
+      begin
+        Result := GetChar(AName,valBuffer.CharValue);
+        if Result then
+          TSDOChar(AData) := valBuffer.CharValue;
+      end;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType :
+      begin
+        Result := GetCurrency(AName,valBuffer.CurrencyValue);
+        if Result then
+          TSDOCurrency(AData) := valBuffer.CurrencyValue;
+      end;
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType :
+      begin
+        Result := GetDate(AName,valBuffer.DateValue);
+        if Result then
+          TSDODateTime(AData) := valBuffer.DateValue;
+      end;
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType :
+      begin
+        Result := GetDouble(AName,valBuffer.DoubleValue);
+        if Result then
+          TSDODouble(AData) := valBuffer.DoubleValue;
+      end;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType :
+      begin
+        Result := GetFloat(AName,valBuffer.FloatValue);
+        if Result then
+          TSDOFloat(AData) := valBuffer.FloatValue;
+      end;
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType :
+      begin
+        Result := GetInteger(AName,valBuffer.IntegerValue);
+        if Result then
+          TSDOInteger(AData) := valBuffer.IntegerValue;
+      end;
+{$IFDEF HAS_SDO_LONG}
+    LongType :
+      begin
+        Result := GetLong(AName,valBuffer.LongValue);
+        if Result then
+          TSDOLong(AData) := valBuffer.LongValue;
+      end;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType :
+      begin
+        Result := GetShort(AName,valBuffer.ShortValue);
+        if Result then
+          TSDOShort(AData) := valBuffer.ShortValue;
+      end;
+{$ENDIF HAS_SDO_SHORT}
+    StringType  :
+      begin
+        strData := TSDOString(AData);
+        Result := GetString(AName,strData);
+        if Result then
+          TSDOString(AData) := strData;
+      end;
+    else
+      Result := False;
+  end;
+end;
+
+function TSDOSerializationStreamBinary.Get(
+  const ANameSpace : string;
+  const ATypeInfo  : ISDOType;
+  var   AName      : string;
+  var   AData
+) : Boolean;
+begin
+  Result := Get(ATypeInfo,AName,AData);
+end;
+
+function TSDOSerializationStreamBinary.GetScopeInnerValue(
+  const ATypeInfo : ISDOType;
+  var   AData
+) : Boolean;
+var
+  dataBuffer : PDataBuffer;
+
+  function HandleDate() : Boolean;
+  var
+    locDate : TSDODateTime;
+    locBuffer : TByteDynArray;
+  begin
+    Result := False;
+    locBuffer := Copy(dataBuffer^.ByteDynArrayData^.Data);
+    if ( Length(locBuffer) = SizeOf(TSDODateTime) ) then begin
+      ReverseBytes(locBuffer[0],SizeOf(TSDODateTime));
+      Move(locBuffer[0],locDate,SizeOf(TSDODateTime));
+      TSDODateTime(AData) := locDate;
+      Result := True;
+    end;
+  end;
+
+begin
+  CheckScope();
+  Result := True;
+  dataBuffer := StackTop().GetInnerBuffer();
+  case ATypeInfo.getTypeEnum() of
+    BooleanType    : TSDOBoolean(AData) := dataBuffer^.BoolData;
+    ByteType       : TSDOByte(AData) := dataBuffer^.Int8U;
+    CharacterType  : TSDOChar(AData) := {$IFDEF USE_UNICODE}dataBuffer^.WideCharData{$ELSE}dataBuffer^.AnsiCharData{$ENDIF};
+    CurrencyType   : TSDOCurrency(AData) := dataBuffer^.CurrencyData;
+    DateTimeType   : HandleDate();
+    DoubleType     : TSDODouble(AData) := dataBuffer^.DoubleData;
+    FloatType      : TSDOFloat(AData) := dataBuffer^.SingleData;
+    IntegerType    : TSDOInteger(AData) := dataBuffer^.Int32S;
+    LongType       : TSDOLong(AData) := dataBuffer^.Int64S;
+    ShortType      : TSDOShort(AData) := dataBuffer^.Int16S;
+    StringType     : TSDOString(AData) := {$IFDEF USE_UNICODE}dataBuffer^.UnicodeStrData^.Data{$ELSE}dataBuffer^.AnsiStrData^.Data{$ENDIF};
+    else
+      Assert(False);
+  end;
+end;
+
+function TSDOSerializationStreamBinary.ReadBuffer (const AName : string) : string;
+Var
+  locStore : IDataStore;
+  bffr : PDataBuffer;
+  locName : string;
+  locStream : TStringStream;
+begin
+  Result := '';
+  if GetDataBuffer(locName,bffr) then begin
+    locStream := TStringStream.Create('');
+    try
+      locStore := CreateBinaryWriter(locStream);
+      SaveObjectToStream(bffr,locStore);
+      Result := locStream.DataString;
+    finally
+      locStream.Free();
+    end;
+  end;
+end;
+
+procedure TSDOSerializationStreamBinary.SaveToStream(AStream: TStream);
+Var
+  locStore : IDataStore;
+begin
+  locStore := CreateBinaryWriter(AStream);
+  SaveObjectToStream(FRootData,locStore);
+end;
+
+procedure TSDOSerializationStreamBinary.LoadFromStream(AStream: TStream);
+Var
+  locRdr : IDataStoreReader;
+  tmpRoot : PDataBuffer;
+begin
+  locRdr := CreateBinaryReader(AStream);
+  tmpRoot := LoadObjectFromStream(locRdr);
+
+  Clear();
+  FRootData := tmpRoot;
+  PushStack(FRootData,stObject);
+end;
+
+procedure TSDOSerializationStreamBinary.Error(const AMsg: string);
+begin
+  Raise ESDOSerializationException.Create(AMsg);
+end;
+
+procedure TSDOSerializationStreamBinary.Error(const AMsg: string;const AArgs: array of const);
+begin
+  Raise ESDOSerializationException.CreateFmt(AMsg,AArgs);
+end;
+
+constructor TSDOSerializationStreamBinary.Create();
+begin
+  //FRootData := CreateObjBuffer(dtObject,sROOT);
+  FStack := TObjectStackEx.Create();
+  //PushStack(FRootData,stObject);
+end;
+
+destructor TSDOSerializationStreamBinary.Destroy();
+begin
+  ClearStack();
+  FreeAndNil(FStack);
+  if ( FRootData <> nil ) then begin
+    ClearObj(FRootData);
+    Freemem(FRootData);
+  end;
+  inherited Destroy();
+end;
+
+function TSDOSerializationStreamBinary.GetFormatName() : string;
+begin
+  Result := sBINARY_FORMAT_NAME;
+end;
+
+procedure TSDOSerializationStreamBinary.WriteBuffer(const AValue: string);
+var
+  locStore : IDataStoreReader;
+  bffr : PDataBuffer;
+  locStream : TStringStream;
+begin
+  CheckScope();
+  locStream := TStringStream.Create(AValue);
+  try
+    locStream.Position := 0;
+    locStore := CreateBinaryReader(locStream);
+    bffr := LoadObjectFromStream(locStore);
+    AddObj(StackTop.ScopeObject,bffr);
+  finally
+    locStream.Free();
+  end;
+end;
+
+function CopyStackItem(const AItem : TObject) : TObject;
+begin
+  if ( AItem <> nil ) then
+    Result := TStackItem(AItem).Clone()
+  else
+    Result := nil;
+end;
+
+function TSDOSerializationStreamBinary.GetBookMark: TStreamBookmark;
+var
+  locRes : TStreamBinaryBookmark;
+begin
+  locRes := TStreamBinaryBookmark.Create();
+  try
+    locRes.FNameStyle := Self.FNameStyle;
+    locRes.FStack := Self.FStack.Clone({$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyStackItem);
+    locRes.FRootData := Self.FRootData;
+    locRes.FSerializationStyle := Self.FSerializationStyle;
+    Result := locRes;
+  except
+    FreeAndNil(locRes);
+    raise;
+  end;
+end;
+
+function TSDOSerializationStreamBinary.GetBoolean(var AName: string; var AData: TSDOBoolean): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.BoolData;
+end;
+
+function TSDOSerializationStreamBinary.GetByte(var AName: string; var AData: TSDOByte): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.Int8U;
+end;
+
+function TSDOSerializationStreamBinary.GetBytes(var AName: string; var AData: TSDOBytes): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := Copy(locBuffer^.ByteDynArrayData^.Data);
+end;
+
+function TSDOSerializationStreamBinary.GetChar(var AName: string; var AData: TSDOChar): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := {$IFDEF USE_UNICODE}locBuffer^.WideCharData{$ELSE}locBuffer^.AnsiCharData{$ENDIF};
+
+end;
+
+function TSDOSerializationStreamBinary.GetCurrency(var AName: string; var AData: TSDOCurrency): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.CurrencyData;
+end;
+
+function TSDOSerializationStreamBinary.GetDate(var AName: string; var AData: TSDODateTime): Boolean;
+var
+  locBytesBuffer : TByteDynArray;
+  locBuffer : PDataBuffer;
+begin
+  Result := False;
+  if GetDataBuffer(AName,locBuffer) then begin
+    locBytesBuffer := Copy(locBuffer^.ByteDynArrayData^.Data);
+    if ( Length(locBytesBuffer) = SizeOf(TSDODateTime) ) then begin
+      ReverseBytes(locBytesBuffer[0],SizeOf(TSDODateTime));
+      Move(locBytesBuffer[0],AData,SizeOf(TSDODateTime));
+      Result := True;
+    end;
+  end;
+end;
+
+function TSDOSerializationStreamBinary.GetDouble(var AName: string; var AData: TSDODouble): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.DoubleData;
+end;
+
+function TSDOSerializationStreamBinary.GetFloat(var AName: string; var AData: TSDOFloat): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.SingleData;
+end;
+
+function TSDOSerializationStreamBinary.GetInteger(var AName: string; var AData: TSDOInteger): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.Int32S;
+end;
+
+function TSDOSerializationStreamBinary.GetLong(var AName: string; var AData: TSDOLong): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.Int64S;
+end;
+
+function TSDOSerializationStreamBinary.GetNameStyle: TNameStyle;
+begin
+  Result := FNameStyle;
+end;
+
+function TSDOSerializationStreamBinary.GetShort(var AName: string; var AData: TSDOShort): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then
+    AData := locBuffer^.Int16S;
+end;
+
+function TSDOSerializationStreamBinary.GetString(var AName: string; var AData: TSDOString): Boolean;
+var
+  locBuffer : PDataBuffer;
+begin
+  Result := GetDataBuffer(AName,locBuffer);
+  if Result then begin
+    if ( locBuffer^.DataType = dtAnsiString ) then
+      AData := locBuffer^.AnsiStrData^.Data
+    else if ( locBuffer^.DataType = dtWideString ) then
+      AData := locBuffer^.WideStrData^.Data
+{$IFDEF USE_UNICODE}
+    else if ( locBuffer^.DataType = dtUnicodeString ) then
+      AData := locBuffer^.UnicodeStrData^.Data
+{$ENDIF USE_UNICODE}
+    else
+      AData := ToStr(locBuffer);
+  end;
+end;
+
+function TSDOSerializationStreamBinary.GotoBookmark(const AValue: TStreamBookmark): Boolean;
+var
+  locBM : TStreamBinaryBookmark;
+begin
+  Result := False;
+  if ( AValue <> nil ) then begin
+    locBM := AValue as TStreamBinaryBookmark;
+    if ( locBM.FRootData = Self.FRootData ) then begin
+      ClearStack();
+      FreeAndNil(FStack);
+      FStack := locBM.FStack.Clone({$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyStackItem);
+      FSerializationStyle := locBM.SerializationStyle;
+      FNameStyle := locBM.NameStyle;
+      Result := True;
+    end;
+  end;
+end;
+
+procedure TSDOSerializationStreamBinary.Initialize;
+begin
+  ClearStack();
+  if ( FRootData <> nil ) then
+    PushStack(FRootData);
+end;
+
+procedure TSDOSerializationStreamBinary.LoadFromFile(
+  const AFileName: string);
+begin
+
+end;
+
+procedure TSDOSerializationStreamBinary.PutBoolean(const AName: string; const AData: TSDOBoolean);
+begin
+  StackTop().CreateBuffer(AName,dtBool)^.BoolData := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutByte(const AName: string; const AData: TSDOByte);
+begin
+  StackTop().CreateBuffer(AName,dtInt8U)^.Int8U := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutBytes(const AName: string; const AData: TSDOBytes);
+begin
+  StackTop().CreateBuffer(AName,dtByteDynArray)^.ByteDynArrayData^.Data := Copy(AData);
+end;
+
+procedure TSDOSerializationStreamBinary.PutChar(const AName: string; const AData: TSDOChar);
+begin
+{$IFDEF USE_UNICODE}
+  StackTop().CreateBuffer(AName,dtWideChar)^.WideCharData := AData;
+{$ELSE USE_UNICODE}
+  StackTop().CreateBuffer(AName,dtAnsiChar)^.AnsiCharData := AData;
+{$ENDIF USE_UNICODE}
+end;
+
+procedure TSDOSerializationStreamBinary.PutCurrency(const AName: string; const AData: TSDOCurrency);
+begin
+  StackTop().CreateBuffer(AName,dtCurrency)^.CurrencyData := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutDate(const AName: string; const AData: TSDODateTime);
+var
+  locBuffer : TByteDynArray;
+begin
+  SetLength(locBuffer,SizeOf(TSDODateTime));
+  Move(AData,locBuffer[0],SizeOf(TSDODateTime));
+  ReverseBytes(locBuffer[0],SizeOf(TSDODateTime));
+  StackTop().CreateBuffer(AName,dtByteDynArray)^.ByteDynArrayData^.Data := locBuffer;
+end;
+
+procedure TSDOSerializationStreamBinary.PutDouble(const AName: string; const AData: TSDODouble);
+begin
+  StackTop().CreateBuffer(AName,dtDouble)^.DoubleData := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutFloat(const AName: string; const AData: TSDOFloat);
+begin
+  StackTop().CreateBuffer(AName,dtSingle)^.SingleData := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutInteger(const AName: string; const AData: TSDOInteger);
+begin
+  StackTop().CreateBuffer(AName,dtInt32S)^.Int32S := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutLong(const AName: string; const AData: TSDOLong);
+begin
+  StackTop().CreateBuffer(AName,dtInt64S)^.Int64S := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutShort(const AName: string; const AData: TSDOShort);
+begin
+  StackTop().CreateBuffer(AName,dtInt16S)^.Int16S := AData;
+end;
+
+procedure TSDOSerializationStreamBinary.PutString(const AName: string; const AData: TSDOString);
+begin
+{$IFDEF USE_UNICODE}
+  StackTop().CreateBuffer(AName,dtUnicodeString)^.UnicodeStrData^.Data := AData;
+{$ELSE}
+  StackTop().CreateBuffer(AName,dtAnsiString)^.AnsiStrData^.Data := AData;
+{$ENDIF}
+end;
+
+procedure TSDOSerializationStreamBinary.SaveToFile(
+  const AFileName: string);
+begin
+
+end;
+
+procedure TSDOSerializationStreamBinary.SetNameStyle(const AValue: TNameStyle);
+begin
+  if ( AValue <> FNameStyle ) then
+    FNameStyle := AValue;
+end;
+
+{ TArrayStackItem }
+
+constructor TArrayStackItem.Create(const AScopeObject: PDataBuffer);
+begin
+  Inherited Create(AScopeObject,stArray);
+  FIndex := 0;
+end;
+
+function TArrayStackItem.GetItemCount(): Integer;
+begin
+  Result := ScopeObject^.ArrayData^.Count;
+end;
+
+function TArrayStackItem.Find(var AName: TDataName): PDataBuffer;
+begin
+  If ( FIndex >= 0 ) And ( FIndex < ScopeObject^.ArrayData^.Count ) Then
+    Result := ScopeObject^.ArrayData^.Items^[FIndex]
+  Else
+    Raise ESDOSerializationException.CreateFmt(SERR_IndexOutOfBound,[FIndex]);
+  Inc(FIndex);
+end;
+
+function TArrayStackItem.GetByIndex(const AIndex: Integer): PDataBuffer;
+begin
+  If ( AIndex >= 0 ) And ( AIndex < ScopeObject^.ArrayData^.Count ) Then
+    Result := ScopeObject^.ArrayData^.Items^[AIndex]
+  Else
+    Raise ESDOSerializationException.CreateFmt(SERR_IndexOutOfBound,[AIndex]);
+end;
+
+function TArrayStackItem.CreateBuffer(
+  const AName     : String;
+  const ADataType : TDataType
+): PDataBuffer;
+begin
+  If ( FIndex >= 0 ) And ( FIndex < ScopeObject^.ArrayData^.Count ) Then
+    Result := CreateObjBuffer(ADataType,AName,Nil)
+  Else
+    Raise ESDOSerializationException.CreateFmt(SERR_IndexOutOfBound,[FIndex]);
+  ScopeObject^.ArrayData^.Items^[FIndex] := Result;
+  Inc(FIndex);
+end;
+
+{$WARNINGS OFF}
+function TArrayStackItem.CreateInnerBuffer(const ADataType: TDataType): PDataBuffer;
+begin
+  raise ESDOSerializationException.CreateFmt(SERR_UnsupportedOperation,['TArrayStackItem.CreateInnerBuffer']);
+end;
+
+function TArrayStackItem.GetInnerBuffer(): PDataBuffer;
+begin
+  raise ESDOSerializationException.CreateFmt(SERR_UnsupportedOperation,['TArrayStackItem.GetInnerBuffer']);
+end;
+{$WARNINGS ON}
+
+procedure TArrayStackItem.NilCurrentScope();
+begin
+end;
+
+function TArrayStackItem.IsCurrentScopeNil(): Boolean;
+begin
+  Result := False;
+end;
+
+function TArrayStackItem.GetScopeItemNames(const AReturnList: TStrings): Integer;
+var
+  locBuffer : PDataBufferList;
+  i : PtrInt;
+begin
+  AReturnList.Clear();
+  if Assigned(ScopeObject) and ( ScopeObject^.ArrayData^.Count > 0 ) then begin
+    locBuffer := ScopeObject^.ArrayData^.Items;
+    for i := 0 to Pred(ScopeObject^.ArrayData^.Count) do begin
+      AReturnList.Add(locBuffer^[i]^.Name);
+    end;
+  end;
+  Result := AReturnList.Count;
+end;
+
+procedure TArrayStackItem.CopyTo(const AClone: TStackItem);
+begin
+  inherited CopyTo(AClone);
+  TArrayStackItem(AClone).FIndex := Self.FIndex;
+end;
+
+function TArrayStackItem.Clone: TStackItem;
+begin
+  Result := TArrayStackItemClass(Self.ClassType).Create(Self.FScopeObject);
+  try
+    CopyTo(Result);
+  except
+    FreeAndNil(Result);
+    raise;
+  end;
+end;
+
+{ TStreamBinaryBookmark }
+
+destructor TStreamBinaryBookmark.Destroy();
+var
+  i : PtrInt;
+begin
+  if ( FStack <> nil ) and ( FStack.Count > 0 ) then begin
+    for i := 0 to Pred(FStack.Count) do
+      FStack.Pop().Free();
+  end;
+  FreeAndNil(FStack);
+  inherited;
+end;
+
+
+end.

+ 155 - 0
packages/fcl-sdo/src/base/sdo_serialization_utils.pas

@@ -0,0 +1,155 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a streaming interface
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_serialization_utils;
+
+interface
+uses
+  SysUtils, Classes, Contnrs,
+  sdo_types, sdo;
+
+type
+
+  TScopeType = ( stObject, stArray );
+  TArrayStyle = ( asScoped, asEmbeded, asNone );
+
+  ESDOSerializationException = class(ESDOException) end;
+
+  TSerializationStyle = ( ssNodeSerialization, ssAttibuteSerialization );
+  TNameStyle = ( nsUnqualified, nsQualified );
+
+  TStreamBookmark = class(TObject)
+  end;
+
+  ISDOSerializerStream = interface
+    ['{3C38D6E1-C4BE-4BFC-B16A-BD8A1A09A5E6}']
+    function GetFormatName() : string;
+    procedure SetSerializationStyle(const ASerializationStyle : TSerializationStyle);
+    function GetSerializationStyle():TSerializationStyle;
+    procedure SetNameStyle(const AValue : TNameStyle);
+    function GetNameStyle() : TNameStyle;
+    function GetCurrentScope():string;
+    procedure Clear();
+    procedure Initialize();
+
+    procedure BeginObject(
+      Const AName      : string;
+      Const ATypeInfo  : ISDOType
+    );
+    procedure BeginArray(
+      const AName         : string;
+      const AItemTypeInfo : ISDOType;
+      const ABounds       : array of Integer
+    );
+    procedure NilCurrentScope();
+    function IsCurrentScopeNil():Boolean;
+    procedure EndScope();
+    function BeginObjectRead(
+      var   AScopeName : string;
+      const ATypeInfo  : ISDOType
+    ) : Integer;
+    function BeginArrayRead(
+      var   AScopeName : string;
+      const ATypeInfo  : ISDOType;
+      const AItemName  : string
+    ):Integer;
+    function GetScopeItemNames(
+      const AItemStyle : TSerializationStyle;
+      const AReturnList : TStrings
+    ) : Integer;
+    procedure EndScopeRead();
+
+    procedure Put(
+      const AName     : string;
+      const ATypeInfo : ISDOType;
+      const AData
+    );overload;
+    procedure Put(
+      const ANameSpace,
+            AName     : string;
+      const ATypeInfo : ISDOType;
+      const AData
+    );overload;
+    procedure PutScopeInnerValue(
+      const ATypeInfo : ISDOType;
+      const AData
+    );
+    function Get(
+      const ATypeInfo : ISDOType;
+      var   AName     : string;
+      var   AData
+    ) : Boolean;overload;
+    function Get(
+      const ANameSpace : string;
+      const ATypeInfo  : ISDOType;
+      var   AName      : string;
+      var   AData
+    ) : Boolean;overload;
+    function GetScopeInnerValue(
+      const ATypeInfo : ISDOType;
+      var   AData
+    ) : Boolean;
+    function ReadBuffer(const AName : string) : string;
+    //Please use this method if and _only_ if you do not have another way to achieve your aim!
+    procedure WriteBuffer(const AValue : string);
+
+    procedure SaveToStream(AStream : TStream);overload;
+    procedure SaveToFile(const AFileName : string);overload;
+    procedure LoadFromStream(AStream : TStream);overload;
+    procedure LoadFromFile(const AFileName : string);overload;
+
+    function GetBookMark() : TStreamBookmark;
+    function GotoBookmark(const AValue : TStreamBookmark) : Boolean;
+    // This procedures will raise exceptions!!!
+    procedure Error(Const AMsg:string);overload;
+    procedure Error(Const AMsg:string; Const AArgs : array of const);overload;
+  end;
+
+  TObjectStackExCopyFunc = function (const AItem : TObject) : TObject;
+  TObjectStackEx = class(TObjectStack)
+  public
+    function Clone(const ACopyFunc : TObjectStackExCopyFunc) : TObjectStackEx;
+  end;
+
+//resourcestring
+  //SMSG_InvalidBookmark = 'Invalid bookmark.';
+
+implementation
+
+{ TObjectStackEx }
+
+function TObjectStackEx.Clone(const ACopyFunc : TObjectStackExCopyFunc) : TObjectStackEx;
+var
+  i, c : PtrInt;
+  rls , sls : TList;
+begin
+  Result := TObjectStackEx.Create();
+  try
+    sls := List;
+    c := sls.Count;
+    if ( c > 0 ) then begin
+      rls := Result.List;
+      rls.Capacity := sls.Capacity;
+      for i := 0 to Pred(c) do
+        rls.Add(ACopyFunc(TObject(sls[i])));
+    end;
+  except
+    FreeAndNil(Result);
+    raise;
+  end
+end;
+
+end.

+ 1806 - 0
packages/fcl-sdo/src/base/sdo_serialization_xml.pas

@@ -0,0 +1,1806 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements serializing SDO objects to XML
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_serialization_xml;
+
+interface
+uses
+  SysUtils, Classes, Contnrs,
+  sdo_types, sdo, sdo_consts, sdo_serialization_utils
+{$IFDEF DELPHI}
+  , xmldom, sdo_win_xml
+{$ENDIF DELPHI}
+{$IFDEF FPC}
+  , DOM, sdo_fpc_xml, XMLRead, XMLWrite
+{$ENDIF FPC}
+  ;
+
+type
+
+  TSDOXMLDocument = {$IFDEF DELPHI}sdo_win_xml.TXMLDocument{$ELSE}TXMLDocument{$ENDIF};
+
+  { TStackItem }
+
+  TStackItem = class
+  private
+    FEmbeddedScopeCount: Integer;
+    FNameSpace: string;
+    FScopeObject: TDOMNode;
+    FScopeType: TScopeType;
+  protected
+    constructor Create();overload; virtual;
+    function GetItemsCount(const AStyle : TSerializationStyle) : Integer;virtual;
+    procedure CopyTo(const AClone : TStackItem);virtual;
+  public
+    constructor Create(AScopeObject : TDOMNode;AScopeType : TScopeType);overload;
+    function Clone() : TStackItem;virtual;
+    function FindNode(var ANodeName : string):TDOMNode;virtual;abstract;
+    procedure SetNameSpace(const ANameSpace : string);
+    property ScopeObject : TDOMNode Read FScopeObject;
+    property ScopeType : TScopeType Read FScopeType;
+    property NameSpace : string Read FNameSpace;
+    property ItemsCount[const AStyle : TSerializationStyle] : Integer read GetItemsCount;
+
+    property EmbeddedScopeCount : Integer read FEmbeddedScopeCount;
+    function BeginEmbeddedScope() : Integer;
+    function EndEmbeddedScope() : Integer;
+
+    function GetScopeItemNames(
+      const AItemStyle : TSerializationStyle;
+      const AReturnList : TStrings
+    ) : Integer;virtual;
+
+    procedure Error(Const AMsg:string);overload;
+    procedure Error(Const AMsg:string; Const AArgs : array of const);overload;
+  end;
+
+  TStackItemClass = class of TStackItem;
+
+  { TObjectStackItem }
+
+  TObjectStackItem = class(TStackItem)
+  public
+    function FindNode(var ANodeName : string):TDOMNode;override;
+  end;
+
+  { TAbstractArrayStackItem }
+
+  TAbstractArrayStackItem = class(TStackItem)
+  private
+    FItemList : TDOMNodeList;
+    FIndex : Integer;
+    FItemName : string;
+  protected
+    procedure CopyTo(const AClone : TStackItem);override;
+    procedure EnsureListCreated();
+    function GetItemsCount(const AStyle : TSerializationStyle) : Integer;override;
+    function CreateList(const ANodeName : string):TDOMNodeList;virtual;abstract;
+  public
+    constructor Create(
+            AScopeObject : TDOMNode;
+      const AScopeType   : TScopeType;
+      const AItemName    : string
+    );
+    destructor Destroy();override;
+    function FindNode(var ANodeName : string):TDOMNode;override;
+  end;
+
+  { TScopedArrayStackItem }
+
+  TScopedArrayStackItem = class(TAbstractArrayStackItem)
+  protected
+    function CreateList(const ANodeName : string):TDOMNodeList;override;
+  public
+    destructor Destroy();override;  
+  end;
+
+  { TEmbeddedArrayStackItem }
+
+  TEmbeddedArrayStackItem = class(TAbstractArrayStackItem)
+  protected
+    function CreateList(const ANodeName : string):TDOMNodeList;override;
+  end;
+
+  TStreamXMLBookmark = class(TStreamBookmark)
+  private
+    FNameStyle: TNameStyle;
+    FStack: TObjectStackEx;
+    FDoc: TSDOXMLDocument;
+    FSerializationStyle: TSerializationStyle;
+  public
+    destructor Destroy();override;
+    property SerializationStyle : TSerializationStyle read FSerializationStyle;
+    property NameStyle : TNameStyle read FNameStyle;
+    property Doc : TSDOXMLDocument read FDoc;
+    property Stack : TObjectStackEx read FStack;
+  end;
+
+  TSDOSerializerStreamXML = class(TInterfacedObject,IInterface,ISDOSerializerStream)
+  private
+    FSerializationStyle : TSerializationStyle;
+    FNameStyle : TNameStyle;
+    FDoc : TSDOXMLDocument;
+    FStack : TObjectStackEx;
+    FPreferedShortNames : TStrings;
+    FNameSpaceCounter : PtrInt;
+  private
+    procedure ClearStack();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function StackTop():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function PushStack(AScopeObject : TDOMNode):TStackItem;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function PushStack(
+      const AScopeObject : TDOMNode;
+      const AItemName    : string;
+      const AStyle       : TArrayStyle = asEmbeded
+    ) : TStackItem;overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function PopStack():TStackItem;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function HasScope():Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure CheckScope();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    //procedure AddScopeAttribute(const AName,AValue : string);
+    procedure InternalClear(const ACreateDoc : Boolean);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetCurrentScopeObject():TDOMElement;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function NextNameSpaceCounter():Integer;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function FindAttributeByValueInScope(const AAttValue : string) : string;
+    function FindAttributeByValueInNode(
+      const AAttValue : string;
+      const ANode     : TDOMNode;
+      out   AResAtt   : string
+    ) : Boolean;
+    function FindNameSpace(const AShortName : string; out ARes : string) : Boolean;
+    procedure BeginScope(
+      const AScopeName,
+            ANameSpace  : string;
+      const AScopeType  : TScopeType;
+      const AStyle      : TArrayStyle = asEmbeded
+    );
+    function InternalBeginScopeRead(
+      var   AScopeName : string;
+      const ATypeInfo  : ISDOType;
+      const AScopeType : TScopeType;
+      const AItemName  : string;
+      const AStyle     : TArrayStyle = asEmbeded
+    ):Integer;
+  private
+    function InternalPutData(
+      const AName : string;
+      const AData : TSDOString; 
+      const ANameSpace : string
+    ) : TDOMNode;
+    function PutBoolean(const AName : string; const AData : TSDOBoolean; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function PutByte(const AName : string; const AData : TSDOByte; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_BYTES}
+    function PutBytes(const AName : string; const AData : TSDOBytes; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    function PutChar(const AName : string; const AData : TSDOChar; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function PutCurrency(const AName : string; const AData : TSDOCurrency; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CURRENCY}
+    function PutDate(const AName : string; const AData : TSDODateTime; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_DOUBLE}
+    function PutDouble(const AName : string; const AData : TSDODouble; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function PutFloat(const AName : string; const AData : TSDOFloat; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_FLOAT}
+    function PutInteger(const AName : string; const AData : TSDOInteger; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_LONG}
+    function PutLong(const AName : string; const AData : TSDOLong; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function PutShort(const AName : string; const AData : TSDOShort; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+    function PutString(const AName : string; const AData : TSDOString; const ANameSpace : string):TDOMNode;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetNodeValue(const ANameSpace : string; var AName : string; out ARes : DOMString) : Boolean;
+    function GetBoolean(var AName : string;var AData : TSDOBoolean; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetByte(var AName : string;var AData : TSDOByte; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_BYTES}
+    function GetBytes(var AName : string;var AData : TSDOBytes; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    function GetChar(var AName : string;var AData : TSDOChar; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function GetCurrency(var AName : string;var AData : TSDOCurrency; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_CURRENCY}
+    function GetDate(var AName : string;var AData : TSDODateTime; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_DOUBLE}
+    function GetDouble(var AName : string;var AData : TSDODouble; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function GetFloat(var AName : string;var AData : TSDOFloat; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_FLOAT}
+    function GetInteger(var AName : string;var AData : TSDOInteger; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$IFDEF HAS_SDO_LONG}
+    function GetLong(var AName : string;var AData : TSDOLong; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function GetShort(var AName : string;var AData : TSDOShort; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+{$ENDIF HAS_SDO_SHORT}
+    function GetString(var AName : string;var AData : TSDOString; const ANameSpace : string) : Boolean;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    function GetFormatName() : string;
+    procedure SetSerializationStyle(const ASerializationStyle : TSerializationStyle);
+    function GetSerializationStyle():TSerializationStyle;
+    procedure SetNameStyle(const AValue : TNameStyle);
+    function GetNameStyle() : TNameStyle;
+    function GetCurrentScope():string;
+    procedure Clear();
+    procedure Initialize();
+
+    procedure BeginObject(
+      Const AName      : string;
+      Const ATypeInfo  : ISDOType
+    );
+    procedure BeginArray(
+      const AName         : string;
+      const AItemTypeInfo : ISDOType;
+      const ABounds       : array of Integer
+    );
+    procedure NilCurrentScope();
+    function IsCurrentScopeNil():Boolean;
+    procedure EndScope();
+    function BeginObjectRead(
+      var   AScopeName : string;
+      const ATypeInfo  : ISDOType
+    ) : Integer;
+    function BeginArrayRead(
+      var   AScopeName : string;
+      const ATypeInfo  : ISDOType;
+      const AItemName  : string
+    ):Integer;
+    function GetScopeItemNames(
+      const AItemStyle : TSerializationStyle;
+      const AReturnList : TStrings
+    ) : Integer;
+    procedure EndScopeRead();
+
+    procedure Put(
+      const AName     : string;
+      const ATypeInfo : ISDOType;
+      const AData
+    );overload;
+    procedure Put(
+      const ANameSpace,
+            AName     : string;
+      const ATypeInfo : ISDOType;
+      const AData
+    );overload;
+    procedure PutScopeInnerValue(
+      const ATypeInfo : ISDOType;
+      const AData
+    );
+    function Get(
+      const ATypeInfo : ISDOType;
+      var   AName     : string;
+      var   AData
+    ) : Boolean;overload;
+    function Get(
+      const ANameSpace : string;
+      const ATypeInfo  : ISDOType;
+      var   AName      : string;
+      var   AData
+    ) : Boolean;overload;
+    function GetScopeInnerValue(
+      const ATypeInfo : ISDOType;
+      var   AData
+    ) : Boolean;
+    function ReadBuffer(const AName : string) : string;
+    //Please use this method if and _only_ if you do not have another way achieve your aim!
+    procedure WriteBuffer(const AValue : string);
+
+    procedure SaveToStream(AStream : TStream);overload;
+    procedure SaveToFile(const AFileName : string);overload;
+    procedure LoadFromStream(AStream : TStream);overload;
+    procedure LoadFromFile(const AFileName : string);overload;
+
+    function GetBookMark() : TStreamBookmark;
+    function GotoBookmark(const AValue : TStreamBookmark) : Boolean;
+    
+    // This procedures will raise exceptions!!!
+    procedure Error(Const AMsg:string);overload;
+    procedure Error(Const AMsg:string; Const AArgs : array of const);overload;
+  public
+    constructor Create();
+    destructor Destroy();override;
+    property PreferedShortNames : TStrings read FPreferedShortNames;
+  end;
+
+resourcestring
+  SMSG_ExpectingValidArrayStyle = 'Expecting valid array style.';
+
+implementation
+
+uses
+  sdo_imp_utils;
+
+function ExtractNameSpaceShortName(const ANameSpaceDeclaration : string):string;
+var
+  i : integer;
+begin
+  i := AnsiPos(s_xml_ns,ANameSpaceDeclaration);
+  if ( i > 0 ) then begin
+    Result := Copy(ANameSpaceDeclaration, (i + Length(s_xml_ns) + 1 ), MaxInt );
+  end else begin
+    Result := '';
+  end;
+end;
+
+{ TStackItem }
+
+function TStackItem.GetItemsCount(const AStyle : TSerializationStyle): Integer;
+begin
+  if ( AStyle = ssAttibuteSerialization ) then
+    Result := GetNodeListCount(ScopeObject.Attributes)
+  else
+    Result := GetNodeItemsCount(ScopeObject);
+end;
+
+constructor TStackItem.Create(AScopeObject: TDOMNode; AScopeType: TScopeType);
+begin
+  FScopeObject := AScopeObject;
+  FScopeType := AScopeType;
+end;
+
+procedure TStackItem.SetNameSpace(const ANameSpace: string);
+begin
+  FNameSpace := ANameSpace;
+end;
+
+function TStackItem.GetScopeItemNames(
+  const AItemStyle : TSerializationStyle;
+  const AReturnList: TStrings
+): Integer;
+var
+  c, i : PtrInt;
+begin
+  AReturnList.Clear();
+  if ( AItemStyle = ssNodeSerialization ) then begin
+    c := GetItemsCount(ssNodeSerialization);
+    for i := 0 to Pred(c) do begin
+      AReturnList.Add(ScopeObject.childNodes.Item[i].NodeName);
+    end;
+  end else begin
+    c := GetNodeListCount(ScopeObject.Attributes);
+    for i := 0 to Pred(c) do begin
+      AReturnList.Add(ScopeObject.Attributes.Item[i].nodeName);
+    end;
+  end;
+  Result := AReturnList.Count;
+end;
+
+procedure TStackItem.Error(const AMsg: string);
+begin
+  raise ESDOSerializationException.Create(AMsg);
+end;
+
+procedure TStackItem.Error(const AMsg: string; const AArgs: array of const);
+begin
+  raise ESDOSerializationException.CreateFmt(AMsg,AArgs);
+end;
+
+function TStackItem.BeginEmbeddedScope(): Integer;
+begin
+  Inc(FEmbeddedScopeCount);
+  Result := FEmbeddedScopeCount;
+end;
+
+function TStackItem.EndEmbeddedScope(): Integer;
+begin
+  if ( FEmbeddedScopeCount < 1 ) then begin
+    raise ESDOSerializationException.Create('Invalid operation on scope, their are no embedded scope.');
+  end;
+  Dec(FEmbeddedScopeCount);
+  Result := FEmbeddedScopeCount;
+end;
+
+
+procedure TStackItem.CopyTo(const AClone: TStackItem);
+begin
+  AClone.FEmbeddedScopeCount := Self.FEmbeddedScopeCount;
+  AClone.FNameSpace := Self.FNameSpace;
+  AClone.FScopeObject := Self.FScopeObject;
+  AClone.FScopeType := Self.FScopeType;
+end;
+
+constructor TStackItem.Create();
+begin
+
+end;
+
+function TStackItem.Clone() : TStackItem;
+begin
+
+  Result := TStackItemClass(Self.ClassType).Create();
+  try
+    Self.CopyTo(Result);
+  except
+    FreeAndNil(Result);
+    raise;
+  end;
+end;
+
+{ TObjectStackItem }
+
+function TObjectStackItem.FindNode(var ANodeName: string): TDOMNode;
+begin
+{$IFNDEF FPC}
+  Result := sdo_win_xml.FindNode(ScopeObject,ANodeName);
+{$ELSE}
+  Result := ScopeObject.FindNode(ANodeName);
+{$ENDIF}
+end;
+
+{ TAbstractArrayStackItem }
+
+procedure TAbstractArrayStackItem.EnsureListCreated();
+begin
+  if (FItemList = nil) then
+    FItemList := CreateList(FItemName);
+end;
+
+function TAbstractArrayStackItem.GetItemsCount(const AStyle : TSerializationStyle): Integer;
+begin
+  EnsureListCreated();
+  if Assigned(FItemList) then begin
+    Result := GetNodeListCount(FItemList);
+  end else begin
+    Result := 0;
+  end;
+end;
+
+constructor TAbstractArrayStackItem.Create(
+        AScopeObject : TDOMNode;
+  const AScopeType   : TScopeType;
+  const AItemName    : string
+);
+begin
+  inherited Create(AScopeObject,AScopeType);
+  FItemName := AItemName;
+end;
+
+destructor TAbstractArrayStackItem.Destroy();
+begin
+  if (FItemList <> nil) then
+    ReleaseDomNode(FItemList);
+  inherited Destroy();
+end;
+
+function TAbstractArrayStackItem.FindNode(var ANodeName: string): TDOMNode;
+begin
+  EnsureListCreated();
+  if ( FIndex >= GetNodeListCount(FItemList) ) then
+    Error('Index out of bound : %d; Node Name = "%s"; Parent Node = "%s"',[FIndex,ANodeName,ScopeObject.NodeName]);
+  Result:= FItemList.Item[FIndex];
+  Inc(FIndex);
+  ANodeName := Result.NodeName;
+end;
+
+procedure TAbstractArrayStackItem.CopyTo(const AClone: TStackItem);
+var
+  locClone : TAbstractArrayStackItem;
+begin
+  inherited;
+  locClone := AClone as TAbstractArrayStackItem;
+  locClone.FIndex := Self.FIndex;
+  locClone.FItemList := Self.FItemList;
+  locClone.FItemName := Self.FItemName;
+end;
+
+{ TScopedArrayStackItem }
+
+destructor TScopedArrayStackItem.Destroy();  
+begin
+  if ( FItemList <> nil ) then
+    FItemList := nil;
+  inherited Destroy();  
+end;
+
+function TScopedArrayStackItem.CreateList(const ANodeName : string): TDOMNodeList;
+begin
+  if ScopeObject.HasChildNodes() then begin
+    Result := ScopeObject.ChildNodes;
+  end else begin
+    Result := nil;
+  end;
+end;
+
+{ TEmbeddedArrayStackItem }
+
+function TEmbeddedArrayStackItem.CreateList(const ANodeName: string): TDOMNodeList;
+begin
+  if ScopeObject.HasChildNodes() then begin
+    Result := FilterList(ScopeObject,ANodeName);
+  end else begin
+    Result := nil;
+  end;
+end;
+
+{ TSDOSerializerStreamXML }
+
+{procedure TSDOSerializerStreamXML.AddScopeAttribute(const AName, AValue: string);
+begin
+  CheckScope();
+  GetCurrentScopeObject().SetAttribute(AName,AValue);
+end;}
+
+procedure TSDOSerializerStreamXML.BeginArray(
+  const AName         : string;
+  const AItemTypeInfo : ISDOType;
+  const ABounds       : array of Integer
+);
+var
+  typData : ISDOType;
+  i,j, k : Integer;
+  ns : string;
+begin
+  if ( Length(ABounds) < 2 ) then begin
+    Error('Invalid array bounds.');
+  end;
+  i := ABounds[0];
+  j := ABounds[1];
+  k := j - i + 1;
+  if ( k < 0 ) then begin
+    Error('Invalid array bounds.');
+  end;
+  typData := AItemTypeInfo;
+  if not Assigned(typData) then begin
+    Error('Typeinfo not provided.');
+  end;
+
+  if HasScope() then
+    ns := StackTop.NameSpace
+  else
+    ns := '';// raise Exception ????
+  BeginScope(AName,'',stArray);
+  StackTop().SetNameSpace(ns);
+end;
+
+function TSDOSerializerStreamXML.BeginArrayRead(
+  var   AScopeName : string;
+  const ATypeInfo  : ISDOType;
+  const AItemName  : string
+): Integer;
+begin
+  Result := InternalBeginScopeRead(AScopeName,ATypeInfo,stArray,AItemName);
+end;
+
+procedure TSDOSerializerStreamXML.BeginObject(const AName: string; const ATypeInfo: ISDOType);
+var
+  typData : ISDOType;
+  nmspc, nmspcSH : string;
+  mustAddAtt : Boolean;
+  strNodeName : string;
+begin
+  typData := ATypeInfo;
+  if not Assigned(typData) then
+    Error('Typeinfo not provided.');
+  mustAddAtt := False;
+  nmspc := typData.getURI();
+  if ( FNameStyle = nsQualified ) then begin
+    if IsStrEmpty(nmspc) then
+      nmspcSH := 'tns'
+    else begin
+      nmspcSH := FindAttributeByValueInScope(nmspc);
+      if IsStrEmpty(nmspcSH) then begin
+        nmspcSH := PreferedShortNames.Values[nmspc];
+        if IsStrEmpty(nmspcSH) then
+          nmspcSH := 'ns' + IntToStr(NextNameSpaceCounter());
+        if HasScope() then
+          FDoc.DocumentElement.SetAttribute('xmlns:'+nmspcSH, nmspc)
+        else begin
+          mustAddAtt := True;
+        end;
+      end else begin
+        nmspcSH := Copy(nmspcSH,Length('xmlns:')+1,MaxInt);
+      end;
+    end;
+
+    if not IsStrEmpty(nmspcSH) then begin
+      strNodeName := nmspcSH + ':' + AName;
+    end else begin
+      strNodeName := AName;
+    end;
+  end else begin
+    strNodeName := AName;
+  end;
+
+  BeginScope(strNodeName,'',stObject);
+  if mustAddAtt then
+    FDoc.DocumentElement.SetAttribute('xmlns:'+nmspcSH, nmspc);
+  StackTop().SetNameSpace(nmspc);
+end;
+
+function TSDOSerializerStreamXML.BeginObjectRead(
+  var   AScopeName : string;
+  const ATypeInfo  : ISDOType
+) : Integer;
+begin
+  Result := InternalBeginScopeRead(AScopeName,ATypeInfo,stObject,'');
+end;
+
+procedure TSDOSerializerStreamXML.BeginScope(
+  const AScopeName,
+        ANameSpace  : string;
+  const AScopeType  : TScopeType;
+  const AStyle      : TArrayStyle
+);
+var
+  nsStr, scpStr : string;
+  e : TDOMElement;
+  hasNmspc, addAtt : Boolean;
+begin
+  if ( AScopeType = stObject ) or
+     ( ( AScopeType = stArray ) and ( AStyle = asScoped ) )
+  then begin
+    addAtt := False;
+    scpStr := AScopeName;
+    hasNmspc := not IsStrEmpty(ANameSpace);
+    if hasNmspc then begin
+      nsStr := FindAttributeByValueInScope(ANameSpace);
+      addAtt := IsStrEmpty(nsStr);
+      if addAtt then begin
+        nsStr := PreferedShortNames.Values[ANameSpace];
+        if IsStrEmpty(nsStr) then
+          nsStr := 'ns' + IntToStr(NextNameSpaceCounter());
+      end else begin
+        nsStr := Copy(nsStr,Succ(AnsiPos(':',nsStr)),MaxInt);
+      end;
+      scpStr := nsStr + ':' + scpStr;
+    end;
+
+    e := FDoc.CreateElement(scpStr);
+    if HasScope() then
+      GetCurrentScopeObject().AppendChild(e)
+    else
+      FDoc.AppendChild(e);
+    if ( AScopeType = stObject ) then begin
+      PushStack(e);
+    end else begin
+      PushStack(e,'');
+    end;
+    if hasNmspc and addAtt then begin
+      e.SetAttribute('xmlns:'+nsStr,ANameSpace);
+      StackTop().SetNameSpace(ANameSpace);
+    end;
+  end else if ( ( AScopeType = stArray ) and ( AStyle = asEmbeded ) ) then begin
+    StackTop().BeginEmbeddedScope();
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.CheckScope();
+begin
+  if not HasScope() then
+    Error('There is no scope.');
+end;
+
+procedure TSDOSerializerStreamXML.Clear();
+begin
+  InternalClear(True);
+end;
+
+procedure TSDOSerializerStreamXML.ClearStack();
+var
+  i, c : Integer;
+begin
+  c := FStack.Count;
+  for I := 1 to c do
+    FStack.Pop().Free();
+end;
+
+constructor TSDOSerializerStreamXML.Create();
+var
+  ls : TStringList;
+begin
+  Inherited Create();
+  FStack := TObjectStackEx.Create();
+  ls := TStringList.Create();
+  FPreferedShortNames := ls;
+  ls.Duplicates := dupIgnore;
+  ls.Values[sdo_namespace] := 'sdo';
+  ls.Values[s_xsi_namespace] := 'xsi';
+  ls.Values[s_xsd_namespace] := 'xdi';
+  ls.Sorted := True;
+  FDoc := CreateDoc();
+end;
+
+destructor TSDOSerializerStreamXML.Destroy();
+begin
+  ReleaseDomNode(FDoc);
+  ClearStack();
+  FStack.Free();
+  FPreferedShortNames.Free();
+  inherited Destroy();
+end;
+
+procedure TSDOSerializerStreamXML.EndScope();
+begin
+  CheckScope();
+  if ( StackTop().EmbeddedScopeCount = 0 ) then begin
+    FStack.Pop().Free();
+  end else begin
+    StackTop().EndEmbeddedScope();
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.EndScopeRead();
+begin
+  PopStack().Free();
+end;
+
+procedure TSDOSerializerStreamXML.Error(const AMsg: string; const AArgs: array of const);
+begin
+  raise ESDOSerializationException.CreateFmt(AMsg,AArgs);
+end;
+
+procedure TSDOSerializerStreamXML.Error(const AMsg: string);
+begin
+  raise ESDOSerializationException.Create(AMsg);
+end;
+
+function TSDOSerializerStreamXML.FindAttributeByValueInNode(
+  const AAttValue : string;
+  const ANode     : TDOMNode;
+  out   AResAtt   : string
+) : Boolean;
+var
+  i,c : Integer;
+begin
+  AResAtt := '';
+  if Assigned(ANode) and
+     Assigned(ANode.Attributes) and
+     ( ANode.Attributes.Length > 0 )
+  then begin
+    c := Pred(ANode.Attributes.Length);
+    for i := 0 to c do begin
+      if AnsiSameText(AAttValue,ANode.Attributes.Item[i].NodeValue) then begin
+        AResAtt := ANode.Attributes.Item[i].NodeName;
+        Result := True;
+        Exit;
+      end;
+    end;
+  end;
+  Result := False;
+end;
+
+function TSDOSerializerStreamXML.FindAttributeByValueInScope(const AAttValue : string) : string;
+var
+  tmpNode : TDOMNode;
+begin
+  if HasScope() then begin
+    tmpNode := GetCurrentScopeObject();
+    while Assigned(tmpNode) do begin
+      if FindAttributeByValueInNode(AAttValue,tmpNode,Result) then
+        Exit;
+      tmpNode := tmpNode.ParentNode;
+    end;
+  end;
+  Result := '';
+end;
+
+function TSDOSerializerStreamXML.FindNameSpace(
+  const AShortName : string;
+  out   ARes : string
+) : Boolean;
+var
+  tmpNode, attNode : TDOMNode;
+  attName : string;
+begin
+  Result := False;
+  if HasScope() then begin
+    attName := Format('%s:%s',[s_xml_ns,AShortName]);
+    tmpNode := GetCurrentScopeObject();
+    while Assigned(tmpNode) do begin
+      if Assigned(tmpNode.Attributes) then begin
+        attNode := tmpNode.Attributes.GetNamedItem(attName);
+        if Assigned(attNode) then begin
+          ARes := attNode.NodeValue;
+          Result := True;
+          Break;
+        end;
+      end;
+      tmpNode := tmpNode.ParentNode;
+    end;
+  end;
+end;
+
+function TSDOSerializerStreamXML.Get(
+  const ATypeInfo : ISDOType;
+  var   AName     : string;
+  var   AData
+) : Boolean;
+begin
+  Result := Get('',ATypeInfo,AName,AData);
+end;
+
+function TSDOSerializerStreamXML.Get(
+  const ANameSpace: string;
+  const ATypeInfo: ISDOType;
+  var AName: string;
+  var AData
+) : Boolean;
+var
+  valBuffer : TValueBuffer;
+  strData : TSDOString;
+  bytesData : TSDOBytes;
+begin
+  FillChar(valBuffer,SizeOf(valBuffer),#0);
+  case ATypeInfo.getTypeEnum() of
+    BooleanType :
+      begin
+        Result := GetBoolean(AName,valBuffer.BooleanValue,ANameSpace);
+        if Result then
+          TSDOBoolean(AData) := valBuffer.BooleanValue;
+      end;
+    ByteType :
+      begin
+        Result := GetByte(AName,valBuffer.ByteValue,ANameSpace);
+        if Result then
+          TSDOByte(AData) := valBuffer.ByteValue;
+      end;
+{$IFDEF HAS_SDO_BYTES}
+    BytesType :
+      begin
+        Result := GetBytes(AName,bytesData,ANameSpace);
+        if Result then
+          TSDOBytes(AData) := bytesData;
+      end;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType :
+      begin
+        Result := GetChar(AName,valBuffer.CharValue,ANameSpace);
+        if Result then
+          TSDOChar(AData) := valBuffer.CharValue;
+      end;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType :
+      begin
+        Result := GetCurrency(AName,valBuffer.CurrencyValue,ANameSpace);
+        if Result then
+          TSDOCurrency(AData) := valBuffer.CurrencyValue;
+      end;
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType :
+      begin
+        Result := GetDate(AName,valBuffer.DateValue,ANameSpace);
+        if Result then
+          TSDODateTime(AData) := valBuffer.DateValue;
+      end;
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType :
+      begin
+        Result := GetDouble(AName,valBuffer.DoubleValue,ANameSpace);
+        if Result then
+          TSDODouble(AData) := valBuffer.DoubleValue;
+      end;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType :
+      begin
+        Result := GetFloat(AName,valBuffer.FloatValue,ANameSpace);
+        if Result then
+          TSDOFloat(AData) := valBuffer.FloatValue;
+      end;
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType :
+      begin
+        Result := GetInteger(AName,valBuffer.IntegerValue,ANameSpace);
+        if Result then
+          TSDOInteger(AData) := valBuffer.IntegerValue;
+      end;
+{$IFDEF HAS_SDO_LONG}
+    LongType :
+      begin
+        Result := GetLong(AName,valBuffer.LongValue,ANameSpace);
+        if Result then
+          TSDOLong(AData) := valBuffer.LongValue;
+      end;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType :
+      begin
+        Result := GetShort(AName,valBuffer.ShortValue,ANameSpace);
+        if Result then
+          TSDOShort(AData) := valBuffer.ShortValue;
+      end;
+{$ENDIF HAS_SDO_SHORT}
+    StringType  :
+      begin
+        strData := TSDOString(AData);
+        Result := GetString(AName,strData,ANameSpace);
+        if Result then
+          TSDOString(AData) := strData;
+      end;
+    else
+      Result := False;
+  end;
+end;
+
+function CopyStackItem(const AItem : TObject) : TObject;
+begin
+  if ( AItem <> nil ) then
+    Result := TStackItem(AItem).Clone()
+  else
+    Result := nil;
+end;
+
+function TSDOSerializerStreamXML.GetBookMark() : TStreamBookmark;
+var
+  locRes : TStreamXMLBookmark;
+begin
+  locRes := TStreamXMLBookmark.Create();
+  try
+    locRes.FNameStyle := Self.FNameStyle;
+    locRes.FStack := Self.FStack.Clone({$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyStackItem);
+    locRes.FDoc := Self.FDoc;
+    locRes.FSerializationStyle := Self.FSerializationStyle;
+    Result := locRes;
+  except
+    FreeAndNil(locRes);
+    raise;
+  end;
+end;
+
+function TSDOSerializerStreamXML.GetBoolean(var AName: string;var AData: TSDOBoolean; const ANameSpace : string) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace, AName,locBuffer);
+  if Result then begin
+    locBuffer := LowerCase(Trim(locBuffer));
+    if IsStrEmpty(locBuffer) then
+      AData := False
+    else
+      AData := TSDOConvertHelper.StringToBool(locBuffer);
+  end;
+end;
+
+function TSDOSerializerStreamXML.GetCurrentScope() : string;
+begin
+  CheckScope();
+  Result:= GetCurrentScopeObject().NodeName;
+end;
+
+function TSDOSerializerStreamXML.GetCurrentScopeObject() : TDOMElement;
+begin
+  Result := StackTop().ScopeObject As TDOMElement;
+end;
+
+function TSDOSerializerStreamXML.GetFormatName() : string;
+begin
+  Result := 'XML';
+end;
+
+function TSDOSerializerStreamXML.GetInteger(var AName: string;var AData: TSDOInteger; const ANameSpace : string) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToInteger(locBuffer);
+end;
+
+function TSDOSerializerStreamXML.GetNameStyle() : TNameStyle;
+begin
+  Result := FNameStyle;
+end;
+
+function TSDOSerializerStreamXML.GetNodeValue(const ANameSpace : string; var AName : string; out ARes : DOMString) : Boolean;
+var
+  locElt : TDOMNode;
+  namespaceShortName, strNodeName, s, locNS : string;
+begin
+  strNodeName := AName;
+  if ( FNameStyle = nsQualified ) then begin
+    if IsStrEmpty(ANameSpace) then
+      locNS := StackTop().NameSpace
+    else
+      locNS := ANameSpace;
+    namespaceShortName := FindAttributeByValueInScope(locNS);
+    if not IsStrEmpty(namespaceShortName) then begin
+      s := ExtractNameSpaceShortName(namespaceShortName);
+      if not IsStrEmpty(s) then
+        strNodeName := s + ':' + strNodeName;
+    end;
+  end;
+
+  if ( FSerializationStyle = ssNodeSerialization ) then begin
+    locElt := StackTop().FindNode(strNodeName) As TDOMElement;
+  end else begin
+    locElt := GetCurrentScopeObject().GetAttributeNode(strNodeName);
+  end;
+
+  if Assigned(locElt) then begin
+    if locElt.HasChildNodes then
+      ARes := locElt.FirstChild.NodeValue
+    else
+      ARes := locElt.NodeValue;
+    Result := True;
+  end else begin
+    ARes := '';
+    Result := False;
+  end;
+end;
+
+function TSDOSerializerStreamXML.GetScopeInnerValue(
+  const ATypeInfo: ISDOType;
+  var AData
+): Boolean;
+var
+  dataBuffer : string;
+  nd : TDOMNode;
+begin
+  CheckScope();
+  nd := StackTop().ScopeObject;
+  if nd.HasChildNodes() then
+    dataBuffer := nd.FirstChild.NodeValue
+  else
+    dataBuffer := StackTop().ScopeObject.NodeValue;
+  case ATypeInfo.getTypeEnum() of
+    BooleanType : TSDOBoolean(AData) := TSDOConvertHelper.StringToBool(dataBuffer);
+    ByteType    : TSDOByte(AData) := TSDOConvertHelper.StringToByte(dataBuffer);
+    IntegerType : TSDOInteger(AData) := TSDOConvertHelper.StringToInteger(dataBuffer);
+    StringType  : TSDOString(AData) := dataBuffer;
+    else
+      Assert(False);
+  end;
+  Result := True;
+end;
+
+function TSDOSerializerStreamXML.GetScopeItemNames(
+  const AItemStyle : TSerializationStyle;
+  const AReturnList: TStrings
+): Integer;
+var
+  i, c, j : PtrInt;
+  buffer, localName, space, expandedName, s : string;
+begin
+  CheckScope();
+  Result := StackTop().GetScopeItemNames(AItemStyle,AReturnList);
+  c := AReturnList.Count;
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      buffer := AReturnList[i];
+      j := AnsiPos(':',buffer);
+      if ( j < 1 ) then begin
+        expandedName := buffer;
+      end else begin
+        s := Copy(buffer,1,Pred(j));
+        localName := Copy(buffer,Succ(j),Length(buffer));
+        FindNameSpace(s,space);
+        expandedName := Format('%s#%s',[space,localName]);
+      end;
+      AReturnList[i] := expandedName;
+    end;
+  end;
+end;
+
+function TSDOSerializerStreamXML.GetSerializationStyle() : TSerializationStyle;
+begin
+  Result := FSerializationStyle;
+end;
+
+function TSDOSerializerStreamXML.GetString(var AName: string; var AData: TSDOString; const ANameSpace : string) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result then
+    AData := locBuffer;
+end;
+
+function TSDOSerializerStreamXML.GotoBookmark(const AValue: TStreamBookmark): Boolean;
+var
+  locBM : TStreamXMLBookmark;
+begin
+  Result := False;
+  if ( AValue <> nil ) then begin
+    locBM := AValue as TStreamXMLBookmark;
+    if ( locBM.Doc = Self.FDoc ) then begin
+      ClearStack();
+      FreeAndNil(FStack);
+      FStack := locBM.FStack.Clone({$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}CopyStackItem);
+      FSerializationStyle := locBM.SerializationStyle;
+      FNameStyle := locBM.NameStyle;
+      Result := True;
+    end;
+  end;
+end;
+
+function TSDOSerializerStreamXML.HasScope() : Boolean;
+begin
+  Result := FStack.AtLeast(1);
+end;
+
+function TSDOSerializerStreamXML.InternalBeginScopeRead(
+  var AScopeName   : string;
+  const ATypeInfo  : ISDOType;
+  const AScopeType : TScopeType;
+  const AItemName  : string;
+  const AStyle     : TArrayStyle
+) : Integer;
+var
+  locNode : TDOMNode;
+  stk : TStackItem;
+  typData : ISDOType;
+  nmspc,nmspcSH : string;
+  strNodeName : string;
+begin
+  typData := ATypeInfo;
+  if not Assigned(typData) then begin
+    Error('Typeinfo not provided.');
+  end;
+  nmspc := typData.getURI();
+  if ( FNameStyle = nsQualified ) then begin
+    if IsStrEmpty(nmspc) then begin
+      nmspcSH := ''
+    end else begin
+      nmspcSH := FindAttributeByValueInScope(nmspc);
+      if not IsStrEmpty(nmspcSH) then begin
+        nmspcSH := Copy(nmspcSH,Length('xmlns:')+1,MaxInt);
+      end;
+    end;
+    if IsStrEmpty(nmspcSH) then begin
+      strNodeName := AScopeName
+    end else begin
+      if ( Pos(':',AScopeName) < 1 ) then begin
+        strNodeName := nmspcSH + ':' + AScopeName
+      end else begin
+        strNodeName := AScopeName;
+      end;
+    end;
+  end else begin
+    strNodeName := AScopeName;
+  end;
+
+  stk := StackTop();
+  if ( AScopeType = stObject ) or
+     ( ( AScopeType = stArray ) and ( AStyle = asScoped ) )
+  then begin
+    locNode := stk.FindNode(strNodeName);
+  end else begin
+    locNode := stk.ScopeObject;
+  end;
+  if ( locNode = nil ) then begin
+    Result := -1;
+  end else begin
+    if ( AScopeType = stObject ) then begin
+      PushStack(locNode);
+    end else begin
+      PushStack(locNode,AItemName);
+    end;
+    StackTop().SetNameSpace(nmspc);
+    Result := StackTop().GetItemsCount(GetSerializationStyle());
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.InternalClear(const ACreateDoc: Boolean);
+begin
+  ClearStack();
+  FNameSpaceCounter := 0;
+  FNameStyle := nsUnqualified;
+  FSerializationStyle := ssNodeSerialization;
+  ReleaseDomNode(FDoc);
+  FDoc := nil;
+  if ACreateDoc then
+    FDoc := CreateDoc();
+end;
+
+function TSDOSerializerStreamXML.InternalPutData(
+  const AName : string;
+  const AData : TSDOString; 
+  const ANameSpace : string
+): TDOMNode;
+var
+  namespaceShortName, strNodeName, s, locNS : TSDOString;
+begin
+  strNodeName := AName;
+  if ( FNameStyle = nsQualified ) then begin
+    if IsStrEmpty(ANameSpace) then
+      locNS := StackTop().NameSpace
+    else
+      locNS := ANameSpace;
+    namespaceShortName := FindAttributeByValueInScope(locNS);
+    if not IsStrEmpty(namespaceShortName) then begin
+      s := ExtractNameSpaceShortName(namespaceShortName);
+      if not IsStrEmpty(s) then
+        strNodeName := s + ':' + strNodeName;
+    end;
+  end;
+
+  if ( FSerializationStyle = ssNodeSerialization ) then begin
+    Result := FDoc.CreateElement(strNodeName);
+    Result.AppendChild(FDoc.CreateTextNode(AData));
+    GetCurrentScopeObject().AppendChild(Result);
+  end else begin
+    Result := GetCurrentScopeObject();
+    (Result as TDOMElement).SetAttribute(strNodeName,AData);
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.Initialize();
+begin
+  ClearStack();
+  if ( FDoc <> nil ) and ( FDoc.DocumentElement <> nil ) then
+    PushStack(FDoc.DocumentElement);
+end;
+
+function TSDOSerializerStreamXML.IsCurrentScopeNil() : Boolean;
+var
+  s,nsShortName,nilName : String;
+begin
+  CheckScope();
+  nsShortName := FindAttributeByValueInScope(s_xsi_namespace);
+  Result := False;
+  if IsStrEmpty(nsShortName) then begin
+    nilName := s_nil;
+  end else begin
+    nsShortName := Copy(nsShortName,1 + Pos(':',nsShortName),MaxInt);
+    if not IsStrEmpty(nsShortName) Then
+      nsShortName := nsShortName + ':';
+    nilName := nsShortName + s_nil;
+  end;
+  s := Trim(GetCurrentScopeObject().GetAttribute(nilName));
+  if ( Length(s) > 0 ) and ( AnsiSameText(s,'true') or AnsiSameText(s,'"true"') ) then begin
+    Result := True;
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.LoadFromFile(const AFileName: string);
+var
+  stream : TFileStream;
+begin
+  if not FileExists(AFileName) then
+    raise ESDOSerializationException.CreateFmt('File not found : "%s".',[AFileName]);
+  stream := TFileStream.Create(AFileName,fmOpenRead or fmShareDenyWrite);
+  try
+    LoadFromStream(stream);
+  finally
+    stream.Free();
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.LoadFromStream(AStream: TStream);
+var
+  nd : TDOMNode;
+begin
+  InternalClear(False);
+  ReadXMLFile(FDoc,AStream);
+  nd := FDoc.DocumentElement;
+  if Assigned(nd) then
+    PushStack(nd);
+end;
+
+function TSDOSerializerStreamXML.NextNameSpaceCounter() : Integer;
+begin
+  Inc(FNameSpaceCounter);
+  Result := FNameSpaceCounter;
+end;
+
+procedure TSDOSerializerStreamXML.NilCurrentScope();
+var
+  nmspcSH : string;
+begin
+  CheckScope();
+  nmspcSH := FindAttributeByValueInScope(s_xsi_namespace);
+  if IsStrEmpty(nmspcSH) then begin
+    nmspcSH := PreferedShortNames.Values[s_xsi_namespace];
+    if IsStrEmpty(nmspcSH) then begin
+      nmspcSH := 'ns' + IntToStr(NextNameSpaceCounter());
+    end;
+    FDoc.DocumentElement.SetAttribute('xmlns:'+nmspcSH, s_xsi_namespace);
+  end else begin
+    nmspcSH := Copy(nmspcSH,Length('xmlns:')+1,MaxInt);
+  end;
+  GetCurrentScopeObject().SetAttribute(nmspcSH + ':' + s_nil,'true');
+end;
+
+function TSDOSerializerStreamXML.PopStack() : TStackItem;
+begin
+  CheckScope();
+  Result := FStack.Pop() as TStackItem;
+end;
+
+function TSDOSerializerStreamXML.PushStack(AScopeObject: TDOMNode): TStackItem;
+begin
+  Result := FStack.Push(TObjectStackItem.Create(AScopeObject,stObject)) as TStackItem;
+end;
+
+function TSDOSerializerStreamXML.PushStack(
+  const AScopeObject : TDOMNode;
+  const AItemName    : string;
+  const AStyle       : TArrayStyle
+): TStackItem;
+begin
+  case AStyle of
+    asScoped  : Result := FStack.Push(TScopedArrayStackItem.Create(AScopeObject,stArray,AItemName)) as TStackItem;
+    asEmbeded : Result := FStack.Push(TEmbeddedArrayStackItem.Create(AScopeObject,stArray,AItemName)) as TStackItem;
+    else
+      raise ESDOSerializationException.Create(SMSG_ExpectingValidArrayStyle);
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.Put(
+  const AName     : string;
+  const ATypeInfo : ISDOType;
+  const AData
+);
+begin
+  Put('',AName,ATypeInfo,AData);
+end;
+
+procedure TSDOSerializerStreamXML.Put(
+  const ANameSpace,
+        AName     : string;
+  const ATypeInfo : ISDOType;
+  const AData
+);
+var
+  valBuffer : TValueBuffer;
+  strData : TSDOString;
+  bytesData : TSDOBytes;
+begin
+  case ATypeInfo.getTypeEnum() Of
+    BooleanType :
+      begin
+        valBuffer.BooleanValue := TSDOBoolean(AData);
+        PutBoolean(AName,valBuffer.BooleanValue,ANameSpace);
+      end;
+    ByteType :
+      begin
+        valBuffer.ByteValue := TSDOByte(AData);
+        PutByte(AName,valBuffer.ByteValue,ANameSpace);
+      end;
+{$IFDEF HAS_SDO_BYTES}
+     BytesType :
+      begin
+        bytesData := TSDOBytes(AData);
+        PutBytes(AName,bytesData,ANameSpace);
+      end;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType :
+      begin
+        valBuffer.CharValue := TSDOChar(AData);
+        PutChar(AName,valBuffer.CharValue,ANameSpace);
+      end;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType :
+      begin
+        valBuffer.CurrencyValue := TSDOCurrency(AData);
+        PutCurrency(AName,valBuffer.CurrencyValue,ANameSpace);
+      end;
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType :
+      begin
+        valBuffer.DateValue := TSDODateTime(AData);
+        PutDate(AName,valBuffer.DateValue,ANameSpace);
+      end;
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType :
+      begin
+        valBuffer.DoubleValue := TSDODouble(AData);
+        PutDouble(AName,valBuffer.DoubleValue,ANameSpace);
+      end;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType :
+      begin
+        valBuffer.FloatValue := TSDOFloat(AData);
+        PutFloat(AName,valBuffer.FloatValue,ANameSpace);
+      end;
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType :
+      begin
+        valBuffer.IntegerValue := TSDOInteger(AData);
+        PutInteger(AName,valBuffer.IntegerValue,ANameSpace);
+      end;
+{$IFDEF HAS_SDO_LONG}
+    LongType :
+      begin
+        valBuffer.LongValue := TSDOLong(AData);
+        PutLong(AName,valBuffer.LongValue,ANameSpace);
+      end;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType :
+      begin
+        valBuffer.ShortValue := TSDOShort(AData);
+        PutShort(AName,valBuffer.ShortValue,ANameSpace);
+      end;
+{$ENDIF HAS_SDO_SHORT}
+    StringType  :
+      begin
+        strData := TSDOString(AData);
+        PutString(AName,strData,ANameSpace);
+      end;
+    else
+      Assert(False);
+  end;
+end;
+
+function TSDOSerializerStreamXML.PutBoolean(const AName: string; const AData: TSDOBoolean; const ANameSpace : string): TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.BoolToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.PutInteger(const AName: string;const AData: TSDOInteger; const ANameSpace : string): TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.IntegerToString(AData),ANameSpace);
+end;
+
+procedure TSDOSerializerStreamXML.PutScopeInnerValue(
+  const ATypeInfo: ISDOType;
+  const AData
+);
+var
+  dataBuffer : string;
+begin
+  case ATypeInfo.getTypeEnum() Of
+    BooleanType : dataBuffer := TSDOConvertHelper.BoolToString(TSDOBoolean(AData));
+{$IFDEF HAS_SDO_BYTES}
+    BytesType   : dataBuffer := TSDOConvertHelper.BytesToString(TSDOBytes(AData));
+{$ENDIF HAS_SDO_BYTES}
+    ByteType    : dataBuffer := TSDOConvertHelper.ByteToString(TSDOByte(AData));
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : dataBuffer := TSDOChar(AData);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType : dataBuffer := TSDOConvertHelper.CurrencyToString(TSDOCurrency(AData));
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType: dataBuffer := TSDOConvertHelper.DateToString(TSDODateTime(AData));
+    IntegerType : dataBuffer := TSDOConvertHelper.IntegerToString(TSDOInteger(AData));
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType  : dataBuffer := TSDOConvertHelper.FloatToString(TSDODouble(AData));
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType   : dataBuffer := TSDOConvertHelper.FloatToString(TSDOFloat(AData));
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    LongType    : dataBuffer := TSDOConvertHelper.LongToString(TSDOLong(AData));
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType   : dataBuffer := TSDOConvertHelper.ShortToString(TSDOShort(AData));
+{$ENDIF HAS_SDO_SHORT}
+    StringType  : dataBuffer := TSDOString(AData);
+    else
+      Assert(False);
+  end;
+  StackTop().ScopeObject.AppendChild(FDoc.CreateTextNode(dataBuffer));
+end;
+
+function TSDOSerializerStreamXML.PutString(const AName: string;const AData: TSDOString; const ANameSpace : string): TDOMNode;
+begin
+  Result := InternalPutData(AName,AData,ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.ReadBuffer(const AName: string): string;
+var
+  locElt : TDOMNode;
+  namespaceShortName, strNodeName, s : string;
+begin
+  strNodeName := AName;
+  namespaceShortName := FindAttributeByValueInScope(StackTop().NameSpace);
+  namespaceShortName := Copy(namespaceShortName,AnsiPos(':',namespaceShortName) + 1,MaxInt);
+  if not IsStrEmpty(namespaceShortName) then begin
+    s := ExtractNameSpaceShortName(namespaceShortName);
+    if not IsStrEmpty(s) then
+      strNodeName := s + ':' + strNodeName;
+  end;
+
+  if ( FSerializationStyle = ssNodeSerialization ) then begin
+    locElt := StackTop().FindNode(strNodeName);
+  end else begin
+    locElt := GetCurrentScopeObject().GetAttributeNode(strNodeName);
+  end;
+  if ( locElt = nil ) and ( not AnsiSameStr(AName,strNodeName) ) then begin
+    strNodeName := AName;
+    if ( FSerializationStyle = ssNodeSerialization ) then begin
+      locElt := StackTop().FindNode(strNodeName);
+    end else begin
+      locElt := GetCurrentScopeObject().GetAttributeNode(strNodeName);
+    end;
+  end;
+
+  if Assigned(locElt) then
+    Result := NodeToBuffer(locElt)
+  else
+    Result := '';
+end;
+
+procedure TSDOSerializerStreamXML.SaveToFile(const AFileName: string);
+var
+  stream : TFileStream;
+begin
+  stream := TFileStream.Create(AFileName,fmCreate);
+  try
+    SaveToStream(stream);
+  finally
+    stream.Free();
+  end;
+end;
+
+procedure TSDOSerializerStreamXML.SaveToStream(AStream: TStream);
+begin
+  WriteXMLFile(FDoc,AStream);
+end;
+
+procedure TSDOSerializerStreamXML.SetNameStyle(const AValue: TNameStyle);
+begin
+  FNameStyle := AValue;
+end;
+
+procedure TSDOSerializerStreamXML.SetSerializationStyle(const ASerializationStyle: TSerializationStyle);
+begin
+  FSerializationStyle := ASerializationStyle;
+end;
+
+function TSDOSerializerStreamXML.StackTop() : TStackItem;
+begin
+  CheckScope();
+  Result := FStack.Peek() as TStackItem;
+end;
+
+procedure TSDOSerializerStreamXML.WriteBuffer(const AValue: string);
+var
+  strm : TStringStream;
+  locDoc : TSDOXMLDocument;
+  locNode : TDOMNode;
+begin
+  CheckScope();
+  locDoc := nil;
+  strm := TStringStream.Create(AValue);
+  try
+    ReadXMLFile(locDoc,strm);
+    locNode := locDoc.DocumentElement.CloneNode(True {$IFDEF FPC}, StackTop().ScopeObject.OwnerDocument{$ENDIF});
+    StackTop().ScopeObject.AppendChild(locNode);
+  finally
+    ReleaseDomNode(locDoc);
+    strm.Free();
+  end;
+end;
+
+
+{ TStreamXMLBookmark }
+
+destructor TStreamXMLBookmark.Destroy();
+var
+  i : PtrInt;
+begin
+  if ( FStack <> nil ) and ( FStack.Count > 0 ) then begin
+    for i := 0 to Pred(FStack.Count) do
+      FStack.Pop().Free();
+  end;
+  FreeAndNil(FStack);
+  inherited;
+end;
+
+function TSDOSerializerStreamXML.PutByte(
+  const AName: string;
+  const AData: TSDOByte;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.ByteToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetByte(
+  var AName: string;
+  var AData: TSDOByte;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToByte(locBuffer);
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+function TSDOSerializerStreamXML.PutBytes(
+  const AName: string;
+  const AData: TSDOBytes;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.BytesToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetBytes(
+  var AName: string;
+  var AData: TSDOBytes;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToBytes(locBuffer);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+function TSDOSerializerStreamXML.PutChar(
+  const AName: string;
+  const AData: TSDOChar;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,AData,ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetChar(
+  var AName: string;
+  var AData: TSDOChar;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToChar(locBuffer);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+function TSDOSerializerStreamXML.PutCurrency(
+  const AName: string;
+  const AData: TSDOCurrency;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.CurrencyToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetCurrency(
+  var AName: string;
+  var AData: TSDOCurrency;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToCurrency(locBuffer);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+function TSDOSerializerStreamXML.PutDate(
+  const AName: string;
+  const AData: TSDODateTime;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.DateToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetDate(
+  var AName: string;
+  var AData: TSDODateTime;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToDate(locBuffer);
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+function TSDOSerializerStreamXML.PutDouble(
+  const AName: string;
+  const AData: TSDODouble;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.FloatToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetDouble(
+  var AName: string;
+  var AData: TSDODouble;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToFloat(locBuffer);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+function TSDOSerializerStreamXML.PutFloat(
+  const AName: string;
+  const AData: TSDOFloat;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.FloatToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetFloat(
+  var AName: string;
+  var AData: TSDOFloat;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToFloat(locBuffer);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+function TSDOSerializerStreamXML.PutLong(
+  const AName: string;
+  const AData: TSDOLong;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.LongToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetLong(
+  var AName: string;
+  var AData: TSDOLong;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToLong(locBuffer);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+function TSDOSerializerStreamXML.PutShort(
+  const AName: string;
+  const AData: TSDOShort;
+  const ANameSpace: string
+) : TDOMNode;
+begin
+  Result := InternalPutData(AName,TSDOConvertHelper.ShortToString(AData),ANameSpace);
+end;
+
+function TSDOSerializerStreamXML.GetShort(
+  var AName: string;
+  var AData: TSDOShort;
+  const ANameSpace: string
+) : Boolean;
+var
+  locBuffer : DOMString;
+begin
+  Result := GetNodeValue(ANameSpace,AName,locBuffer);
+  if Result and ( locBuffer <> '' ) then
+    AData := TSDOConvertHelper.StringToShort(locBuffer);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+end.

+ 2287 - 0
packages/fcl-sdo/src/base/sdo_type.pas

@@ -0,0 +1,2287 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements basic SDO data type definitions
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_type;
+
+interface
+uses SysUtils, Classes,
+     sdo_types, sdo;
+
+const
+  VALUE_STATUS_LENGTH = 1;
+
+type
+
+  ISDOTypeEx = interface(ISDOType)
+    ['{19C39BF1-397C-4A10-98B2-EB4D23CB027C}']
+    procedure setBaseType(const ABaseType : ISDOType);
+    procedure setAlias(const AAlias : string);
+    procedure setUsedFlag(const AUsed : Boolean);
+    function isUsed() : Boolean;
+    function getFieldSize() : PtrUInt;
+    function inherits(const AType : ISDOType) : Boolean;
+  end;
+
+  ISDOObjectType = interface(ISDOTypeEx)
+    ['{19C39BF1-397C-4A10-98B2-EB4D23CB027C}']
+    procedure AddProperty(
+      const AName : string;
+      const AType : ISDOType;
+      const AFlags  : TPropertyFlags
+    );
+    procedure DropProperty(const AProperty : ISDOProperty);
+    function IsOwnerOf(const AProp : ISDOProperty) : Boolean;
+    procedure Clear();
+  end;
+
+  ISDOTypeListEx = interface(ISDOTypeList)
+    ['{7C23199E-F9CB-4704-AD51-93C7FB22BB6A}']
+    procedure insert(const AType : ISDOType);
+  end;
+
+  TSDOTypeAsbtract = class(TInterfacedObject,IInterface,ISDOType,ISDOTypeEx)
+  private
+    FOwner : Pointer; //ISDODataFactory;
+    FName : string;
+    FURI : string;
+    FALiasList : TStringList;
+    FFlags : TTypeFlags;
+    FUsed : Boolean;
+  protected
+    procedure CheckNotUsed(const AOperationName : string);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    function getName() : string;
+	  function getAlias(const AIndex : PtrInt) : string;
+	  function getAliasCount() : PtrInt;
+	  function getBaseType() : ISDOType; virtual;
+	  function getURI() : string;virtual;
+	  function getProperties() : ISDOPropertyList;virtual;abstract;
+    function getProperty(const APropertyName : string) : ISDOProperty;overload;virtual;abstract;
+    function getProperty(const APropertyIndex : Integer) : ISDOProperty;overload;virtual;abstract;
+	  function getPropertyIndex(const APropertyName : string) : Integer; virtual;abstract;
+	  function isDataObjectType() : Boolean;virtual;abstract;
+	  function isSequencedType() : Boolean; 
+	  function isOpenType() : Boolean; 
+	  function isAbstractType() : Boolean;
+    function isDataType() : Boolean;
+    function isChangeSummaryType() : Boolean;virtual;abstract;
+    function getTypeEnum() : TSDOTypeKind; virtual;abstract;
+    function equals(const AOther : ISDOType) : Boolean; virtual;
+    function getFlags() : TTypeFlags;
+    // ISDOTypeEx
+    procedure setBaseType(const ABaseType : ISDOType);virtual;
+    procedure setAlias(const AAlias : string);
+    procedure setUsedFlag(const AUsed : Boolean);virtual;
+    function isUsed() : Boolean;
+    function getFieldSize() : PtrUInt;virtual;abstract;
+    function inherits(const AType : ISDOType) : Boolean;virtual;
+    function getOwner() : ISDODataFactory;
+  public
+    constructor Create(const AOwner : ISDODataFactory; const AName, AURI : string);
+    destructor Destroy();override;
+  end;
+
+  TSDOSimpleType = class(TSDOTypeAsbtract)
+  protected
+    function getProperties() : ISDOPropertyList;override;
+    function getProperty(const APropertyName : string) : ISDOProperty;overload;override;
+    function getProperty(const APropertyIndex : Integer) : ISDOProperty;overload;override;
+	  function getPropertyIndex(const APropertyName : string) : Integer; override;
+	  function isDataObjectType() : Boolean;override;
+	  //function isAbstractType() : Boolean;override;
+    function isChangeSummaryType() : Boolean;override;
+    //function getTypeEnum() : TSDOTypeKind; override;
+  public
+    constructor Create(const AOwner : ISDODataFactory; const AName, AURI : string);
+  end;
+
+  TSDOChangeSummaryType = class(TSDOTypeAsbtract)
+  protected
+	  function getProperties() : ISDOPropertyList;override;
+    function getProperty(const APropertyName : string) : ISDOProperty;overload;override;
+    function getProperty(const APropertyIndex : Integer) : ISDOProperty;overload;override;
+	  function getPropertyIndex(const APropertyName : string) : Integer; override;
+	  function isDataObjectType() : Boolean;override;
+    function isChangeSummaryType() : Boolean;override;
+    function getTypeEnum() : TSDOTypeKind; override;
+    // ISDOTypeEx
+    procedure setBaseType(const ABaseType : ISDOType);override;
+    //procedure setAlias(const AAlias : string);
+    //procedure setUsedFlag(const AUsed : Boolean);virtual;
+    //function isUsed() : Boolean;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+
+  TSDOConcreteSimpleType = class(TSDOSimpleType)
+  end;
+
+  TSDOUserDefinedSimpleType = class(TSDOConcreteSimpleType)
+  private
+    FBaseType : ISDOType;
+  protected
+    function getBaseType() : ISDOType; override;
+    function getTypeEnum() : TSDOTypeKind; override;
+    procedure setBaseType(const ABaseType : ISDOType);override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(
+      const AOwner : ISDODataFactory;
+      const AName, AURI : string;
+      const AIsAbstract : Boolean
+    );
+  end;
+
+  TSDONativeSimpleType = class(TSDOConcreteSimpleType)
+  protected
+    procedure setBaseType(const ABaseType : ISDOType);override;
+  end;
+
+  TSDOBooleanType = class(TSDONativeSimpleType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+
+  TSDOByteType = class(TSDONativeSimpleType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+
+{$IFDEF HAS_SDO_BYTES}
+  TSDOBytesType = class(TSDONativeSimpleType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  TSDOCharacterType = class(TSDONativeSimpleType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+{$ENDIF HAS_SDO_CHAR}
+
+  TSDOBaseNumericType = class(TSDONativeSimpleType)
+  end;
+
+{$IFDEF HAS_SDO_CURRENCY}
+  TSDOCurrencyType = class(TSDOBaseNumericType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+  TSDOBaseStringType = class(TSDONativeSimpleType)
+  end;
+
+  TSDODateTimeType = class(TSDONativeSimpleType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+  TSDODoubleType = class(TSDOBaseNumericType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  TSDOFloatType = class(TSDOBaseNumericType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+{$ENDIF HAS_SDO_FLOAT}
+
+  TSDOBaseOrdinalType = class(TSDONativeSimpleType)
+  end;
+
+  TSDOIntegerType = class(TSDOBaseOrdinalType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+
+{$IFDEF HAS_SDO_LONG}
+  TSDOLongType = class(TSDOBaseOrdinalType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+{$ENDIF HAS_SDO_LONG}  
+
+{$IFDEF HAS_SDO_SHORT}
+  TSDOShortType = class(TSDOBaseOrdinalType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+{$ENDIF HAS_SDO_SHORT}
+
+  TSDOStringType = class(TSDOBaseStringType)
+  protected
+	  function getTypeEnum() : TSDOTypeKind; override;
+    function getFieldSize() : PtrUInt;override;
+  public
+    constructor Create(const AOwner : ISDODataFactory);
+  end;
+
+  TSDOBaseObjectType = class(
+    TSDOTypeAsbtract,
+    IInterface,
+    ISDOType,
+    ISDOTypeEx,
+    ISDOObjectType
+  )
+  private
+    FBaseType : ISDOObjectType;
+    FProperties : ISDOPropertyList;
+  protected
+	  function getBaseType() : ISDOType; override;
+	  function getProperties() : ISDOPropertyList; override;
+    function getProperty(const APropertyName : string) : ISDOProperty;overload; override;
+    function getProperty(const APropertyIndex : Integer) : ISDOProperty;overload; override;
+	  function getPropertyIndex(const APropertyName : string) : Integer;  override;
+	  function isDataObjectType() : Boolean; override;
+    function isChangeSummaryType() : Boolean;override;
+    function getTypeEnum() : TSDOTypeKind;  override;
+    procedure setBaseType(const ABaseType : ISDOType);override;
+    procedure AddProperty(
+      const AName : string;
+      const AType : ISDOType;
+      const AFlags  : TPropertyFlags
+    );
+    function getFieldSize() : PtrUInt;override;
+
+    //ISDOTypeEx
+    procedure setUsedFlag(const AUsed : Boolean);override;
+    procedure DropProperty(const AProperty : ISDOProperty);
+    function IsOwnerOf(const AProp : ISDOProperty) : Boolean;
+    function inherits(const AType : ISDOType) : Boolean;override;
+    procedure Clear();
+  public
+    constructor Create(
+      const AOwner : ISDODataFactory;
+      const AName, AURI : string;
+      const ASequenced  : Boolean;
+      const AOpened     : Boolean;
+      const AAbstract   : Boolean
+    );
+    destructor Destroy();override;
+  end;
+
+  TSDOObjectType = class(
+    TSDOBaseObjectType
+  )
+  end;
+
+  TSDOTypeList = class(
+    TInterfacedObject,
+    IInterface,
+    ISDOTypeList,
+    ISDOTypeListEx
+  )
+  private
+    FList : IInterfaceList;
+  protected
+    function getCount() : Integer;
+    function getItem(const AIndex : Integer) : ISDOType;
+    procedure insert(const AType : ISDOType);
+    function find(const AUri, AName : string) : ISDOType;
+    function getIndex(const AUri, AName : string) : Integer;
+  public
+    constructor Create();
+    destructor Destroy();override;
+  end;
+
+  ISDOPropertyEx = interface(ISDOProperty)
+    ['{C0ECCD8C-5727-4E1A-A389-BE15F3F8B350}']
+    procedure setAlias(const AAlias : string);
+    function getBufferOffset() : PtrUInt;
+    function setBufferOffset(const AStartingAddress : PtrUInt) : PtrUInt;
+    // do not use this : it is only for houskeeping
+    procedure ClearType();
+  end;
+
+  ISDOPropertyListEx = interface(ISDOPropertyList)
+    ['{C67F5513-7833-4DE1-870F-DFBEDFFCF5BA}']
+    procedure add(const AProperty : ISDOProperty);
+    function SetBase(const ABaseList : ISDOPropertyList) : ISDOPropertyList;
+    procedure drop(const AProperty : ISDOProperty);
+  end;
+
+  TSDOPropertyAsbtract = class(
+    TInterfacedObject,
+    IInterface,
+    ISDOProperty,
+    ISDOPropertyEx
+  )
+  private
+    FName : string;
+    FALiasList : TStrings;
+    FType : Pointer; //ISDOType;
+    FContainingType : Pointer;
+    FBufferOffset : PtrUInt;
+    FDefault : TValueBuffer;
+    FDefaultSet : Boolean;
+    FFlags : TPropertyFlags;
+    FWeakReferenceToType : Boolean;
+    FTypeKind : TSDOTypeKind;
+  private
+    procedure InternalSetBufferOffset(const AOffset : PtrUInt);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure FreeDefaultBuffer();
+    procedure CheckIfContainingTypeIsUsed(const AOperation : string);{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+ 	  function getName() : string;
+    function getAlias(const AIndex : Integer) : string;
+    function getAliasCount() : Integer;
+    function getType() : ISDOType;
+    function getTypeEnum() : TSDOTypeKind;
+    function isMany() : Boolean;
+    function isContainment() : Boolean;
+    function isReference() : Boolean;
+    function getContainingType() : ISDOType;
+    function isReadOnly() : Boolean;
+    function getOpposite() : ISDOProperty; virtual;
+	  function isDefaulted() : Boolean;
+    function getStringDefault() : TSDOString;
+{$IFDEF HAS_SDO_BYTES}
+    function getBytesDefault() : TSDOBytes;
+{$ENDIF HAS_SDO_BYTES}
+    function getBooleanDefault() : TSDOBoolean;
+    function getByteDefault() : TSDOByte;
+{$IFDEF HAS_SDO_CHAR}
+    function getCharacterDefault() : TSDOChar;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    function getCurrencyDefault() : TSDOCurrency;
+{$ENDIF HAS_SDO_CURRENCY}
+    function getDateDefault() : TSDODate;
+{$IFDEF HAS_SDO_DOUBLE}
+    function getDoubleDefault() : TSDODouble;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    function getFloatDefault() : TSDOFloat;
+{$ENDIF HAS_SDO_FLOAT}
+    function getIntegerDefault() : TSDOInteger;
+{$IFDEF HAS_SDO_LONG}
+    function getLongDefault() : TSDOLong;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    function getShortDefault() : TSDOShort;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setDefault(const AValue : TSDOBoolean);overload;
+    procedure setDefault(const AValue : TSDOByte);overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure setDefault(AValue : TSDOBytes);overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setDefault(const AValue : TSDOChar);overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY }
+    procedure setDefaultCurrency(const AValue : TSDOCurrency);
+{$ENDIF HAS_SDO_CURRENCY }
+    procedure setDefault(const AValue : TSDODate);overload;
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDefault(const AValue : TSDODouble);overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setDefault(const AValue : TSDOFloat);overload;
+{$ENDIF HAS_SDO_FLOAT}
+    procedure setDefault(const AValue : TSDOInteger);overload;
+{$IFDEF HAS_SDO_LONG}
+    procedure setDefault(const AValue : TSDOLong);overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setDefault(const AValue : TSDOShort);overload;
+{$ENDIF HAS_SDO_SHORT}
+    procedure setDefault(const AValue : TSDOString);overload;
+
+    function isNullable() : Boolean;
+    function isAttribute() : Boolean;
+
+    // ISDOPropertyEx
+    procedure setAlias(const AAlias : string);
+    function setBufferOffset(const AStartingAddress : PtrUInt) : PtrUInt;
+    function getBufferOffset() : PtrUInt;
+    procedure ClearType();
+  public
+    constructor Create(
+      const AName  : string;
+      const AType  : ISDOType;
+      const AFlags  : TPropertyFlags;
+      const AContainingType : ISDOType
+    );
+    destructor Destroy();override;
+  end;
+
+  TSDOProperty = class(TSDOPropertyAsbtract,IInterface,ISDOProperty)
+  end;
+
+  TSDOPropertyList = class(
+    TInterfacedObject,
+    IInterface,
+    ISDOPropertyList,
+    ISDOPropertyListEx
+  )
+  private
+    FList : IInterfaceList;
+    FBaseList : ISDOPropertyList;
+  protected
+    function getCount() : Integer;
+    function getItem(const AIndex : Integer) : ISDOProperty;
+    procedure add(const AProperty : ISDOProperty);
+    function find(const AName : string) : ISDOProperty;
+    function getIndex(const APropertyName : string) : Integer;
+    function SetBase(const ABaseList : ISDOPropertyList) : ISDOPropertyList;
+    procedure drop(const AProperty : ISDOProperty);
+  public
+    constructor Create(const ABaseList : ISDOPropertyList);
+    destructor Destroy();override;
+  end;
+
+implementation
+uses
+  sdo_imp_utils, sdo_date_utils;
+
+
+{ TSDOTypeAsbtract }
+
+procedure TSDOTypeAsbtract.CheckNotUsed(const AOperationName : string);
+begin
+  if FUsed then
+    raise ESDOInvalidStateOperationException.Create(AOperationName);
+end;
+
+constructor TSDOTypeAsbtract.Create(const AOwner : ISDODataFactory; const AName, AURI: string);
+begin
+  FOwner := Pointer(AOwner);
+  FName := AName;
+  FURI := AURI;
+  FALiasList := TStringList.Create();
+  FALiasList.Duplicates := dupIgnore;
+  //FALiasList.Sorted := True;
+  FALiasList.CaseSensitive := False;
+end;
+
+destructor TSDOTypeAsbtract.Destroy;
+begin
+  FreeAndNil(FALiasList);
+  inherited;
+end;
+
+function TSDOTypeAsbtract.equals(const AOther: ISDOType): Boolean;
+var
+  i, c : PtrInt;
+begin
+  Result := False;
+  if AnsiSameText(Self.getURI(),AOther.getURI()) then begin
+    if AnsiSameText(Self.getName(),AOther.getName()) or
+       ( Self.FALiasList.IndexOf(AOther.getName()) > -1 )
+    then begin
+      Result := True;
+    end else begin
+      c := AOther.getAliasCount();
+      if ( c > 0 ) then begin
+        for i := 0 to Pred(c) do begin
+          if AnsiSameText(FName,AOther.getAlias(i)) then begin
+            Result := True;
+            Break;
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+function TSDOTypeAsbtract.getAlias(const AIndex: PtrInt): string;
+begin
+  if ( AIndex >= 0 ) and ( AIndex < FALiasList.Count ) then
+    Result := FALiasList[AIndex]
+  else
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+end;
+
+function TSDOTypeAsbtract.getAliasCount() : PtrInt;
+begin
+  Result := FALiasList.Count;
+end;
+
+function TSDOTypeAsbtract.getBaseType() : ISDOType;
+begin
+  Result := nil;
+end;
+
+function TSDOTypeAsbtract.getFlags() : TTypeFlags;
+begin
+  Result := FFlags;
+end;
+
+function TSDOTypeAsbtract.getName() : string;
+begin
+  Result := FName;
+end;
+
+function TSDOTypeAsbtract.getOwner() : ISDODataFactory;
+begin
+  Result := ISDODataFactory(FOwner);
+end;
+
+function TSDOTypeAsbtract.getURI() : string;
+begin
+  Result := FURI;
+end;
+
+function TSDOTypeAsbtract.inherits(const AType: ISDOType): Boolean;
+begin
+  Result := False;
+end;
+
+function TSDOTypeAsbtract.isAbstractType() : Boolean;
+begin
+  Result := ( tfIsAbstract in FFlags );
+end;
+
+function TSDOTypeAsbtract.isDataType() : Boolean;
+begin
+  Result := ( tfIsDataType in FFlags );
+end;
+
+function TSDOTypeAsbtract.isOpenType() : Boolean;
+begin
+  Result := ( tfIsOpen in FFlags );
+end;
+
+function TSDOTypeAsbtract.isSequencedType() : Boolean;
+begin
+  Result := ( tfIsSequenced in FFlags );
+end;
+
+function TSDOTypeAsbtract.isUsed() : Boolean;
+begin
+  Result := FUsed;
+end;
+
+procedure TSDOTypeAsbtract.setAlias(const AAlias: string);
+var
+  i : Integer;
+begin
+  CheckNotUsed('AAlias');
+  for i := 0 to FALiasList.Count - 1 do begin
+    if (FALiasList[i] = AAlias) then
+      Exit;
+  end;
+  FALiasList.Add(AAlias);
+end;
+
+procedure TSDOTypeAsbtract.setBaseType(const ABaseType: ISDOType);
+begin
+  CheckNotUsed('setBaseType');
+end;
+
+procedure TSDOTypeAsbtract.setUsedFlag(const AUsed: Boolean);
+begin
+  FUsed := AUsed;
+end;
+
+{ TSDOSimpleType }
+
+constructor TSDOSimpleType.Create(const AOwner: ISDODataFactory; const AName, AURI: string);
+begin
+  inherited Create(AOwner, AName, AURI);
+  Include(FFlags, tfIsDataType);
+end;
+
+{$WARNINGS OFF}
+function TSDOSimpleType.getProperties() : ISDOPropertyList;
+begin
+  raise ESDOUnsupportedOperationException.Create('getProperties');
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOSimpleType.getProperty(const APropertyName: string): ISDOProperty;
+begin
+  raise ESDOUnsupportedOperationException.Create('getProperty');
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOSimpleType.getProperty(const APropertyIndex: Integer): ISDOProperty;
+begin
+  raise ESDOUnsupportedOperationException.Create('getProperty');
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOSimpleType.getPropertyIndex(const APropertyName: string): Integer;
+begin
+  raise ESDOUnsupportedOperationException.Create('getPropertyIndex');
+end;
+{$WARNINGS ON}
+
+function TSDOSimpleType.isChangeSummaryType() : Boolean;
+begin
+  Result := False;
+end;
+
+function TSDOSimpleType.isDataObjectType() : Boolean;
+begin
+  Result := False;
+end;
+
+{ TSDOBooleanType }
+
+constructor TSDOBooleanType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Boolean', sdo_namespace);
+end;
+
+function TSDOBooleanType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(Byte);
+end;
+
+function TSDOBooleanType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := BooleanType;
+end;
+
+{ TSDOByteType }
+
+constructor TSDOByteType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Byte',sdo_namespace);
+end;
+
+function TSDOByteType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDOByte);
+end;
+
+function TSDOByteType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := ByteType;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+{ TSDOBytesType }
+
+constructor TSDOBytesType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Bytes',sdo_namespace);
+  setAlias('hexBinary');
+end;
+
+function TSDOBytesType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(PPSDOBytes);
+end;
+
+function TSDOBytesType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := BytesType;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+{ TSDOCharacterType }
+
+constructor TSDOCharacterType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Character',sdo_namespace);
+  setAlias('Char');
+  setAlias('WideChar');
+  setAlias('AnsiChar');
+end;
+
+function TSDOCharacterType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDOChar);
+end;
+
+function TSDOCharacterType.getTypeEnum: TSDOTypeKind;
+begin
+  Result := CharacterType;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+{ TSDOCurrencyType }
+
+constructor TSDOCurrencyType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Currency',sdo_namespace);
+end;
+
+function TSDOCurrencyType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDOCurrency);
+end;
+
+function TSDOCurrencyType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := CurrencyType;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{ TSDODateTimeType }
+
+constructor TSDODateTimeType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'DateTime',sdo_namespace);
+  setAlias('Date');
+end;
+
+function TSDODateTimeType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDODateTime);
+end;
+
+function TSDODateTimeType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := DateTimeType;
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+{ TSDODoubleType }
+
+constructor TSDODoubleType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Double',sdo_namespace);
+end;
+
+function TSDODoubleType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDODouble);
+end;
+
+function TSDODoubleType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := DoubleType;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+{ TSDOFloatType }
+
+constructor TSDOFloatType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Float',sdo_namespace);
+end;
+
+function TSDOFloatType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDOFloat);
+end;
+
+function TSDOFloatType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := FloatType;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{ TSDOIntegerType }
+
+constructor TSDOIntegerType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Integer',sdo_namespace);
+  setAlias('Int');
+end;
+
+function TSDOIntegerType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDOInteger);
+end;
+
+function TSDOIntegerType.getTypeEnum: TSDOTypeKind;
+begin
+  Result := IntegerType;
+end;
+
+{ TSDOStringType }
+
+constructor TSDOStringType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'String',sdo_namespace);
+  setAlias('Strings');
+end;
+
+function TSDOStringType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(PPSDOString);
+end;
+
+function TSDOStringType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := StringType;
+end;
+
+{$IFDEF HAS_SDO_LONG}
+{ TSDOLongType }
+
+constructor TSDOLongType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Long',sdo_namespace);
+end;
+
+function TSDOLongType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDOLong);
+end;
+
+function TSDOLongType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := LongType;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+{ TSDOShortType }
+
+constructor TSDOShortType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, 'Short',sdo_namespace);
+end;
+
+function TSDOShortType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(TSDOShort);
+end;
+
+function TSDOShortType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := ShortType;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+{ TSDOBaseObjectType }
+
+procedure TSDOBaseObjectType.AddProperty(
+  const AName: string;
+  const AType: ISDOType;
+  const AFlags  : TPropertyFlags
+);
+var
+  prpList : ISDOPropertyListEx;
+begin
+  CheckNotUsed('AddProperty');
+  if ( AType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if ( pfIsContainment in AFlags ) and ( not AType.isDataObjectType() ) then
+    raise ESDOIllegalArgumentException.Create('AIsContainment');
+  prpList := getProperties() as ISDOPropertyListEx;
+  if ( prpList.getIndex(AName) > -1 ) then
+    raise ESDOIllegalArgumentException.Create('AName');
+  if ( pfIsMany in AFlags ) and AType.isChangeSummaryType() then
+    raise ESDOIllegalArgumentException.Create('AIsMany');
+  prpList.add(
+    TSDOProperty.Create(AName,AType,AFlags,Self as ISDOType) as ISDOProperty
+  );
+end;
+
+procedure TSDOBaseObjectType.Clear();
+
+  procedure NilPropsBase();
+  var
+    exProps : ISDOPropertyListEx;
+  begin
+    exProps := FProperties as ISDOPropertyListEx;
+    exProps.SetBase(nil)
+  end;
+
+var
+  i, c, j : PtrInt;
+begin
+  setUsedFlag(False);
+  if ( FProperties <> nil ) then begin
+    c := FProperties.getCount();
+    if ( FBaseType <> nil ) then
+      j := FBaseType.getProperties().getCount()
+    else
+      j := 0;
+    if ( c > 0 ) then begin
+      for i := Pred(c) downto j do begin
+        DropProperty(FProperties.getItem(i));
+      end;
+    end;
+    if ( FBaseType <> nil ) then
+      NilPropsBase();
+  end;
+  FBaseType := nil;
+end;
+
+constructor TSDOBaseObjectType.Create(
+  const AOwner : ISDODataFactory;
+  const AName, AURI : string;
+  const ASequenced, AOpened, AAbstract: Boolean
+);
+begin
+  inherited Create(AOwner, AName,AURI);
+  if ASequenced then
+    Include(FFlags, tfIsSequenced);
+  if AOpened then
+    Include(FFlags, tfIsOpen);
+  if AAbstract then
+    Include(FFlags, tfIsAbstract);
+  FProperties := TSDOPropertyList.Create(nil) as ISDOPropertyList;
+end;
+
+destructor TSDOBaseObjectType.Destroy();
+begin
+  Clear();
+  FBaseType := nil;
+  FProperties := nil;
+  inherited;
+end;
+
+procedure TSDOBaseObjectType.DropProperty(const AProperty: ISDOProperty);
+var
+  lsX : ISDOPropertyListEx;
+begin
+  CheckNotUsed('DropProperty');
+  lsX := FProperties as ISDOPropertyListEx;
+  lsX.drop(AProperty);
+end;
+
+function TSDOBaseObjectType.getBaseType() : ISDOType;
+begin
+  Result := FBaseType;
+end;
+
+function TSDOBaseObjectType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(PPSDODataObject);
+end;
+
+function TSDOBaseObjectType.getProperties() : ISDOPropertyList;
+begin
+  Result := FProperties;
+end;
+
+function TSDOBaseObjectType.getProperty(const APropertyName: string): ISDOProperty;
+begin
+  Result := getProperties().find(APropertyName);
+  if ( Result = nil ) then
+    raise ESDOPropertyNotFoundException.Create(APropertyName);
+end;
+
+function TSDOBaseObjectType.getProperty(const APropertyIndex: Integer): ISDOProperty;
+begin
+  Result := getProperties().getItem(APropertyIndex);
+end;
+
+function TSDOBaseObjectType.getPropertyIndex(const APropertyName: string): Integer;
+begin
+  Result := getProperties().getIndex(APropertyName);
+  if ( Result = -1 ) then
+    raise ESDOPropertyNotFoundException.Create(APropertyName);
+end;
+
+function TSDOBaseObjectType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := ObjectType;
+end;
+
+function TSDOBaseObjectType.inherits(const AType: ISDOType): Boolean;
+var
+  locType : ISDOType;
+begin
+  Result := False;
+  if ( AType <> nil ) and AType.isDataObjectType() then begin
+    if AnsiSameText(sdo_namespace,AType.getURI()) and
+       AnsiSameText(SDOTypeDefaultTypeNames[ObjectType],AType.getName())
+    then begin
+      Result := True;
+    end else begin
+      locType := Self as ISDOType;
+      while ( locType <> nil ) do begin
+        if locType.equals(AType) then begin
+          Result := True;
+          break;
+        end;
+        locType := locType.getBaseType();
+      end;
+    end;
+  end;
+end;
+
+function TSDOBaseObjectType.isChangeSummaryType() : Boolean;
+begin
+  Result := False;
+end;
+
+function TSDOBaseObjectType.isDataObjectType() : Boolean;
+begin
+  Result := True;
+end;
+
+function TSDOBaseObjectType.IsOwnerOf(const AProp: ISDOProperty): Boolean;
+begin
+  Result := (AProp <> nil) and
+            ( ( ( AProp.getContainingType() as ISDOType ) = ( Self as ISDOType ) ) or
+              ( (FBaseType <> nil) and FBaseType.IsOwnerOf(AProp) )
+            );
+
+end;
+
+procedure TSDOBaseObjectType.setBaseType(const ABaseType: ISDOType);
+var
+  exProps : ISDOPropertyListEx;
+begin
+  inherited setBaseType(ABaseType);
+  FBaseType := ABaseType as ISDOObjectType;
+  exProps := FProperties as ISDOPropertyListEx;
+  if ( ABaseType = nil ) then
+    exProps.SetBase(nil)
+  else
+    exProps.SetBase(ABaseType.getProperties());
+end;
+
+procedure TSDOBaseObjectType.setUsedFlag(const AUsed: Boolean);
+var
+  i : PtrInt;
+  typ : ISDOTypeEx;
+begin
+  inherited setUsedFlag(AUsed);
+  if AUsed then begin
+    if Assigned(FBaseType) then begin
+      typ := FBaseType as ISDOTypeEx;
+      if not typ.isUsed() then
+        typ.setUsedFlag(True);
+    end;
+
+    for i := 0 to Pred(FProperties.getCount()) do begin
+      typ := FProperties.getItem(i).getType() as ISDOTypeEx;
+      if not typ.isUsed() then
+        typ.setUsedFlag(True);
+    end;
+  end;
+end;
+
+{ TSDOTypeList }
+
+constructor TSDOTypeList.Create();
+begin
+  inherited;
+  FList := TInterfaceList.Create();
+end;
+
+destructor TSDOTypeList.Destroy();
+begin
+  FList := nil;
+  inherited;
+end;
+
+function TSDOTypeList.find(const AUri, AName: string): ISDOType;
+var
+  i : Integer;
+begin
+  i := getIndex(AUri,AName);
+  if ( i > -1  ) then
+    Result := getItem(i)
+  else
+    Result := nil;
+end;
+
+function TSDOTypeList.getCount() : Integer;
+begin
+  Result := FList.Count;
+end;
+
+function TSDOTypeList.getIndex(const AUri, AName: string): Integer;
+var
+  i, j, c : PtrInt;
+  typ : ISDOType;
+begin
+  Result := -1;
+  for i := 0 to Pred(getCount()) do begin
+    typ := getItem(i);
+    if AnsiSameText(AUri,typ.getURI()) and
+       AnsiSameText(AName,typ.getName())
+    then begin
+      Result := i;
+      Break;
+    end;
+    c := typ.getAliasCount();
+    if ( c > 0 ) then begin
+      for j := 0 to Pred(c) do begin
+        if AnsiSameText(AUri,typ.getURI()) and
+           AnsiSameText(AName,typ.getAlias(j))
+        then begin
+          Result := i;
+          Break;
+        end;
+      end;
+    end;
+  end;
+end;
+
+function TSDOTypeList.getItem(const AIndex: Integer) : ISDOType;
+begin
+  if ( AIndex >= 0 ) and ( AIndex < FList.Count ) then begin
+    Result := FList[AIndex] as ISDOType;
+  end else begin
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+  end;
+end;
+
+procedure TSDOTypeList.insert(const AType : ISDOType);
+begin
+  if ( AType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if ( find(AType.getURI(),AType.getName()) = nil ) then begin
+    FList.Add(AType);
+  end;
+end;
+
+
+
+{ TSDONativeSimpleType }
+
+procedure TSDONativeSimpleType.setBaseType(const ABaseType: ISDOType);
+begin
+  raise ESDOUnsupportedOperationException.Create('SetBaseType');
+end;
+
+{ TSDOUserDefinedSimpleType }
+
+constructor TSDOUserDefinedSimpleType.Create(
+  const AOwner : ISDODataFactory;
+  const AName, AURI: string;
+  const AIsAbstract: Boolean
+);
+begin
+  inherited Create(AOwner, AName, AURI);
+  if AIsAbstract then
+    Include(FFlags, tfIsAbstract);
+end;
+
+function TSDOUserDefinedSimpleType.getBaseType() : ISDOType;
+begin
+  Result := FBaseType;
+end;
+
+function TSDOUserDefinedSimpleType.getFieldSize() : PtrUInt;
+var
+  fb : ISDOType;
+  fbX : ISDOTypeEx;
+begin
+  fb := getBaseType();
+  if ( fb = nil ) then
+    raise ESDOIncompleteTypeException.Create(Self.ClassName());
+  fbX := fb as ISDOTypeEx;
+  Result := fbX.getFieldSize();
+end;
+
+function TSDOUserDefinedSimpleType.getTypeEnum() : TSDOTypeKind;
+var
+  fb : ISDOType;
+begin
+  fb := getBaseType();
+  if ( fb = nil ) then
+    raise ESDOIncompleteTypeException.Create(Self.ClassName());
+  Result := fb.getTypeEnum();
+end;
+
+procedure TSDOUserDefinedSimpleType.setBaseType(const ABaseType: ISDOType);
+begin
+  inherited setBaseType(ABaseType);
+  if ( ABaseType <> nil ) then begin
+    if not (
+         ABaseType.isDataType() or
+         ( ABaseType = ( Self as ISDOType ) )
+       )
+    then begin
+      raise ESDOIllegalArgumentException.Create(ABaseType.getName());
+    end;
+  end;
+  FBaseType := ABaseType;
+end;
+
+{ TSDOChangeSummaryType }
+
+constructor TSDOChangeSummaryType.Create(const AOwner : ISDODataFactory);
+begin
+  inherited Create(AOwner, SDOTypeDefaultTypeNames[ChangeSummaryType],sdo_namespace);
+  Include(FFlags, tfIsDataType);
+end;
+
+function TSDOChangeSummaryType.getFieldSize() : PtrUInt;
+begin
+  Result := VALUE_STATUS_LENGTH + SizeOf(PPSDOChangeSummary);
+end;
+
+{$WARNINGS OFF}
+function TSDOChangeSummaryType.getProperties() : ISDOPropertyList;
+begin
+  raise ESDOUnsupportedOperationException.Create('getProperties');
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOChangeSummaryType.getProperty(const APropertyName: string): ISDOProperty;
+begin
+  raise ESDOUnsupportedOperationException.Create('getProperty');
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOChangeSummaryType.getProperty(const APropertyIndex: Integer): ISDOProperty;
+begin
+  raise ESDOUnsupportedOperationException.Create('getProperty');
+end;
+{$WARNINGS ON}
+
+{$WARNINGS OFF}
+function TSDOChangeSummaryType.getPropertyIndex(const APropertyName: string): Integer;
+begin
+  raise ESDOUnsupportedOperationException.Create('getPropertyIndex');
+end;
+{$WARNINGS ON}
+
+function TSDOChangeSummaryType.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := ChangeSummaryType;
+end;
+
+function TSDOChangeSummaryType.isChangeSummaryType() : Boolean;
+begin
+  Result := True;
+end;
+
+function TSDOChangeSummaryType.isDataObjectType() : Boolean;
+begin
+  Result := False;
+end;
+
+{$WARNINGS OFF}
+procedure TSDOChangeSummaryType.setBaseType(const ABaseType: ISDOType);
+begin
+  raise ESDOUnsupportedOperationException.Create('setBaseType');
+end;
+{$WARNINGS ON}
+
+{ TSDOPropertyAsbtract }
+
+procedure TSDOPropertyAsbtract.CheckIfContainingTypeIsUsed(const AOperation : string);
+var
+  tX : ISDOTypeEx;
+begin
+  if ( FContainingType <> nil ) then begin
+    tX := ISDOType(FContainingType) as ISDOTypeEx;
+    if tX.isUsed() then
+      raise ESDOUnsupportedOperationException.Create(AOperation);
+  end;
+end;
+
+procedure TSDOPropertyAsbtract.ClearType();
+begin
+  FreeDefaultBuffer();
+  if FWeakReferenceToType then
+    FType := nil
+  else
+    ISDOType(FType) := nil;
+end;
+
+constructor TSDOPropertyAsbtract.Create(
+  const AName  : string;
+  const AType  : ISDOType;
+  const AFlags  : TPropertyFlags;
+  const AContainingType : ISDOType
+);
+var
+  locName : string;
+begin
+  locName := Trim(AName);
+  if not IsValidName(locName) then
+    raise ESDOIllegalArgumentException.Create('AName');
+  if ( AContainingType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AContainingType');
+  if ( AType = nil ) then
+    raise ESDOIllegalArgumentException.Create('AType');
+  if ( pfIsContainment in AFlags ) and ( not AType.isDataObjectType() ) then
+    raise ESDOIllegalArgumentException.Create('AContainingType');
+  FName := AName;
+  FALiasList := TStringList.Create();
+  FWeakReferenceToType := AType.equals(AContainingType);
+  if FWeakReferenceToType then
+    FType := Pointer(AType)
+  else
+    ISDOType(FType) := AType;
+  FFlags := AFlags;
+  FContainingType := Pointer(AContainingType);
+  FTypeKind := AType.getTypeEnum();
+end;
+
+destructor TSDOPropertyAsbtract.Destroy;
+begin
+  FreeDefaultBuffer();
+  FContainingType := nil;
+  if FWeakReferenceToType then
+    FType := nil
+  else
+    ISDOType(FType) := nil;
+  FreeAndNil(FALiasList);
+  inherited;
+end;
+
+procedure TSDOPropertyAsbtract.FreeDefaultBuffer();
+begin
+  if ( FType <> nil ) then begin
+    case FTypeKind of
+{$IFDEF HAS_SDO_BYTES}
+      BytesType :
+        begin
+          if ( FDefault.BytesValue <> nil ) then begin
+            Dispose(FDefault.BytesValue);
+          end;
+        end;
+{$ENDIF HAS_SDO_BYTES}
+      ObjectType :
+        begin
+          if ( FDefault.ObjectValue <> nil ) then begin
+            Dispose(FDefault.ObjectValue);
+          end;
+        end;
+      StringType :
+        begin
+          if ( FDefault.StringValue <> nil ) then begin
+            Dispose(FDefault.StringValue);
+          end;
+        end;
+    end;
+    FillChar(FDefault,SizeOf(FDefault),#0);
+    FDefaultSet := False;
+  end;
+end;
+
+function TSDOPropertyAsbtract.getAlias(const AIndex: Integer): string;
+begin
+  if ( AIndex >= 0 ) and ( AIndex < FALiasList.Count ) then
+    Result := FALiasList[AIndex]
+  else
+    raise ESDOException.CreateFmt('Invalid alias index, Type = %s, Index = %d.',[ClassName,AIndex]);
+end;
+
+function TSDOPropertyAsbtract.getAliasCount() : Integer;
+begin
+  Result := FALiasList.Count;
+end;
+
+function TSDOPropertyAsbtract.getBooleanDefault(): TSDOBoolean;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BooleanType   : Result := FDefault.BooleanValue;
+      ByteType      : Result := TSDOConvertHelper.ByteToBool(FDefault.ByteValue);
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType : Result := TSDOConvertHelper.CharToBool(FDefault.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+      IntegerType   : Result := TSDOConvertHelper.IntegerToBool(FDefault.IntegerValue);
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := TSDOConvertHelper.LongToBool(FDefault.LongValue);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := TSDOConvertHelper.ShortToBool(FDefault.ShortValue);
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToBool(FDefault.StringValue^);
+      else
+        Result := False;
+    end;
+  end else begin
+    Result := False;
+  end;
+end;
+
+function TSDOPropertyAsbtract.getBufferOffset() : PtrUInt;
+begin
+  Result := FBufferOffset;
+end;
+
+function TSDOPropertyAsbtract.getByteDefault(): TSDOByte;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BooleanType   : Result := TSDOConvertHelper.BoolToByte(FDefault.BooleanValue);
+      ByteType      : Result := FDefault.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType : Result := TSDOConvertHelper.CharToByte(FDefault.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+      IntegerType   : Result := FDefault.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := FDefault.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := FDefault.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToByte(FDefault.StringValue^);
+      else
+        Result := 0;
+    end;
+  end else begin
+    Result := 0;
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+function TSDOPropertyAsbtract.getBytesDefault() : TSDOBytes;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BytesType       : Result := FDefault.BytesValue^;
+      StringType      : Result := TSDOConvertHelper.StringToBytes(FDefault.StringValue^);
+    end;
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+function TSDOPropertyAsbtract.getCharacterDefault() : TSDOChar;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BooleanType   : Result := TSDOConvertHelper.BoolToChar(FDefault.BooleanValue);
+      ByteType      : Result := TSDOConvertHelper.ByteToChar(FDefault.ByteValue);
+      CharacterType : Result := FDefault.CharValue;
+      IntegerType   : Result := TSDOConvertHelper.IntegerToChar(FDefault.IntegerValue);
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := TSDOConvertHelper.LongToChar(FDefault.LongValue);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := TSDOConvertHelper.ShortToChar(FDefault.ShortValue);
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToChar(FDefault.StringValue^);
+      else
+        Result := #0;
+    end;
+  end else begin
+    Result := #0;
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY }
+function TSDOPropertyAsbtract.getCurrencyDefault() : TSDOCurrency;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      ByteType      : Result := FDefault.ByteValue;
+      CurrencyType  : Result := FDefault.CurrencyValue;
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType    : Result := FDefault.DoubleValue;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT }
+      FloatType     : Result := FDefault.FloatValue;
+{$ENDIF HAS_SDO_FLOAT }
+      IntegerType   : Result := FDefault.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := FDefault.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := FDefault.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToFloat(FDefault.StringValue^);
+      else
+        Result := 0;
+    end;
+  end else begin
+    Result := 0;
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY }
+
+function TSDOPropertyAsbtract.getContainingType() : ISDOType;
+begin
+  Result := ISDOType(FContainingType);
+end;
+
+function TSDOPropertyAsbtract.getDateDefault() : TSDODate;
+begin
+  if FDefaultSet and ( getTypeEnum() = DateTimeType ) then
+    Result := FDefault.DateValue
+  else
+    Result := ZERO_DATE;
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+function TSDOPropertyAsbtract.getDoubleDefault() : TSDODouble;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      ByteType      : Result := FDefault.ByteValue;
+{$IFDEF HAS_SDO_CURRENCY }
+      CurrencyType  : Result := FDefault.CurrencyValue;
+{$ENDIF HAS_SDO_CURRENCY }
+      DoubleType    : Result := FDefault.DoubleValue;
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType     : Result := FDefault.FloatValue;
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType   : Result := FDefault.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := FDefault.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := FDefault.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToFloat(FDefault.StringValue^);
+      else
+        Result := 0;
+    end;
+  end else begin
+    Result := 0;
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+function TSDOPropertyAsbtract.getFloatDefault() : TSDOFloat;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      ByteType      : Result := FDefault.ByteValue;
+{$IFDEF HAS_SDO_CURRENCY }
+      CurrencyType  : Result := FDefault.CurrencyValue;
+{$ENDIF HAS_SDO_CURRENCY }
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType    : Result := FDefault.DoubleValue;
+{$ENDIF HAS_SDO_DOUBLE}
+      FloatType     : Result := FDefault.FloatValue;
+      IntegerType   : Result := FDefault.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := FDefault.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := FDefault.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToFloat(FDefault.StringValue^);
+      else
+        Result := 0;
+    end;
+  end else begin
+    Result := 0;
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+function TSDOPropertyAsbtract.getIntegerDefault() : TSDOInteger;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BooleanType   : Result := TSDOConvertHelper.BoolToInteger(FDefault.BooleanValue);
+      ByteType      : Result := FDefault.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType : Result := TSDOConvertHelper.CharToInteger(FDefault.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+      IntegerType   : Result := FDefault.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := FDefault.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := FDefault.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToInteger(FDefault.StringValue^);
+      else
+        Result := 0;
+    end;
+  end else begin
+    Result := 0;
+  end;
+end;
+
+function TSDOPropertyAsbtract.getLongDefault() : TSDOLong;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BooleanType   : Result := TSDOConvertHelper.BoolToLong(FDefault.BooleanValue);
+      ByteType      : Result := FDefault.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType : Result := TSDOConvertHelper.CharToLong(FDefault.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+      IntegerType   : Result := FDefault.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := FDefault.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := FDefault.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToLong(FDefault.StringValue^);
+      else
+        Result := 0;
+    end;
+  end else begin
+    Result := 0;
+  end;
+end;
+
+function TSDOPropertyAsbtract.getName() : string;
+begin
+  Result := FName;
+end;
+
+function TSDOPropertyAsbtract.getOpposite() : ISDOProperty;
+begin
+  Result := nil;
+end;
+
+function TSDOPropertyAsbtract.getShortDefault() : TSDOShort;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BooleanType   : Result := TSDOConvertHelper.BoolToShort(FDefault.BooleanValue);
+      ByteType      : Result := FDefault.ByteValue;
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType : Result := TSDOConvertHelper.CharToShort(FDefault.CharValue);
+{$ENDIF HAS_SDO_CHAR}
+      IntegerType   : Result := FDefault.IntegerValue;
+{$IFDEF HAS_SDO_LONG}
+      LongType      : Result := FDefault.LongValue;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : Result := FDefault.ShortValue;
+{$ENDIF HAS_SDO_SHORT}
+      StringType    : Result := TSDOConvertHelper.StringToShort(FDefault.StringValue^);
+      else
+        Result := 0;
+    end;
+  end else begin
+    Result := 0;
+  end;
+end;
+
+function TSDOPropertyAsbtract.getStringDefault() : TSDOString;
+begin
+  if FDefaultSet then begin
+    case getTypeEnum() of
+      BooleanType     : Result := TSDOConvertHelper.BoolToString(FDefault.BooleanValue);
+      ByteType        : Result := TSDOConvertHelper.ByteToString(FDefault.ByteValue);
+{$IFDEF HAS_SDO_BYTES}
+      BytesType       : Result := TSDOConvertHelper.BytesToString(FDefault.BytesValue^);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType   : Result := FDefault.CharValue;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType      : Result := TSDOConvertHelper.FloatToString(FDefault.DoubleValue);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType       : Result := TSDOConvertHelper.FloatToString(FDefault.FloatValue);
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType     : Result := TSDOConvertHelper.IntegerToString(FDefault.IntegerValue);
+{$IFDEF HAS_SDO_LONG}
+      LongType        : Result := TSDOConvertHelper.LongToString(FDefault.LongValue);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType       : Result := TSDOConvertHelper.ShortToString(FDefault.ShortValue);
+{$ENDIF HAS_SDO_SHORT}
+      StringType      : Result := FDefault.StringValue^;
+    end;
+  end;
+end;
+
+function TSDOPropertyAsbtract.getType() : ISDOType;
+begin
+  Result := ISDOType(FType);
+end;
+
+function TSDOPropertyAsbtract.getTypeEnum() : TSDOTypeKind;
+begin
+  Result := getType().getTypeEnum();
+end;
+
+procedure TSDOPropertyAsbtract.InternalSetBufferOffset(const AOffset: PtrUInt);
+begin
+  FBufferOffset := AOffset;
+end;
+
+function TSDOPropertyAsbtract.isContainment() : Boolean;
+begin
+  Result := ( pfIsContainment in FFlags );
+end;
+
+function TSDOPropertyAsbtract.isDefaulted() : Boolean;
+begin
+  Result := FDefaultSet;
+end;
+
+function TSDOPropertyAsbtract.isMany() : Boolean;
+begin
+  Result := ( pfIsMany in FFlags );;
+end;
+
+function TSDOPropertyAsbtract.isNullable() : Boolean;
+begin
+  Result := not ( pfIsNotNullable in FFlags );
+end;
+
+function TSDOPropertyAsbtract.isReadOnly() : Boolean;
+begin
+  Result := ( pfIsReadOnly in FFlags );
+end;
+
+function TSDOPropertyAsbtract.isReference() : Boolean;
+begin
+  Result := ( not isContainment() ) and ( getType().isDataObjectType() );
+end;
+
+procedure TSDOPropertyAsbtract.setAlias(const AAlias: string);
+begin
+  if ( FALiasList.IndexOf(AAlias) = -1 ) then
+    FALiasList.Add(AAlias);
+end;
+
+function TSDOPropertyAsbtract.setBufferOffset(const AStartingAddress: PtrUInt): PtrUInt;
+var
+  typ : ISDOTypeEx;
+  bufferLen : PtrInt;
+begin
+  Result := AStartingAddress;
+  InternalSetBufferOffset(Result);
+  if isMany() then begin
+    bufferLen := SizeOf(Pointer);
+  end else begin
+    typ := getType() as ISDOTypeEx;
+    bufferLen := typ.getFieldSize();
+  end;
+  Inc(Result,bufferLen);
+end;
+
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOBoolean);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [
+             BooleanType,ByteType
+             {$IFDEF HAS_SDO_CHAR},CharacterType{$ENDIF}
+             {$IFDEF HAS_SDO_LONG},LongType{$ENDIF}
+             {$IFDEF HAS_SDO_SHORT},ShortType{$ENDIF}
+             ,IntegerType,StringType
+          ]
+         )
+  then begin
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  end;
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BooleanType    : FDefault.BooleanValue := AValue;
+    ByteType       : FDefault.ByteValue := TSDOConvertHelper.BoolToByte(AValue);
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType  : FDefault.CharValue := TSDOConvertHelper.BoolToChar(AValue);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_LONG}
+    LongType       : FDefault.LongValue := TSDOConvertHelper.BoolToLong(AValue);
+{$ENDIF HAS_SDO_LONG}
+    IntegerType    : FDefault.IntegerValue := TSDOConvertHelper.BoolToInteger(AValue);
+{$IFDEF HAS_SDO_SHORT}
+    ShortType      : FDefault.ShortValue := TSDOConvertHelper.BoolToShort(AValue);
+{$ENDIF HAS_SDO_SHORT}
+    StringType   :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.BoolToString(AValue);
+      end;
+  end;
+end;
+
+{$IFDEF HAS_SDO_CURRENCY }
+procedure TSDOPropertyAsbtract.setDefaultCurrency(const AValue: TSDOCurrency);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [DoubleType,FloatType,CurrencyType,StringType] ) then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    CurrencyType  : FDefault.CurrencyValue := AValue;
+{$IFDEF HAS_SDO_DOUBLE }
+    DoubleType    : FDefault.DoubleValue := AValue;
+{$ENDIF HAS_SDO_DOUBLE }
+{$IFDEF HAS_SDO_FLOAT }
+    FloatType     : FDefault.FloatValue := AValue;
+{$ENDIF HAS_SDO_FLOAT }
+    StringType   :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.FloatToString(AValue);
+      end;
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY }
+
+{$IFDEF HAS_SDO_DOUBLE }
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDODouble);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [DoubleType,FloatType,CurrencyType,StringType] ) then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+{$IFDEF HAS_SDO_CURRENCY }
+    CurrencyType  : FDefault.CurrencyValue := AValue;
+{$ENDIF HAS_SDO_CURRENCY }
+    DoubleType    : FDefault.DoubleValue := AValue;
+{$IFDEF HAS_SDO_FLOAT }
+    FloatType     : FDefault.FloatValue := AValue;
+{$ENDIF HAS_SDO_FLOAT }
+    StringType   :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.FloatToString(AValue);
+      end;
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE }
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOFloat);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [DoubleType,FloatType,CurrencyType,StringType] ) then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+{$IFDEF HAS_SDO_CURRENCY }
+    CurrencyType  : FDefault.CurrencyValue := AValue;
+{$ENDIF HAS_SDO_CURRENCY }
+{$IFDEF HAS_SDO_FLOAT}
+    DoubleType    : FDefault.DoubleValue := AValue;
+{$ENDIF HAS_SDO_FLOAT}
+    FloatType     : FDefault.FloatValue := AValue;
+    StringType   :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.FloatToString(AValue);
+      end;
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOInteger);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [BooleanType,ByteType,IntegerType,StringType] ) then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BooleanType  : FDefault.BooleanValue := ( AValue <> 0 );
+    ByteType     : FDefault.ByteValue := AValue;
+    IntegerType  : FDefault.IntegerValue := AValue;
+    StringType   :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := IntToStr(AValue);
+      end;
+  end;
+end;
+
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOString);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BooleanType    : FDefault.BooleanValue := TSDOConvertHelper.StringToBool(AValue);
+    ByteType       : FDefault.ByteValue := TSDOConvertHelper.StringToByte(AValue);
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType  : FDefault.CharValue := TSDOConvertHelper.StringToChar(AValue);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_LONG}
+    LongType       : FDefault.LongValue := TSDOConvertHelper.StringToLong(AValue);
+{$ENDIF HAS_SDO_LONG}
+    DateTimeType   : FDefault.DateValue := TSDOConvertHelper.StringToDate(AValue);
+    IntegerType    : FDefault.IntegerValue := TSDOConvertHelper.StringToInteger(AValue);
+{$IFDEF HAS_SDO_SHORT}
+    ShortType      : FDefault.ShortValue := TSDOConvertHelper.StringToShort(AValue);
+{$ENDIF HAS_SDO_SHORT}
+    StringType     :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := AValue;
+      end;
+  end;
+end;
+
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOByte);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [
+             BooleanType,ByteType
+             {$IFDEF HAS_SDO_CHAR},CharacterType{$ENDIF}
+             {$IFDEF HAS_SDO_LONG},LongType{$ENDIF}
+             {$IFDEF HAS_SDO_SHORT},ShortType{$ENDIF}
+             ,IntegerType,StringType
+          ]
+         )
+  then begin
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  end;
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BooleanType    : FDefault.BooleanValue := TSDOConvertHelper.ByteToBool(AValue);
+    ByteType       : FDefault.ByteValue := AValue;
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType  : FDefault.CharValue := TSDOConvertHelper.ByteToChar(AValue);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_LONG}
+    LongType       : FDefault.LongValue := AValue;
+{$ENDIF HAS_SDO_LONG}
+    IntegerType    : FDefault.IntegerValue := AValue;
+{$IFDEF HAS_SDO_SHORT}
+    ShortType      : FDefault.ShortValue := AValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType     :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.ByteToString(AValue);
+      end;
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOPropertyAsbtract.setDefault(AValue: TSDOBytes);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [BytesType,StringType] ) then begin
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  end;
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BytesType     :
+      begin
+        New(FDefault.BytesValue);
+        FDefault.BytesValue^ := Copy(AValue);
+      end;
+    StringType     :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.BytesToString(AValue);
+      end;
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOChar);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [
+             BooleanType,ByteType
+             {$IFDEF HAS_SDO_CHAR},CharacterType{$ENDIF}
+             {$IFDEF HAS_SDO_LONG},LongType{$ENDIF}
+             {$IFDEF HAS_SDO_SHORT},ShortType{$ENDIF}
+             ,IntegerType,StringType
+          ]
+         )
+  then begin
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  end;
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BooleanType    : FDefault.BooleanValue := TSDOConvertHelper.CharToBool(AValue);
+    ByteType       : FDefault.ByteValue := TSDOConvertHelper.CharToByte(AValue);
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType  : FDefault.CharValue := AValue;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_LONG}
+    LongType       : FDefault.LongValue := TSDOConvertHelper.CharToLong(AValue);
+{$ENDIF HAS_SDO_LONG}
+    IntegerType    : FDefault.IntegerValue := TSDOConvertHelper.CharToInteger(AValue);
+{$IFDEF HAS_SDO_SHORT}
+    ShortType      : FDefault.ShortValue := TSDOConvertHelper.CharToShort(AValue);
+{$ENDIF HAS_SDO_SHORT}
+    StringType     :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := AValue;
+      end;
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOLong);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [
+             BooleanType,ByteType
+             {$IFDEF HAS_SDO_CHAR},CharacterType{$ENDIF}
+             {$IFDEF HAS_SDO_LONG},LongType{$ENDIF}
+             {$IFDEF HAS_SDO_SHORT},ShortType{$ENDIF}
+             ,IntegerType,StringType
+          ]
+         )
+  then begin
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  end;
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BooleanType    : FDefault.BooleanValue := TSDOConvertHelper.LongToBool(AValue);
+    ByteType       : FDefault.ByteValue := AValue;
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType  : FDefault.CharValue := TSDOConvertHelper.LongToChar(AValue);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_LONG}
+    LongType       : FDefault.LongValue := AValue;
+{$ENDIF HAS_SDO_LONG}
+    IntegerType    : FDefault.IntegerValue := AValue;
+{$IFDEF HAS_SDO_SHORT}
+    ShortType      : FDefault.ShortValue := AValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType     :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.LongToString(AValue);
+      end;
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDOShort);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [
+             BooleanType,ByteType
+             {$IFDEF HAS_SDO_CHAR},CharacterType{$ENDIF}
+             {$IFDEF HAS_SDO_LONG},LongType{$ENDIF}
+             {$IFDEF HAS_SDO_SHORT},ShortType{$ENDIF}
+             ,IntegerType,StringType
+          ]
+         )
+  then begin
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  end;
+
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    BooleanType    : FDefault.BooleanValue := TSDOConvertHelper.ShortToBool(AValue);
+    ByteType       : FDefault.ByteValue := AValue;
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType  : FDefault.CharValue := TSDOConvertHelper.ShortToChar(AValue);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_LONG}
+    LongType       : FDefault.LongValue := AValue;
+{$ENDIF HAS_SDO_LONG}
+    IntegerType    : FDefault.IntegerValue := AValue;
+{$IFDEF HAS_SDO_SHORT}
+    ShortType      : FDefault.ShortValue := AValue;
+{$ENDIF HAS_SDO_SHORT}
+    StringType     :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.ShortToString(AValue);
+      end;
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOPropertyAsbtract.setDefault(const AValue: TSDODate);
+begin
+  if getType().isDataObjectType or getType().isChangeSummaryType() then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  CheckIfContainingTypeIsUsed('setDefault');
+  if not ( getTypeEnum() in [DateTimeType,StringType] ) then
+    raise ESDOUnsupportedOperationException.Create('setDefault');
+  FreeDefaultBuffer();
+  FDefaultSet := True;
+  case getTypeEnum() of
+    DateTimeType : FDefault.DateValue := AValue;
+    StringType   :
+      begin
+        New(FDefault.StringValue);
+        FDefault.StringValue^ := TSDOConvertHelper.DateToString(AValue);
+      end;
+  end;
+end;
+
+function TSDOPropertyAsbtract.isAttribute() : Boolean;
+begin
+  Result := (pfIsAttribute in FFlags);
+end;
+
+{ TSDOPropertyList }
+
+constructor TSDOPropertyList.Create(const ABaseList : ISDOPropertyList);
+begin
+  FList := TInterfaceList.Create();
+  FBaseList := ABaseList;
+end;
+
+destructor TSDOPropertyList.Destroy();
+begin
+  FBaseList := nil;
+  FList := nil;
+  inherited;
+end;
+
+procedure TSDOPropertyList.drop(const AProperty: ISDOProperty);
+var
+  locProp : ISDOProperty;
+  //locPropX : ISDOPropertyEx;
+begin
+  if ( AProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  locProp := AProperty as ISDOProperty;
+  if ( FList.Remove(AProperty) < 0 ) then
+    raise ESDOPropertyNotFoundException.Create(AProperty.getName());
+  //locPropX := locProp as ISDOPropertyEx;
+  //locPropX.ClearType();
+end;
+
+function TSDOPropertyList.find(const AName: string): ISDOProperty;
+var
+  i : Integer;
+begin
+  i := getIndex(AName);
+  if ( i >= 0 ) then
+    Result := GetItem(i)
+  else
+    Result := nil;
+end;
+
+function TSDOPropertyList.getCount() : Integer;
+begin
+  Result := FList.Count;
+  if ( FBaseList <> nil ) then
+    Inc(Result,FBaseList.getCount());
+end;
+
+function TSDOPropertyList.getIndex(const APropertyName: string): Integer;
+var
+  i : Integer;
+  prp : ISDOProperty;
+begin
+  if ( FBaseList <> nil ) then
+    Result := FBaseList.getIndex(APropertyName)
+  else
+    Result := -1;
+  if ( Result = -1 ) then begin
+    for i := 0 to Pred(FList.Count) do begin
+      prp := FList[i] as ISDOProperty;
+      if AnsiSameText(APropertyName,prp.getName()) then begin
+        Result := i;
+        if ( FBaseList <> nil ) then
+          Inc(Result,FBaseList.getCount());
+        Break;
+      end;
+    end;
+  end;
+end;
+
+function TSDOPropertyList.getItem(const AIndex: Integer): ISDOProperty;
+begin
+  if ( AIndex >= 0 ) and ( AIndex < getCount() ) then begin
+    if ( FBaseList <> nil ) then begin
+      if ( AIndex < FBaseList.getCount() ) then
+        Result := FBaseList.getItem(AIndex)
+      else
+        Result := FList[AIndex - FBaseList.getCount()] as ISDOProperty;
+    end else begin
+      Result := FList[AIndex] as ISDOProperty;
+    end;
+  end else begin
+    raise ESDOIndexOutOfRangeException.Create(AIndex);
+  end;
+end;
+
+procedure TSDOPropertyList.add(const AProperty: ISDOProperty);
+var
+  locProp : ISDOProperty;
+begin
+  if ( AProperty = nil ) then
+    raise ESDOIllegalArgumentException.Create('AProperty');
+  if ( find(AProperty.getName()) = nil ) then begin
+    locProp := AProperty as ISDOProperty;
+    FList.Add(locProp);
+  end;
+end;
+
+function TSDOPropertyList.SetBase(const ABaseList: ISDOPropertyList): ISDOPropertyList;
+begin
+  Result := FBaseList;
+  FBaseList := ABaseList;
+end;
+
+end.

+ 58 - 0
packages/fcl-sdo/src/base/sdo_types.pas

@@ -0,0 +1,58 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements basic platform independent types
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_types;
+
+interface
+uses
+  Types;
+
+{$IFDEF DELPHI}
+  type
+    QWord = type Int64;
+    DWORD = LongWord;
+    PtrInt = Integer;
+    PtrUInt = Cardinal;
+    SizeInt = Longint;
+    PPtrInt  = ^PtrInt;
+{$ENDIF}
+
+
+{$IF NOT Defined(PPtrUInt)}
+type
+  PPtrUInt = ^PtrUInt;
+{$IFEND}
+
+{$IFDEF FPC}
+type
+  TStringBufferType = AnsiString;
+{$ENDIF}
+
+{$IFDEF DELPHI}
+  {$IFDEF HAS_UNICODE}
+    UnicodeChar = WideChar;
+    TStringBufferType = RawByteString;
+  {$ELSE HAS_UNICODE}
+    TStringBufferType = AnsiString;
+  {$ENDIF HAS_UNICODE}
+{$ENDIF}
+  TBinaryString = TStringBufferType;
+
+  TByteDynArray = Types.TByteDynArray;
+  
+implementation
+
+end.

+ 315 - 0
packages/fcl-sdo/src/base/sdo_utils.pas

@@ -0,0 +1,315 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements some SDO utilities
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_utils;
+
+interface
+uses
+  sdo, sdo_types;
+
+type
+  TListValueExtractProc = procedure (const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+  function getExtractor(const AType : TSDOTypeKind) : TListValueExtractProc ; {$IFDEF USE_INLINE}inline;{$ENDIF}
+
+  function getRoot(const ADataObject : ISDODataObject) : ISDODataObject;
+  function xpath_ExcludeRootElement(const APath, ARootName : string) : string;
+
+  procedure ClearList(const AList : ISDODataObjectList);
+  function indexOf(
+    const ADataObject :ISDODataObject;
+    const AList : ISDODataObjectList;
+    out APos : ISDOCursorBookmark
+  ) : Boolean; overload;
+  function indexOf(
+    const ADataObject :ISDODataObject;
+    const AList : ISDODataObjectList
+  ) : PtrInt; overload;
+  function indexOf(
+    const ADataObject :ISDODataObject;
+    const AList : ISDOChangedDataObjectList
+  ) : PtrInt; overload;
+
+  function InheritsFrom(const AChild, AParent : ISDOType) : Boolean;
+
+implementation
+uses
+  SysUtils;
+
+function InheritsFrom(const AChild, AParent : ISDOType) : Boolean;
+var
+  locType : ISDOType;
+begin
+  Result := False;
+  if (AParent = nil) then
+    Exit;
+
+  locType := AChild;
+  while (locType <> nil) do begin
+    if locType.equals(AParent) then begin
+      Result := True;
+      Break;
+    end;
+    locType := locType.getBaseType();
+  end;
+end;
+
+function getRoot(const ADataObject : ISDODataObject) : ISDODataObject;
+var
+  p, q : ISDODataObject;
+begin
+  if ( ADataObject <> nil ) then begin
+    p := ADataObject;
+    repeat
+      q := p;
+      p := p.getContainer();
+    until ( p = nil );
+  end else begin
+    q := nil;
+  end;
+  Result := q;
+end;
+
+function xpath_ExcludeRootElement(const APath, ARootName : string) : string;
+var
+  i : PtrInt;
+begin
+  Result := TrimLeft(APath);
+  if ( Length(Result) > 0 ) then begin
+    if ( Result[1] = '#' ) then
+      Delete(Result,1,1);
+    if ( Length(Result) > 0 ) then begin
+      if ( Result[1] = '/' ) then
+        Delete(Result,1,1);
+      i := Pos(ARootName,Result);
+      if ( i = 1 ) then begin
+        if ( Length(Result) > Length(ARootName) ) then begin
+          if ( Result[Length(ARootName) + 1] = '/' ) then
+            Delete(Result,1,Length(ARootName) + 1);
+        end else begin
+          Result := '';
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure ClearList(const AList : ISDODataObjectList);
+var
+  crs : ISDOCursor;
+begin
+  if Assigned(AList) then begin
+    crs := AList.getCursor();
+    crs.Reset();
+    while crs.MoveFirst() do begin
+      AList.delete();
+    end;
+  end;
+end;
+
+function indexOf(
+  const ADataObject :ISDODataObject;
+  const AList : ISDODataObjectList;
+  out APos : ISDOCursorBookmark
+) : Boolean;
+var
+  bm : ISDOCursorBookmark;
+  crs : ISDOCursor;
+begin
+  APos := nil;
+  Result := False;
+  crs := AList.getCursor();
+  bm := crs.GetBookmark();
+  try
+    crs.Reset();
+    while crs.MoveNext() do begin
+      if ( ADataObject = AList.getDataObject() ) then begin
+        APos := crs.GetBookmark();
+        Result := True;
+        Break;
+      end;
+    end;
+  finally
+    crs.GotoBookmark(bm);
+  end;
+end;
+
+function indexOf(
+  const ADataObject :ISDODataObject;
+  const AList : ISDODataObjectList
+) : PtrInt;
+var
+  bm : ISDOCursorBookmark;
+  crs : ISDOCursor;
+begin
+  Result := -1;
+  crs := AList.getCursor();
+  bm := crs.GetBookmark();
+  try
+    crs.Reset();
+    while crs.MoveNext() do begin
+      if ( ADataObject = AList.getDataObject() ) then begin
+        Result := crs.GetPosition();
+        Break;
+      end;
+    end;
+  finally
+    crs.GotoBookmark(bm);
+  end;
+end;
+
+function indexOf(
+  const ADataObject :ISDODataObject;
+  const AList : ISDOChangedDataObjectList
+) : PtrInt;
+var
+  i, c : PtrInt;
+begin
+  Result := -1;
+  c := AList.size();
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      if ( ADataObject = AList.getDataObject(i) ) then begin
+        Result := i;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+// START : List value extractors
+procedure list_extractor_error(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  raise ESDONotImplementedException.Create('list_extractor_error');
+end;
+
+procedure list_extractor_bool(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.BooleanValue := AList.getBoolean();
+end;
+
+procedure list_extractor_byte(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.ByteValue := AList.getByte();
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure list_extractor_bytes(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.BytesValue^ := AList.getBytes();
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure list_extractor_char(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.CharValue := AList.getCharacter();
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure list_extractor_currency(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.CurrencyValue := AList.getCurrency();
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+procedure list_extractor_date(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.DateValue := AList.getDate();
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure list_extractor_double(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.DoubleValue := AList.getDouble();
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure list_extractor_float(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.FloatValue := AList.getFloat();
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure list_extractor_integer(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.IntegerValue := AList.getInteger();
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure list_extractor_long(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.LongValue := AList.getLong();
+end;
+{$ENDIF HAS_SDO_LONG}
+
+procedure list_extractor_object(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.ObjectValue^ := AList.getDataObject();
+end;
+
+{$IFDEF HAS_SDO_SHORT}
+procedure list_extractor_short(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.ShortValue := AList.getShort();
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure list_extractor_string(const AList : ISDODataObjectList; var AValueBuffer : TValueBuffer);
+begin
+  AValueBuffer.StringValue^ := AList.getString();
+end;
+
+var
+  ListValueExtractProcs : array[TSDOTypeKind] of TListValueExtractProc = (
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_bool, // BooleanType,
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_byte, // ByteType,
+{$IFDEF HAS_SDO_BYTES}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_bytes, // BytesType,
+{$ENDIF HAS_SDO_BYTES}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_error, // ChangeSummaryType,
+{$IFDEF HAS_SDO_CHAR}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_char, // CharacterType,
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_currency, // CurrencyType,
+{$ENDIF HAS_SDO_CURRENCY}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_date, // DateTimeType,
+{$IFDEF HAS_SDO_DOUBLE}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_double, // DoubleType,
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_float, // FloatType,
+{$ENDIF HAS_SDO_FLOAT}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_integer , //IntegerType,
+{$IFDEF HAS_SDO_LONG}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_long, // LongType,
+{$ENDIF HAS_SDO_LONG}    
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_object, // ObjectType,
+{$IFDEF HAS_SDO_SHORT}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_short, // ShortType,
+{$ENDIF HAS_SDO_SHORT}
+    {$IFDEF ATT_PROC_ADDRESS}@{$ENDIF}list_extractor_string // StringType,
+  );
+
+function getExtractor(const AType : TSDOTypeKind) : TListValueExtractProc ;
+begin
+  Result := ListValueExtractProcs[AType];
+end;
+
+// END : List value extractors
+end.

+ 1401 - 0
packages/fcl-sdo/src/base/sdo_xpath_helper.pas

@@ -0,0 +1,1401 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements an XPATH helper
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_xpath_helper;
+
+interface
+uses
+  SysUtils, Contnrs,
+  sdo_types, sdo;
+
+type
+
+  EXPathException = class(ESDOException)
+  end;
+
+  TXPathNode = class;
+  TXPathExecContext = class;
+
+  TXPathExpression = class
+  private
+    FRoot: TXPathNode;
+  public
+    destructor Destroy();override;
+    property Root : TXPathNode read FRoot;
+    procedure SetRoot(const ARoot : TXPathNode);
+  end;
+
+  TXPathNode = class
+  private
+    FNext: TXPathNode;
+  public
+    destructor Destroy();override;
+    property Next : TXPathNode read FNext;
+  end;
+
+  TXPathAbstractSymbolNode = class(TXPathNode) end;
+    TXPathLeftSquareBraketNode = class(TXPathAbstractSymbolNode) end;
+    TXPathRigthSquareBraketNode = class(TXPathAbstractSymbolNode) end;
+    TXPathSymbolNode = class(TXPathAbstractSymbolNode) end;
+      TXPathSlashNode = class(TXPathSymbolNode) end;
+
+  TXPathPredicateCode = ( xpcEqual );
+  TXPathPredicateNode = class(TXPathSymbolNode)
+  public
+    class function GetCode() : TXPathPredicateCode;virtual;abstract;
+  end;
+
+  TXPathValueNode = class;
+  TXPathEqualNode = class(TXPathPredicateNode)
+  private
+    FLeft: TXPathValueNode;
+    FRight: TXPathValueNode;
+  public
+    destructor Destroy();override;
+    class function GetCode() : TXPathPredicateCode;override;
+    property Left : TXPathValueNode read FLeft write FLeft;
+    property Right : TXPathValueNode read FRight write FRight;
+  end;
+
+  TXPathValueNode = class(TXPathNode) end;
+  TXPathValueSymbolNode = class(TXPathValueNode)
+  private
+    FSymbol: string;
+  public
+    property Symbol : string read FSymbol write FSymbol;
+  end;
+  TXPathValuePropertySymbolNode = class(TXPathValueSymbolNode)
+  end;
+  TXPathValueFunctionSymbolNode = class(TXPathValueSymbolNode)
+  public
+    //property Arguments
+  end;
+
+  TXPathAtomicDataType = ( xadtString, xadtBoolean, xadtNumber );
+  TXPathValueBuffer = record
+    StringValue : string;
+    case Kind : TXPathAtomicDataType of
+      xadtString  : ();
+      xadtBoolean : ( BoolValue : TSDOBoolean );
+      xadtNumber  : ( NumberValue : Extended );
+  end;
+
+  TXPathTypedValueNode = class(TXPathValueNode)
+  public
+    class function GetDataType() : TXPathAtomicDataType;virtual;abstract;
+    function Evaluate() : TXPathValueBuffer;virtual;abstract;
+  end;
+
+  TXPathStringValueNode = class(TXPathTypedValueNode)
+  public
+    class function GetDataType() : TXPathAtomicDataType;override;
+  end;
+
+  TXPathNumberValueNode = class(TXPathTypedValueNode)
+  public
+    class function GetDataType() : TXPathAtomicDataType;override;
+  end;
+
+  TXPathBooleanValueNode = class(TXPathTypedValueNode)
+  public
+    class function GetDataType() : TXPathAtomicDataType;override;
+  end;
+
+  TXPathStringConstantNode = class(TXPathStringValueNode)
+  private
+    FValue: string;
+  public
+    constructor Create(const AValue : string);
+    function Evaluate() : TXPathValueBuffer;override;
+    property Value : string read FValue write FValue;
+  end;
+
+  TXPathNumberConstantNode = class(TXPathNumberValueNode)
+  private
+    FValue: Extended;
+  public
+    constructor Create(const AValue : Extended);
+    function Evaluate() : TXPathValueBuffer;override;
+    property Value : Extended read FValue write FValue;
+  end;
+
+  TXPathBooleanConstantNode = class(TXPathBooleanValueNode)
+  private
+    FValue: TSDOBoolean;
+  public
+    constructor Create(const AValue : TSDOBoolean);
+    function Evaluate() : TXPathValueBuffer;override;
+    property Value : TSDOBoolean read FValue write FValue;
+  end;
+
+  TXPathInstructionCode = ( xicContextChange, xicMove, xicLocate );
+  TXPathInstructionStepNode = class(TXPathNode)
+  public
+    class function GetCode() : TXPathInstructionCode;virtual;abstract;
+  end;
+
+  TXPathContextSwitch = ( xcsSelf, xcsParent, xcsRoot, xcsProperty );
+  TXPathContextStepNode = class(TXPathInstructionStepNode)
+  private
+    FSwitch: TXPathContextSwitch;
+    FPropertyName: string;
+  public
+    class function GetCode() : TXPathInstructionCode;override;
+    property Switch : TXPathContextSwitch read FSwitch;
+    property PropertyName : string read FPropertyName;
+  end;
+
+  TXPathMoveInstructionStepNode = class(TXPathInstructionStepNode)
+  private
+    FDistance: TXPathTypedValueNode;
+  public
+    class function GetCode() : TXPathInstructionCode;override;
+    destructor Destroy();override;
+    property Distance : TXPathTypedValueNode read FDistance;
+  end;
+
+  TXPathLocateInstructionStepNode = class(TXPathInstructionStepNode)
+  private
+    FCondition: TXPathPredicateNode;
+  public
+    class function GetCode() : TXPathInstructionCode;override;
+    destructor Destroy();override;
+    property Condition : TXPathPredicateNode read FCondition;
+  end;
+
+  TXPathExecContentKind = ( xckNull, xckObject, xckList, xckValue, xckListFiltered );
+  TXPathExecContentKinds = set of TXPathExecContentKind;
+  TXPathExecContext = class
+  private
+    FObjectItem : Pointer; // do not add a reference count
+    FListItem : Pointer; // do not add a reference count
+    FContentKind: TXPathExecContentKind;
+    FCurrentProperty: ISDOProperty;
+    FPropertyOwner: Pointer;
+    FListFiltered : ISDODataObjectList;
+  private
+    procedure CheckKind(const AKind : TXPathExecContentKind);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure CheckKind(const AKinds : TXPathExecContentKinds);overload;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function GetListItem: ISDODataObjectList;
+    function GetObjectItem: ISDODataObject;
+    function GetListFilteredItem : ISDODataObjectList;
+    function GetPropertyOwner: ISDODataObject;
+  public
+    destructor Destroy(); override;
+    property ContentKind : TXPathExecContentKind read FContentKind;
+    property ObjectItem : ISDODataObject read GetObjectItem;
+    property ListItem : ISDODataObjectList read GetListItem;
+    property ListFiltered : ISDODataObjectList read GetListFilteredItem;
+    property CurrentProperty : ISDOProperty read FCurrentProperty;
+    property PropertyOwner : ISDODataObject read GetPropertyOwner;
+    procedure SetObject(const AValue : ISDODataObject; const AProperty : ISDOProperty);
+    procedure SetList(const AValue : ISDODataObjectList; const AProperty : ISDOProperty);
+    procedure SetNull(const AProperty : ISDOProperty);
+    procedure SetValue(const AProperty : ISDOProperty);
+  end;
+
+  TXPathProcessorOption = ( xppoEvaluateSet );
+  TXPathProcessorOptions = set of TXPathProcessorOption;
+  TXPathProcessor = class
+  private
+    FExpression : TXPathExpression;
+    FContext: TXPathExecContext;
+    FCurrentNode : TXPathNode;
+    FOptions: TXPathProcessorOptions;
+  private
+    procedure Clear(const AClearContext : Boolean);
+    procedure WalkTree();
+    procedure WalkNode(const ANode : TXPathInstructionStepNode);
+    function Evaluate(
+      const ATarget : ISDODataObject;
+      const AValueNode : TXPathValueNode
+    ) : TXPathValueBuffer;
+  public
+    constructor Create(const AOptions : TXPathProcessorOptions = []);
+    destructor Destroy();override;
+    function IsTrue(
+      const ATarget : ISDODataObject;
+      const ACondition : TXPathPredicateNode
+    ) : Boolean;
+    property Context : TXPathExecContext read FContext;
+    procedure Execute(AExpression : TXPathExpression);
+
+    property Options : TXPathProcessorOptions read FOptions;
+  end;
+
+  TXPathToken = (
+    xtkEof,
+    xtkNull,
+    xtkTrue,
+    xtkFalse,
+    xtkNumber,
+    xtkString,
+    xtkSymbol,
+    xtkAt,                    // @
+    xtkSlash,                 // "/"
+    xtkPeriod,                // "."
+    xtkDoublePeriod,          // ".."
+    xtkSquaredBraceLeft,      // '['
+    xtkSquaredBraceRigth,     // ']'
+    xtkEqual                  // =
+  );
+  TXPathScanner = class
+  private
+    FBuffer : string;
+    FTokenString : string;
+    FPosition : PtrInt;
+    FToken: TXPathToken;
+    FLength : PtrInt;
+  public
+    constructor Create(const AXPathString : string);
+    function NextToken() : TXPathToken;
+    function TokenInt() : PtrInt;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function TokenNumber() : Extended;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    property Token : TXPathToken read FToken;
+    property TokenString : string read FTokenString;
+    property Position : PtrInt read FPosition;
+  end;
+
+  TXPathParser = class
+  private
+    FScanner : TXPathScanner;
+    FTermStack : TObjectStack;
+    FSymbolStack : TObjectStack;
+    FRootNode : TXPathNode;
+    FXPath : string;
+    FInConditionExpression : PtrInt;
+  private
+    procedure BeginConditionExpression();
+    function IsInConditionExpression() : Boolean;
+    procedure EndConditionExpression();
+    procedure Clear();
+    procedure ReadSymbol();
+    procedure ReadStringConst();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure ReadBooleanConst();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure ReadNumberConst();{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function InternalTryReduction():Boolean;
+    procedure TryReduction();{$IFDEF USE_INLINE}inline;{$ENDIF}
+  public
+    constructor Create(const AXPathString : string);
+    destructor Destroy();override;
+    function Parse() : TXPathNode;
+    property RootNode : TXPathNode read FRootNode;
+  end;
+
+  function ParseXPath(const AString : string) : TXPathNode;
+
+  function getXpath(const ADataObject: ISDODataObject): string;
+  function IndexOf(const AObject : ISDODataObject; const AList : ISDODataObjectList) : PtrInt;
+
+implementation
+
+uses
+  TypInfo;
+
+function ParseXPath(const AString : string) : TXPathNode;
+var
+  locParser : TXPathParser;
+begin
+  locParser := TXPathParser.Create(AString);
+  try
+    Result := locParser.Parse();
+  finally
+    FreeAndNil(locParser);
+  end;
+end;
+
+function IndexOf(const AObject : ISDODataObject; const AList : ISDODataObjectList) : PtrInt;
+var
+  crs : ISDOCursor;
+  oldPos : ISDOCursorBookmark;
+begin
+  crs := AList.getCursor();
+  if crs.IsPosValid() and ( AList.getDataObject() = AObject ) then begin
+    Result := crs.GetPosition();
+  end else begin
+    Result := -1;
+    oldPos := crs.GetBookmark();
+    try
+      crs.Reset();
+      while crs.MoveNext() do begin
+        if ( AList.getDataObject() = AObject ) then begin
+          Result := crs.GetPosition();
+          Break;
+        end;
+      end;
+    finally
+      crs.GotoBookmark(oldPos);
+    end;
+  end;
+end;
+
+function getXpath(const ADataObject: ISDODataObject): string;
+var
+  locBuffer : string;
+  obj : ISDODataObject;
+  prop : ISDOProperty;
+begin
+  if Assigned(ADataObject) then begin
+    locBuffer := '';
+    obj := ADataObject;
+    repeat
+      if ( obj.getContainer() <> nil ) then begin
+        prop := obj.getContainmentProperty();
+        if prop.isMany() then
+          locBuffer := Format(
+                         '%s[%d]/%s',
+                         [prop.getName(),IndexOf(obj,obj.getContainer().getList(prop)),locBuffer]
+                       )
+        else
+          locBuffer := prop.getName() + '/' + locBuffer;
+      end;
+      obj := obj.getContainer();
+    until ( obj = nil );
+  end;
+  if ( Length(locBuffer) > 0 ) and ( locBuffer[Length(locBuffer)] = '/' ) then
+    Delete(locBuffer,Length(locBuffer),1);
+  Result := locBuffer;
+end;
+
+{ TXPathNode }
+
+destructor TXPathNode.Destroy();
+begin
+  FreeAndNil(FNext);
+  inherited;
+end;
+
+{ TXPathExecContext }
+
+procedure TXPathExecContext.CheckKind(const AKind: TXPathExecContentKind);
+const   //xckNull, xckObject, xckList, xckValue, xckListFiltered
+  ACCESS_METHOD_MAP : array[TXPathExecContentKind] of string = ('GetNull','GetObjectItem','GetListItem','GetValue','GetListFilteredItem');
+begin
+  if ( FContentKind <> AKind ) then
+    raise ESDOInvalidStateOperationException.Create('TXPathExecContext.' + ACCESS_METHOD_MAP[AKind]);
+end;
+
+procedure TXPathExecContext.CheckKind(const AKinds: TXPathExecContentKinds);
+begin
+  if not ( FContentKind in AKinds ) then
+    raise ESDOInvalidStateOperationException.Create('TXPathExecContext.');
+end;
+
+destructor TXPathExecContext.Destroy();
+begin
+  FListFiltered := nil;
+  inherited;
+end;
+
+function TXPathExecContext.GetListFilteredItem: ISDODataObjectList;
+begin
+  Result := FListFiltered;
+end;
+
+function TXPathExecContext.GetListItem() : ISDODataObjectList;
+begin
+  Result := ISDODataObjectList(FListItem);
+end;
+
+function TXPathExecContext.GetObjectItem() : ISDODataObject;
+begin
+  Result := ISDODataObject(FObjectItem);
+end;
+
+function TXPathExecContext.GetPropertyOwner() : ISDODataObject;
+begin
+  Result := ISDODataObject(FPropertyOwner);
+end;
+
+procedure TXPathExecContext.SetList(const AValue: ISDODataObjectList; const AProperty : ISDOProperty);
+begin
+  FPropertyOwner := FObjectItem;
+  //FObjectItem := nil;
+  FListItem := Pointer(AValue);
+  FCurrentProperty := AProperty;
+  if ( FListItem <> nil ) then
+    FContentKind := xckList
+  else
+    FContentKind := xckNull;
+end;
+
+procedure TXPathExecContext.SetNull(const AProperty : ISDOProperty);
+begin
+  if ( FContentKind <> xckList ) then
+    FPropertyOwner := FObjectItem;
+  FObjectItem := nil;
+  FListItem := nil;
+  FCurrentProperty := AProperty;
+  FContentKind := xckNull;
+end;
+
+procedure TXPathExecContext.SetObject(const AValue: ISDODataObject; const AProperty : ISDOProperty);
+begin
+  if ( FContentKind = xckList ) then begin
+    //if ( ListItem <> nil ) then
+     // ListItem.
+    //FPropertyOwner := f
+  end else begin
+    FPropertyOwner := FObjectItem;
+  end;
+  FObjectItem := Pointer(AValue);
+  FCurrentProperty := AProperty;
+  //FListItem := nil;
+  if ( FObjectItem <> nil ) then
+    FContentKind := xckObject
+  else
+    FContentKind := xckNull;
+end;
+
+procedure TXPathExecContext.SetValue(const AProperty: ISDOProperty);
+begin
+  CheckKind(xckObject);
+  FPropertyOwner := FObjectItem;
+  FContentKind := xckValue;
+  FCurrentProperty := AProperty;
+end;
+
+{ TXPathProcessor }
+
+procedure TXPathProcessor.Clear(const AClearContext : Boolean);
+begin
+  FExpression := nil;
+  FCurrentNode := nil;
+  if ( FContext <> nil ) and AClearContext then
+    FContext.SetNull(nil);
+end;
+
+constructor TXPathProcessor.Create(const AOptions : TXPathProcessorOptions);
+begin
+  FOptions := AOptions;
+  FContext := TXPathExecContext.Create();
+end;
+
+destructor TXPathProcessor.Destroy;
+begin
+  FExpression := nil;
+  FreeAndNil(FContext);
+  inherited;
+end;
+
+function TXPathProcessor.Evaluate(
+  const ATarget: ISDODataObject;
+  const AValueNode: TXPathValueNode
+) : TXPathValueBuffer;
+
+  function EvaluateProperty() : TXPathValueBuffer;
+  var
+    propNode : TXPathValuePropertySymbolNode;
+    prop : ISDOProperty;
+  begin
+    propNode := TXPathValuePropertySymbolNode(AValueNode);
+    prop := ATarget.getType().getProperty(propNode.Symbol);
+    case prop.getTypeEnum() of
+      BooleanType :
+        begin
+          Result.Kind := xadtBoolean;
+          Result.BoolValue := ATarget.getBoolean(prop);
+        end;
+      ByteType :
+        begin
+          Result.Kind := xadtNumber;
+          Result.NumberValue := ATarget.getByte(prop);
+        end;
+{$IFDEF HAS_SDO_BYTES}
+      BytesType :
+        begin
+          Result.Kind := xadtString;
+          Result.StringValue := TSDOConvertHelper.BytesToString(ATarget.getBytes(prop));
+        end;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType :
+        begin
+          Result.Kind := xadtString;
+          Result.StringValue := ATarget.getCharacter(prop);
+        end;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      CurrencyType :
+        begin
+          Result.Kind := xadtNumber;
+          Result.NumberValue := ATarget.getCurrency(prop);
+        end;
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType :
+        begin
+          Result.Kind := xadtNumber;
+          Result.NumberValue := ATarget.getDouble(prop);
+        end;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType :
+        begin
+          Result.Kind := xadtNumber;
+          Result.NumberValue := ATarget.getFloat(prop);
+        end;
+{$ENDIF HAS_SDO_FLOAT}
+      DateTimeType :
+        begin
+          Result.Kind := xadtString;
+          Result.StringValue := TSDOConvertHelper.DateToString(ATarget.getDate(prop));
+        end;
+      IntegerType :
+        begin
+          Result.Kind := xadtNumber;
+          Result.NumberValue := ATarget.getInteger(prop);
+        end;
+{$IFDEF HAS_SDO_LONG}
+      LongType :
+        begin
+          Result.Kind := xadtNumber;
+          Result.NumberValue := ATarget.getLong(prop);
+        end;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType :
+        begin
+          Result.Kind := xadtNumber;
+          Result.NumberValue := ATarget.getShort(prop);
+        end;
+{$ENDIF HAS_SDO_SHORT}
+      StringType  :
+        begin
+          Result.Kind := xadtString;
+          Result.StringValue := ATarget.getString(prop);
+        end;
+      else
+        raise ESDONotImplementedException.CreateFmt('TXPathProcessor.Evaluate.EvaluateProperty() not implemented for this type : "%s".',[prop.getType().getName()]);
+    end;
+  end;
+
+begin
+  if AValueNode.InheritsFrom(TXPathTypedValueNode) then begin
+    Result := TXPathTypedValueNode(AValueNode).Evaluate();
+  end else if AValueNode.InheritsFrom(TXPathValuePropertySymbolNode) then begin
+    Result := EvaluateProperty();
+  end else begin
+    raise EXPathException.CreateFmt('Unhandle value node type : "%s".',[AValueNode.ClassName]);
+  end;
+end;
+
+procedure TXPathProcessor.Execute(AExpression: TXPathExpression);
+begin
+  if ( AExpression = nil ) or ( AExpression.Root = nil ) then
+    raise EXpathException.Create('Invalid XPath tree.');
+  if not AExpression.Root.InheritsFrom(TXPathInstructionStepNode) then
+    raise EXpathException.Create('Invalid XPath tree : the root node must be an instruction one.');
+  Clear(False);
+  FExpression := AExpression;
+  FCurrentNode := FExpression.Root;
+  WalkTree();
+end;
+
+function TXPathProcessor.IsTrue(
+  const ATarget: ISDODataObject;
+  const ACondition: TXPathPredicateNode
+): Boolean;
+
+  function HandleEqual(const ACond : TXPathEqualNode) : Boolean;
+  var
+    lval, rval : TXPathValueBuffer;
+  begin
+    Result := False;
+    lval := Evaluate(ATarget,ACond.Left);
+    rval := Evaluate(ATarget,ACond.Right);
+    case lval.Kind of
+      xadtString :
+        begin
+          case rval.Kind of
+            xadtString   : Result := ( lval.StringValue = rval.StringValue );
+            xadtBoolean  : Result := ( lval.StringValue = TSDOConvertHelper.BoolToString(rval.BoolValue) );
+            xadtNumber   : Result := ( lval.StringValue = TSDOConvertHelper.FloatToString(rval.NumberValue) );
+          end;
+        end;
+      xadtBoolean :
+        begin
+          case rval.Kind of
+            xadtString   : Result := ( lval.BoolValue = TSDOConvertHelper.StringToBool(rval.StringValue) );
+            xadtBoolean  : Result := ( lval.BoolValue = rval.BoolValue );
+            xadtNumber   : Result := ( lval.BoolValue = ( rval.NumberValue <> 0 ) );
+          end;
+        end;
+      xadtNumber :
+        begin
+          case rval.Kind of
+            xadtString   : Result := ( lval.NumberValue = TSDOConvertHelper.StringToFloat(rval.StringValue) );
+            xadtBoolean  : Result := ( lval.NumberValue = TSDOConvertHelper.BoolToInteger(rval.BoolValue) );
+            xadtNumber   : Result := ( lval.NumberValue = rval.NumberValue );
+          end;
+        end;
+    end;
+  end;
+
+var
+  locRes : Boolean;
+  locNode : TXPathPredicateNode;
+begin
+  Result := False;
+  if ( ATarget <> nil ) then begin
+    if ( ACondition = nil ) then begin
+      Result := True;
+    end else begin
+      locRes := False;
+      locNode := ACondition;
+      while ( locNode <> nil ) do begin
+        case locNode.GetCode() of
+          xpcEqual : locRes := HandleEqual(TXPathEqualNode(locNode));
+          else
+            raise EXPathException.CreateFmt('Unhandle predicate type : "%s".',[GetEnumName(TypeInfo(TXPathPredicateCode), Ord(locNode.GetCode()))]);
+        end;
+        if not locRes then
+          Break;
+        locNode := locNode.Next as TXPathPredicateNode;
+      end;
+      Result := locRes;
+    end;
+  end;
+end;
+
+procedure TXPathProcessor.WalkNode(const ANode: TXPathInstructionStepNode);
+  procedure ExecContextNode();
+  var
+    ctxNode : TXPathContextStepNode;
+    tmpObj, lastObj : ISDODataObject;
+    prop : ISDOProperty;
+  begin
+    ctxNode := TXPathContextStepNode(ANode);
+    case ctxNode.Switch of
+      xcsSelf : ; // nothing to do
+      xcsParent :
+        begin
+          Context.CheckKind(xckObject);
+          Context.SetObject(Context.ObjectItem.getContainer(),nil);
+        end;
+      xcsRoot :
+        begin
+          Context.CheckKind(xckObject);
+          tmpObj := Context.ObjectItem;
+          repeat
+            lastObj := tmpObj;
+            tmpObj := tmpObj.getContainer();
+          until ( tmpObj = nil );
+          Context.SetObject(lastObj,nil);
+        end;
+      xcsProperty :
+        begin
+          Context.CheckKind([xckObject,xckList]);
+          prop := Context.ObjectItem.getProperty(ctxNode.PropertyName);
+          if prop.isMany() then begin
+            Context.SetList(Context.ObjectItem.getList(prop),prop)
+          end else begin
+            if prop.getType().isDataObjectType() then
+              Context.SetObject(Context.ObjectItem.getDataObject(prop),prop)
+            else
+              Context.SetValue(prop);
+          end;
+        end;
+    end;
+  end;
+
+  procedure ExecMove();
+  var
+    moveNode : TXPathMoveInstructionStepNode;
+    dist : PtrInt;
+  begin
+    moveNode := TXPathMoveInstructionStepNode(ANode);
+    dist := Round(moveNode.Distance.Evaluate().NumberValue);
+    if ( dist >= 0 ) then begin
+      if ( Context.ContentKind <> xckList ) then
+        raise EXpathException.Create('Invalid context : list expected.');
+      if ( Context.CurrentProperty = nil ) then
+        raise EXpathException.Create('Invalid context : no available property.');
+      if not Context.CurrentProperty.isMany() then
+        raise EXpathException.CreateFmt('Invalid context property indexing : "%s" is not a multi-value property.',[Context.CurrentProperty.getName()]);
+      if not Context.ListItem.getCursor().MoveTo(dist) then
+        raise EXpathException.CreateFmt('Unable to reach this position in the list : %s[%d]',[Context.CurrentProperty.getName(),dist]);
+      if Context.CurrentProperty.getType().isDataObjectType() then
+        Context.SetObject(Context.ListItem.getDataObject(),Context.CurrentProperty)
+    end;
+  end;
+
+  procedure ExecLocate();
+  var
+    locateNode : TXPathLocateInstructionStepNode;
+    conditionNode : TXPathPredicateNode;
+    crs : ISDOCursor;
+    ls : ISDODataObjectList;
+    found : Boolean;
+  begin
+    if ( Context.CurrentProperty = nil ) then
+      raise EXPathException.Create('Invalid context : no property set.');
+    if not Context.CurrentProperty.isMany() then
+      raise EXPathException.CreateFmt('Invalid context , multi-valued property expected : "%s".',[Context.CurrentProperty.getName()]);
+    locateNode := TXPathLocateInstructionStepNode(ANode);
+    conditionNode := locateNode.Condition;
+    ls := Context.ListItem;
+    crs := ls.getCursor();
+    crs.Reset();
+    found :=False;
+    while crs.MoveNext() do begin
+      if IsTrue(ls.getDataObject(),conditionNode) then begin
+        Context.SetObject(ls.getDataObject(),Context.CurrentProperty);
+        found := True;
+        Break;
+      end;
+    end;
+    if not found then
+      Context.SetNull(Context.CurrentProperty);
+  end;
+
+begin
+  case ANode.GetCode() of
+    xicContextChange : ExecContextNode();
+    xicMove          : ExecMove();
+    xicLocate        : ExecLocate();
+  end;
+end;
+
+procedure TXPathProcessor.WalkTree();
+begin
+  while ( FCurrentNode <> nil ) do begin
+    WalkNode(FCurrentNode as TXPathInstructionStepNode);
+    FCurrentNode := FCurrentNode.Next;
+  end;
+end;
+
+{ TXPathExpression }
+
+destructor TXPathExpression.Destroy();
+begin
+  FreeAndNil(FRoot);
+  inherited;
+end;
+
+procedure TXPathExpression.SetRoot(const ARoot: TXPathNode);
+begin
+  FreeAndNil(FRoot);
+  FRoot := ARoot;
+end;
+
+{ TXPathScanner }
+
+constructor TXPathScanner.Create(const AXPathString: string);
+begin
+  FBuffer := AXPathString;
+  FLength := Length(FBuffer);
+  FPosition := 1;
+  FToken := xtkEof;
+end;
+
+function TXPathScanner.NextToken() : TXPathToken;
+var
+  locPosStart : PtrInt;
+begin
+  FTokenString := '';
+  FToken := xtkEof;
+  //skip blanks
+  while ( FPosition <= FLength ) and ( FBuffer[FPosition] in [' ',#9,#10,#13] ) do begin
+    Inc(FPosition);
+  end;
+  if ( FPosition <= FLength ) then begin
+    while ( FPosition <= FLength ) do begin
+      case FBuffer[FPosition] of
+        '[' :
+          begin
+            FToken := xtkSquaredBraceLeft;
+            FTokenString := '[';
+            Inc(FPosition);
+            Break;
+          end;
+        ']' :
+          begin
+            FToken := xtkSquaredBraceRigth;
+            FTokenString := ']';
+            Inc(FPosition);
+            Break;
+          end;
+        '=' :
+          begin
+            FToken := xtkEqual;
+            FTokenString := '=';
+            Inc(FPosition);
+            Break;
+          end;
+        '"' :
+          begin
+            Inc(FPosition);
+            locPosStart := FPosition;
+            while ( FPosition <= FLength ) and ( FBuffer[FPosition] <> '"' ) do begin
+              Inc(FPosition);
+            end;
+            if ( FBuffer[FPosition] <> '"' ) then
+              raise EXpathException.Create('Not terminated string at the end of the expression.');
+            FTokenString := Copy(FBuffer,locPosStart,( FPosition - locPosStart ) );
+            Inc(FPosition);
+            FToken := xtkString;
+            Break;
+          end;
+        '''' :
+          begin
+            Inc(FPosition);
+            locPosStart := FPosition;
+            while ( FPosition <= FLength ) and ( FBuffer[FPosition] <> '''' ) do begin
+              Inc(FPosition);
+            end;
+            if ( FBuffer[FPosition] <> '''' ) then
+              raise EXpathException.Create('Not terminated string at the end of the expression.');
+            FTokenString := Copy(FBuffer,locPosStart,( FPosition - locPosStart ) );
+            Inc(FPosition);
+            FToken := xtkString;
+            Break;
+          end;
+        '-', '0'..'9' :
+          begin
+            locPosStart := FPosition;
+            Inc(FPosition);
+            while ( FPosition <= FLength ) and ( FBuffer[FPosition] in ['0'..'9'] ) do begin
+              Inc(FPosition);
+            end;
+            if ( FPosition < FLength ) then begin
+              if ( FBuffer[FPosition] = '.' ) then begin
+                Inc(FPosition);
+                while ( FPosition < FLength ) and ( FBuffer[FPosition] in ['0'..'9'] ) do begin
+                  Inc(FPosition);
+                end;
+              end;
+            end;
+            if ( locPosStart = ( FPosition + 1 ) ) then
+              raise EXpathException.Create('Invalid character at the end of the expression : "-".');
+            FTokenString := Copy(FBuffer,locPosStart,( FPosition - locPosStart ));
+            FToken := xtkNumber;
+            Break;
+          end;
+        '/' :
+          begin
+            FToken := xtkSlash;
+            FTokenString := '/';
+            Inc(FPosition);
+            Break;
+          end;
+        '.' :
+          begin
+            if ( FPosition < FLength ) then begin
+              if ( FBuffer[( FPosition + 1 )] = '.' ) then begin
+                FToken := xtkDoublePeriod;
+                FTokenString := '..';
+                Inc(FPosition);
+              end else if ( FBuffer[( FPosition + 1 )] in  ['0'..'9'] ) then begin
+                locPosStart := FPosition;
+                Inc(FPosition);
+                while ( FPosition <= FLength ) and ( FBuffer[FPosition] in  ['0'..'9'] ) do begin
+                  Inc(FPosition);
+                end;
+                FTokenString := '0' + Copy(FBuffer,locPosStart,( FPosition - locPosStart ) );
+                Dec(FPosition);
+                FToken := xtkNumber;
+              end;
+            end else begin
+              FTokenString := '.';
+              FToken := xtkPeriod;
+            end;
+            Inc(FPosition);
+            Break;
+          end;
+        'a'..'z','A'..'Z', '_' :
+          begin
+            locPosStart := FPosition;
+            while ( FPosition <= FLength ) and ( FBuffer[FPosition] in ['a'..'z','A'..'Z', '_', '0'..'9'] ) do begin
+              Inc(FPosition);
+            end;
+            FTokenString := Copy(FBuffer,locPosStart,( FPosition - locPosStart ));
+            if ( FTokenString = 'true' ) then
+              FToken := xtkTrue
+            else if ( FTokenString = 'false' ) then
+              FToken := xtkFalse
+            else if ( FTokenString = 'null' ) then
+              FToken := xtkNull
+            else
+              FToken := xtkSymbol;
+            Break;
+          end;
+        '@' :
+          begin
+            FToken := xtkAt;
+            FTokenString := '@';
+            Inc(FPosition);
+            Break;
+          end;
+        else
+          raise EXpathException.CreateFmt('Invalid character at %d : "%s".',[FPosition,FBuffer[FPosition]]);
+      end;
+    end;
+  end;
+  Result := FToken;
+end;
+
+function TXPathScanner.TokenInt() : PtrInt;
+begin
+  Result := StrToInt(TokenString);
+end;
+
+function TXPathScanner.TokenNumber() : Extended;
+begin
+  Result := TSDOConvertHelper.StringToFloat(TokenString);
+end;
+
+{ TXPathParser }
+
+procedure TXPathParser.BeginConditionExpression();
+begin
+  Inc(FInConditionExpression);
+end;
+
+procedure TXPathParser.Clear();
+var
+  c, i : PtrInt;
+begin
+  if ( FTermStack <> nil ) then begin
+    c := FTermStack.Count;
+    if ( FRootNode <> nil ) then
+      c := c - 1;
+    for i  := 1 to c do begin
+      FTermStack.Pop().Free();
+    end;
+    if ( FRootNode <> nil ) and ( FTermStack.Count > 0 ) then
+      FTermStack.Pop(); // <<-- FRootNode
+  end;
+  if ( FSymbolStack <> nil ) then begin
+    c := FSymbolStack.Count;
+    for i  := 1 to c do begin
+      FSymbolStack.Pop().Free();
+    end;
+  end;
+  FreeAndNil(FRootNode);
+end;
+
+constructor TXPathParser.Create(const AXPathString: string);
+begin
+  FXPath := AXPathString;
+  FScanner := TXPathScanner.Create(FXPath);
+  FTermStack := TObjectStack.Create();
+  FSymbolStack := TObjectStack.Create();
+end;
+
+destructor TXPathParser.Destroy();
+begin
+  Clear();
+  FreeAndNil(FTermStack);
+  FreeAndNil(FSymbolStack);
+  FreeAndNil(FScanner);
+  inherited;
+end;
+
+procedure TXPathParser.EndConditionExpression();
+begin
+  Dec(FInConditionExpression);
+  if ( FInConditionExpression < 0 ) then
+    raise EXPathException.Create('Invalid condition ending.');
+end;
+
+function TXPathParser.InternalTryReduction() : Boolean;
+var
+  locSymbol : TXPathSymbolNode;
+  locFreeSym : Boolean;
+
+  function ReduceSlash() : Boolean;
+  var
+    a, b : TXPathNode;
+  begin
+    Result := False;
+    if ( FTermStack.Count = 0 ) then begin
+      a := TXPathContextStepNode.Create();
+      FTermStack.Push(a);
+      TXPathContextStepNode(a).FSwitch := xcsRoot;
+      FRootNode := a;
+    end else if FTermStack.AtLeast(2) then begin
+      FSymbolStack.Pop();
+      b := FTermStack.Pop() as TXPathNode;
+      if b.InheritsFrom(TXPathContextStepNode) then begin
+        a := FTermStack.Pop() as TXPathNode;
+        if ( a.FNext <> nil ) then begin
+          FreeAndNil(a);
+          FreeAndNil(b);
+          raise EXpathException.CreateFmt('nil expected but "%s" found.',[a.ClassName]);
+        end;
+        a.FNext := b;
+        FTermStack.Push(b);
+      end else begin
+        FreeAndNil(b);
+        raise EXpathException.CreateFmt('A context step expected but "%s" found.',[b.ClassName]);
+      end;
+      Result := True;
+      locFreeSym := True;
+    end;
+  end;
+
+  function ReduceEqual() : Boolean;
+  var
+    left, right : TXPathNode;
+    eqlNode : TXPathEqualNode;
+  begin
+    if not FTermStack.AtLeast(2) then
+      raise EXpathException.Create('Invalid "=" expression.');
+    right := FTermStack.Pop() as TXPathNode;
+    if not right.InheritsFrom(TXPathValueNode) then begin
+      FTermStack.Push(right);
+      raise EXpathException.Create('"Right" member of an "Equal" expression must be a value expression.');
+    end;
+    left := FTermStack.Pop() as TXPathNode;
+    if not left.InheritsFrom(TXPathValueNode) then begin
+      FTermStack.Push(left);
+      raise EXpathException.Create('"Left" member of an "Equal" expression must be a value expression.');
+    end;
+    eqlNode := locSymbol as TXPathEqualNode;
+    eqlNode.Left := left as TXPathValueNode;
+    eqlNode.Right := right as TXPathValueNode;
+    FTermStack.Push(eqlNode);
+    Result := True;
+    locFreeSym := False;
+    FSymbolStack.Pop();
+  end;
+
+  function ReducePredicate() : Boolean;
+  var
+    locExp, locTmpNode : TXPathNode;
+    distNode : TXPathMoveInstructionStepNode;
+    locateNode : TXPathLocateInstructionStepNode;
+  begin
+    if not FTermStack.AtLeast(3) then
+      raise EXpathException.Create('A predicate needs a expression to evaluate as its condition.');
+    locTmpNode := FTermStack.Pop() as TXPathNode;
+    if not locTmpNode.InheritsFrom(TXPathRigthSquareBraketNode) then begin
+      FTermStack.Push(locTmpNode);
+      raise EXpathException.Create('Predicate begining expected.');
+    end;
+    FreeAndNil(locTmpNode);
+    locExp := FTermStack.Pop() as TXPathNode;
+    if locExp.InheritsFrom(TXPathTypedValueNode) then begin
+      locTmpNode := FTermStack.Pop() as TXPathNode;
+      if not locTmpNode.InheritsFrom(TXPathLeftSquareBraketNode) then begin
+        FTermStack.Push(locTmpNode);
+        FTermStack.Push(locExp);
+        raise EXpathException.Create('Predicate ending expected.');
+      end;
+      FreeAndNil(locTmpNode);
+      case TXPathTypedValueNode(locExp).GetDataType() of
+        xadtBoolean : ;
+        xadtNumber :
+          begin
+            distNode := TXPathMoveInstructionStepNode.Create();
+            if FTermStack.AtLeast(1) then
+              locTmpNode := FTermStack.Pop() as TXPathNode
+            else
+              locTmpNode := nil;
+            FTermStack.Push(distNode);
+            if ( locTmpNode <> nil ) then begin
+              locTmpNode.FNext := distNode;
+            end;
+            distNode.FDistance := TXPathTypedValueNode(locExp);
+          end;
+        else
+          raise EXpathException.Create('A predicate''s condition expression must be of type "boolean" or "number".');
+      end;
+      locFreeSym := True;
+    end else if locExp.InheritsFrom(TXPathPredicateNode) then begin
+      locTmpNode := FTermStack.Pop() as TXPathNode;
+      if not locTmpNode.InheritsFrom(TXPathLeftSquareBraketNode) then begin
+        FTermStack.Push(locTmpNode);
+        FTermStack.Push(locExp);
+        raise EXpathException.Create('Predicate ending expected.');
+      end;
+      FreeAndNil(locTmpNode);
+      if FTermStack.AtLeast(1) then
+        locTmpNode := FTermStack.Pop() as TXPathNode
+      else
+        locTmpNode := nil;
+      locateNode := TXPathLocateInstructionStepNode.Create();
+      locateNode.FCondition := TXPathPredicateNode(locExp);
+      FTermStack.Push(locateNode);
+      if ( locTmpNode <> nil ) then begin
+        locTmpNode.FNext := locateNode;
+      end;
+      locFreeSym := False;
+    end else begin
+      FTermStack.Push(locExp);
+      raise EXpathException.Create('A predicate needs a typed expression to evaluate as its condition.');
+    end;
+    EndConditionExpression();
+    Result := True;
+  end;
+
+var
+  locRes : Boolean;
+begin
+  locRes := False;
+  if FSymbolStack.AtLeast(1) then begin
+    locFreeSym := False;
+    locSymbol := FSymbolStack.Peek() as TXPathSymbolNode;
+    try
+      if locSymbol.InheritsFrom(TXPathSlashNode) then begin
+        locRes := ReduceSlash();
+      end else if locSymbol.InheritsFrom(TXPathEqualNode) then begin
+        locRes := ReduceEqual();
+      end;
+    finally
+      if locFreeSym then
+        FreeAndNil(locSymbol);
+    end;
+  end;
+  if ( not locRes ) and FTermStack.AtLeast(1) then begin
+    if FTermStack.Peek().InheritsFrom(TXPathRigthSquareBraketNode) then
+      locRes := ReducePredicate();
+  end;
+  Result := locRes;
+end;
+
+function TXPathParser.IsInConditionExpression() : Boolean;
+begin
+  Result := ( FInConditionExpression > 0 );
+end;
+
+function TXPathParser.Parse() : TXPathNode;
+begin
+  Clear();
+  if ( FScanner.NextToken() = xtkEof ) then
+    raise EXpathException.Create('Invalid XPath expression.');
+  Result := nil;
+  try
+    while True do begin
+      case FScanner.Token of
+        xtkEof : Break;
+        xtkTrue,
+        xtkFalse :
+          begin
+            ReadBooleanConst();
+            TryReduction();
+          end;
+        xtkNumber :
+          begin
+            ReadNumberConst();
+            TryReduction();
+          end;
+        xtkString :
+          begin
+            ReadStringConst();
+            TryReduction();
+          end;
+        xtkSymbol :
+          begin
+            ReadSymbol();
+            TryReduction();
+          end;
+        xtkSlash :
+          begin
+            FSymbolStack.Push(TXPathSlashNode.Create());
+            if ( FTermStack.Count = 0 ) then
+              TryReduction();
+          end;
+        xtkSquaredBraceLeft :
+          begin
+            BeginConditionExpression();
+            FTermStack.Push(TXPathLeftSquareBraketNode.Create());
+          end;
+        xtkSquaredBraceRigth :
+          begin
+            FTermStack.Push(TXPathRigthSquareBraketNode.Create());
+            TryReduction();
+          end;
+        xtkEqual : FSymbolStack.Push(TXPathEqualNode.Create());
+      end;
+      FScanner.NextToken();
+    end;
+    if ( FTermStack.Count <> 1 ) then
+      raise EXpathException.CreateFmt('Invalid xpath string : "%s".',[FXPath]);
+    if ( FRootNode = nil ) then
+      raise EXpathException.Create('Invalid xpath string');
+    if not FRootNode.InheritsFrom(TXPathContextStepNode) then
+      raise EXpathException.Create('Invalid xpath string');
+    FTermStack.Pop();
+    Result := FRootNode;
+    FRootNode := nil;
+  finally
+    Clear();
+  end;
+end;
+
+procedure TXPathParser.ReadBooleanConst();
+begin
+  FTermStack.Push(TXPathBooleanConstantNode.Create(FScanner.Token = xtkTrue));
+end;
+
+procedure TXPathParser.ReadNumberConst();
+begin
+  FTermStack.Push(TXPathNumberConstantNode.Create(FScanner.TokenNumber));
+end;
+
+procedure TXPathParser.ReadStringConst();
+begin
+  FTermStack.Push(TXPathStringConstantNode.Create(FScanner.TokenString));
+end;
+
+procedure TXPathParser.ReadSymbol();
+
+  procedure ReadContextSymbol();
+  var
+    locCtxNode : TXPathContextStepNode;
+  begin
+    locCtxNode := TXPathContextStepNode.Create();
+    locCtxNode.FSwitch := xcsProperty;
+    locCtxNode.FPropertyName := FScanner.TokenString;
+    FTermStack.Push(locCtxNode);
+    if ( FRootNode = nil ) then
+      FRootNode := locCtxNode;
+  end;
+
+  procedure ReadConditionSymbol();
+  var
+    locProp : TXPathValuePropertySymbolNode;
+  begin
+    locProp := TXPathValuePropertySymbolNode.Create();
+    locProp.Symbol := FScanner.TokenString;
+    FTermStack.Push(locProp);
+  end;
+
+begin
+  if IsInConditionExpression() then
+    ReadConditionSymbol()
+  else
+    ReadContextSymbol();
+end;
+
+procedure TXPathParser.TryReduction();
+begin
+  while InternalTryReduction() do begin
+    ;// nothing!!
+  end;
+end;
+
+{ TXPathStringConstantNode }
+
+constructor TXPathStringConstantNode.Create(const AValue: string);
+begin
+  FValue := AValue;
+end;
+
+function TXPathStringConstantNode.Evaluate(): TXPathValueBuffer;
+begin
+  Result.Kind := GetDataType();
+  Result.StringValue := Value;
+end;
+
+{ TXPathNumberConstantNode }
+
+constructor TXPathNumberConstantNode.Create(const AValue: Extended);
+begin
+  FValue := AValue;
+end;
+
+function TXPathNumberConstantNode.Evaluate(): TXPathValueBuffer;
+begin
+  Result.Kind := GetDataType();
+  Result.NumberValue := Value;
+end;
+
+{ TXPathBooleanConstantNode }
+
+constructor TXPathBooleanConstantNode.Create(const AValue: TSDOBoolean);
+begin
+  FValue := AValue;
+end;
+
+function TXPathBooleanConstantNode.Evaluate(): TXPathValueBuffer;
+begin
+  Result.Kind := GetDataType();
+  Result.BoolValue := Value;
+end;
+
+{ TXPathMoveInstructionStepNode }
+
+destructor TXPathMoveInstructionStepNode.Destroy();
+begin
+  FreeAndNil(FDistance);
+  inherited;
+end;
+
+class function TXPathMoveInstructionStepNode.GetCode() : TXPathInstructionCode;
+begin
+  Result := xicMove;
+end;
+
+{ TXPathContextStepNode }
+
+class function TXPathContextStepNode.GetCode() : TXPathInstructionCode;
+begin
+  Result := xicContextChange;
+end;
+
+{ TXPathStringValueNode }
+
+class function TXPathStringValueNode.GetDataType() : TXPathAtomicDataType;
+begin
+  Result := xadtString;
+end;
+
+{ TXPathNumberValueNode }
+
+class function TXPathNumberValueNode.GetDataType() : TXPathAtomicDataType;
+begin
+  Result := xadtNumber;
+end;
+
+{ TXPathBooleanValueNode }
+
+class function TXPathBooleanValueNode.GetDataType() : TXPathAtomicDataType;
+begin
+  Result := xadtBoolean;
+end;
+
+
+{ TXPathEqualNode }
+
+destructor TXPathEqualNode.Destroy();
+begin
+  FreeAndNil(FRight);
+  FreeAndNil(FLeft);
+  inherited;
+end;
+
+class function TXPathEqualNode.GetCode() : TXPathPredicateCode;
+begin
+  Result := xpcEqual;
+end;
+
+{ TXPathLocateInstructionStepNode }
+
+destructor TXPathLocateInstructionStepNode.Destroy;
+begin
+  FreeAndNil(FCondition);
+  inherited;
+end;
+
+class function TXPathLocateInstructionStepNode.GetCode() : TXPathInstructionCode;
+begin
+  Result := xicLocate;
+end;
+
+end.

+ 888 - 0
packages/fcl-sdo/src/base/sdo_xsd_helper.pas

@@ -0,0 +1,888 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements XSD to SDO translation
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_xsd_helper;
+
+interface
+uses SysUtils, Classes,
+     sdo, sdo_type, sdo_datafactory;
+
+type
+
+  { TXSDHelper }
+
+  TXSDHelper = class(TInterfacedObject, IInterface, IXSDHelper)
+  private
+    FDataFactory : ISDODataFactory;
+  protected
+    procedure LoadFromStream(AStream : TStream);
+    procedure LoadFromFile(const AFileName : string);
+    procedure LoadFromString(const ASchemaString : string);
+
+    procedure Generate(
+            ATypeList : ISDOTypeList;
+            ADestStream : TStream;
+      const ATargetNamespace : string
+    );overload;
+    function Generate(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string
+    ) : string;overload;
+    procedure Generate(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string;
+      const AFileName : string
+    );overload;
+    procedure GenerateCode(
+            ATypeList : ISDOTypeList;
+            ADestStream : TStream;
+      const ATargetNamespace : string
+    );overload;
+    function GenerateCode(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string
+    ) : string;overload;
+    procedure GenerateCode(
+            ATypeList : ISDOTypeList;
+      const ATargetNamespace : string;
+      const AFileName : string
+    );overload;
+
+    function  GetDataFactory() : ISDODataFactory;
+  public
+    constructor Create(ADataFactory : ISDODataFactory);
+  end;
+
+implementation
+uses
+   sdo_types, sdo_parserutils,
+{$IFNDEF FPC}
+   xmldom, sdo_win_xml,
+{$ELSE}
+   DOM, XmlRead, XmlWrite, sdo_fpc_xml,
+{$ENDIF}
+   sdo_xsdparser, sdo_imp_utils, xsd_generator, xsd_consts, sdo_consts,
+   sdo_xsdintf, pas_generator;
+
+const
+  SDO_SPECIAL_TYPES = [CharacterType, CurrencyType];
+
+type
+  TPasTreeSdoConverter = class
+  private
+    FDataFactory : ISDODataFactory;
+    FTree : ISDODataObject;
+    FTypeList : ISDOTypeListEx;
+  private
+    function FindType(const AUri, AName : string) : ISDOType;
+
+    function TranslateType(AType : ISDODataObject) : ISDOType;
+    function TranslateClass(AElement : ISDODataObject) : ISDOType;
+    function TranslateEnum(AElement : ISDODataObject) : ISDOType;
+    function TranslateVariable(AElement : ISDODataObject) : ISDOType;
+
+    procedure TranslateModule(AModule : ISDODataObject);
+  public
+    constructor Create(
+      ATree : ISDODataObject;
+      ADataFactory : ISDODataFactory
+    );
+    procedure Execute();
+  end;
+
+  TSdoPasConverter = class
+  private
+    FDataFactory : ISDODataFactory;
+    FTree : ISDODataObject;
+    FTypeList : ISDOTypeList;
+  private
+    function FindType(const AUri, AName : string) : ISDODataObject;
+    function FindOrCreateModule(const ANamespace : string) : ISDODataObject;
+
+    function TranslateType(const AType : ISDOType) : ISDODataObject;
+    function TranslateAlias(const AType : ISDOType) : ISDODataObject;
+    function TranslateObject(const AType : ISDOType) : ISDODataObject;
+    function TranslateChangeSummary(const AType : ISDOType) : ISDODataObject;
+  public
+    constructor Create(
+      ATree : ISDODataObject;
+      ADataFactory : ISDODataFactory;
+      ATypeList : ISDOTypeList
+    );
+    procedure Execute();
+  end;
+
+procedure PasTreeToSdoTypes(
+  ATree : ISDODataObject;
+  ADataFactory : ISDODataFactory
+);
+var
+  loc_converter : TPasTreeSdoConverter;
+begin
+  loc_converter := TPasTreeSdoConverter.Create(ATree,ADataFactory);
+  try
+    loc_converter.Execute();
+  finally
+    loc_converter.Free();
+  end;
+end;
+
+procedure SdoTypesToPasTree(
+  ATree : ISDODataObject;
+  ADataFactory : ISDODataFactory;
+  ATypeList : ISDOTypeList
+);
+var
+  loc_converter : TSdoPasConverter;
+begin
+  loc_converter := TSdoPasConverter.Create(ATree,ADataFactory,ATypeList);
+  try
+    loc_converter.Execute();
+  finally
+    loc_converter.Free();
+  end;
+end;
+
+{ TXSDHelper }
+
+constructor TXSDHelper.Create(ADataFactory : ISDODataFactory);
+begin
+  if ( ADataFactory = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADataFactory');
+  FDataFactory := ADataFactory;
+end;
+
+procedure TXSDHelper.Generate(
+        ATypeList : ISDOTypeList;
+        ADestStream : TStream;
+  const ATargetNamespace : string
+);
+var
+  doc : TXMLDocument;
+  gnrt : IXsdGenerator;
+  tree : ISDODataObject;
+  lst : ISDOTypeList;
+  locXsdFactory :ISDODataFactory;
+begin
+  if ( ADestStream = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADestStream');
+  if Assigned(ATypeList) then
+    lst := ATypeList
+  else
+    lst := FDataFactory.getTypes();
+  locXsdFactory := TSDODataFactory.Create();
+  AddTypeTree(locXsdFactory);
+  doc := nil;
+  try
+    tree := locXsdFactory.CreateNew(s_XsdParserNS,s_TypeTreeType); 
+    AddXsdTypes(tree);
+    SdoTypesToPasTree(tree,FDataFactory,lst);
+    doc := CreateDoc();
+    gnrt := TXsdGenerator.Create(doc,[xsd_generator.xgoIgnorembeddedArray]);
+    gnrt.SetPreferedShortNames(sdo_namespace,s_sdo);
+    gnrt.Execute(tree,ATargetNamespace);
+    WriteXMLFile(doc,ADestStream);
+  finally
+    ReleaseDomNode(doc);
+    tree := nil;
+  end;
+end;
+
+function TXSDHelper.Generate(
+        ATypeList : ISDOTypeList;
+  const ATargetNamespace : string
+) : string;
+var
+  locStream : TStringStream;
+begin
+  locStream := TStringStream.Create('');
+  try
+    Generate(ATypeList,locStream,ATargetNamespace);
+    Result := locStream.DataString;
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXSDHelper.Generate(
+        ATypeList : ISDOTypeList;
+  const ATargetNamespace : string;
+  const AFileName : string
+);
+var
+  locStream : TFileStream;
+begin
+  locStream := TFileStream.Create(AFileName,fmCreate);
+  try
+    Generate(ATypeList,locStream,ATargetNamespace);
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXSDHelper.GenerateCode(ATypeList: ISDOTypeList;
+  ADestStream: TStream; const ATargetNamespace: string);
+var
+  gnrt : IPasGenerator;
+  tree : ISDODataObject;
+  lst : ISDOTypeList;
+  locXsdFactory :ISDODataFactory;
+begin
+  if ( ADestStream = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADestStream');
+  if Assigned(ATypeList) then
+    lst := ATypeList
+  else
+    lst := FDataFactory.getTypes();
+  locXsdFactory := TSDODataFactory.Create();
+  AddTypeTree(locXsdFactory);
+  tree := locXsdFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+  try
+    AddXsdTypes(tree);
+    SdoTypesToPasTree(tree,FDataFactory,lst);
+    gnrt := TPasGenerator.Create(ADestStream,[pas_generator.xgoIgnorembeddedArray]);
+    gnrt.SetPreferedShortNames(sdo_namespace,s_sdo);
+    gnrt.Execute(tree,ATargetNamespace);
+  finally
+    tree := nil;
+  end;
+end;
+
+function TXSDHelper.GenerateCode(ATypeList: ISDOTypeList;
+  const ATargetNamespace: string): string;
+var
+  locStream : TStringStream;
+begin
+  locStream := TStringStream.Create('');
+  try
+    Generate(ATypeList,locStream,ATargetNamespace);
+    Result := locStream.DataString;
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXSDHelper.GenerateCode(ATypeList: ISDOTypeList;
+  const ATargetNamespace: string; const AFileName: string);
+var
+  locStream : TFileStream;
+begin
+  locStream := TFileStream.Create(AFileName,fmCreate);
+  try
+    Generate(ATypeList,locStream,ATargetNamespace);
+  finally
+    locStream.Free();
+  end;
+end;
+
+function TXSDHelper.GetDataFactory() : ISDODataFactory;
+begin
+  Result := FDataFactory;
+end;
+
+procedure TXSDHelper.LoadFromFile(const AFileName: string);
+var
+  FileStream: TStream;
+begin
+  FileStream := TFileStream.Create(AFilename, fmOpenRead+fmShareDenyWrite);
+  try
+    LoadFromStream(FileStream);
+  finally
+    FileStream.Free();
+  end;
+end;
+
+procedure AddSDOTypes(const ATree : ISDODataObject);
+var
+  locClassType : ISDODataObject;
+  locSdoTable : ISDODataObject;
+begin
+  locSdoTable := ATree.createDataObject(s_Module);
+  locSdoTable.setBoolean(s_Native,True);
+  locSdoTable.setString(s_Name,'sdo');
+  locSdoTable.setString(s_NameSpace,sdo_namespace);
+  ATree.getList(s_Module).append(locSdoTable);
+
+  locClassType := locSdoTable.createDataObject(s_Type);
+  locClassType.setString(s_Name,SDOTypeDefaultTypeNames[ChangeSummaryType]);
+  locSdoTable.getList(s_Type).append(locClassType);
+end;
+
+
+procedure TXSDHelper.LoadFromStream(AStream: TStream);
+var
+  doc : TXMLDocument;
+  prsr : IXsdParser;
+  treeFactory : ISDODataFactory;
+  tree : ISDODataObject;
+begin
+  if ( AStream = nil ) then
+    raise ESDOIllegalArgumentException.Create('AStream');
+  doc := nil;
+  try
+    ReadXMLFile(doc,AStream);
+    treeFactory := TSDODataFactory.Create();
+    AddTypeTree(treeFactory);
+    tree := treeFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+    AddXsdTypes(tree);
+    AddSDOTypes(tree);
+    prsr := TXsdParser.Create(doc,tree,'');
+    prsr.ParseTypes();
+    PasTreeToSdoTypes(tree,GetDataFactory());
+  finally
+    ReleaseDomNode(doc);
+    tree := nil;
+  end;
+end;
+
+procedure TXSDHelper.LoadFromString(const ASchemaString: string);
+var
+  locStream : TStream;
+begin
+  locStream := TStringStream.Create(ASchemaString);
+  try
+    locStream.Position := 0;
+    LoadFromStream(locStream);
+  finally
+    locStream.Free();
+  end;
+end;
+
+{ TPasTreeSdoConverter }
+
+constructor TPasTreeSdoConverter.Create(
+  ATree: ISDODataObject;
+  ADataFactory : ISDODataFactory
+);
+begin
+  if ( ATree = nil ) then
+    raise ESDOIllegalArgumentException.Create('ATree');
+  if ( ADataFactory = nil ) then
+    raise ESDOIllegalArgumentException.Create('ADataFactory');
+  FTree := ATree;
+  FDataFactory := ADataFactory;
+  FTypeList := FDataFactory.getTypes() as ISDOTypeListEx;
+end;
+
+procedure TPasTreeSdoConverter.Execute();
+var
+  i, c : PtrInt;
+  mdl : ISDODataObject;
+  mdlLs : ISDODataObjectList;
+begin
+  mdlLs := FTree.getList(s_Module);
+  c := mdlLs.size();
+  for i := 0 to Pred(c) do begin
+    mdl := mdlLs.getDataObject(i);
+    if not mdl.getBoolean(s_Native) then
+      TranslateModule(mdl);
+  end;
+end;
+
+function TPasTreeSdoConverter.FindType(const AUri, AName: string): ISDOType;
+begin
+  Result := FTypeList.find(AUri,AName);
+  if ( Result = nil ) and AnsiSameText(AUri,s_xs) then
+    Result := FTypeList.find(sdo_namespace,AName);
+end;
+
+function TPasTreeSdoConverter.TranslateVariable(AElement: ISDODataObject): ISDOType;
+var
+  new_type : ISDOType;
+  loc_uri, loc_name : string;
+  dest_type : ISDOType;
+begin
+  loc_uri := GetVariableNameSpace(AElement);
+  loc_name := AElement.getString(s_Name);
+  new_type := FindType(loc_uri,loc_name);
+  if ( new_type = nil ) then begin
+    dest_type := TranslateType(AElement.getDataObject(s_DataType));
+    if AnsiSameText(loc_uri,dest_type.getURI()) then begin
+      new_type := dest_type;
+      FDataFactory.setAlias(dest_type.getURI(),dest_type.getName(),loc_name);// dest_type.setAlias(loc_name);
+    end else begin
+      FDataFactory.AddType(
+        loc_uri,
+        loc_name,
+        dest_type.getFlags()
+      );
+      new_type := FDataFactory.getType(loc_uri,loc_name);
+      FDataFactory.setBaseType(new_type,dest_type);
+    end;
+  end;
+  Result := new_type;
+end;
+
+{function TPasTreeSdoConverter.TranslateArray(AElement: TPasArrayType): ISDOType;
+var
+  new_type : ISDOType;
+  loc_uri, loc_name : string;
+  item_type : ISDOType;
+  typeflgs : TTypeFlags;
+  propFlags : TPropertyFlags;
+  ls : TStrings;
+begin
+  loc_uri := FTree.GetNameSpace(AElement);
+  loc_name := FTree.GetExternalName(AElement);
+  new_type := FindType(loc_uri,loc_name);
+  if ( new_type = nil ) then begin
+    item_type := TranslateType(AElement.ElType);
+    typeflgs := [];
+    ls := FTree.Properties.FindList(AElement);
+    if ( ls <> nil ) and
+       ( ( ls.IndexOfName(s_xsd_namespace + '#' + s_any) >= 0 ) or
+         ( ls.IndexOfName(s_xsd_namespace + '#' + s_anyAttribute) >= 0 )
+       )
+    then begin
+      Include(typeflgs,tfIsOpen);
+    end;
+    FDataFactory.AddType(loc_uri,loc_name,typeflgs);
+    new_type := FDataFactory.getType(loc_uri,loc_name);
+    propFlags := [pfIsMany];
+    if item_type.isDataObjectType() then
+      Include(propFlags,pfIsContainment (* TODO : what for array of ID ( array of object reference ) ? *));
+    FDataFactory.addProperty(new_type,FTree.GetArrayItemExternalName(AElement),item_type,propFlags);
+  end;
+  Result := new_type;
+end;}
+
+function TPasTreeSdoConverter.TranslateClass(AElement: ISDODataObject) : ISDOType;
+var
+  new_type : ISDOType;
+
+  function FindSpecialType(const AProp : ISDODataObject) : ISDOType;
+  var
+    line, ns, localName : string;
+    k : PtrInt;
+  begin
+    Result := nil;
+    line := Trim(FindTag(AProp,Format('%s#%s',[sdo_namespace,sdo_consts.s_propertyType])));
+    if ( Length(line) > 0 ) then begin
+      k := Pos('#',line);
+      if ( k > 0 ) then begin
+        ns := Copy(line,1,Pred(k));
+        localName := Copy(line,Succ(k),MaxInt);
+        Result := FDataFactory.getTypes().find(ns,localName);
+        if ( Result = nil ) then
+          raise ESDOTypeNotFoundException.Create(Format('%s#%s',[ns,localName]));
+      end;
+    end;
+  end;
+
+  function FindReferenceType(const AProp : ISDODataObject) : ISDOType;
+  begin
+    Result := FindSpecialType(AProp);
+  end;
+
+  procedure ProcessProperty(const AProp : ISDODataObject);
+  var
+    p : ISDODataObject;
+    pt, tmp : ISDODataObject;
+    loc_isArray, loc_isReadOnly, loc_isContainment, loc_isReference, loc_isNullable : Boolean;
+    ptSDO : ISDOType;
+    flgs : TPropertyFlags;
+  begin
+    loc_isReference := False;
+    p := AProp;
+    pt := p.getDataObject(s_DataType);
+    ptSDO := FindReferenceType(AProp);
+    if pt.getBoolean(s_Unresolved) then begin
+      tmp := Find(FTree,GetTypeNameSpace(pt),pt.getString(s_Name));
+      if (tmp <> nil) then
+        pt := tmp;
+    end;
+    if (pt.getString(s_Name) = s_anyURI) and (GetTypeNameSpace(pt) = s_xs) then begin
+      //ptSDO := FindReferenceType(AProp);
+      if ( ptSDO <> nil ) then
+        loc_isReference := True;
+    end;
+    pt := GetUltimeType(pt);
+    loc_isArray := (p.getInteger(s_PropertyMaxOccurs) > 1);
+    if (pt.getString(s_Name) = s_anyURI) and (GetTypeNameSpace(pt) = s_xs) then begin
+      //ptSDO := FindReferenceType(AProp);
+      if ( ptSDO <> nil ) then
+        loc_isReference := True;
+    end;
+    if (pt.getString(s_Name) = SDOTypeDefaultTypeNames[ChangeSummaryType]) and
+       (GetTypeNameSpace(pt) = sdo_namespace)
+    then begin
+      loc_isReadOnly := True;
+      loc_isContainment := False;
+      ptSDO := FDataFactory.getType(sdo_namespace,s_changeSummary);
+    end else begin
+      loc_isReadOnly := False;
+      loc_isContainment := (not loc_isReference) and pt.getBoolean(s_IsComplex);
+    end;
+    loc_isNullable := (p.getInteger(s_PropertyMinOccurs) = 0);
+    if ( ptSDO = nil ) then
+      ptSDO := TranslateType(pt);
+    flgs := [];
+    if loc_isArray then
+      Include(flgs, pfIsMany);
+    if loc_isReadOnly then
+      Include(flgs, pfIsReadOnly);
+    if loc_isContainment then
+      Include(flgs, pfIsContainment);
+    if loc_isNullable then
+      Exclude(flgs, pfIsNotNullable);
+    if p.getBoolean(s_IsAttribute) then
+      Include(flgs, pfIsAttribute);
+    FDataFactory.addProperty(
+      new_type,
+      p.getString(s_Name),
+      ptSDO,
+      flgs
+    );
+  end;
+
+  function IsOpenType() : Boolean;
+  var
+    locStrBuffer : string;
+  begin
+    locStrBuffer := FindTag(AElement,Format('%s#%s',[s_xsd_namespace,s_any]));
+    Result := not IsStrEmpty(locStrBuffer);
+    if not Result then begin
+      locStrBuffer := FindTag(AElement,Format('%s#%s',[s_xsd_namespace,s_anyAttribute]));
+      Result := not IsStrEmpty(locStrBuffer);
+    end;
+  end;
+
+  procedure TranslateBaseType();
+  var
+    base : ISDODataObject;
+    sdoBase : ISDOType;
+  begin
+    base := AElement.getDataObject(s_BaseType);
+    if (base = nil) then
+      Exit;
+    sdoBase := TranslateType(base);
+    if (sdoBase <> nil) then
+      FDataFactory.setBaseType(new_type,sdoBase);
+  end;
+
+var
+  loc_uri, loc_name : string;
+  memberList : ISDODataObjectList;
+  i : PtrInt;
+  typFlags : TTypeFlags;
+begin
+  loc_uri := GetTypeNameSpace(AElement);
+  loc_name := AElement.getString(s_Name);
+  new_type := FindType(loc_uri,loc_name);
+  if ( new_type = nil ) then begin
+    typFlags := [];
+    if IsOpenType() then
+      Include(typFlags,tfIsOpen);
+    FDataFactory.AddType(loc_uri,loc_name,typFlags);
+    new_type := FDataFactory.getType(loc_uri,loc_name);
+    TranslateBaseType();
+    memberList := AElement.getList(s_Property);
+    for i := 0 to memberList.size() - 1 do
+      ProcessProperty(memberList.getDataObject(i));
+  end;
+  Result := new_type;
+end;
+
+function TPasTreeSdoConverter.TranslateEnum(AElement: ISDODataObject): ISDOType;
+var
+  new_type : ISDOType;
+  new_typeX : ISDOTypeEx;
+  loc_uri, loc_name : string;
+begin
+  loc_uri := GetTypeNameSpace(AElement);
+  loc_name := AElement.getString(s_Name);
+  new_type := FindType(loc_uri,loc_name);
+  if ( new_type = nil ) then begin
+    FDataFactory.AddType(loc_uri,loc_name,[tfIsDataType]);
+    new_type := FDataFactory.getType(loc_uri,loc_name);
+    new_typeX := new_type as ISDOTypeEx;
+    new_typeX.setBaseType(FDataFactory.getType(sdo_namespace,'string'));
+  end;
+  Result := new_type;
+end;
+
+procedure TPasTreeSdoConverter.TranslateModule(AModule: ISDODataObject);
+var
+  i : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  ls := AModule.getList(s_Type);
+  for i := 0 to ls.size() - 1 do
+    TranslateType(ls.getDataObject(i));
+  ls := AModule.getList(s_Variable);
+  for i := 0 to ls.size() - 1 do
+    TranslateVariable(ls.getDataObject(i));
+end;
+
+function TPasTreeSdoConverter.TranslateType(AType: ISDODataObject): ISDOType;
+var
+  locUri, locName : string;
+  locType : ISDODataObject;
+begin
+  Result := nil;
+  locType := AType;
+  if locType.getBoolean(s_Unresolved) then begin
+    locType := Find(FTree,GetTypeNameSpace(AType),AType.getString(s_Name));
+    if (locType = nil) then
+      locType := AType;
+  end;
+  locUri := GetTypeNameSpace(locType);
+  locName := locType.getString(s_Name);
+  if ( Result = nil ) then
+    Result := FindType(locUri,locName);
+  if ( Result = nil ) then begin
+    if locType.getBoolean(s_IsComplex) then
+      Result := TranslateClass(locType)
+    else if (locType.getList(s_EnumValue).size() > 0) then
+      Result := TranslateEnum(locType)
+    else if (locType.getByte(s_ElementKind) = ELEMENT_KIND_VARIABLE) then
+      Result := TranslateVariable(locType);
+  end;
+  if ( Result = nil ) then
+    raise ESDOException.CreateFmt('Unable to translate this type : Name = "%s"; Uri = "%s".',[locName,locUri]);
+end;
+
+{ TSdoPasConverter }
+
+constructor TSdoPasConverter.Create(
+  ATree: ISDODataObject;
+  ADataFactory: ISDODataFactory;
+  ATypeList: ISDOTypeList
+);
+begin
+  FTree := ATree;
+  FDataFactory := ADataFactory;
+  FTypeList := ATypeList;
+end;
+
+procedure TSdoPasConverter.Execute();
+var
+  c, i : PtrInt;
+begin
+  c := FTypeList.getCount();
+  for i := 0 to Pred(c) do begin
+    TranslateType(FTypeList.getItem(i));
+  end;
+end;
+
+function TSdoPasConverter.FindOrCreateModule(const ANamespace: string): ISDODataObject;
+var
+  locName : string;
+begin
+  Result := FindModule(FTree,ANamespace);
+  if (Result = nil) then begin
+    locName := ExtractIdentifier(ANamespace);
+    Result := FTree.createDataObject(s_Module);
+    Result.setString(s_Name,locName);
+    Result.setString(s_NameSpace,ANamespace);
+    FTree.getList(s_Module).append(Result);
+    FTree.setDataObject(s_CurrentModule,Result);
+  end;
+end;
+
+function TSdoPasConverter.FindType(const AUri, AName: string): ISDODataObject;
+var
+  locElement : ISDODataObject;
+begin
+  locElement := Find(FTree,AUri,AName);
+  if Assigned(locElement) and (locElement.getByte(s_ElementKind) = ELEMENT_KIND_TYPE) then
+    Result := locElement
+  else
+    Result := nil;
+end;
+
+function TSdoPasConverter.TranslateAlias(const AType: ISDOType): ISDODataObject;
+var
+  res : ISDODataObject;
+  locModule : ISDODataObject;
+begin
+  locModule := FindOrCreateModule(AType.getURI());
+  res := locModule.createDataObject(s_Variable);
+    res.setByte(s_ElementKind,ELEMENT_KIND_VARIABLE);
+    res.setString(s_Name,AType.getName());
+    res.setDataObject(s_DataType,TranslateType(AType.getBaseType()));
+  locModule.getList(s_Variable).append(res);
+  Result := res;
+end;
+
+function TSdoPasConverter.TranslateChangeSummary(const AType: ISDOType): ISDODataObject;
+var
+  res : ISDODataObject;
+  locModule : ISDODataObject;
+begin
+  locModule := FindOrCreateModule(AType.getURI());
+  res := locModule.createDataObject(s_Type);
+    res.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+    res.setString(s_Name,AType.getName());
+  locModule.getList(s_Type).append(res);
+  Result := res;
+end;
+
+function TSdoPasConverter.TranslateObject(const AType: ISDOType): ISDODataObject;
+var
+  res : ISDODataObject;
+  locModule : ISDODataObject;
+
+  procedure TranslateProps();
+  var
+    propList : ISDOPropertyList;
+
+    procedure TranslateProperty(const AProperty : ISDOProperty);
+    var
+      propType : ISDODataObject;
+      prop : ISDODataObject;
+      propTypeSDO : ISDOType;
+      isObjRefProp : Boolean;
+    begin
+      if not AProperty.getContainingType().equals(AType) then
+        Exit;
+      propTypeSDO := AProperty.getType();
+      isObjRefProp := propTypeSDO.isDataObjectType() and AProperty.isReference();
+      if isObjRefProp then
+        propType := Find(FTree,s_xs,s_anyURI)
+      else
+        propType := TranslateType(propTypeSDO);
+      prop := res.createDataObject(s_Property);
+        prop.setString(s_Name,AProperty.getName());
+        prop.setDataObject(s_DataType,propType);
+        if AProperty.getType().isChangeSummaryType() then
+          prop.setInteger(s_PropertyMinOccurs,1);
+        if AProperty.isMany() then
+          prop.setInteger(s_PropertyMaxOccurs,MaxInt);
+        prop.setBoolean(
+          s_IsAttribute,
+          (not( propTypeSDO.isDataObjectType() or
+                isObjRefProp or
+                AProperty.isMany() or
+                AProperty.getType().isChangeSummaryType()
+              )
+          ) and
+          AProperty.isAttribute()
+        );
+      res.getList(s_Property).append(prop);
+      if isObjRefProp or (propTypeSDO.getTypeEnum() in SDO_SPECIAL_TYPES) then
+        SetTagValue(
+          prop,
+          Format('%s#%s',[sdo_namespace,sdo_consts.s_propertyType]),
+          Format('%s#%s',[propTypeSDO.getURI(),propTypeSDO.getName()])
+        );
+    end;
+
+  var
+    k , propCount : PtrUInt;
+  begin
+    propList := AType.getProperties();
+    propCount := propList.getCount();
+    if ( propCount > 0 ) then begin
+      for k := 0 to Pred(propCount) do begin
+        TranslateProperty(propList.getItem(k));
+      end;
+    end;
+  end;
+
+  procedure MarkAsOpenType();
+  begin
+    SetTagValue(
+      res,
+      s_xsd_namespace + '#' + s_any,
+      s_maxOccurs + '=' + s_unbounded +
+        ';' + s_processContents + '=lax'
+    );
+    SetTagValue(
+      res,
+      s_xsd_namespace + '#' + s_anyAttribute,
+      s_processContents + '=lax'
+    );
+  end;
+
+  procedure TranslateBaseType();
+  var
+    base : ISDOType;
+    pasBase : ISDODataObject;
+  begin
+    base := AType.getBaseType();
+    if (base = nil) then
+      Exit;
+    pasBase := TranslateType(base);
+    if (pasBase <> nil) then
+      res.setDataObject(s_BaseType,pasBase);
+  end;
+
+begin
+  locModule := FindOrCreateModule(AType.getURI());
+  res := locModule.createDataObject(s_Type);
+    res.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+    res.setBoolean(s_IsComplex,True);
+    res.setString(s_Name,AType.getName());
+  locModule.getList(s_Type).append(res);
+  TranslateBaseType();
+  TranslateProps();
+  if AType.isOpenType() then
+    MarkAsOpenType();
+  Result := res;
+end;
+
+function TSdoPasConverter.TranslateType(const AType : ISDOType) : ISDODataObject;
+var
+  elt : ISDODataObject;
+  res : ISDODataObject;
+  c, i : PtrInt;
+  locURI, locName : TSDOString;
+begin
+  locURI := AType.getURI();
+  locName := AType.getName();
+  res := FindType(locURI,locName);
+  if ( res = nil ) then begin
+    c := AType.getAliasCount();
+    for i := 0 to Pred(c) do begin
+      res := FindType(locURI,AType.getAlias(i));
+      if Assigned(res) then
+        Break;
+    end;
+  end;
+  if ( res = nil ) then begin
+    if AType.isDataType() then begin
+      if AType.isChangeSummaryType() then begin
+        res := TranslateChangeSummary(AType);
+      end else if ( AType.getBaseType() = nil ) then begin
+        elt := Find(FTree,s_xs,locName);
+        if not (Assigned(elt) and (elt.getByte(s_ElementKind) = ELEMENT_KIND_TYPE)) then begin
+          c := AType.getAliasCount();
+          if ( c > 0 ) then begin
+            for i := 0 to Pred(c) do begin
+              elt := Find(FTree,s_xs,AType.getAlias(i));
+              if Assigned(elt) and (elt.getByte(s_ElementKind) = ELEMENT_KIND_TYPE) then
+                Break;
+            end;
+          end;
+        end;
+        if Assigned(elt) and (elt.getByte(s_ElementKind) = ELEMENT_KIND_TYPE) then
+          res := elt
+        else
+          res := Find(FTree,s_xs,'string');
+      end else begin
+        res := TranslateAlias(AType);
+      end;
+    end else if AType.isChangeSummaryType() then begin
+      res := TranslateChangeSummary(AType);
+    end else begin
+      res := TranslateObject(AType);
+    end;
+  end;
+  Result := res;
+end;
+
+end.

+ 508 - 0
packages/fcl-sdo/src/base/sdo_xsdintf.pas

@@ -0,0 +1,508 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements basic XSD - SDO type mapping
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_xsdintf;
+
+interface
+uses
+  SysUtils,
+  sdo;
+
+const
+{ Type tree :
+    s_TypeTreeType
+      s_Module (s_ModuleType)
+        s_Type (s_SchemaTypeType)
+        s_Variable (s_VariableType)
+      s_Unresolved (s_SchemaTypeType)
+      s_UnresolvedLink (s_UnresolvedLink)
+
+
+  Type Tree properties
+    s_NameValueType
+      Name (String)
+      Value (String)
+
+    s_ElementType
+      Name (String)
+      NameSpace (String, if in module use the module name instead of this!)
+      ElementKind (Byte, ELEMENT_KIND_TYPE, ELEMENT_KIND_VARIABLE, ...)
+      Tag (array, s_NameValueType)
+
+    s_TypeTreeType (inherits s_ElementType)
+      Module (array, s_ModuleType)
+      CurrentModule (s_ModuleType)
+      Unresolved (s_SchemaTypeType)
+
+    s_Module_Type (inherits s_ElementType)
+      Native (Boolean)
+      Type (array, s_SchemaTypeType)
+      Variable (array, s_VariableType)
+
+    s_SchemaTypeType (inherits s_ElementType)
+      IsComplex (Boolean)
+      BaseType (s_SchemaTypeType)
+      Unresolved (Boolean)
+      Embedded (Boolean)
+      Property (array, s_PropertyType)
+      EnumValue(array, String)
+
+    s_VariableType (inherits s_ElementType)
+      DataType (s_SchemaTypeType)
+
+    s_PropertyType (inherits s_ElementType)
+      DataType (s_SchemaTypeType)
+      IsAttribute (Boolean)
+      DefaultValue (String)
+      MinOccurs (Integer)
+      MaxOccurs (Integer)
+
+    s_UnresolvedLinkType
+      Element (s_SchemaTypeType)
+      Target (s_SchemaTypeType)
+      LinkKind (String)
+      Resolved (Boolean)
+}
+  s_XsdParserNS       = 'xsd:parser:ns';
+  s_SchemaTypeType    = 'SchemaTypeType';
+
+  s_BaseType          = 'BaseType';
+  s_CurrentModule     = 'CurrentModule';
+  s_DataType          = 'DataType';
+  s_DefaultValue      = 'DefaultValue';
+  s_Element           = 'Element';
+  s_ElementKind       = 'ElementKind';
+  s_ElementType       = 'ElementType';
+  s_Embedded          = 'Embedded';
+  s_EnumValue         = 'EnumValue';
+  s_IsAttribute       = 'IsAttribute';
+  s_IsComplex         = 'IsComplex';
+  s_LinkKind          = 'LinkKind';
+  s_Module            = 'Module';
+  s_ModuleType        = 'ModuleType';
+  s_Name              = 'Name';
+  s_NameSpace         = 'NameSpace';
+  s_NameValueType     = 'NameValueType';
+  s_Native            = 'Native';
+  s_Property          = 'Property';
+  s_PropertyMaxOccurs = 'MaxOccurs';
+  s_PropertyMinOccurs = 'MinOccurs';
+  s_PropertyType      = 'PropertyType';
+  s_Resolved          = 'Resolved';
+  s_Tag               = 'Tag';
+  s_Target            = 'Target';
+  s_Type              = 'Type';
+  s_TypeTreeType      = 'TypeTreeType';
+  s_Unresolved        = 'Unresolved';
+  s_UnresolvedLink    = 'UnresolvedLink';
+  s_UnresolvedLinkType= 'UnresolvedLinkType';
+  s_UnresolvedType    = 'UnresolvedType';
+  s_Value             = 'Value';
+  s_Variable          = 'Variable';
+  s_VariableType      = 'VariableType';
+
+  ELEMENT_KIND_TYPE       = TSDOByte(1);
+  ELEMENT_KIND_VARIABLE   = TSDOByte(2);
+  ELEMENT_KIND_PROPERTY   = TSDOByte(4);
+
+  LINK_KIND_BASE_TYPE = 'BASE_TYPE';
+  LINK_KIND_PROP_TYPE = 'PROPERTY_TYPE';
+
+  XSD_NAME_SPACE = 'http://www.w3.org/2001/XMLSchema';
+  XSD_TYPES : array[0..26] of string = (
+    'anyType', 'anyURI',
+    'base64Binary', 'boolean', 'byte',
+    'date', 'dateTime', 'decimal', 'double', 'duration',
+    'float',
+    'hexBinary',
+    'ID', 'int',
+    'language', 'long',
+    'nonNegativeInteger',
+    'positiveInteger',
+    'schema', 'short', 'string',
+    'time', 'token',
+    'unsignedByte', 'unsignedInt', 'unsignedLong', 'unsignedShort'
+  );
+
+  procedure AddTypeTree(const AFactory : ISDODataFactory);
+  function FindInModule(
+    const AModule : ISDODataObject;
+    const AName   : string
+  ) : ISDODataObject;
+  function FindVariableInModule(
+    const AModule : ISDODataObject;
+    const AName   : string
+  ) : ISDODataObject;
+  function Find(
+    const ATypeTree : ISDODataObject;
+    const AName     : string
+  ) : ISDODataObject; overload;
+  function Find(
+    const ATypeTree : ISDODataObject;
+    const ANameSpace,
+          AName     : string
+  ) : ISDODataObject; overload;
+  function FindVariable(
+    const ATypeTree : ISDODataObject;
+    const AName     : string
+  ) : ISDODataObject;
+  function FindModule(
+    const ATypeTree  : ISDODataObject;
+    const AName : string
+  ) : ISDODataObject;
+
+  procedure SetTagValue(
+    const AObject : ISDODataObject;
+    const AName,
+          AValue  : string
+  );
+
+  procedure AddXsdTypes(ATypeTree  : ISDODataObject);
+
+  function GetUltimeType(AType : ISDODataObject) : ISDODataObject;
+  function FindTag(
+          AObject  : ISDODataObject;
+    const ATagName : TSDOString
+  ) : TSDOString; overload;
+  function FindTag(
+          AObject  : ISDODataObject;
+    const ATagName : TSDOString;
+    var   AResult  : TSDOString
+  ) : Boolean; overload;
+
+  function GetVariableNameSpace(AVariable : ISDODataObject) : string;
+  function GetTypeNameSpace(AType : ISDODataObject) : string;
+  function IsNativeType(AType : ISDODataObject) : Boolean;
+
+
+implementation
+
+procedure AddTypeTree(const AFactory : ISDODataFactory);
+var
+  f, m, e, st, nv, vt, pt, ul : ISDOType;
+begin
+  f := AFactory.getTypes().find(s_XsdParserNS,s_TypeTreeType);
+  if (f <> nil) then
+    Exit;
+
+  AFactory.AddType(s_XsdParserNS,s_ModuleType,[]);
+  AFactory.AddType(s_XsdParserNS,s_TypeTreeType,[]);
+  AFactory.AddType(s_XsdParserNS,s_ElementType,[]);
+  AFactory.AddType(s_XsdParserNS,s_SchemaTypeType,[]);
+  AFactory.AddType(s_XsdParserNS,s_VariableType,[]);
+  AFactory.AddType(s_XsdParserNS,s_PropertyType,[]);
+  AFactory.AddType(s_XsdParserNS,s_UnresolvedLinkType,[]);
+  AFactory.AddType(s_XsdParserNS,s_NameValueType,[]);
+
+  f := AFactory.getType(s_XsdParserNS,s_TypeTreeType);
+  m := AFactory.getType(s_XsdParserNS,s_ModuleType);
+  e := AFactory.getType(s_XsdParserNS,s_ElementType);
+  st := AFactory.getType(s_XsdParserNS,s_SchemaTypeType);
+  nv := AFactory.getType(s_XsdParserNS,s_NameValueType);
+  vt := AFactory.getType(s_XsdParserNS,s_VariableType);
+  pt := AFactory.getType(s_XsdParserNS,s_PropertyType);
+  ul := AFactory.getType(s_XsdParserNS,s_UnresolvedLinkType);
+
+  AFactory.addProperty(f,s_Module,m,[pfIsMany,pfIsContainment,pfIsNotNullable]);
+  AFactory.addProperty(f,s_CurrentModule,m,[]);
+  AFactory.addProperty(f,s_Unresolved,st,[pfIsMany,pfIsContainment,pfIsNotNullable]);
+  AFactory.addProperty(f,s_UnresolvedLink,ul,[pfIsMany,pfIsContainment,pfIsNotNullable]);
+
+  AFactory.setBaseType(m,e);
+  AFactory.addProperty(m,s_Native,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+  AFactory.addProperty(m,s_Type,st,[pfIsMany,pfIsContainment,pfIsNotNullable]);
+  AFactory.addProperty(m,s_Variable,vt,[pfIsMany,pfIsContainment,pfIsNotNullable]);
+
+  AFactory.addProperty(e,s_Name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+  AFactory.addProperty(e,s_NameSpace,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+  AFactory.addProperty(e,s_ElementKind,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsReadOnly,pfIsNotNullable]);
+  AFactory.addProperty(e,s_Tag,s_XsdParserNS,s_NameValueType,[pfIsMany,pfIsContainment]);
+
+  AFactory.setBaseType(st,e);
+  AFactory.addProperty(st,s_IsComplex,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+  AFactory.addProperty(st,s_BaseType,st,[]);
+  AFactory.addProperty(st,s_Unresolved,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+  AFactory.addProperty(st,s_Embedded,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+  AFactory.addProperty(st,s_Property,pt,[pfIsMany,pfIsContainment,pfIsNotNullable]);
+  AFactory.addProperty(st,s_EnumValue,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  //st.getProperty(s_ElementKind).setDefault(ELEMENT_KIND_TYPE);
+
+  AFactory.setBaseType(vt,e);
+  AFactory.addProperty(vt,s_DataType,st,[]);
+  //vt.getProperty(s_ElementKind).setDefault(ELEMENT_KIND_VARIABLE);
+
+  AFactory.setBaseType(pt,e);
+  //AFactory.addProperty(pt,s_DataType,st,[]);
+  AFactory.addProperty(pt,s_DataType,sdo_namespace,SDOTypeDefaultTypeNames[ObjectType],[]);
+  AFactory.addProperty(pt,s_IsAttribute,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+  AFactory.addProperty(pt,s_PropertyMinOccurs,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+  AFactory.addProperty(pt,s_PropertyMaxOccurs,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+  AFactory.addProperty(pt,s_DefaultValue,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+  //vt.getProperty(s_ElementKind).setDefault(ELEMENT_KIND_PROPERTY);
+
+  AFactory.addProperty(nv,s_Name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+  AFactory.addProperty(nv,s_Value,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+
+
+  AFactory.addProperty(ul,s_Element,st,[]);
+  AFactory.addProperty(ul,s_Target,st,[]);
+  AFactory.addProperty(ul,s_LinkKind,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+  AFactory.addProperty(ul,s_Name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+  AFactory.addProperty(ul,s_Resolved,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+
+end;
+
+function InheritsFrom(const AChild, AParent : ISDOType) : Boolean;
+begin
+  Result := False;
+  if (AChild = nil) or (AParent = nil)
+  then
+    Exit;
+
+  Result := (AChild <> nil) and
+            (AParent <> nil) and
+            (AChild.equals(AParent) or InheritsFrom(AChild.getBaseType(),AParent));
+end;
+
+function FindInModule(
+  const AModule : ISDODataObject;
+  const AName   : string
+) : ISDODataObject;
+begin
+  Result := AModule.getDataObject(Format('%s[%s=%s]',[s_Type,s_Name,QuotedStr(AName)]));
+  if (Result = nil) then
+    Result := AModule.getDataObject(Format('%s[%s=%s]',[s_Variable,s_Name,QuotedStr(AName)]));
+end;
+
+function FindVariableInModule(
+  const AModule : ISDODataObject;
+  const AName   : string
+) : ISDODataObject;
+begin
+  Result := AModule.getDataObject(Format('%s[%s=%s]',[s_Variable,s_Name,QuotedStr(AName)]));
+end;
+
+function Find(
+  const ATypeTree : ISDODataObject;
+  const AName     : string
+) : ISDODataObject;
+var
+  locCurrentModule, locModule : ISDODataObject;
+  locModules : ISDODataObjectList;
+  i : Integer;
+  locRes : ISDODataObject;
+begin
+  locCurrentModule := ATypeTree.getDataObject(s_CurrentModule);
+  if (locCurrentModule <> nil) then
+    Result := FindInModule(locCurrentModule,AName);
+  if (Result = nil) then begin
+    locModules := ATypeTree.getList(s_Module);
+    if (locModules.size() > 0) then begin
+      for i := 0 to locModules.size() - 1 do begin
+        locModule := locModules.getDataObject(i);
+        if (locModule <> locCurrentModule) then begin
+          locRes := FindInModule(locModule,AName);
+          if (locRes <> nil) then begin
+            Result := locRes;
+            Break;
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+function FindVariable(
+  const ATypeTree : ISDODataObject;
+  const AName     : string
+) : ISDODataObject;
+var
+  locCurrentModule, locModule : ISDODataObject;
+  locModules : ISDODataObjectList;
+  i : Integer;
+  locRes : ISDODataObject;
+begin
+  locCurrentModule := ATypeTree.getDataObject(s_CurrentModule);
+  if (locCurrentModule <> nil) then
+    Result := FindVariableInModule(locCurrentModule,AName);
+  if (Result = nil) then begin
+    locModules := ATypeTree.getList(s_Module);
+    if (locModules.size() > 0) then begin
+      for i := 0 to locModules.size() - 1 do begin
+        locModule := locModules.getDataObject(i);
+        if (locModule <> locCurrentModule) then begin
+          locRes := FindVariableInModule(locModule,AName);
+          if (locRes <> nil) then begin
+            Result := locRes;
+            Break;
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+function Find(
+  const ATypeTree : ISDODataObject;
+  const ANameSpace,
+        AName     : string
+) : ISDODataObject;
+var
+  locModule : ISDODataObject;
+begin
+  locModule := ATypeTree.getDataObject(Format('%s[%s=%s]',[s_Module,s_NameSpace,QuotedStr(ANameSpace)]));
+  if (locModule <> nil) then
+    Result := FindInModule(locModule,AName);
+end;
+
+function FindModule(
+  const ATypeTree  : ISDODataObject;
+  const AName : string
+) : ISDODataObject;
+begin
+  Result := ATypeTree.getDataObject(Format('%s[%s=%s]',[s_Module,s_Name,QuotedStr(AName)]));
+  if (Result = nil) then
+    Result := ATypeTree.getDataObject(Format('%s[%s=%s]',[s_Module,s_NameSpace,QuotedStr(AName)]));
+end;
+
+procedure SetTagValue(
+  const AObject : ISDODataObject;
+  const AName,
+        AValue  : string
+);
+var
+  locTag : ISDODataObject;
+begin
+  locTag := AObject.getDataObject(Format('%s[%s=%s]',[s_Tag,s_Name,QuotedStr(AName)]));
+  if (locTag = nil) then begin
+    locTag := AObject.createDataObject(s_Tag);
+    locTag.setString(s_Name,AName);
+    AObject.getList(s_Tag).append(locTag);
+  end;
+  locTag.setString(s_Value,AValue);
+end;
+
+procedure AddXsdTypes(ATypeTree  : ISDODataObject);
+var
+  locModule, locType : ISDODataObject;
+  locTypeList : ISDODataObjectList;
+  i : Integer;
+begin
+  locModule := FindModule(ATypeTree,XSD_NAME_SPACE);
+  if (locModule <> nil) then
+    exit;
+
+  locModule := ATypeTree.createDataObject(s_Module);
+  locModule.setBoolean(s_Native,True);
+  locModule.setString(s_NameSpace,XSD_NAME_SPACE);
+  locModule.setString(s_Name,XSD_NAME_SPACE);
+  ATypeTree.getList(s_Module).append(locModule);
+
+  locTypeList := locModule.getList(s_Type);
+  for i := Low(XSD_TYPES) to High(XSD_TYPES) do begin
+    locType := locModule.createDataObject(s_Type);
+    locType.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+    locType.setString(s_Name,XSD_TYPES[i]);
+    locTypeList.append(locType);
+  end;
+end;
+
+function GetUltimeType(AType : ISDODataObject) : ISDODataObject;
+var
+  p, q : ISDODataObject;
+begin
+  if (AType <> nil) then begin
+    p := AType;
+    if (p.getByte(s_ElementKind) = ELEMENT_KIND_TYPE) then begin
+      Result := p;
+      Exit;
+    end;
+    if (p.getByte(s_ElementKind) = ELEMENT_KIND_VARIABLE) then begin
+      q := p.getDataObject(s_DataType);
+      if (q <> nil) then begin
+        p := q;
+        q := GetUltimeType(q);
+        if (q <> nil) then
+          p := q;
+      end;
+    end;
+    Result := p;
+  end;
+end;
+
+function FindTag(
+        AObject  : ISDODataObject;
+  const ATagName : TSDOString;
+  var   AResult  : TSDOString
+) : Boolean;
+var
+  tagObj : ISDODataObject;
+begin
+  tagObj := AObject.getDataObject(Format('%s[%s=%s]',[s_Tag,s_Name,QuotedStr(ATagName)]));
+  Result := (tagObj <> nil);
+  if Result then
+    AResult := tagObj.getString(s_Value);
+end;
+
+function FindTag(
+        AObject  : ISDODataObject;
+  const ATagName : TSDOString
+) : TSDOString;
+begin
+  if not FindTag(AObject,ATagName,Result) then
+    Result := '';
+end;
+
+function GetTypeNameSpace(AType : ISDODataObject) : string;
+
+  function GetParentNS() : string;
+  var
+    locParent : ISDODataObject;
+  begin
+    locParent := AType.getContainer();
+    if (locParent <> nil) then
+      Result := locParent.getString(s_namespace);
+  end;
+
+var
+  locRes : string;
+begin
+  locRes := AType.getString(s_namespace);
+  if (Trim(locRes) = '') then
+    locRes := GetParentNS();
+  Result := Trim(locRes);
+end;
+
+function GetVariableNameSpace(AVariable : ISDODataObject) : string;
+begin
+  Result := GetTypeNameSpace(AVariable)
+end;
+
+function IsNativeType(AType : ISDODataObject) : Boolean;
+var
+  locParent : ISDODataObject;
+begin
+  Result := False;
+  if (AType <> nil) then begin
+    locParent := AType.getContainer();
+    if AType.getBoolean(s_Unresolved) then
+      locParent := FindModule(locParent,AType.getString(s_NameSpace));
+    if (locParent <> nil) then
+      Result := locParent.getBoolean(s_Native);
+  end
+end;
+
+end.

+ 2178 - 0
packages/fcl-sdo/src/base/sdo_xsdparser.pas

@@ -0,0 +1,2178 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements an XSD parser
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_xsdparser;
+
+interface
+uses
+  Classes, SysUtils, Contnrs,
+{$IFDEF DELPHI}
+  xmldom, sdo_win_xml,
+{$ENDIF DELPHI}
+{$IFDEF FPC}
+  DOM, sdo_fpc_xml,
+{$ENDIF FPC}
+  sdo_cursor_intf, sdo_rtti_filters, sdo_logger_intf,
+  sdo_types, sdo;
+
+type
+
+  EXsdParserException = class(Exception)
+  end;
+
+  EXsdParserAssertException = class(EXsdParserException)
+  end;
+
+  EXsdTypeNotFoundException = class(EXsdParserException)
+  end;
+
+  EXsdInvalidDefinitionException = class(EXsdParserException)
+  end;
+
+  EXsdInvalidTypeDefinitionException = class(EXsdInvalidDefinitionException)
+  end;
+
+  EXsdInvalidElementDefinitionException = class(EXsdInvalidDefinitionException)
+  end;
+
+  TOnParserMessage = procedure (const AMsgType : TMessageType; const AMsg : string) of object;
+
+
+  TNameSpaceValueType = ( nvtExpandValue, nvtShortSynonym );
+  TSearchSpace = ( ssCurrentModule, ssGlobal );
+
+  IDocumentLocator = interface
+    ['{D364A50B-64B1-461C-ADDE-B5918CAB0FE8}']
+    function Find(
+      const ADocLocation : string;
+      out   ADoc : TXMLDocument
+    ) : Boolean;
+  end;
+
+  IParserContext = interface
+    ['{3E924ECE-A9B9-4FBB-BC12-4E728B7E34C5}']
+    function GetXsShortNames() : TStrings;
+    function GetSymbolTable() : ISDODataObject;
+    function FindNameSpace(const AShortName : string; out AResult : string) : Boolean;
+    function FindShortNamesForNameSpace(const ANameSpace : string) : TStrings;
+    function GetTargetNameSpace() : string;
+    function GetTargetModule() : ISDODataObject;
+    function GetDocumentLocator() : IDocumentLocator;
+    procedure SetDocumentLocator(const ALocator : IDocumentLocator);
+  end;
+
+  IXsdParser = interface
+    ['{F0CEC726-A068-4CCC-B1E7-D31F018415B2}']
+    function FindParser(const ANamespace : string) : IXsdParser;
+    function ParseType(
+      const AName,
+            ATypeKind : string { ATypeKind "ComplexType", "SimpleType", "Element" }
+    ) : ISDODataObject; overload;
+    function ParseType(
+      const AName     : string;
+      const ATypeNode : TDOMNode
+    ) : ISDODataObject; overload;
+    procedure ParseTypes();
+    procedure SetNotifier(ANotifier : TOnParserMessage);
+  end;
+
+  TAbstractTypeParserClass = class of TAbstractTypeParser;
+
+  { TAbstractTypeParser }
+
+  TAbstractTypeParser = class
+  private
+    FContext : IParserContext;
+    FTypeNode : TDOMNode;
+    FSymbols : ISDODataObject;
+    FTypeName : string;
+    FEmbededDef : Boolean;
+  private
+    function GetModule: ISDODataObject;{$IFDEF USE_INLINE}inline;{$ENDIF}
+  protected
+    function FindElementNS(
+      const ANameSpace,
+            ALocalName : string;
+      const ASpaceType : TNameSpaceValueType
+    ) : ISDODataObject;
+    function FindElementWithHint(const AName, AHint : string; const ASpace : TSearchSpace) : ISDODataObject;
+    function ExtractTypeHint(AElement : TDOMNode) : string;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure SetAsEmbeddedType(AType : ISDODataObject; const AValue : Boolean);{$IFDEF USE_INLINE}inline;{$ENDIF}
+    function IsEmbeddedType(AType : ISDODataObject) : Boolean;
+    procedure AddUnresolvedLink(
+            AElement,
+            ATarget  : ISDODataObject;
+      const ALinkKind,
+            AName    : string
+    );
+{$IFDEF SDO_HANDLE_DOC}
+    procedure ParseDocumentation(AType : ISDODataObject);
+{$ENDIF SDO_HANDLE_DOC}
+  public
+    constructor Create(
+            AOwner       : IParserContext;
+            ATypeNode    : TDOMNode;
+      const ATypeName    : string;
+      const AEmbededDef  : Boolean
+    );
+    class function ExtractEmbeddedTypeFromElement(
+            AOwner       : IParserContext;
+            AEltNode     : TDOMNode;
+            ASymbols     : ISDODataObject;
+      const ATypeName    : string
+    ) : ISDODataObject;
+    class function GetParserSupportedStyle():string;virtual;abstract;
+    class procedure RegisterParser(AParserClass : TAbstractTypeParserClass);
+    class function GetRegisteredParserCount() : Integer;
+    class function GetRegisteredParser(const AIndex : Integer):TAbstractTypeParserClass;
+    function Parse():ISDODataObject;virtual;abstract;
+    property Module : ISDODataObject read GetModule;
+    property Context : IParserContext read FContext;
+  end;
+
+  TDerivationMode = ( dmNone, dmExtension, dmRestriction );
+  TSequenceType = ( stElement, stAll );
+  TParserTypeHint = ( pthDeriveFromSoapArray );
+  TParserTypeHints = set of TParserTypeHint;
+
+  { TComplexTypeParser }
+
+  TComplexTypeParser = class(TAbstractTypeParser)
+  private
+    FAttCursor : IObjectCursor;
+    FChildCursor : IObjectCursor;
+    FContentNode : TDOMNode;
+    FContentType : string;
+    FBaseType : ISDODataObject;
+    FDerivationMode : TDerivationMode;
+    FDerivationNode : TDOMNode;
+    FSequenceType : TSequenceType;
+    FHints : TParserTypeHints;
+  private
+    //helper routines
+    function ExtractElementCursor(
+      out AAttCursor : IObjectCursor;
+      out AAnyNode, AAnyAttNode : TDOMNode
+    ):IObjectCursor;
+    procedure ExtractExtendedMetadata(const AItem : ISDODataObject; const ANode : TDOMNode);
+  private
+    procedure CreateNodeCursors();
+    procedure ExtractTypeName();
+    procedure ExtractContentType();
+    procedure ExtractBaseType();
+    function ParseSimpleContent(const ATypeName : string) : ISDODataObject;
+    function ParseEmptyContent(const ATypeName : string):ISDODataObject;
+    function ParseComplexContent(const ATypeName : string):ISDODataObject;virtual;
+  public
+    class function GetParserSupportedStyle():string;override;
+    function Parse():ISDODataObject;override;
+  end;
+
+  { TSimpleTypeParser }
+
+  TSimpleTypeParser = class(TAbstractTypeParser)
+  private
+    FAttCursor : IObjectCursor;
+    FChildCursor : IObjectCursor;
+    FBaseName : string;
+    FBaseNameSpace : string;
+    FRestrictionNode : TDOMNode;
+    FIsEnum : Boolean;
+  private
+    procedure CreateNodeCursors();
+    procedure ExtractTypeName();
+    function ExtractContentType() : Boolean;
+    function ParseEnumContent():ISDODataObject;
+    function ParseOtherContent():ISDODataObject;
+  public
+    class function GetParserSupportedStyle():string;override;
+    function Parse():ISDODataObject;override;
+  end;
+
+  { TCustomXsdSchemaParser }
+
+  TCustomXsdSchemaParser = class(TInterfacedObject, IInterface, IParserContext, IXsdParser)
+  private
+    FDoc : TXMLDocument;
+    FParentContext : Pointer;//IParserContext;
+    FSymbols : ISDODataObject;
+    FModuleName : string;
+    FModule : ISDODataObject;
+    FTargetNameSpace : string;
+    FSchemaNode : TDOMNode;
+  private
+    FNameSpaceList : TStringList;
+    FXSShortNames : TStrings;
+    FChildCursor : IObjectCursor;
+    FOnMessage: TOnParserMessage;
+    FDocumentLocator : IDocumentLocator;
+    FImportParsed : Boolean;
+    FXsdParsers : TStringList;
+  private
+    procedure DoOnMessage(const AMsgType : TMessageType; const AMsg : string);
+  private
+    function FindNamedNode(AList : IObjectCursor; const AName : WideString; const AOrder : Integer = 0):TDOMNode;
+    function GetParentContext() : IParserContext;{$IFDEF USE_INLINE}inline;{$ENDIF}
+    procedure Prepare();
+    function FindElementNS(
+      const ANameSpace,
+            ALocalName : string;
+      const ASpaceType : TNameSpaceValueType
+    ) : ISDODataObject;
+  protected
+    function GetXsShortNames() : TStrings;
+    function GetSymbolTable() : ISDODataObject;
+    function FindNameSpace(const AShortName : string; out AResult : string) : Boolean;
+    function FindShortNamesForNameSpaceLocal(const ANameSpace : string) : TStrings;
+    function FindShortNamesForNameSpace(const ANameSpace : string) : TStrings;
+    function GetDocumentLocator() : IDocumentLocator;
+    procedure SetDocumentLocator(const ALocator : IDocumentLocator);
+
+    procedure SetNotifier(ANotifier : TOnParserMessage);
+    function InternalParseType(
+      const AName : string;
+      const ATypeNode : TDOMNode
+    ) : ISDODataObject;
+    procedure CreateImportParsers();
+    procedure ParseImportDocuments(); virtual;
+    procedure HandleUnresolvedLinks();
+  public
+    constructor Create(
+      ADoc           : TXMLDocument;
+      ASchemaNode    : TDOMNode;
+      ASymbols       : ISDODataObject;
+      AParentContext : IParserContext
+    );
+    destructor Destroy();override;
+    function FindParser(const ANamespace : string) : IXsdParser;
+    function ParseType(
+      const AName,
+            ATypeKind : string { ATypeKind "ComplexType", "SimpleType", "Element" }
+    ) : ISDODataObject; overload;
+    function ParseType(
+      const AName     : string;
+      const ATypeNode : TDOMNode
+    ) : ISDODataObject; overload;
+
+    procedure ParseTypes();
+
+    function GetTargetNameSpace() : string;
+    function GetTargetModule() : ISDODataObject;
+
+    property SymbolTable : ISDODataObject read FSymbols;
+    property Module : ISDODataObject read FModule;
+    property OnMessage : TOnParserMessage read FOnMessage write FOnMessage;
+  end;
+  TCustomXsdSchemaParserClass = class of TCustomXsdSchemaParser;
+
+  TXsdParser = class(TCustomXsdSchemaParser)
+  public
+    constructor Create(
+            ADoc : TXMLDocument;
+            ASymbols : ISDODataObject;
+      const AModuleName : string;
+      const ANotifier : TOnParserMessage = nil
+    );
+  end;
+
+
+  procedure ParseSchema(
+    const AFileName : string;
+          ATypeTree : ISDODataObject
+  );
+
+
+implementation
+uses
+{$IFDEF FPC}
+  xmlread,
+{$ENDIF FPC}
+  sdo_dom_cursors, sdo_parserutils, StrUtils, xsd_consts, sdo_consts,
+  sdo_xsdintf, sdo_utils;
+
+procedure ParseSchema(
+  const AFileName : string;
+        ATypeTree : ISDODataObject
+);
+var
+  locDoc : TXMLDocument;
+  locParser : IXsdParser;
+begin
+  ReadXMLFile(locDoc,AFileName);
+  locParser := TXsdParser.Create(locDoc,ATypeTree,'');
+  locParser.ParseTypes();
+end;
+
+
+function NodeValue(const ANode : TDOMNode) : DOMString;{$IFDEF USE_INLINE}inline;{$ENDIF}
+begin
+  if ( ANode = nil ) then
+    Result := ''
+  else
+    Result := ANode.NodeValue;
+end;
+
+function CreateUnresolvedType(
+  const ATypeTree  : ISDODataObject;
+  const ANamespace,
+        AName      : string
+) : ISDODataObject;
+var
+  locRes : ISDODataObject;
+begin
+  locRes := ATypeTree.createDataObject(s_Unresolved);
+    locRes.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+    locRes.setBoolean(s_Unresolved,True);
+    locRes.setString(s_NameSpace,ANamespace);
+    locRes.setString(s_Name,AName);
+    ATypeTree.getList(s_Unresolved).append(locRes);
+  Result := locRes;
+end;
+
+{ TAbstractTypeParser }
+
+constructor TAbstractTypeParser.Create(
+        AOwner       : IParserContext;
+        ATypeNode    : TDOMNode;
+  const ATypeName    : string;
+  const AEmbededDef  : Boolean
+);
+var
+  symtbl : ISDODataObject;
+begin
+  Assert(Assigned(AOwner));
+  Assert(Assigned(ATypeNode));
+  symtbl := AOwner.GetSymbolTable();
+  Assert(Assigned(symtbl));
+  FContext := AOwner;
+  FTypeNode := ATypeNode;
+  FSymbols := symtbl;
+  FTypeName := ATypeName;
+  FEmbededDef := AEmbededDef;
+end;
+
+class function TAbstractTypeParser.ExtractEmbeddedTypeFromElement(
+        AOwner       : IParserContext;
+        AEltNode     : TDOMNode;
+        ASymbols     : ISDODataObject;
+  const ATypeName    : string
+) : ISDODataObject;
+
+  function ExtractTypeName() : string;
+  var
+    locCrs : IObjectCursor;
+  begin
+    locCrs := CreateCursorOn(
+                CreateAttributesCursor(AEltNode,cetRttiNode),
+                ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer)
+              );
+    locCrs.Reset();
+    if not locCrs.MoveNext() then
+      raise EXsdParserException.Create(SERR_UnableToFindNameTagInNode);
+    Result := (locCrs.GetCurrent() as TDOMNodeRttiExposer).NodeValue;
+    if IsStrEmpty(Result) then begin
+      raise EXsdParserException.Create(SERR_InvalidTypeName);
+    end;
+  end;
+
+  function FindParser(out AFoundTypeNode : TDOMNode):TAbstractTypeParserClass;
+  var
+    k : Integer;
+    locPrsClss : TAbstractTypeParserClass;
+    locFilter : string;
+    locCrs : IObjectCursor;
+  begin
+    Result := nil;
+    AFoundTypeNode := nil;
+    for k := 0 to Pred(GetRegisteredParserCount()) do begin
+      locPrsClss := GetRegisteredParser(k);
+      locFilter := locPrsClss.GetParserSupportedStyle();
+      if not IsStrEmpty(locFilter) then begin
+        locFilter := CreateQualifiedNameFilterStr(locFilter,AOwner.GetXsShortNames());
+        locCrs := CreateCursorOn(CreateChildrenCursor(AEltNode,cetRttiNode),ParseFilter(locFilter,TDOMNodeRttiExposer));
+        locCrs.Reset();
+        if locCrs.MoveNext() then begin
+          AFoundTypeNode := (locCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+          Result := locPrsClss;
+          Break;
+        end;
+      end;
+    end;
+  end;
+
+var
+  typName : string;
+  prsClss : TAbstractTypeParserClass;
+  prs : TAbstractTypeParser;
+  typNode : TDOMNode;
+begin
+  if not AEltNode.HasChildNodes() then begin;
+    raise EXsdParserException.Create(SERR_InvalidTypeDef_NoChild);
+  end;
+  typName := ATypeName;
+  if IsStrEmpty(typName) then begin
+    typName := ExtractTypeName();
+  end;
+  prsClss := FindParser(typNode);
+  if ( prsClss = nil ) then begin;
+    raise EXsdInvalidTypeDefinitionException.CreateFmt(SERR_TypeStyleNotSupported,[typName]);
+  end;
+  prs := prsClss.Create(AOwner,typNode,typName,True);
+  try
+    Result := prs.Parse();
+  finally
+    FreeAndNil(prs);
+  end;
+end;
+
+var
+  FTypeParserList : TClassList = nil;
+class procedure TAbstractTypeParser.RegisterParser(AParserClass: TAbstractTypeParserClass);
+begin
+  if ( FTypeParserList = nil ) then begin
+    FTypeParserList := TClassList.Create();
+  end;
+  if ( FTypeParserList.IndexOf(AParserClass) < 0 ) then begin
+    FTypeParserList.Add(AParserClass);
+  end;
+end;
+
+class function TAbstractTypeParser.GetRegisteredParserCount(): Integer;
+begin
+  if Assigned(FTypeParserList) then begin
+    Result := FTypeParserList.Count;
+  end else begin
+    Result := 0;
+  end;
+end;
+
+class function TAbstractTypeParser.GetRegisteredParser(const AIndex: Integer): TAbstractTypeParserClass;
+begin
+  Result := TAbstractTypeParserClass(FTypeParserList[AIndex]);
+end;
+
+function TAbstractTypeParser.FindElementNS(
+  const ANameSpace,
+        ALocalName : string;
+  const ASpaceType : TNameSpaceValueType
+) : ISDODataObject;
+var
+  locNS : string;
+begin
+  if ( ASpaceType = nvtExpandValue ) then begin
+    locNS := ANameSpace
+  end else begin
+    if not Context.FindNameSpace(ANameSpace,locNS) then
+      raise EXsdParserAssertException.CreateFmt(SERR_CannotResolveNamespace,[ANameSpace]);
+  end;
+  Result := Find(FSymbols,locNS,ALocalName);
+end;
+
+function TAbstractTypeParser.GetModule : ISDODataObject;
+begin
+  Result := Context.GetTargetModule();
+end;
+
+function TAbstractTypeParser.FindElementWithHint(
+  const AName,
+        AHint      : string;
+  const ASpace : TSearchSpace
+) : ISDODataObject;
+begin
+  Result := nil;
+  if ( ASpace = ssCurrentModule ) then begin
+    if ( Length(AHint) > 0 ) then
+      Result := Find(FSymbols,AHint);
+    if ( Result = nil ) then
+      Result := Find(FSymbols,AName);
+  end else if ( ASpace = ssGlobal ) then begin
+    if ( Length(AHint) > 0 ) then
+      Result := Find(FSymbols,AHint);
+    if ( Result = nil ) then
+      Result := Find(FSymbols,AName);
+  end;
+end;
+
+function TAbstractTypeParser.ExtractTypeHint(AElement: TDOMNode): string;
+begin
+  if not sdo_findCustomAttributeXsd(Context.GetXsShortNames(),AElement,s_SDO_typeHint,Result) then
+    Result := '';
+end;
+
+procedure TAbstractTypeParser.SetAsEmbeddedType(AType : ISDODataObject; const AValue : Boolean);
+begin
+  AType.setBoolean(s_Embedded,AValue);
+end;
+
+function TAbstractTypeParser.IsEmbeddedType(AType : ISDODataObject) : Boolean;
+begin
+  Result := AType.getBoolean(s_Embedded)
+end;
+
+{$IFDEF SDO_HANDLE_DOC}
+procedure TAbstractTypeParser.ParseDocumentation(AType : ISDODataObject);
+var
+  tmpCursor : IObjectCursor;
+  props : TStrings;
+  docString : string;
+  i : PtrInt;
+  tempNode : TDOMNode;
+begin
+  if FTypeNode.HasChildNodes() then begin
+    tmpCursor := CreateCursorOn(
+                   CreateChildrenCursor(FTypeNode,cetRttiNode),
+                   ParseFilter(CreateQualifiedNameFilterStr(s_annotation,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                 );
+    if ( tmpCursor <> nil ) then begin
+      tmpCursor.Reset();
+      if tmpCursor.MoveNext() then begin
+        tmpCursor := CreateCursorOn(
+                       CreateChildrenCursor(TDOMNodeRttiExposer(tmpCursor.GetCurrent()).InnerObject,cetRttiNode),
+                       ParseFilter(CreateQualifiedNameFilterStr(s_documentation,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                     );
+        if ( tmpCursor <> nil ) then begin
+          tmpCursor.Reset();
+          if tmpCursor.MoveNext() then begin
+            tempNode := TDOMNodeRttiExposer(tmpCursor.GetCurrent()).InnerObject.FirstChild;
+            if ( tempNode <> nil ) then
+              docString := tempNode.NodeValue
+            else
+              docString := '';
+            props := FSymbols.Properties.FindList(AType);
+            if IsStrEmpty(docString) then begin
+              if ( props <> nil ) then begin
+                i := props.IndexOfName(s_documentation);
+                if ( i >= 0 ) then
+                  props.Values[s_documentation] := '';
+              end
+            end else begin
+              if ( props = nil ) then
+                props := FSymbols.Properties.GetList(AType);
+              props.Values[s_documentation] := EncodeLineBreak(docString);
+            end;
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+{$ENDIF SDO_HANDLE_DOC}
+
+procedure TAbstractTypeParser.AddUnresolvedLink(
+        AElement,
+        ATarget   : ISDODataObject;
+  const ALinkKind,
+        AName     : string
+);
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FSymbols.createDataObject(s_UnresolvedLink);
+    locObj.setDataObject(s_Element,AElement);
+    locObj.setDataObject(s_Target,ATarget);
+    locObj.setString(s_LinkKind,ALinkKind);
+    locObj.setString(s_Name,AName);
+  FSymbols.getList(s_UnresolvedLink).append(locObj);
+end;
+
+{ TComplexTypeParser }
+
+function TComplexTypeParser.ExtractElementCursor(
+  out AAttCursor : IObjectCursor;
+  out AAnyNode, AAnyAttNode : TDOMNode
+) : IObjectCursor;
+var
+  frstCrsr : IObjectCursor;
+
+  function ParseContent_ALL() : IObjectCursor;
+  var
+    locTmpCrs : IObjectCursor;
+    locTmpNode : TDOMNode;
+  begin
+    locTmpCrs := CreateCursorOn(
+                   frstCrsr.Clone() as IObjectCursor,
+                   ParseFilter(CreateQualifiedNameFilterStr(s_all,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                 );
+    locTmpCrs.Reset();
+    if locTmpCrs.MoveNext() then begin
+      FSequenceType := stElement;
+      locTmpNode := (locTmpCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+      if  locTmpNode.HasChildNodes() then begin
+        locTmpCrs := CreateCursorOn(
+                       CreateChildrenCursor(locTmpNode,cetRttiNode),
+                       ParseFilter(CreateQualifiedNameFilterStr(s_element,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                     );
+        Result := locTmpCrs;
+      end;
+    end;
+  end;
+
+  function ParseContent_SEQUENCE(out ARes : IObjectCursor) : Boolean;
+  var
+    tmpCursor : IObjectCursor;
+    tmpNode : TDOMNode;
+  begin
+    ARes := nil;
+    tmpCursor := CreateCursorOn(
+                   frstCrsr.Clone() as IObjectCursor,
+                   ParseFilter(CreateQualifiedNameFilterStr(s_sequence,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                 );
+    tmpCursor.Reset();
+    Result := tmpCursor.MoveNext();
+    if Result then begin
+      FSequenceType := stElement;
+      tmpNode := (tmpCursor.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+      if  tmpNode.HasChildNodes() then begin
+        tmpCursor := CreateCursorOn(
+                       CreateChildrenCursor(tmpNode,cetRttiNode),
+                       ParseFilter(CreateQualifiedNameFilterStr(s_element,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                     );
+        ARes := tmpCursor;
+        tmpCursor := CreateCursorOn(
+                       CreateChildrenCursor(tmpNode,cetRttiNode),
+                       ParseFilter(CreateQualifiedNameFilterStr(s_any,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                     );
+        tmpCursor.Reset();
+        if tmpCursor.MoveNext() then
+          AAnyNode := TDOMNodeRttiExposer(tmpCursor.GetCurrent()).InnerObject;
+      end;
+    end
+  end;
+
+var
+  parentNode : TDOMNode;
+  crs : IObjectCursor;
+begin
+  Result := nil;
+  AAttCursor := nil;
+  AAnyNode := nil;
+  AAnyAttNode := nil;
+  case FDerivationMode of
+    dmNone          : parentNode := FContentNode;
+    dmRestriction,
+    dmExtension     : parentNode := FDerivationNode;
+  end;
+  if parentNode.HasChildNodes() then begin;
+    AAttCursor := CreateCursorOn(
+                   CreateChildrenCursor(parentNode,cetRttiNode),
+                   ParseFilter(CreateQualifiedNameFilterStr(s_attribute,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                 );
+    crs := CreateChildrenCursor(parentNode,cetRttiNode);
+    if ( crs <> nil ) then begin
+      crs := CreateCursorOn(
+               crs,
+               ParseFilter(CreateQualifiedNameFilterStr(s_anyAttribute,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+             );
+      if ( crs <> nil ) then begin
+        crs.Reset();
+        if crs.MoveNext() then
+          AAnyAttNode := TDOMNodeRttiExposer(crs.GetCurrent()).InnerObject;
+      end;
+    end;
+    frstCrsr := CreateChildrenCursor(parentNode,cetRttiNode);
+    if not ParseContent_SEQUENCE(Result) then
+      Result := ParseContent_ALL();
+  end;
+end;
+
+procedure TComplexTypeParser.ExtractExtendedMetadata(
+  const AItem : ISDODataObject;
+  const ANode : TDOMNode
+);
+var
+  ls : TDOMNamedNodeMap;
+  e : TDOMNode;
+  k, q : PtrInt;
+  ns_short, ns_long, localName, locBuffer, locBufferNS, locBufferNS_long, locBufferLocalName : string;
+begin
+  if ( ANode.Attributes <> nil ) and ( GetNodeListCount(ANode.Attributes) > 0 ) then begin
+    ls := ANode.Attributes;
+    q := GetNodeListCount(ANode.Attributes);
+    for k := 0 to ( q - 1 ) do begin
+      e := ls.Item[k];
+      if ( Pos(':', e.NodeName) > 1 ) then begin
+        ExplodeQName(e.NodeName,localName,ns_short);
+        if Context.FindNameSpace(ns_short, ns_long) then begin
+          locBuffer := e.NodeValue;
+          ExplodeQName(locBuffer,locBufferLocalName,locBufferNS);
+          if IsStrEmpty(locBufferNS) then
+            locBuffer := locBufferLocalName
+          else if Context.FindNameSpace(locBufferNS, locBufferNS_long) then
+            locBuffer := Format('%s#%s',[locBufferNS_long,locBufferLocalName]);
+          SetTagValue(AItem,Format('%s#%s',[ns_long,localName]),locBuffer);
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TComplexTypeParser.CreateNodeCursors();
+begin
+  FAttCursor := CreateAttributesCursor(FTypeNode,cetRttiNode);
+  FChildCursor := CreateChildrenCursor(FTypeNode,cetRttiNode);
+end;
+
+procedure TComplexTypeParser.ExtractTypeName();
+var
+  locCrs : IObjectCursor;
+begin
+  if not FEmbededDef then begin
+    locCrs := CreateCursorOn(
+                FAttCursor.Clone() as IObjectCursor,
+                ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer)
+              );
+    locCrs.Reset();
+    if not locCrs.MoveNext() then
+      raise EXsdParserException.Create(SERR_UnableToFindNameTagInNode);
+    FTypeName := (locCrs.GetCurrent() as TDOMNodeRttiExposer).NodeValue;
+  end;
+  if IsStrEmpty(FTypeName) then
+    raise EXsdParserException.Create(SERR_InvalidTypeName);
+end;
+
+procedure TComplexTypeParser.ExtractContentType();
+var
+  locCrs : IObjectCursor;
+begin
+  FContentType := '';
+  if Assigned(FChildCursor) then begin
+    locCrs := CreateCursorOn(
+                FChildCursor.Clone() as IObjectCursor,
+                ParseFilter(CreateQualifiedNameFilterStr(s_complexContent,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+              );
+    if Assigned(locCrs) then begin
+      locCrs.Reset();
+      if locCrs.MoveNext() then begin
+        FContentNode := (locCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+        FContentType := FContentNode.NodeName;
+      end else begin
+        locCrs := CreateCursorOn(
+                    FChildCursor.Clone() as IObjectCursor,
+                    ParseFilter(CreateQualifiedNameFilterStr(s_simpleContent,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                  );
+        locCrs.Reset();
+        if locCrs.MoveNext() then begin
+          FContentNode := (locCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+          FContentType := FContentNode.NodeName;
+        end else begin
+          FContentNode := FTypeNode;
+          FContentType := s_complexContent;
+        end;
+      end;
+      FContentType := ExtractNameFromQName(FContentType);
+    end;
+  end;
+end;
+
+procedure TComplexTypeParser.ExtractBaseType();
+var
+  locContentChildCrs, locCrs : IObjectCursor;
+  locSymbol : ISDODataObject;
+  locBaseTypeLocalSpace, locBaseTypeLocalName, locFilterStr : string;
+  locBaseTypeLocalSpaceExpanded : string;
+begin
+  locFilterStr := CreateQualifiedNameFilterStr(s_extension,Context.GetXsShortNames());
+  locContentChildCrs := CreateChildrenCursor(FContentNode,cetRttiNode);
+  locCrs := CreateCursorOn(
+              locContentChildCrs.Clone() as IObjectCursor,
+              ParseFilter(locFilterStr,TDOMNodeRttiExposer)
+            );
+  locCrs.Reset();
+  if locCrs.MoveNext() then begin
+    FDerivationMode := dmExtension;
+    FDerivationNode := (locCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+  end else begin
+    locFilterStr := CreateQualifiedNameFilterStr(s_restriction,Context.GetXsShortNames());
+    locCrs := CreateCursorOn(
+                locContentChildCrs.Clone() as IObjectCursor,
+                ParseFilter(locFilterStr,TDOMNodeRttiExposer)
+              );
+    locCrs.Reset();
+    if locCrs.MoveNext() then begin
+      FDerivationMode := dmRestriction;
+      FDerivationNode := (locCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+    end else begin
+      FDerivationMode := dmNone;
+      FDerivationNode := nil;
+   end;
+  end;
+  if ( FDerivationMode > dmNone ) then begin
+    locCrs := CreateCursorOn(
+      CreateAttributesCursor(FDerivationNode,cetRttiNode),
+      ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_base)]),TDOMNodeRttiExposer)
+    );
+    locCrs.Reset();
+    if not locCrs.MoveNext() then
+      raise EXsdParserException.CreateFmt(SERR_InvalidTypeDef_BaseAttributeNotFound,[FTypeName]);
+    ExplodeQName((locCrs.GetCurrent() as TDOMNodeRttiExposer).NodeValue,locBaseTypeLocalName,locBaseTypeLocalSpace);
+    locSymbol := FindElementNS(locBaseTypeLocalSpace,locBaseTypeLocalName,nvtShortSynonym);
+    if Assigned(locSymbol) then begin
+      if (locSymbol.getByte(s_ElementKind) = ELEMENT_KIND_VARIABLE) then
+        locSymbol := locSymbol.getDataObject(s_DataType);
+      if (locSymbol.getByte(s_ElementKind) = ELEMENT_KIND_TYPE) then begin
+        FBaseType := locSymbol;
+        { TODO -cXSD : Handle "Complex Type" that extend ""Simple Type }
+        {if FBaseType.InheritsFrom(TPasNativeSimpleType) then begin
+          Assert(Assigned(TPasNativeSimpleType(FBaseType).ExtendableType));
+          FBaseType := TPasNativeSimpleType(FBaseType).ExtendableType;
+        end else if FBaseType.InheritsFrom(TPasNativeClassType) then begin
+          if Assigned(TPasNativeClassType(FBaseType).ExtendableType) then
+            FBaseType := TPasNativeClassType(FBaseType).ExtendableType;
+        end; }
+      end else begin
+        raise EXsdParserException.CreateFmt(SERR_ExpectedTypeDefinition,[locSymbol.getString(s_Name)]);
+      end;
+    end else begin
+      if ( FDerivationMode = dmRestriction ) and
+         ( locBaseTypeLocalName = 'Array' ) and
+         ( Context.FindNameSpace(locBaseTypeLocalSpace,locBaseTypeLocalSpaceExpanded) and
+           ( locBaseTypeLocalSpaceExpanded = s_soapEncodingNameSpace )
+         )
+      then begin
+        FHints := FHints + [pthDeriveFromSoapArray];
+      end else begin
+        if IsStrEmpty(locBaseTypeLocalSpaceExpanded) then begin
+          if not Context.FindNameSpace(locBaseTypeLocalSpace,locBaseTypeLocalSpaceExpanded) then
+            locBaseTypeLocalSpaceExpanded := Self.Module.getString(s_Name);
+        end;
+        FBaseType := CreateUnresolvedType(FSymbols,locBaseTypeLocalSpaceExpanded,locBaseTypeLocalName);
+      end;
+    end;
+  end;
+end;
+
+function TComplexTypeParser.ParseComplexContent(const ATypeName : string) : ISDODataObject;
+var
+  classDef : ISDODataObject;
+  isArrayDef : Boolean;
+
+  function IsCollectionArray(AElement : TDOMNode) : Boolean;
+  var
+    strBuffer : string;
+  begin
+    Result := sdo_findCustomAttributeXsd(Context.GetXsShortNames(),AElement,s_SDO_collection,strBuffer) and AnsiSameText('true',Trim(strBuffer));
+  end;
+
+  procedure ParseElement(AElement : TDOMNode);
+  var
+    locAttCursor, locPartCursor : IObjectCursor;
+    locName, locTypeName, locTypeNameSpace : string;
+    locType : ISDODataObject;
+    locProp : ISDODataObject;
+    locMinOccur, locMaxOccur : Integer;
+    locMaxOccurUnbounded : Boolean;
+    locStrBuffer : string;
+    locIsRefElement : Boolean;
+    locTypeHint : string;
+    locVariable : ISDODataObject;
+  begin
+    locType := nil;
+    locTypeName := '';
+    locTypeHint := '';
+    locAttCursor := CreateAttributesCursor(AElement,cetRttiNode);
+    locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer));
+    locPartCursor.Reset();
+    locIsRefElement := False;
+    if not locPartCursor.MoveNext() then begin
+      locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_ref)]),TDOMNodeRttiExposer));
+      locPartCursor.Reset();
+      if not locPartCursor.MoveNext() then begin
+        raise EXsdParserException.Create(SERR_InvalidElementDef_MissingNameOrRef);
+      end;
+      locIsRefElement := True;
+    end;
+    locName := (locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue;
+    if locIsRefElement then begin
+      locName := ExtractNameFromQName(locName);
+    end;
+    if IsStrEmpty(locName) then
+      raise EXsdParserException.Create(SERR_InvalidElementDef_EmptyName);
+    if locIsRefElement then begin
+      locVariable := FindVariable(FSymbols,locName);
+      if (locVariable <> nil) then begin
+        if not locVariable.getBoolean(Format('%s/%s',[s_DataType,s_Unresolved])) then
+          locType := locVariable.getDataObject(s_DataType);
+        locTypeName := locVariable.getString(Format('%s/%s',[s_DataType,s_Name]));// locName;
+      end else begin
+        locTypeName := locName;
+      end;
+    end else begin
+      locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_type)]),TDOMNodeRttiExposer));
+      locPartCursor.Reset();
+      if locPartCursor.MoveNext() then begin
+        ExplodeQName(
+          TDOMNodeRttiExposer(locPartCursor.GetCurrent()).NodeValue,
+          locTypeName,locTypeNameSpace
+        );
+        locTypeName := ExtractNameFromQName(TDOMNodeRttiExposer(locPartCursor.GetCurrent()).NodeValue);
+        locTypeHint := ExtractTypeHint(AElement);
+      end else begin
+        locTypeName := Format('%s_%s_Type',[FTypeName,locName]);
+        locType := TAbstractTypeParser.ExtractEmbeddedTypeFromElement(Context,AElement,FSymbols,locTypeName);
+        if ( locType = nil ) then begin
+          raise EXsdInvalidElementDefinitionException.CreateFmt(SERR_InvalidElementDef_Type,[FTypeName,locName]);
+        end;
+        //Self.Module.getList(s_Type).append(locType);
+      end;
+    end;
+    if IsStrEmpty(locTypeName) then
+      raise EXsdInvalidElementDefinitionException.Create(SERR_InvalidElementDef_EmptyType);
+    if (locType = nil) then
+      locType := FindElementNS(locTypeNameSpace,locTypeName,nvtShortSynonym);
+    if (locType = nil) then
+      locType := FindElementWithHint(locTypeName,locTypeHint,ssGlobal);
+    if (locType = nil) then
+      locType := CreateUnresolvedType(FSymbols,Self.Module.getString(s_NameSpace),locTypeName);
+
+    locProp := classDef.createDataObject(s_Property);
+    locProp.setByte(s_ElementKind,ELEMENT_KIND_PROPERTY);
+    locProp.setString(s_Name,locName);
+    locProp.setDataObject(s_DataType,locType);
+    classDef.getList(s_Property).append(locProp);
+    if locType.getBoolean(s_Unresolved) then
+      AddUnresolvedLink(classDef,locType,LINK_KIND_PROP_TYPE,locProp.getString(s_Name));
+
+    if AnsiSameText(s_attribute,ExtractNameFromQName(AElement.NodeName)) then begin
+      locProp.setBoolean(s_IsAttribute,True);
+      locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_use)]),TDOMNodeRttiExposer));
+      locPartCursor.Reset();
+      if locPartCursor.MoveNext() then begin
+        locStrBuffer := ExtractNameFromQName((locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue);
+        if IsStrEmpty(locStrBuffer) then
+          raise EXsdInvalidDefinitionException.Create(SERR_InvalidAttributeDef_EmptyUse);
+        case AnsiIndexText(locStrBuffer,[s_required,s_optional,s_prohibited]) of
+          0 : locMinOccur := 1;
+          1 : locMinOccur := 0;
+          2 : locMinOccur := -1;
+          else
+            raise EXsdInvalidDefinitionException.CreateFmt(SERR_InvalidAttributeDef_InvalidUse,[locStrBuffer]);
+        end;
+      end else begin
+        locMinOccur := 0;
+      end;
+    end else begin
+      locMinOccur := 1;
+      locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_minOccurs)]),TDOMNodeRttiExposer));
+      locPartCursor.Reset();
+      if locPartCursor.MoveNext() then begin
+        if not TryStrToInt((locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue,locMinOccur) then
+          raise EXsdParserException.CreateFmt(SERR_InvalidMinOccursValue,[FTypeName,locName]);
+        if ( locMinOccur < 0 ) then
+          raise EXsdParserException.CreateFmt(SERR_InvalidMinOccursValue,[FTypeName,locName]);
+      end;
+    end;
+    locProp.setInteger(s_PropertyMinOccurs,locMinOccur);
+
+    locMaxOccur := 1;
+    locMaxOccurUnbounded := False;
+    locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_maxOccurs)]),TDOMNodeRttiExposer));
+    locPartCursor.Reset();
+    if locPartCursor.MoveNext() then begin
+      locStrBuffer := (locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue;
+      if AnsiSameText(locStrBuffer,s_unbounded) then begin
+        locMaxOccurUnbounded := True;
+      end else begin
+        if not TryStrToInt(locStrBuffer,locMaxOccur) then
+          raise EXsdParserException.CreateFmt(SERR_InvalidMaxOccursValue,[FTypeName,locName]);
+        if ( locMaxOccur < 0 ) then
+          raise EXsdParserException.CreateFmt(SERR_InvalidMaxOccursValue,[FTypeName,locName]);
+      end;
+    end;
+    if locMaxOccurUnbounded then
+      locMaxOccur := MaxInt - 1;
+    locProp.setInteger(s_PropertyMaxOccurs,locMaxOccur);
+    isArrayDef := locMaxOccurUnbounded or ( locMaxOccur > 1 );
+    if isArrayDef then
+      SetTagValue(locProp,s_SDO_collection,TSDOConvertHelper.BoolToString(IsCollectionArray(AElement)));
+    if not isArrayDef then begin
+      SetTagValue(
+        locProp,s_attribute,
+        TSDOConvertHelper.BoolToString(AnsiSameText(s_attribute,ExtractNameFromQName(AElement.NodeName)))
+      );
+    end;
+    locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_default)]),TDOMNodeRttiExposer));
+    locPartCursor.Reset();
+    if locPartCursor.MoveNext() then
+      locProp.setString(s_DefaultValue,(locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue);
+    ExtractExtendedMetadata(locProp,AElement);
+  end;
+
+  function IsRecordType() : Boolean;
+  var
+    strBuffer : string;
+  begin
+    Result := sdo_findCustomAttributeXsd(Context.GetXsShortNames(),FTypeNode,s_SDO_record,strBuffer) and AnsiSameText('true',Trim(strBuffer));
+  end;
+
+  procedure ParseElementsAndAttributes(AEltCrs, AEltAttCrs : IObjectCursor);
+  begin
+    if Assigned(AEltCrs) then begin
+      AEltCrs.Reset();
+      while AEltCrs.MoveNext() do begin
+        ParseElement((AEltCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject);
+      end;
+    end;
+    if Assigned(AEltAttCrs) then begin
+      AEltAttCrs.Reset();
+      while AEltAttCrs.MoveNext() do begin
+        ParseElement((AEltAttCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject);
+      end;
+    end;
+  end;
+
+  procedure CopyExtendedMetaData(ASource,ADesc : ISDODataObject);
+  begin
+    CopySimpleList(ASource.getList(s_Tag),ADesc.getList(s_Tag),StringType);
+  end;
+
+  procedure ProcessXsdAnyDeclarations(AAnyNode, AAnyAttNode : TDOMNode; AType : ISDODataObject);
+  var
+    anyElt : TDOMElement;
+    ls : TStringList;
+    anyDec : string;
+  begin
+    if ( AAnyNode <> nil ) then begin
+      anyElt := AAnyNode as TDOMElement;
+      ls := TStringList.Create();
+      try
+        if anyElt.hasAttribute(s_processContents) then
+          ls.Values[s_processContents] := anyElt.GetAttribute(s_processContents);
+        if anyElt.hasAttribute(s_minOccurs) then
+          ls.Values[s_minOccurs] := anyElt.GetAttribute(s_minOccurs);
+        if anyElt.hasAttribute(s_maxOccurs) then
+          ls.Values[s_maxOccurs] := anyElt.GetAttribute(s_maxOccurs);
+        if ( ls.Count > 0 ) then begin
+          ls.Delimiter := ';';
+          anyDec := ls.DelimitedText;
+        end;
+      finally
+        ls.Free();
+      end;
+      SetTagValue(AType,Format('%s#%s',[s_xs,s_any]),anyDec);
+    end;
+    if ( AAnyAttNode <> nil ) then begin
+      anyDec := '';
+      anyElt := AAnyAttNode as TDOMElement;
+      if anyElt.hasAttribute(s_processContents) then
+        anyDec := anyElt.GetAttribute(s_processContents);
+      SetTagValue(AType,Format('%s#%s',[s_xs,s_anyAttribute]),Format('%s=%s',[s_processContents,anyDec]));
+    end;
+  end;
+
+var
+  eltCrs, eltAttCrs : IObjectCursor;
+  locAnyNode, locAnyAttNode : TDOMNode;
+begin
+  ExtractBaseType();
+  eltCrs := ExtractElementCursor(eltAttCrs,locAnyNode,locAnyAttNode);
+
+  classDef := Module.createDataObject(s_Type);
+  classDef.setBoolean(s_IsComplex,True);
+  classDef.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+  classDef.setString(s_Name,ATypeName);
+  Module.getList(s_Type).append(classDef);
+  Result := classDef;
+  if (FDerivationMode in [dmExtension, dmRestriction]) and
+     (FBaseType <> nil)
+  then begin
+    classDef.setDataObject(s_BaseType,FBaseType);
+    if FBaseType.getBoolean(s_Unresolved) then
+      AddUnresolvedLink(classDef,FBaseType,LINK_KIND_BASE_TYPE,'');
+  end;
+  if Assigned(eltCrs) or Assigned(eltAttCrs) then begin
+    isArrayDef := False;
+    ParseElementsAndAttributes(eltCrs,eltAttCrs);
+  end;
+  if ( locAnyNode <> nil ) or ( locAnyAttNode <> nil ) then
+    ProcessXsdAnyDeclarations(locAnyNode,locAnyAttNode,Result);
+end;
+
+function TComplexTypeParser.ParseSimpleContent(const ATypeName : string) : ISDODataObject;
+
+  function ExtractAttributeCursor():IObjectCursor;
+  var
+    frstCrsr, tmpCursor : IObjectCursor;
+    parentNode, tmpNode : TDOMNode;
+    locFilterStr : string;
+    xsShortNameList : TStrings;
+  begin
+    Result := nil;
+    parentNode := FContentNode;
+    if parentNode.HasChildNodes() then begin;
+      xsShortNameList := Context.GetXsShortNames();
+      frstCrsr := CreateChildrenCursor(parentNode,cetRttiNode);
+      locFilterStr := CreateQualifiedNameFilterStr(s_extension,xsShortNameList) + ' or ' +
+                      CreateQualifiedNameFilterStr(s_restriction,xsShortNameList) ;
+      tmpCursor := CreateCursorOn(frstCrsr.Clone() as IObjectCursor,ParseFilter(locFilterStr,TDOMNodeRttiExposer));
+      if Assigned(tmpCursor) then begin
+        tmpCursor.Reset();
+        if tmpCursor.MoveNext() then begin
+          tmpNode := (tmpCursor.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+          if tmpNode.HasChildNodes() then begin
+            locFilterStr := CreateQualifiedNameFilterStr(s_attribute,xsShortNameList);
+            tmpCursor := CreateCursorOn(CreateChildrenCursor(tmpNode,cetRttiNode),ParseFilter(locFilterStr,TDOMNodeRttiExposer));
+            if Assigned(tmpCursor) then begin
+              Result := tmpCursor;
+              Result.Reset();
+            end;
+          end;
+        end;
+      end;
+    end else begin
+      Result := nil;
+    end;
+  end;
+
+var
+  locClassDef : ISDODataObject;
+
+  procedure ParseAttribute(AElement : TDOMNode);
+  var
+    locAttCursor, locPartCursor : IObjectCursor;
+    locName, locTypeName, locTypeNameSpace, locStoreOpt : string;
+    locType : ISDODataObject;
+    locStoreOptIdx : Integer;
+    locAttObj : ISDODataObject;
+  begin
+    locAttCursor := CreateAttributesCursor(AElement,cetRttiNode);
+    locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer));
+    locPartCursor.Reset();
+    if not locPartCursor.MoveNext() then
+      raise EXsdInvalidDefinitionException.Create(SERR_InvalidAttributeDef_MissingName);
+    locName := (locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue;
+    if IsStrEmpty(locName) then
+      raise EXsdInvalidDefinitionException.Create(SERR_InvalidAttributeDef_EmptyName);
+
+    locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_type)]),TDOMNodeRttiExposer));
+    locPartCursor.Reset();
+    if not locPartCursor.MoveNext() then
+      raise EXsdInvalidDefinitionException.Create(SERR_InvalidAttributeDef_MissingType);
+    ExplodeQName(
+      (locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue,
+      locTypeName,locTypeNameSpace
+    ); //locTypeName := ExtractNameFromQName((locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue);
+    if IsStrEmpty(locTypeName) then
+      raise EXsdInvalidDefinitionException.Create(SERR_InvalidAttributeDef_EmptyType);
+    locType := FindElementNS(locTypeNameSpace,locTypeName,nvtShortSynonym);
+    //locType := FSymbols.FindElement(locTypeName) as TPasType;
+    if not Assigned(locType) then begin
+      if not IsStrEmpty(locTypeNameSpace) then begin
+        if not Context.FindNameSpace(Copy(locTypeNameSpace,1,Length(locTypeNameSpace)),locTypeNameSpace) then
+          locTypeNameSpace := Module.getString(s_NameSpace);
+      end;
+      if IsStrEmpty(locTypeNameSpace) then
+        locTypeNameSpace := Module.getString(s_NameSpace);
+      locType := CreateUnresolvedType(FSymbols,locTypeNameSpace,locTypeName);
+      //locType := TPasUnresolvedTypeRef(FSymbols.CreateElement(TPasUnresolvedTypeRef,locTypeName,Self.Module.InterfaceSection,visPublic,'',0));
+    end;
+
+    locPartCursor := CreateCursorOn(locAttCursor.Clone() as IObjectCursor,ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_use)]),TDOMNodeRttiExposer));
+    locPartCursor.Reset();
+    if locPartCursor.MoveNext() then begin
+      locStoreOpt := ExtractNameFromQName((locPartCursor.GetCurrent() as TDOMNodeRttiExposer).NodeValue);
+      if IsStrEmpty(locStoreOpt) then
+        raise EXsdInvalidDefinitionException.Create(SERR_InvalidAttributeDef_EmptyUse);
+      locStoreOptIdx := AnsiIndexText(locStoreOpt,[s_required,s_optional,s_prohibited]);
+      if ( locStoreOptIdx < 0 ) then
+        raise EXsdInvalidDefinitionException.CreateFmt(SERR_InvalidAttributeDef_InvalidUse,[locStoreOpt]);
+    end else begin
+      locStoreOptIdx := 1{optional by default!}; //0;
+    end;
+
+    locAttObj := locClassDef.createDataObject(s_Property);
+    locAttObj.setByte(s_ElementKind,ELEMENT_KIND_PROPERTY);
+    locClassDef.getList(s_Property).append(locAttObj);
+    locAttObj.setString(s_Name,locName);
+    locAttObj.setDataObject(s_DataType,locType);
+    locAttObj.setBoolean(s_IsAttribute,True);
+    if locType.getBoolean(s_Unresolved) then
+      AddUnresolvedLink(locClassDef,locType,LINK_KIND_PROP_TYPE,locAttObj.getString(s_Name));
+    case locStoreOptIdx of
+      0 :
+        begin
+          locAttObj.setInteger(s_PropertyMinOccurs,1);
+          locAttObj.setInteger(s_PropertyMaxOccurs,1);
+        end;
+      1 :
+        begin
+          locAttObj.setInteger(s_PropertyMinOccurs,0);
+          locAttObj.setInteger(s_PropertyMaxOccurs,1);
+        end;
+      2 :
+        begin
+          locAttObj.setInteger(s_PropertyMinOccurs,0);
+          locAttObj.setInteger(s_PropertyMaxOccurs,0);
+        end;
+    end;
+  end;
+
+var
+  locAttCrs : IObjectCursor;
+begin
+  ExtractBaseType();
+  if not ( FDerivationMode in [dmExtension, dmRestriction] ) then
+    raise EXsdInvalidTypeDefinitionException.Create(SERR_InvalidComplexSimpleTypeDef_NoRestOrExt);
+
+  locAttCrs := ExtractAttributeCursor();
+  locClassDef := Module.createDataObject(s_Type);
+  locClassDef.setBoolean(s_IsComplex,True);
+  locClassDef.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+  Module.getList(s_Type).append(locClassDef);
+  locClassDef.setString(s_Name,ATypeName);
+  Result := locClassDef;
+  if ( FDerivationMode in [dmExtension, dmRestriction] ) then begin
+    if (FBaseType <> nil) then
+      locClassDef.setDataObject(s_BaseType,FBaseType);
+  end;
+  if ( locAttCrs <> nil ) then begin
+    locAttCrs.Reset();
+    while locAttCrs.MoveNext() do begin
+      ParseAttribute((locAttCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject);
+    end;
+  end;
+end;
+
+function TComplexTypeParser.ParseEmptyContent(const ATypeName: string): ISDODataObject;
+begin
+  Result := Module.createDataObject(s_Type);
+  Result.setBoolean(s_IsComplex,True);
+  Result.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+  Module.getList(s_Type).append(Result);
+  Result.setString(s_Name,ATypeName);
+end;
+
+class function TComplexTypeParser.GetParserSupportedStyle(): string;
+begin
+  Result := s_complexType;
+end;
+
+function TComplexTypeParser.Parse() : ISDODataObject;
+var
+  locSym : ISDODataObject;
+  locContinue : Boolean;
+begin
+  if not AnsiSameText(ExtractNameFromQName(FTypeNode.NodeName),s_complexType) then
+    raise EXsdParserAssertException.CreateFmt(SERR_ExpectedButFound,[s_complexType,ExtractNameFromQName(FTypeNode.NodeName)]);
+  Result := nil;
+  CreateNodeCursors();
+  ExtractTypeName();
+  locContinue := True;
+  locSym := FindInModule(Module,FTypeName); //FSymbols.FindElement(FTypeName);
+  if (locSym = nil) then
+    locSym := Find(FSymbols,FTypeName);
+  if Assigned(locSym) then begin
+    if (locSym.getByte(s_ElementKind) <> ELEMENT_KIND_TYPE) then
+      raise EXsdParserException.CreateFmt(SERR_ExpectedTypeDefinition,[FTypeName]);
+    locContinue := locSym.getBoolean(s_Unresolved) or
+                   (IsEmbeddedType(locSym) <> FEmbededDef);
+    if not locContinue then;
+      Result := locSym;
+  end;
+  if locContinue then begin
+    ExtractContentType();
+    if IsStrEmpty(FContentType) then begin
+      Result := ParseEmptyContent(FTypeName);
+    end else begin
+      if AnsiSameText(FContentType,s_complexContent) then
+        Result := ParseComplexContent(FTypeName)
+      else
+        Result := ParseSimpleContent(FTypeName);
+    end;
+    if ( Result <> nil ) then begin
+      if ( IsEmbeddedType(Result) <> FEmbededDef ) then
+        SetAsEmbeddedType(Result,FEmbededDef);
+    end;
+{$IFDEF SDO_HANDLE_DOC}
+    if ( Result <> nil ) then
+      ParseDocumentation(Result);
+{$ENDIF SDO_HANDLE_DOC}
+  end;
+end;
+
+{ TSimpleTypeParser }
+
+procedure TSimpleTypeParser.CreateNodeCursors();
+begin
+  FAttCursor := CreateAttributesCursor(FTypeNode,cetRttiNode);
+  FChildCursor := CreateChildrenCursor(FTypeNode,cetRttiNode);
+end;
+
+procedure TSimpleTypeParser.ExtractTypeName();
+var
+  locCrs : IObjectCursor;
+begin
+  if not FEmbededDef then begin
+    locCrs := CreateCursorOn(
+                FAttCursor.Clone() as IObjectCursor,
+                ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer)
+              );
+    locCrs.Reset();
+    if not locCrs.MoveNext() then
+      raise EXsdParserAssertException.Create(SERR_UnableToFindNameTagInNode);
+    FTypeName := (locCrs.GetCurrent() as TDOMNodeRttiExposer).NodeValue;
+  end;
+  if IsStrEmpty(FTypeName) then
+    raise EXsdParserAssertException.Create(SERR_InvalidTypeName);
+end;
+
+function TSimpleTypeParser.ExtractContentType() : Boolean;
+var
+  locCrs, locAttCrs : IObjectCursor;
+  tmpNode : TDOMNode;
+  spaceShort : string;
+begin
+  locCrs := CreateCursorOn(
+              FChildCursor.Clone() as IObjectCursor,
+              ParseFilter(CreateQualifiedNameFilterStr(s_restriction,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+            );
+  locCrs.Reset();
+  if locCrs.MoveNext() then begin
+    FRestrictionNode := (locCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+    tmpNode := nil;
+    locAttCrs := CreateAttributesCursor(FRestrictionNode,cetRttiNode);
+    if Assigned(locAttCrs) then begin
+      locAttCrs := CreateCursorOn(locAttCrs,ParseFilter(Format('%s=%s',[s_NODE_NAME,QuotedStr(s_base)]),TDOMNodeRttiExposer));
+      locAttCrs.Reset();
+      if locAttCrs.MoveNext() then begin
+        tmpNode := (locAttCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+      end;
+    end;
+    FBaseName := '';
+    FBaseNameSpace := '';
+    if Assigned(tmpNode) then begin
+      ExplodeQName(tmpNode.NodeValue,FBaseName,spaceShort);
+      if not Context.FindNameSpace(spaceShort,FBaseNameSpace) then
+        raise EXsdParserAssertException.CreateFmt(SERR_CannotResolveNamespace,[spaceShort]);
+    end;
+    locCrs := CreateChildrenCursor(FRestrictionNode,cetRttiNode) as IObjectCursor;
+    if Assigned(locCrs) then begin
+      locCrs := CreateCursorOn(
+                  locCrs,
+                  ParseFilter(CreateQualifiedNameFilterStr(s_enumeration,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+                );
+      locCrs.Reset();
+      if locCrs.MoveNext() then begin
+        FIsEnum := True;
+      end else begin
+        if IsStrEmpty(FBaseName) then
+          raise EXsdParserAssertException.CreateFmt(SERR_BaseTypeNotSpecfifiedForSimpleType,[FTypeName]);
+        FIsEnum := False
+      end;
+    end else begin
+      if IsStrEmpty(FBaseName) then
+        raise EXsdParserAssertException.CreateFmt(SERR_BaseTypeNotSpecfifiedForSimpleType,[FTypeName]);
+      FIsEnum := False
+    end;
+    Result := True;
+  end else begin
+    //raise EWslParserException.CreateFmt('The parser only support "Restriction" mode simple type derivation, parsing : "%s".',[FTypeName]);
+    Result := False;
+  end;
+end;
+
+function TSimpleTypeParser.ParseEnumContent(): ISDODataObject;
+
+  function ExtractEnumCursor():IObjectCursor ;
+  begin
+    Result := CreateCursorOn(
+                CreateChildrenCursor(FRestrictionNode,cetRttiNode),
+                ParseFilter(CreateQualifiedNameFilterStr(s_enumeration,Context.GetXsShortNames()),TDOMNodeRttiExposer)
+              );
+  end;
+
+var
+  locRes : ISDODataObject;
+  locEnumValueList : ISDODataObjectList;
+
+  procedure ParseEnumItem(AItemNode : TDOMNode);
+  var
+    tmpNode : TDOMNode;
+    locCrs : IObjectCursor;
+  begin
+    locCrs := CreateCursorOn(CreateAttributesCursor(AItemNode,cetRttiNode),ParseFilter(Format('%s=%s',[s_NODE_NAME,QuotedStr(s_value)]),TDOMNodeRttiExposer)) as IObjectCursor;
+    if not Assigned(locCrs) then
+      raise EXsdInvalidDefinitionException.CreateFmt(SERR_InvalidEnumItemNode_NoValueAttribute,[FTypeName]);
+    locCrs.Reset();
+    if not locCrs.MoveNext() then
+      raise EXsdInvalidDefinitionException.CreateFmt(SERR_InvalidEnumItemNode_NoValueAttribute,[FTypeName]);
+    tmpNode := (locCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+    locEnumValueList.append(tmpNode.nodeValue);
+  end;
+
+var
+  locEnumCrs : IObjectCursor;
+begin
+  locEnumCrs := ExtractEnumCursor();
+
+  locRes := Module.createDataObject(s_Type);
+  locRes.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+  locRes.setString(s_Name,FTypeName);
+  Module.getList(s_Type).append(locRes);
+  locEnumValueList := locRes.getList(s_EnumValue);
+  locEnumCrs.Reset();
+  while locEnumCrs.MoveNext() do begin
+    ParseEnumItem((locEnumCrs.GetCurrent() as TDOMNodeRttiExposer).InnerObject);
+  end;
+  Result := locRes;
+end;
+
+function TSimpleTypeParser.ParseOtherContent(): ISDODataObject;
+var
+  locRes, locBaseType : ISDODataObject;
+begin  // todo : implement TSimpleTypeParser.ParseOtherContent
+  if IsStrEmpty(FBaseName) then
+    raise EXsdInvalidTypeDefinitionException.CreateFmt(SERR_BaseTypeNotSpecfifiedForSimpleType,[FTypeName]);
+  locRes := Module.createDataObject(s_Type);
+  locRes.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+  locRes.setString(s_Name,FTypeName);
+  Module.getList(s_Type).append(locRes);
+  locBaseType := FindElementNS(FBaseNameSpace,FBaseName,nvtExpandValue);
+  if (locBaseType <> nil) then
+    locRes.setDataObject(s_BaseType,locBaseType);
+  Result := locRes;
+end;
+
+class function TSimpleTypeParser.GetParserSupportedStyle(): string;
+begin
+  Result := s_simpleType;
+end;
+
+function TSimpleTypeParser.Parse(): ISDODataObject;
+var
+  locSym : ISDODataObject;
+  locContinue : Boolean;
+begin
+  if not AnsiSameText(ExtractNameFromQName(FTypeNode.NodeName),s_simpleType) then
+    raise EXsdParserAssertException.CreateFmt(SERR_ExpectedButFound,[s_simpleType,ExtractNameFromQName(FTypeNode.NodeName)]);
+  Result := nil;
+  CreateNodeCursors();
+  ExtractTypeName();
+  locContinue := True;
+  locSym := FindInModule(Module,FTypeName);
+  if Assigned(locSym) then begin
+    if (locSym.getByte(s_ElementKind) <> ELEMENT_KIND_TYPE) then
+      raise EXsdParserAssertException.CreateFmt(SERR_ExpectedTypeDefinition,[FTypeName]);
+    locContinue := locSym.getBoolean(s_Unresolved);
+    if not locContinue then
+      Result := locSym;
+  end;
+  if locContinue then begin
+    if ExtractContentType() then begin
+      if FIsEnum then begin
+        Result := ParseEnumContent()
+      end else begin
+        Result := ParseOtherContent();
+      end;
+    end else begin
+      FBaseName := 'string';
+      FBaseNameSpace := s_xs;
+      Result := ParseOtherContent();
+    end;
+    if ( Result <> nil ) then begin
+      if ( IsEmbeddedType(Result) <> FEmbededDef ) then
+        SetAsEmbeddedType(Result,FEmbededDef);
+    end;
+{$IFDEF SDO_HANDLE_DOC}
+    if ( Result <> nil ) then
+      ParseDocumentation(Result);
+{$ENDIF SDO_HANDLE_DOC}
+  end;
+end;
+
+{ TCustomXsdSchemaParser }
+
+constructor TCustomXsdSchemaParser.Create(
+  ADoc           : TXMLDocument;
+  ASchemaNode    : TDOMNode;
+  ASymbols       : ISDODataObject;
+  AParentContext : IParserContext
+);
+begin
+  if ( ADoc = nil ) then
+    raise EXsdParserAssertException.Create(SERR_InvalidDomDocument);
+  if ( ASchemaNode = nil ) then
+    raise EXsdParserAssertException.Create(SERR_InvalidSchemaNode);
+  if ( ASymbols = nil ) then
+    raise EXsdParserAssertException.Create(SERR_InvalidSymbolTable);
+
+  FDoc := ADoc;
+  FParentContext := Pointer(AParentContext);
+  FSymbols := ASymbols;
+  FSchemaNode := ASchemaNode;
+
+  FNameSpaceList := TStringList.Create();
+  FNameSpaceList.Duplicates := dupError;
+  FNameSpaceList.Sorted := True;
+
+  Prepare();
+end;
+
+destructor TCustomXsdSchemaParser.Destroy();
+
+  procedure FreeList(AList : TStrings);
+  var
+    j : PtrInt;
+  begin
+    if Assigned(AList) then begin
+      for j := 0  to Pred(AList.Count) do begin
+        AList.Objects[j].Free();
+        AList.Objects[j] := nil;
+      end;
+      AList.Free();
+    end;
+  end;
+
+begin
+  FParentContext := nil;
+  FreeList(FNameSpaceList);
+  FreeList(FXsdParsers);
+  inherited;
+end;
+
+function TCustomXsdSchemaParser.FindParser(const ANamespace : string) : IXsdParser;
+var
+  i : PtrInt;
+  p, p1 : IXsdParser;
+begin
+  Result := nil;
+  if (ANamespace = FTargetNameSpace) then begin
+    Result := Self;
+    Exit;
+  end;
+  if (FXsdParsers = nil) then
+    CreateImportParsers();
+  if (FXsdParsers = nil) then
+    Exit;
+  i := FXsdParsers.IndexOf(ANamespace);
+  if ( i >= 0 ) then begin
+    Result := (FXsdParsers.Objects[i] as TIntfObjectRef).Intf as IXsdParser;
+  end else begin
+    for i := 0 to Pred(FXsdParsers.Count) do begin
+      p := (FXsdParsers.Objects[i] as TIntfObjectRef).Intf as IXsdParser;
+      p1 := p.FindParser(ANamespace);
+      if (p1 <> nil) then begin
+        Result := p1;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+procedure TCustomXsdSchemaParser.DoOnMessage(
+  const AMsgType: TMessageType;
+  const AMsg: string
+);
+begin
+  if Assigned(FOnMessage) then begin
+    FOnMessage(AMsgType,AMsg);
+  end else if IsConsole and HasLogger() then begin
+    GetLogger().Log(AMsgType, AMsg);
+  end;
+end;
+
+procedure TCustomXsdSchemaParser.ParseImportDocuments();
+var
+  locOldCurrentModule : ISDODataObject;
+  i : Integer;
+  p : IXsdParser;
+begin
+  if FImportParsed then
+    Exit;
+  CreateImportParsers();
+  if (FXsdParsers = nil) then
+    Exit;
+
+  FImportParsed := True;
+  if Assigned(FChildCursor) then begin
+    locOldCurrentModule := SymbolTable.getDataObject(s_CurrentModule);
+    try
+      for i := 0 to FXsdParsers.Count - 1 do begin
+        p := TIntfObjectRef(FXsdParsers.Objects[i]).Intf as IXsdParser;
+        p.ParseTypes();
+      end;
+    finally
+      SymbolTable.setDataObject(s_CurrentModule,locOldCurrentModule);
+    end;
+  end;
+end;
+
+function TCustomXsdSchemaParser.FindNamedNode(
+        AList : IObjectCursor;
+  const AName : WideString;
+  const AOrder : Integer
+): TDOMNode;
+var
+  attCrs, crs : IObjectCursor;
+  curObj : TDOMNodeRttiExposer;
+  fltr : IObjectFilter;
+  locOrder : Integer;
+begin
+  Result := nil;
+  if Assigned(AList) then begin
+    fltr := ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer);
+    AList.Reset();
+    locOrder := AOrder;
+    while AList.MoveNext() do begin
+      curObj := AList.GetCurrent() as TDOMNodeRttiExposer;
+      attCrs := CreateAttributesCursor(curObj.InnerObject,cetRttiNode);
+      if Assigned(attCrs) then begin
+        crs := CreateCursorOn(attCrs,fltr);
+        crs.Reset();
+        if crs.MoveNext() and AnsiSameText(AName,TDOMNodeRttiExposer(crs.GetCurrent()).NodeValue) then begin
+          Dec(locOrder);
+          if ( locOrder <= 0 ) then begin
+            Result := curObj.InnerObject;
+            exit;
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+function TCustomXsdSchemaParser.FindNameSpace(
+  const AShortName : string;
+  out   AResult : string
+) : Boolean;
+var
+  i : PtrInt;
+  ls : TStrings;
+  pc : IParserContext;
+begin
+  AResult := '';
+  Result := False;
+  for i := 0 to Pred(FNameSpaceList.Count) do begin
+    ls := FNameSpaceList.Objects[i] as TStrings;
+    if ( ls.IndexOf(AShortName) >= 0 ) then begin
+      AResult := FNameSpaceList[i];
+      Result := True;
+      Break;
+    end;
+  end;
+  if not Result then begin
+    pc := GetParentContext();
+    if ( pc <> nil ) then
+      Result := GetParentContext().FindNameSpace(AShortName,AResult);
+  end;
+end;
+
+function TCustomXsdSchemaParser.FindShortNamesForNameSpace(const ANameSpace: string): TStrings;
+var
+  prtCtx : IParserContext;
+begin
+  Result := FindShortNamesForNameSpaceLocal(ANameSpace);
+  if ( Result = nil ) then begin
+    prtCtx := GetParentContext();
+    if Assigned(prtCtx) then
+      Result := prtCtx.FindShortNamesForNameSpace(ANameSpace);
+  end;
+end;
+
+function TCustomXsdSchemaParser.GetDocumentLocator(): IDocumentLocator;
+begin
+  Result := FDocumentLocator;
+  if (Result = nil) and (FParentContext <> nil) then
+    Result := GetParentContext().GetDocumentLocator();
+end;
+
+procedure TCustomXsdSchemaParser.SetDocumentLocator(const ALocator: IDocumentLocator);
+begin
+  FDocumentLocator := ALocator;
+end;
+
+procedure TCustomXsdSchemaParser.SetNotifier(ANotifier: TOnParserMessage);
+begin
+  FOnMessage := ANotifier;
+end;
+
+function TCustomXsdSchemaParser.FindShortNamesForNameSpaceLocal(const ANameSpace: string): TStrings;
+var
+  i : PtrInt;
+begin
+  i := FNameSpaceList.IndexOf(ANameSpace);
+  if ( i >= 0 ) then
+    Result := FNameSpaceList.Objects[i] as TStrings
+  else
+    Result := nil;
+end;
+
+function TCustomXsdSchemaParser.GetParentContext() : IParserContext;
+begin
+  Result := IParserContext(FParentContext);
+end;
+
+function TCustomXsdSchemaParser.GetSymbolTable() : ISDODataObject;
+begin
+  Result := FSymbols;
+end;
+
+function TCustomXsdSchemaParser.GetTargetModule() : ISDODataObject;
+begin
+  Result := FModule;
+end;
+
+function TCustomXsdSchemaParser.GetTargetNameSpace() : string;
+begin
+  Result := FTargetNameSpace;
+end;
+
+function TCustomXsdSchemaParser.GetXsShortNames() : TStrings;
+begin
+  Result := FXSShortNames;
+end;
+
+function TCustomXsdSchemaParser.ParseType(const AName, ATypeKind : string): ISDODataObject;
+begin
+  Result := InternalParseType(AName,nil);
+end;
+
+function TCustomXsdSchemaParser.ParseType(
+  const AName : string;
+  const ATypeNode : TDOMNode
+) : ISDODataObject;
+begin
+  Result := InternalParseType(AName,ATypeNode);
+end;
+
+function TCustomXsdSchemaParser.InternalParseType(
+  const AName : string;
+  const ATypeNode : TDOMNode
+): ISDODataObject;
+var
+  crsSchemaChild : IObjectCursor;
+  typNd : TDOMNode;
+  typName : string;
+  embededType : Boolean;
+  localTypeName : string;
+
+  procedure Init();
+  begin
+    crsSchemaChild := FChildCursor.Clone() as IObjectCursor;
+  end;
+
+  function ExtractTypeHint(AElement: TDOMNode): string;
+  begin
+    if not sdo_findCustomAttributeXsd(FXSShortNames,AElement,s_SDO_typeHint,Result) then
+      Result := '';
+  end;
+
+  function FindTypeNode(out ASimpleTypeAlias : ISDODataObject) : Boolean;
+  var
+    nd, oldTypeNode : TDOMNode;
+    crs : IObjectCursor;
+    locStrFilter : string;
+    locLocalName, locNamespace : string;
+  begin
+    ASimpleTypeAlias := nil;
+    Result := True;
+    if ( ATypeNode <> nil ) then
+      typNd := ATypeNode
+    else
+      typNd := FindNamedNode(crsSchemaChild,localTypeName);
+    if not Assigned(typNd) then
+      raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['1',AName]);
+    if AnsiSameText(ExtractNameFromQName(typNd.NodeName),s_element) then begin
+      crs := CreateCursorOn(CreateAttributesCursor(typNd,cetRttiNode),ParseFilter(Format('%s = %s',[s_NODE_NAME,QuotedStr(s_type)]),TDOMNodeRttiExposer));
+      crs.Reset();
+      if crs.MoveNext() then begin
+        nd := (crs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+        ExplodeQName(nd.NodeValue,locLocalName,locNamespace);
+        ASimpleTypeAlias := FindElementNS(locNamespace,locLocalName,nvtShortSynonym); //ASimpleTypeAlias := FindElement(ExtractNameFromQName(nd.NodeValue));
+        if Assigned(ASimpleTypeAlias) then begin
+          Result := False;
+        end else begin
+          oldTypeNode := typNd;
+          typNd := FindNamedNode(crsSchemaChild,ExtractNameFromQName(nd.NodeValue));
+          if not Assigned(typNd) then
+            raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['2',AName]);
+          embededType := False;
+          if ( typNd = oldTypeNode ) then begin
+            typNd := FindNamedNode(crsSchemaChild,ExtractNameFromQName(nd.NodeValue),2);
+            if not Assigned(typNd) then
+              raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['2.1',AName]);
+          end;
+        end;
+      end else begin
+        //locStrFilter := Format('%s = %s or %s = %s ',[s_NODE_NAME,QuotedStr(s_complexType),s_NODE_NAME,QuotedStr(s_simpleType)]);
+        locStrFilter := CreateQualifiedNameFilterStr(s_complexType,FXSShortNames) + ' or ' +
+                        CreateQualifiedNameFilterStr(s_simpleType,FXSShortNames);
+        crs := CreateCursorOn(CreateChildrenCursor(typNd,cetRttiNode),ParseFilter(locStrFilter,TDOMNodeRttiExposer));
+        crs.Reset();
+        if not crs.MoveNext() then begin
+          raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeDefinitionNotFound,['3',AName]);
+        end;
+        typNd := (crs.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+        typName := ExtractNameFromQName(AName);
+        embededType := True;
+      end;
+    end;
+  end;
+
+  function ParseComplexType():ISDODataObject;
+  var
+    locParser : TComplexTypeParser;
+  begin
+    locParser := TComplexTypeParser.Create(Self,typNd,typName,embededType);
+    try
+      Result := locParser.Parse();
+    finally
+      FreeAndNil(locParser);
+    end;
+  end;
+
+  function ParseSimpleType():ISDODataObject;
+  var
+    locParser : TSimpleTypeParser;
+  begin
+    locParser := TSimpleTypeParser.Create(Self,typNd,typName,embededType);
+    try
+      Result := locParser.Parse();
+    finally
+      FreeAndNil(locParser);
+    end;
+  end;
+
+  {function CreateTypeAlias(const ABase : ISDODataObject): ISDODataObject;
+  begin
+    Result := Module.createDataObject(s_Type);
+    Result.setByte(s_ElementKind,ELEMENT_KIND_TYPE);
+    Result.setString(s_Name,ExtractNameFromQName(AName));
+    Module.getList(s_Type).append(Result);
+    Result.setDataObject(s_BaseType,ABase);
+  end;}
+
+  function CreateTypeAlias(const ABase : ISDODataObject): ISDODataObject;
+  begin
+    Result := Module.createDataObject(s_Variable);
+    Result.setByte(s_ElementKind,ELEMENT_KIND_VARIABLE);
+    Result.setString(s_Name,ExtractNameFromQName(AName));
+    Module.getList(s_Variable).append(Result);
+    Result.setDataObject(s_DataType,ABase);
+  end;
+
+  function CreateUnresolveType(): ISDODataObject;
+  var
+    locTypeLocalName, locTypeLocalSpaceShort, locTypeLocalSpaceExpanded : string;
+  begin
+    ExplodeQName(AName,locTypeLocalName,locTypeLocalSpaceShort);
+    if not IsStrEmpty(locTypeLocalSpaceShort) then begin
+      if not FindNameSpace(locTypeLocalSpaceShort,locTypeLocalSpaceExpanded) then
+        locTypeLocalSpaceExpanded := locTypeLocalSpaceShort;
+    end;
+    Result := CreateUnresolvedType(SymbolTable,locTypeLocalSpaceExpanded,locTypeLocalName);
+  end;
+
+var
+  frwType, aliasType : ISDODataObject;
+  shortNameSpace, longNameSpace : string;
+  typeModule : ISDODataObject;
+  locTypeNodeFound : Boolean;
+  i : Integer;
+begin
+  if not FImportParsed then
+    ParseImportDocuments();
+  DoOnMessage(mtInfo, Format(SERR_Parsing,[AName]));
+  try
+    embededType := False;
+    aliasType := nil;
+    ExplodeQName(AName,localTypeName,shortNameSpace);
+    if IsStrEmpty(shortNameSpace) then begin
+      typeModule := FModule;
+    end else begin
+      if not FindNameSpace(shortNameSpace,longNameSpace) then
+        raise EXsdParserAssertException.CreateFmt(SERR_UnableToResolveNamespace,[shortNameSpace]);
+      typeModule := FindModule(SymbolTable,longNameSpace);
+    end;
+    if ( typeModule = nil ) then
+      raise EXsdTypeNotFoundException.Create(AName);
+    Result := FindInModule(typeModule,localTypeName);
+    if (Result <> nil) and (not Result.getBoolean(s_Unresolved)) then
+      Exit;
+    Init();
+    locTypeNodeFound := FindTypeNode(aliasType);
+    if ( Result <> nil ) and ( typeModule = FModule ) and
+       ( not Result.getBoolean(s_Unresolved) )
+    then begin
+      if locTypeNodeFound and (embededType <> Result.getBoolean(s_Embedded)) then
+        Result := nil;
+    end;
+    if ( ( Result = nil ) or Result.getBoolean(s_Unresolved) ) and
+       ( typeModule = FModule )
+    then begin
+      frwType := Result;
+      Result := nil;
+      Init();
+      if locTypeNodeFound {FindTypeNode(aliasType)} then begin
+        if AnsiSameText(ExtractNameFromQName(typNd.NodeName),s_complexType) then begin
+          Result := ParseComplexType();
+        end else if AnsiSameText(ExtractNameFromQName(typNd.NodeName),s_simpleType) then begin
+          Result := ParseSimpleType();
+        end;
+        if not Assigned(Result) then
+          raise EXsdTypeNotFoundException.CreateFmt(SERR_TypeNodeFoundButUnableToParseIt,[AName]);
+      end else begin
+        Result := CreateTypeAlias(aliasType);
+      end;
+      if ( frwType <> nil ) then begin
+        i := indexOf(frwType,SymbolTable.getList(s_Unresolved));
+        if (i >= 0) then
+          SymbolTable.getList(s_Unresolved).delete(i);
+      end;
+    end;
+  except
+    on e : EXsdTypeNotFoundException do begin
+      Result := CreateUnresolveType();
+    end;
+  end;
+end;
+
+procedure TCustomXsdSchemaParser.CreateImportParsers();
+var
+  crsSchemaChild : IObjectCursor;
+  strFilter, locFileName, locNameSpace : string;
+  importNode : TDOMElement;
+  importDoc : TXMLDocument;
+  locParser : IXsdParser;
+  locOldCurrentModule : ISDODataObject;
+  locContinue : Boolean;
+  locLocator : IDocumentLocator;
+begin
+  if FImportParsed then
+    Exit;
+  locLocator := GetDocumentLocator();
+  if (locLocator = nil) then
+    Exit;
+
+  if Assigned(FChildCursor) then begin
+    locOldCurrentModule := SymbolTable.getDataObject(s_CurrentModule);
+    try
+      crsSchemaChild := FChildCursor.Clone() as IObjectCursor;
+      strFilter := CreateQualifiedNameFilterStr(s_import,FXSShortNames);
+      crsSchemaChild := CreateCursorOn(crsSchemaChild,ParseFilter(strFilter,TDOMNodeRttiExposer));
+      crsSchemaChild.Reset();
+      while crsSchemaChild.MoveNext() do begin
+        importNode := (crsSchemaChild.GetCurrent() as TDOMNodeRttiExposer).InnerObject as TDOMElement;
+        if ( importNode.Attributes <> nil ) and ( importNode.Attributes.Length > 0 ) then begin
+          locFileName := NodeValue(importNode.Attributes.GetNamedItem(s_schemaLocation));
+          if ( not IsStrEmpty(locFileName) ) and
+             locLocator.Find(locFileName,importDoc)
+          then begin
+            locNameSpace := NodeValue(importNode.Attributes.GetNamedItem(s_namespace));
+            locContinue := IsStrEmpty(locNameSpace) or (FXsdParsers = nil) or (FXsdParsers.IndexOf(locNameSpace) = -1);//( SymbolTable.FindModule(locNameSpace) = nil );
+            if locContinue then begin
+              if (FXsdParsers = nil) then begin
+                FXsdParsers := TStringList.Create();
+                FXsdParsers.Duplicates := dupIgnore;
+                FXsdParsers.Sorted := True;
+              end;
+              locParser := TCustomXsdSchemaParserClass(Self.ClassType).Create(
+                             importDoc,
+                             importDoc.DocumentElement,
+                             SymbolTable,
+                             Self as IParserContext
+                           );
+              FXsdParsers.AddObject(locNameSpace,TIntfObjectRef.Create(locParser));
+              locParser.SetNotifier(FOnMessage);
+              //locParser.ParseTypes();
+            end;
+          end;
+        end;
+      end;
+    finally
+      SymbolTable.setDataObject(s_CurrentModule,locOldCurrentModule);
+    end;
+  end;
+end;
+
+procedure TCustomXsdSchemaParser.ParseTypes();
+var
+  crsSchemaChild, typTmpCrs : IObjectCursor;
+  typFilterStr : string;
+  typNode : TDOMNode;
+begin
+  if Assigned(FChildCursor) then begin
+    crsSchemaChild := FChildCursor.Clone() as IObjectCursor;
+    typFilterStr := Format(
+                      '%s or %s or %s',
+                      [ CreateQualifiedNameFilterStr(s_complexType,FXSShortNames),
+                        CreateQualifiedNameFilterStr(s_simpleType,FXSShortNames),
+                        CreateQualifiedNameFilterStr(s_element,FXSShortNames)
+                      ]
+                    );
+    crsSchemaChild := CreateCursorOn(crsSchemaChild,ParseFilter(typFilterStr,TDOMNodeRttiExposer));
+    crsSchemaChild.Reset();
+    while crsSchemaChild.MoveNext() do begin
+      typNode := (crsSchemaChild.GetCurrent() as TDOMNodeRttiExposer).InnerObject;
+      typTmpCrs := CreateAttributesCursor(typNode,cetRttiNode);
+      if Assigned(typTmpCrs) then begin
+        typTmpCrs.Reset();
+        typTmpCrs := CreateCursorOn(typTmpCrs,ParseFilter(Format('%s=%s',[s_NODE_NAME,QuotedStr(s_name)]),TDOMNodeRttiExposer));
+        typTmpCrs.Reset();
+        if typTmpCrs.MoveNext() then begin
+          InternalParseType(
+            (typTmpCrs.GetCurrent() as TDOMNodeRttiExposer).NodeValue,
+            typNode
+          );
+        end;
+      end;
+    end;
+    HandleUnresolvedLinks();
+  end;
+end;
+
+procedure TCustomXsdSchemaParser.Prepare();
+var
+  locAttCursor : IObjectCursor;
+  prntCtx : IParserContext;
+  nd : TDOMNode;
+  i : PtrInt;
+  ls : TStrings;
+begin
+  if ( FSchemaNode.Attributes = nil ) or ( GetNodeListCount(FSchemaNode.Attributes) = 0 ) then
+    raise EXsdParserAssertException.CreateFmt(SERR_SchemaNodeRequiredAttribute,[s_targetNamespace]);
+  nd := FSchemaNode.Attributes.GetNamedItem(s_targetNamespace);
+  if ( nd = nil ) then
+    raise EXsdParserAssertException.CreateFmt(SERR_SchemaNodeRequiredAttribute,[s_targetNamespace]);
+  FTargetNameSpace := nd.NodeValue;
+  if IsStrEmpty(FModuleName) then
+    FModuleName := ExtractIdentifier(FTargetNameSpace);
+  if (FindModule(SymbolTable,s_xs) = nil) then
+    AddXsdTypes(SymbolTable);
+  FChildCursor := CreateChildrenCursor(FSchemaNode,cetRttiNode);
+
+  locAttCursor := CreateAttributesCursor(FSchemaNode,cetRttiNode);
+  BuildNameSpaceList(locAttCursor,FNameSpaceList);
+  FXSShortNames := FindShortNamesForNameSpaceLocal(s_xs);
+  prntCtx := GetParentContext();
+  if ( FXSShortNames = nil ) then begin
+    if ( prntCtx = nil ) then
+      raise EXsdParserAssertException.CreateFmt(SERR_InvalidSchemaDoc_NamespaceNotFound,[s_xs]);
+    FXSShortNames := prntCtx.FindShortNamesForNameSpace(s_xs);
+    if ( FXSShortNames = nil ) then
+      raise EXsdParserAssertException.CreateFmt(SERR_InvalidSchemaDoc_NamespaceNotFoundShort,[s_xs]);
+  end;
+
+  if Assigned(prntCtx) then begin
+    for i:= 0 to Pred(FNameSpaceList.Count) do begin
+      ls := prntCtx.FindShortNamesForNameSpace(FNameSpaceList[i]);
+      if Assigned(ls) then
+        (FNameSpaceList.Objects[i] as TStrings).AddStrings(ls);
+    end;
+  end;
+
+  FModule := FindModule(SymbolTable,FTargetNameSpace);
+  if ( FModule = nil ) then begin
+    FModule := SymbolTable.createDataObject(s_Module);
+    FModule.setString(s_Name,FModuleName);
+    FModule.setString(s_NameSpace,FTargetNameSpace);
+    SymbolTable.getList(s_Module).append(FModule);
+  end;
+  SymbolTable.setDataObject(s_CurrentModule,FModule);
+end;
+
+procedure TCustomXsdSchemaParser.HandleUnresolvedLinks();
+var
+  locCursor : ISDOCursor;
+  locList, locUnresolvedList : ISDODataObjectList;
+  locLink, locType, locUnresolved, locTmp : ISDODataObject;
+  i, c, j : PtrInt;
+begin
+  locList := FSymbols.getList(s_UnresolvedLink);
+  locCursor := locList.getCursor();
+  locCursor.Reset();
+  while locCursor.MoveNext() do begin
+    locLink := locList.getDataObject();
+    if locLink.getBoolean(s_Resolved) then
+      Continue;
+    locUnresolved := locLink.getDataObject(s_Target);
+    locType := Find(FSymbols,locUnresolved.getString(s_NameSpace),locUnresolved.getString(s_Name));
+    if (locType <> nil) and
+       (not locType.getBoolean(s_Unresolved))
+    then begin
+      if SameText(locLink.getString(s_LinkKind),LINK_KIND_BASE_TYPE) then begin
+        locLink.getDataObject(s_Element).setDataObject(s_BaseType,locType);
+        locLink.setBoolean(s_Resolved,True);
+      end else if SameText(locLink.getString(s_LinkKind),LINK_KIND_PROP_TYPE) then begin
+        locTmp := locLink.getDataObject(Format('%s/%s[%s=%S]',[s_Element,s_Property,s_Name,QuotedStr(locLink.getString(s_Name))]));
+        if (locTmp <> nil) then
+          locTmp.setDataObject(s_DataType,locType);
+        locLink.setBoolean(s_Resolved,True);
+      end;
+    end;
+  end;
+  c := locList.size();
+  if (c > 0) then begin
+    locUnresolvedList := FSymbols.getList(s_Unresolved);
+    for i := (c - 1) downto 0 do begin
+      locLink := locList.getDataObject(i);
+      if locLink.getBoolean(s_Resolved) then begin
+        j := indexOf(locLink.getDataObject(s_Target),locUnresolvedList);
+        locList.delete(i);
+        if (j >= 0) then
+          locUnresolvedList.delete(j);
+      end;
+    end;
+  end;
+end;
+
+function TCustomXsdSchemaParser.FindElementNS(
+  const ANameSpace,
+        ALocalName : string;
+  const ASpaceType : TNameSpaceValueType
+) : ISDODataObject;
+var
+  locNS : string;
+begin
+  if ( ASpaceType = nvtExpandValue ) then begin
+    locNS := ANameSpace
+  end else begin
+    if not FindNameSpace(ANameSpace,locNS) then
+      raise EXsdParserAssertException.CreateFmt(SERR_CannotResolveNamespace,[ANameSpace]);
+  end;
+  Result := Find(FSymbols,locNS,ALocalName);
+end;
+
+{ TXsdParser }
+
+constructor TXsdParser.Create(
+        ADoc : TXMLDocument;
+        ASymbols : ISDODataObject;
+  const AModuleName : string;
+  const ANotifier : TOnParserMessage
+);
+var
+  locName : string;
+begin
+  inherited Create(ADoc,ADoc.DocumentElement,ASymbols,nil);
+  if Assigned(ANotifier) then
+    FOnMessage := ANotifier;
+  if not IsStrEmpty(AModuleName) then begin
+    locName := ExtractIdentifier(AModuleName);
+    if not IsStrEmpty(locName) then begin
+      FModuleName := locName;
+      Module.setString(s_Name,FModuleName);
+    end;
+  end;
+end;
+
+initialization
+  TAbstractTypeParser.RegisterParser(TSimpleTypeParser);
+  TAbstractTypeParser.RegisterParser(TComplexTypeParser);
+
+finalization
+  FreeAndNil(FTypeParserList);
+
+end.

+ 112 - 0
packages/fcl-sdo/src/base/xsd_consts.pas

@@ -0,0 +1,112 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements XSD Constants
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit xsd_consts;
+
+interface
+
+const
+  s_address                    : WideString = 'address';
+  s_all                        : WideString = 'all';
+  s_annotation                 : WideString = 'annotation';
+  s_any                                     = 'any';
+  s_anyAttribute                            = 'anyAttribute';
+  s_anyURI                                  = 'anyURI';
+  s_appinfo                    : WideString = 'appinfo';
+  s_array                      : WideString = 'array';
+  s_arrayType                  : WideString = 'arrayType';
+  s_attribute                  : WideString = 'attribute';
+  s_base                       : WideString = 'base';
+  s_binding                    : WideString = 'binding';
+  s_body                       : WideString = 'body';
+  s_complexContent             : WideString = 'complexContent';
+  s_complexType                : WideString = 'complexType';
+  s_customAttributes           : WideString = 'customAttributes';
+  s_definitions                             = 'definitions';
+  s_default                                 = 'default';
+  s_document                   : WideString = 'document';
+  s_documentation                           = 'documentation';
+  s_element                    : WideString = 'element';
+  s_enumeration                : WideString = 'enumeration';
+  s_extension                  : WideString = 'extension';
+  s_guid                       : WideString = 'GUID';
+  s_import                                  = 'import';
+  s_input                      : WideString = 'input';
+  s_item                       : WideString = 'item';
+  s_literal                                 = 'literal';
+  s_location                   : WideString = 'location';
+  s_message                    : WideString = 'message';
+  s_maxOccurs                  : WideString = 'maxOccurs';
+  s_minOccurs                  : WideString = 'minOccurs';
+  s_name                       : WideString = 'name';
+  s_namespace                               = 'namespace';
+  s_operation                               = 'operation';
+  s_optional                   : WideString = 'optional';
+  s_output                     : WideString = 'output';
+  s_paramAccess                             = 'ParamAccess';
+  s_part                       : WideString = 'part';
+  s_port                       : WideString = 'port';
+  s_portType                                = 'portType';
+  s_processContents                         = 'processContents';
+  s_prohibited                              = 'prohibited';
+
+  s_ref                        : WideString = 'ref';
+  s_required                   : WideString = 'required';
+  s_restriction                : WideString = 'restriction';
+  //s_return                     : WideString = 'return';
+  s_rpc                                     = 'rpc';
+  s_schema                     : WideString = 'schema';
+  s_schemaLocation                          = 'schemaLocation';
+  s_xs                         : WideString = 'http://www.w3.org/2001/XMLSchema';
+  s_xs_short                                = 'xsd';
+  s_sequence                   : WideString = 'sequence';
+  s_service                    : WideString = 'service';
+  s_simpleContent              : WideString = 'simpleContent';
+  s_simpleType                 : WideString = 'simpleType';
+  s_soap                       : WideString = 'http://schemas.xmlsoap.org/wsdl/soap/';
+  s_soap_short_name                         = 'soap';
+  s_soapAction                              = 'soapAction';
+  s_soapEncodingNameSpace                   = 'http://schemas.xmlsoap.org/soap/encoding/';
+  s_soapInputEncoding                       = 'Input_EncodingStyle';
+  s_soapOutputEncoding                      = 'OutputEncodingStyle';
+  s_soapStyle                               = 'style';
+  s_soapTransport                           = 'http://schemas.xmlsoap.org/soap/http';
+  s_style                                   = 'style';
+  s_targetNamespace                         = 'targetNamespace';
+  s_tns                                     = 'tns';
+  s_transport                               = 'transport';
+  s_type                                    = 'type';
+  s_types                                   = 'types';
+  s_unbounded                               = 'unbounded';
+  s_use                                     = 'use';
+  s_value                                   = 'value';
+  s_wsdl                                    = 'http://schemas.xmlsoap.org/wsdl/';
+  s_xmlns                                   = 'xmlns';
+
+  
+  s_SDO                           = 'sdo';
+  s_SDO_base_namespace            = 'urn:sdo_base';
+  s_SDO_collection                = 'sdo_collection';
+  s_SDO_headerBlock               = 'sdo_headerBlock';
+  s_SDO_headerBlockSimpleContent  = 'sdo_headerBlockSimpleContent';
+  s_SDO_record                    = 'sdo_record';
+  s_SDO_storeType                 = 'StoreType';
+  s_SDO_typeHint                  = 'TypeHint';
+
+  
+implementation
+
+end.
+

+ 550 - 0
packages/fcl-sdo/src/base/xsd_generator.pas

@@ -0,0 +1,550 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements creating a XSD file from SDO metadata
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit xsd_generator;
+
+interface
+
+uses
+  Classes, SysUtils, TypInfo,
+  {$IFNDEF FPC}xmldom, sdo_win_xml,{$ELSE}DOM, sdo_fpc_xml,{$ENDIF}
+  sdo;
+
+type
+
+  TGeneratorOption = ( xgoIgnorembeddedArray );
+  TGeneratorOptions = set of TGeneratorOption;
+
+  EXsdGeneratorException = class(Exception) end;
+
+  IGenerator = interface
+    ['{F69523B3-A6FF-4BFB-9ACB-D4B9F32DBCA9}']
+    procedure Execute(
+      ASymTable   : ISDODataObject;
+      AModuleName : string
+    );
+  end;
+
+  IXsdGenerator = interface(IGenerator)
+    ['{FBFF92BC-B72B-4B85-8D16-379F9E548DDB}']
+    function GetSchemaNode(ADocument : TDOMDocument) : TDOMNode;
+    procedure SetPreferedShortNames(const ALongName, AShortName : string);
+    function GetPreferedShortNames() : TStrings;
+  end;
+
+  { TCustomXsdGenerator }
+
+  TCustomXsdGenerator = class(
+    TInterfacedObject,
+    IInterface,
+    IGenerator,
+    IXsdGenerator
+  )
+  private
+    FDocument : TDOMDocument;
+    FOptions: TGeneratorOptions;
+    FShortNames : TStrings;
+  protected
+    function GetSchemaNode(ADocument : TDOMDocument) : TDOMNode;virtual;abstract;
+    procedure SetPreferedShortNames(const ALongName, AShortName : string);
+    function GetPreferedShortNames() : TStrings;
+
+    procedure GenerateEnum(AContainer, ASymbol : ISDODataObject);
+    procedure GenerateComplex(AContainer, ASymbol : ISDODataObject);
+    procedure Execute(
+      ASymTable   : ISDODataObject;
+      AModuleName : string
+    );
+
+    procedure Prepare(
+      ASymTable,
+      AModule   : ISDODataObject
+    );virtual;
+    property Document : TDOMDocument read FDocument;
+    property Options : TGeneratorOptions read FOptions;
+  public
+    constructor Create(const ADocument : TDOMDocument);overload;
+    constructor Create(
+      const ADocument : TDOMDocument;
+      const AOptions : TGeneratorOptions
+    );overload;
+    destructor Destroy();override;
+  end;
+
+  { TXsdGenerator }
+
+  TXsdGenerator = class(TCustomXsdGenerator)
+  private
+    FSchemaNode : TDOMElement;
+  protected
+    function GetSchemaNode(ADocument : TDOMDocument) : TDOMNode;override;
+    procedure Prepare(ASymTable, AModule : ISDODataObject);override;
+  end;
+
+  function GetNameSpaceShortName(
+    const ANameSpace    : string;
+          ADocument : TDOMDocument;
+    const APreferedList : TStrings
+  ):string;
+
+  function CreateElement(const ANodeName : DOMString; AParent : TDOMNode; ADoc : TDOMDocument):TDOMElement;{$IFDEF USE_INLINE}inline;{$ENDIF}
+
+implementation
+uses
+  sdo_xsdintf, xsd_consts, Contnrs, StrUtils, sdo_types, sdo_parserutils;
+
+function FindAttributeByValueInNode(
+  const AAttValue        : string;
+  const ANode            : TDOMNode;
+  out   AResAtt          : string;
+  const AStartIndex      : Integer = 0;
+  const AStartingWith    : string = ''
+):boolean;
+var
+  i,c : Integer;
+  b : Boolean;
+begin
+  AResAtt := '';
+  if Assigned(ANode) and Assigned(ANode.Attributes) then begin
+    b := ( Length(AStartingWith) = 0);
+    c := Pred(ANode.Attributes.Length);
+//    if ( AStartIndex >= 0 ) then
+  //    i := AStartIndex;
+    for i := AStartIndex to c do begin
+      if AnsiSameText(AAttValue,ANode.Attributes.Item[i].NodeValue) and
+         ( b or ( Pos(AStartingWith,ANode.Attributes.Item[i].NodeName) = 1 ))
+      then begin
+        AResAtt := ANode.Attributes.Item[i].NodeName;
+        Result := True;
+        Exit;
+      end;
+    end;
+  end;
+  Result := False;
+end;
+
+function GetNameSpaceShortName(
+  const ANameSpace    : string;
+        ADocument : TDOMDocument;
+  const APreferedList : TStrings
+):string;
+begin
+  if FindAttributeByValueInNode(ANameSpace,ADocument.DocumentElement,Result,0, s_xmlns) then begin
+    Result := Copy(Result,Length(s_xmlns+':')+1,MaxInt);
+  end else begin
+    if ( APreferedList <> nil ) then
+      Result := Trim(APreferedList.Values[ANameSpace]);
+    if ( Result = '' ) then
+      Result := Format('ns%d',[GetNodeListCount(ADocument.DocumentElement.Attributes)]) ;
+    ADocument.DocumentElement.SetAttribute(Format('%s:%s',[s_xmlns,Result]),ANameSpace);
+  end;
+end;
+
+function CreateElement(const ANodeName : DOMString; AParent : TDOMNode; ADoc : TDOMDocument):TDOMElement;//inline;
+begin
+  Result := ADoc.CreateElement(ANodeName);
+  AParent.AppendChild(Result);
+end;
+
+{ TCustomXsdGenerator }
+
+procedure TCustomXsdGenerator.Execute(
+  ASymTable   : ISDODataObject;
+  AModuleName : string
+);
+var
+  i : Integer;
+  locModule : ISDODataObject;
+  locList : ISDODataObjectList;
+  locElement : ISDODataObject;
+begin
+  if ( ASymTable = nil ) then
+    raise EXsdGeneratorException.Create('Invalid symbol table.');
+  locModule := FindModule(ASymTable,AModuleName);
+  if ( locModule = nil ) then
+    raise EXsdGeneratorException.CreateFmt('Unable to find module : "%s".',[AModuleName]);
+  Prepare(ASymTable,locModule);
+  locList := locModule.getList(s_Type);
+  for i := 0 to locList.size() - 1 do begin
+    locElement := locList.getDataObject(i);
+    if locElement.getBoolean(s_IsComplex) then
+      GenerateComplex(ASymTable,locElement)
+    else if (locElement.getList(s_EnumValue).size() > 0) then
+      GenerateEnum(ASymTable,locElement);
+  end
+end;
+
+procedure TCustomXsdGenerator.Prepare(
+  ASymTable,
+  AModule   : ISDODataObject
+);
+begin
+
+end;
+
+constructor TCustomXsdGenerator.Create(const ADocument : TDOMDocument);
+begin
+  Create(ADocument,[]);
+end;
+
+constructor TCustomXsdGenerator.Create(
+  const ADocument: TDOMDocument;
+  const AOptions: TGeneratorOptions
+);
+var
+  sl : TStringList;
+begin
+  if ( ADocument = nil ) then
+    raise EXsdGeneratorException.Create('Invalid document.');
+  FDocument := ADocument;
+  FOptions := AOptions;
+  FShortNames := TStringList.Create();
+  sl := TStringList(FShortNames);
+  //sl.Sorted := True;
+  sl.Duplicates := dupIgnore;
+end;
+
+procedure TCustomXsdGenerator.SetPreferedShortNames(const ALongName, AShortName: string);
+begin
+  FShortNames.Values[ALongName] := AShortName;
+end;
+
+function TCustomXsdGenerator.GetPreferedShortNames() : TStrings;
+begin
+  Result := FShortNames;
+end;
+
+destructor TCustomXsdGenerator.Destroy();
+begin
+  FreeAndNil(FShortNames);
+  inherited;
+end;
+
+procedure TCustomXsdGenerator.GenerateEnum(AContainer, ASymbol : ISDODataObject);
+var
+  typItm : ISDODataObject;
+  valueList : ISDODataObjectList;
+  ns_shortName, s : string;
+  defSchemaNode, resNode, restrictNode : TDOMElement;
+  i : Integer;
+  unitExternalName : string;
+{$IFDEF SDO_HANDLE_DOC}
+  ls : TStrings;
+{$ENDIF SDO_HANDLE_DOC}
+begin
+  if (ASymbol = nil) then
+    Exit;
+  typItm := ASymbol;
+  unitExternalName := GetTypeNameSpace(typItm);
+  if FindAttributeByValueInNode(unitExternalName,Document.DocumentElement,ns_shortName) then begin
+    ns_shortName := Copy(ns_shortName,Length(s_xmlns+':')+1,MaxInt);
+  end else begin
+    ns_shortName := Format('ns%d',[GetNodeListCount(Document.DocumentElement.Attributes)]) ;
+    Document.DocumentElement.SetAttribute(Format('%s:%s',[s_xmlns,ns_shortName]),unitExternalName);
+  end;
+  defSchemaNode := GetSchemaNode(Document) as TDOMElement;
+
+  s := Format('%s:%s',[s_xs_short,s_simpleType]);
+  resNode := CreateElement(s,defSchemaNode,Document);
+  resNode.SetAttribute(s_name, typItm.getString(sdo_xsdintf.s_Name)) ;
+{$IFDEF SDO_HANDLE_DOC}
+  ls := AContainer.Properties.FindList(typItm);
+  if ( ls <> nil ) then begin
+    i := ls.IndexOfName(s_documentation);
+    if ( i >= 0 ) then
+      GenerateDocumentation(resNode,DecodeLineBreak(ls.ValueFromIndex[i]),ADocument);
+  end;
+{$ENDIF SDO_HANDLE_DOC}
+
+  s := Format('%s:%s',[s_xs_short,s_restriction]);
+  restrictNode := CreateElement(s,resNode,Document);
+  restrictNode.SetAttribute(s_base,Format('%s:%s',[s_xs_short,'string'])) ;
+  valueList := typItm.getList(s_EnumValue);
+  for i := 0 to (valueList.size() - 1) do begin
+    s := Format('%s:%s',[s_xs_short,s_enumeration]);
+    CreateElement(s,restrictNode,Document).SetAttribute(
+      s_value,
+      valueList.getString(i)
+    );
+  end;
+end;
+
+type TTypeCategory = ( tcComplexContent, tcSimpleContent );
+procedure TCustomXsdGenerator.GenerateComplex(AContainer, ASymbol: ISDODataObject);
+
+  function TypeHasSequence(const AClassType : ISDODataObject; const ACategory : TTypeCategory) : Boolean;
+  var
+    kc, k : PtrInt;
+    pl : ISDODataObjectList;
+    p : ISDODataObject;
+  begin
+    Result := False;
+    pl := AClassType.getList(s_Property);
+    kc := pl.size();
+    if (kc > 0) then begin
+      for k := 0 to kc - 1 do begin
+        p := pl.getDataObject(k);
+        if not p.getBoolean(s_IsAttribute) then begin
+          if ( ACategory = tcSimpleContent ) then begin
+            raise EXsdGeneratorException.CreateFmt(
+                    'Invalid type definition, a simple type cannot have "not attribute" properties : "%s"',
+                    [AClassType.getString(sdo_xsdintf.s_Name)]
+                  );
+          end;
+          Result := True;
+        end;
+      end;
+    end;
+  end;
+
+  procedure ProcessPropertyExtendedMetadata(const AProp : ISDODataObject; const APropNode : TDOMElement);
+  var
+    ls : ISDODataObjectList;
+    tagObj : ISDODataObject;
+    line, ns, ns_short, localName, attName, attValue : TSDOString;
+    k, q : PtrInt;
+  begin
+    ls := AProp.getList(s_Tag);
+    if (ls.size() > 0) then begin
+      for k := 0 to ls.size() - 1 do begin
+        tagObj := ls.getDataObject(k);
+        line := tagObj.getString(sdo_xsdintf.s_Name);
+        q := Pos('#',line);
+        if ( q > 0 ) then begin
+          ns := Copy(line,1,Pred(q));
+          localName := Copy(line,Succ(q),MaxInt);
+          ns_short := GetNameSpaceShortName(ns,Document,GetPreferedShortNames());
+          attName := Format('%s:%s',[ns_short,localName]);
+          line := tagObj.getString(sdo_xsdintf.s_Value);
+          q := Pos('#',line);
+          if ( q > 0 ) then begin
+            ns := Copy(line,1,Pred(q));
+            localName := Copy(line,Succ(q),MaxInt);
+            ns_short := GetNameSpaceShortName(ns,Document,GetPreferedShortNames());
+            attValue := Format('%s:%s',[ns_short,localName]);
+          end else begin
+            attValue := line;
+          end;
+          APropNode.SetAttribute(attName,attValue);
+        end;
+      end;
+    end;
+  end;
+
+  procedure ProcessXsdAny(const AContentNode : TDOMElement; const AXsdInfo : string);
+  var
+    xsdAnyNode : TDOMElement;
+    ss : string;
+    locLS : TStringList;
+  begin
+    xsdAnyNode := CreateElement(Format('%s:%s',[s_xs_short,s_any]),AContentNode,Document);
+    locLS := TStringList.Create();
+    try
+      locLS.Delimiter := ';';
+      locLS.DelimitedText := AXsdInfo;
+      ss := locLS.Values[s_processContents];
+      if not IsStrEmpty(ss) then
+        xsdAnyNode.SetAttribute(s_processContents,ss);
+      ss := locLS.Values[s_minOccurs];
+      if not IsStrEmpty(ss) then
+        xsdAnyNode.SetAttribute(s_minOccurs,ss);
+      ss := locLS.Values[s_maxOccurs];
+      if not IsStrEmpty(ss) then
+        xsdAnyNode.SetAttribute(s_maxOccurs,ss);
+    finally
+      locLS.Free();
+    end;
+  end;
+
+  procedure ProcessXsdAnyAttribute(const AContentNode : TDOMElement; const AXsdInfo : string);
+  var
+    xsdAnyNode : TDOMElement;
+    ss : string;
+    locLS : TStringList;
+  begin
+    xsdAnyNode := CreateElement(Format('%s:%s',[s_xs_short,s_anyAttribute]),AContentNode,Document);
+    locLS := TStringList.Create();
+    try
+      locLS.Delimiter := ';';
+      locLS.DelimitedText := AXsdInfo;
+      ss := locLS.Values[s_processContents];
+      if not IsStrEmpty(ss) then
+        xsdAnyNode.SetAttribute(s_processContents,ss);
+    finally
+      locLS.Free();
+    end;
+  end;
+
+var
+  cplxNode, sqcNode, derivationNode, defSchemaNode : TDOMElement;
+
+  procedure ProcessProperty(const AProp : ISDODataObject);
+  var
+    p : ISDODataObject;
+    s : string;
+    propNode : TDOMElement;
+    propTypItm, propItmUltimeType : ISDODataObject;
+    prop_ns_shortName : string;
+  begin
+    p := AProp;
+    if p.getBoolean(sdo_xsdintf.s_IsAttribute) then begin
+      s := Format('%s:%s',[s_xs_short,s_attribute]);
+      if Assigned(derivationNode) then
+        propNode := CreateElement(s,derivationNode,Document)
+      else
+        propNode := CreateElement(s,cplxNode,Document);
+    end else begin
+      s := Format('%s:%s',[s_xs_short,s_element]);
+      propNode := CreateElement(s,sqcNode,Document);
+    end;
+    propNode.SetAttribute(s_name,p.getString(sdo_xsdintf.s_Name));
+    propTypItm := p.getDataObject(s_DataType);
+    if Assigned(propTypItm) then begin
+      if propTypItm.getBoolean(sdo_xsdintf.s_Unresolved) then
+        propTypItm := Find( AContainer,propTypItm.getString(sdo_xsdintf.s_NameSpace),propTypItm.getString(sdo_xsdintf.s_Name));
+      propItmUltimeType := GetUltimeType(propTypItm);
+      s := propTypItm.getString(sdo_xsdintf.s_Name);
+      prop_ns_shortName := GetNameSpaceShortName(GetTypeNameSpace(propTypItm),Document,GetPreferedShortNames());
+      propNode.SetAttribute(s_type,Format('%s:%s',[prop_ns_shortName,s]));
+      if (Length(p.getString(s_DefaultValue)) > 0) then
+        propNode.SetAttribute(s_default,p.getString(s_DefaultValue));
+      if p.getBoolean(s_IsAttribute) then begin
+        if (p.getInteger(s_PropertyMinOccurs) > 0) then
+          propNode.SetAttribute(s_use,'required');
+      end else begin
+        if (p.getInteger(s_PropertyMinOccurs) = 0) or (p.getInteger(s_PropertyMinOccurs) <> 1) then
+          propNode.SetAttribute(s_minOccurs,p.getString(s_PropertyMinOccurs));
+        if (p.getInteger(s_PropertyMaxOccurs) = MaxInt) then
+          propNode.SetAttribute(s_maxOccurs,s_unbounded)
+        else if (p.getInteger(s_PropertyMaxOccurs) > 1) then
+          propNode.SetAttribute(s_maxOccurs,p.getString(s_PropertyMaxOccurs));
+      end;
+    end;
+    ProcessPropertyExtendedMetadata(p,propNode);
+  end;
+
+var
+  typItm : ISDODataObject;
+  s : string;
+  i : Integer;
+  typeCategory : TTypeCategory;
+  hasSequence : Boolean;
+  trueParent : ISDODataObject;
+  hasXsdAny, hasXsdAnyAtt : Boolean;
+  xsdAnyString, xsdAnyAttString : TSDOString;
+  pl : ISDODataObjectList;
+begin
+  if (ASymbol = nil) then
+    Exit;
+  typItm := ASymbol;
+  GetNameSpaceShortName(
+    AContainer.getDataObject(s_CurrentModule).getString(sdo_xsdintf.s_NameSpace),
+    Document,GetPreferedShortNames()
+  );
+  defSchemaNode := GetSchemaNode(Document) as TDOMElement;
+
+  s := Format('%s:%s',[s_xs_short,s_complexType]);
+  cplxNode := CreateElement(s,defSchemaNode,Document);
+  cplxNode.SetAttribute(s_name, typItm.getString(sdo_xsdintf.s_Name)) ;
+
+{$IFDEF SDO_HANDLE_DOC}
+  ls := AContainer.Properties.FindList(typItm);
+  if ( ls <> nil ) then begin
+    i := ls.IndexOfName(s_documentation);
+    if ( i >= 0 ) then
+      GenerateDocumentation(cplxNode,DecodeLineBreak(ls.ValueFromIndex[i]),ADocument);
+  end;
+{$ENDIF SDO_HANDLE_DOC}
+
+  typeCategory := tcComplexContent;
+  derivationNode := nil;
+  hasSequence := True;
+  trueParent := typItm.getDataObject(sdo_xsdintf.s_BaseType);
+  if (trueParent <> nil) then begin
+    if trueParent.getBoolean(s_Unresolved) then
+      trueParent := Find(AContainer,trueParent.getString(sdo_xsdintf.s_NameSpace), trueParent.getString(sdo_xsdintf.s_Name));
+    if (trueParent <> nil) then begin
+      if (trueParent.getByte(s_ElementKind) = sdo_xsdintf.ELEMENT_KIND_VARIABLE) then
+        trueParent := GetUltimeType(trueParent);
+      if not trueParent.getBoolean(s_IsComplex) then
+        typeCategory := tcSimpleContent;
+      if ( typeCategory = tcSimpleContent ) then begin
+        derivationNode := CreateElement(Format('%s:%s',[s_xs_short,s_simpleContent]),cplxNode,Document);
+        derivationNode := CreateElement(Format('%s:%s',[s_xs_short,s_extension]),derivationNode,Document);
+      end else begin
+        derivationNode := CreateElement(Format('%s:%s',[s_xs_short,s_extension]),cplxNode,Document);
+      end;
+      s := Trim(GetNameSpaceShortName(GetTypeNameSpace(trueParent),Document,GetPreferedShortNames()));
+      if ( Length(s) > 0 ) then
+        s := s + ':';
+      s := s + trueParent.getString(sdo_xsdintf.s_Name);
+      derivationNode.SetAttribute(s_base,s);
+      hasSequence := False;
+    end;
+  end;
+  pl := typItm.getList(s_Property);
+  if (pl.size() > 0) then
+    hasSequence := TypeHasSequence(typItm,typeCategory);
+  hasXsdAny := False;
+  hasXsdAnyAtt := False;
+  if (typeCategory = tcComplexContent) then begin
+    hasXsdAny := FindTag(typItm,Format('%s#%s',[s_xs,s_any]),xsdAnyString);
+    if hasXsdAny then begin
+      if not hasSequence then
+        hasSequence := True;
+    end;
+    hasXsdAnyAtt := FindTag(typItm,Format('%s#%s',[s_xs,s_anyAttribute]),xsdAnyAttString);
+  end;
+  if hasSequence then begin
+    s := Format('%s:%s',[s_xs_short,s_sequence]);
+    if Assigned(derivationNode) then
+      sqcNode := CreateElement(s,derivationNode,Document)
+    else
+      sqcNode := CreateElement(s,cplxNode,Document);
+  end else begin
+    sqcNode := nil;
+  end;
+
+  for i := 0 to pl.size() -1 do
+    ProcessProperty(pl.getDataObject(i));
+  if hasXsdAny then
+    ProcessXsdAny(sqcNode,xsdAnyString);
+  if hasXsdAnyAtt then
+    ProcessXsdAnyAttribute(cplxNode,xsdAnyAttString);
+end;
+
+{ TXsdGenerator }
+
+function TXsdGenerator.GetSchemaNode(ADocument : TDOMDocument) : TDOMNode;
+begin
+  Result := FSchemaNode;
+end;
+
+procedure TXsdGenerator.Prepare(ASymTable, AModule : ISDODataObject);
+var
+  unitExternalName : string;
+begin
+  inherited Prepare(ASymTable, AModule);
+  unitExternalName := AModule.getString(s_namespace);
+  FSchemaNode := CreateElement(s_schema,Document,Document);
+  FSchemaNode.SetAttribute(s_targetNamespace,unitExternalName);
+  FSchemaNode.SetAttribute(Format('%s:%s',[s_xmlns,s_xs_short]),s_xs);
+  FSchemaNode.SetAttribute(Format('%s:%s',[s_xmlns,s_tns]),unitExternalName);
+end;
+
+
+  
+end.

+ 137 - 0
packages/fcl-sdo/src/das/data_acces_intf.pas

@@ -0,0 +1,137 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a basic SDO data access interface.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$I sdo_global.inc}
+unit data_acces_intf;
+
+interface
+uses
+  SysUtils, Classes, DB;
+
+const
+  s_DatabaseName = 'DatabaseName';
+  s_HostName = 'HostName';
+  s_Password = 'Password';
+  s_UserName = 'UserName';
+
+const
+  sCONFIGURATION =  'CONFIGURATION';
+  sDB_ALIAS       = 'DBALIAS';
+  sSERVER_ADDRESS = 'SERVER_ADDRESS';
+  sSERVER_INFO    = 'SERVER_INFO';
+    
+type
+
+  EDataAccessException = class(Exception);
+
+  TDACTransactionHandle = ^TDACTransactionStruct;
+  TDACTransactionStruct = record end;
+
+  TDataAccessInterface = class;
+
+  TDacFactory = class
+  public
+    function CreateDAC(AParams : TStrings) : TDataAccessInterface;virtual;abstract;
+  end;
+
+  TSequenceValueType = Integer;
+  TDataAccessInterface = class
+  protected
+    procedure CheckInTransaction();
+  public
+    class function New(const AName : string; AParams : TStrings) : TDataAccessInterface;overload;
+    class function New(AParams : TStrings) : TDataAccessInterface;overload;
+    class procedure RegisterFactory(const AName : string; AFactory : TDacFactory);
+
+    function GetTransactionHanlde() : TDACTransactionHandle;virtual;abstract;
+    procedure SetTransactionHanlde(const ANewX : TDACTransactionHandle);virtual;abstract;
+    procedure RestoreTransactionHanlde();virtual;abstract;
+    function IsIntransaction() : Boolean;virtual;abstract;
+    //returns FALSE if there is a already transaction, TRUE otherwhise
+    function StartTransaction() : Boolean;virtual;abstract;
+    procedure RollbackTransaction(); virtual;abstract;
+    procedure CommitTransaction();virtual;abstract;
+
+    function ExecuteDataset(
+      const AQuery : string;
+      const AParams : array of Variant
+    ) : TDataSet;overload;virtual;abstract;
+    function ExecuteDataset(const AQuery : string) : TDataSet;overload;virtual;abstract;
+
+    procedure ExecuteNonDataset(
+      const AQuery : string;
+      const AParams : array of Variant
+    );overload;virtual;abstract;
+    procedure ExecuteNonDataset(const AQuery : string);overload;virtual;abstract;
+    procedure ExecuteNonDatasetSP(
+      const ASPName : string;
+      const AParamNames : array of string;
+      const AParamValues : array of Variant
+    );overload;virtual;abstract;
+    procedure ExecuteNonDatasetSP(const ASPName : string);overload;virtual;abstract;
+
+    function GetNextSequenceValue(const ASequenceName : string) : TSequenceValueType;virtual;abstract;
+  end;
+
+
+resourcestring
+  sNO_ACTIVE_TRANSACTION = 'No active transaction.';
+
+implementation
+
+var
+  FFactoryList : TStringList;
+
+{ TDataAccessInterface }
+
+procedure TDataAccessInterface.CheckInTransaction();
+begin
+  if not IsIntransaction() then
+    raise EDataAccessException.Create(sNO_ACTIVE_TRANSACTION);
+end;
+
+class function TDataAccessInterface.New(AParams : TStrings) : TDataAccessInterface;
+begin
+  Assert(FFactoryList.Count > 0);
+  Result := New(FFactoryList[0],AParams);
+end;
+
+class function TDataAccessInterface.New(const AName: string; AParams : TStrings): TDataAccessInterface;
+var
+  i : Integer;
+begin
+  i := FFactoryList.IndexOf(AName);
+  if ( i >= 0 ) then
+    Result := TDacFactory(FFactoryList.Objects[i]).CreateDAC(AParams)
+  else
+    raise EDataAccessException.CreateFmt('DAC not found : %s.',[AName]);
+end;
+
+class procedure TDataAccessInterface.RegisterFactory(const AName: string; AFactory: TDacFactory);
+begin
+  Assert(Assigned(AFactory));
+  if ( FFactoryList.IndexOf(AName) = -1 ) then
+    FFactoryList.AddObject(AName,AFactory);
+end;
+
+initialization
+  FFactoryList := TStringList.Create();
+  FFactoryList.Duplicates := dupIgnore;
+  FFactoryList.Sorted := True;
+
+finalization
+  FreeAndNil(FFactoryList);
+  
+end.

+ 99 - 0
packages/fcl-sdo/src/das/sdo_das.pas

@@ -0,0 +1,99 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements basic SDO DAS definitions
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_das;
+
+interface
+uses
+  SysUtils, Classes, DB, 
+  sdo, data_acces_intf;
+
+type
+
+  TSDODASOption = ( sdoAddProperty );
+  TSDODASOptions = set of TSDODASOption;
+
+  ESDODASException = class(ESDOException)
+  end;
+
+  ISDODAS = interface;
+  ISDODASObjectHandler = interface;
+
+
+  ISDODASObjectHandler = interface
+    ['{A67BA4DC-05DC-44FD-9EE8-921732D9CFDB}']
+    procedure UpdateDataStore(
+      const ADas : ISDODAS;
+      const AObject : ISDODataObject;
+      const AUpdateKind : TChangeType
+    );
+  end;
+
+  ISDODAS = interface
+    ['{3EC60A22-2474-49D9-A9AB-DFCBE92E39C7}'] 
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string;
+      const AQueryParams : array of Variant;
+      const ARowType : ISDOType;
+      const AResList : ISDODataObjectList;
+      const AOptions : TSDODASOptions
+    ) : ISDODataObjectList;overload; 
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string;
+      const ARowType : ISDOType;
+      const AResList : ISDODataObjectList;
+      const AOptions : TSDODASOptions
+    ) : ISDODataObjectList;overload;
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string;     
+      const AQueryParams : array of Variant 
+    ) : ISDODataObject;overload;  
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string
+    ) : ISDODataObject;overload;
+    function ExecuteQuery(
+      const ADac          : TDataAccessInterface;
+      const AQuery        : string;
+      const AContainer    : ISDODataObject;
+      const ADestListName : string;
+      const AOptions      : TSDODASOptions
+    ) : ISDODataObjectList;overload;
+    procedure UpdateDataStore(
+      const ADac : TDataAccessInterface;
+      const AChanges : ISDOChangeSummary
+    );
+
+    function GetDataFactory() : ISDODataFactory;
+    procedure RegisterObjectHandler(
+      const ATargetObjectType : ISDOType;
+      const AHandler : ISDODASObjectHandler
+    );
+    function FindObjectHandler(const ATargetObjectType : ISDOType) : ISDODASObjectHandler;
+  end;
+
+  TSDODAS_Implementor = function(AFactory : ISDODataFactory) : ISDODAS;
+
+var
+  DefaultImplementor : TSDODAS_Implementor = nil;
+
+implementation
+
+
+end.

+ 437 - 0
packages/fcl-sdo/src/das/sdo_das_imp.pas

@@ -0,0 +1,437 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements a SDO DAS implementation.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_das_imp;
+
+interface
+uses
+  SysUtils, Classes, Contnrs, DB,
+  sdo, sdo_das, sdo_consts, sdo_types, data_acces_intf;
+
+type
+
+  TSDODAS = class(TInterfacedObject,ISDODAS)
+  private
+    FFactory : ISDODataFactory;
+    FObjectHandlerList : TObjectList;
+  private
+    procedure AddDatasetType();
+    function IndexOfHandler(const AType : ISDOType) : Integer;
+  protected
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string;
+      const AQueryParams : array of Variant;
+      const ARowType : ISDOType;
+      const AResList : ISDODataObjectList;
+      const AOptions : TSDODASOptions
+    ) : ISDODataObjectList;overload;
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string;
+      const ARowType : ISDOType;
+      const AResList : ISDODataObjectList;
+      const AOptions : TSDODASOptions
+    ) : ISDODataObjectList;overload; 
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string;     
+      const AQueryParams : array of Variant 
+    ) : ISDODataObject;overload; 
+    function ExecuteQuery(
+      const ADac : TDataAccessInterface;
+      const AQuery : string
+    ) : ISDODataObject;overload;
+    function ExecuteQuery(
+      const ADac          : TDataAccessInterface;
+      const AQuery        : string;
+      const AContainer    : ISDODataObject;
+      const ADestListName : string;
+      const AOptions      : TSDODASOptions
+    ) : ISDODataObjectList; overload;
+    procedure UpdateDataStore(
+      const ADac : TDataAccessInterface;
+      const AChanges : ISDOChangeSummary
+    );
+
+    function GetDataFactory() : ISDODataFactory;
+    procedure RegisterObjectHandler(
+      const ATargetObjectType : ISDOType;
+      const AHandler : ISDODASObjectHandler
+    );
+    function FindObjectHandler(const ATargetObjectType : ISDOType) : ISDODASObjectHandler;
+  public
+    constructor Create(AFactory : ISDODataFactory);
+    destructor Destroy(); override;
+  end;
+
+  TSDODASSqlInfo = class(TPersistent)
+  private
+    FKeyFieldName: string;
+    FTableName: string;
+  published
+    property TableName : string read FTableName write FTableName;
+    property KeyFieldName : string read FKeyFieldName write FKeyFieldName;
+  end;
+
+  TSDODASSqlObjectHandler = class(TInterfacedObject,ISDODASObjectHandler)
+  private
+    FSqlInfo : TSDODASSqlInfo;
+  protected
+    procedure HandleCreate(
+      const ADas : ISDODAS;
+      const AObject : ISDODataObject
+    );
+    procedure HandleDelete(
+      const ADas : ISDODAS;
+      const AObject : ISDODataObject
+    );
+    procedure HandleUpdate(
+      const ADas : ISDODAS;
+      const AObject : ISDODataObject
+    );
+
+    procedure UpdateDataStore(
+      const ADas : ISDODAS;
+      const AObject : ISDODataObject;
+      const AUpdateKind : TChangeType
+    );
+  public
+    constructor Create(ASqlInfo : TSDODASSqlInfo);
+    destructor Destroy(); override;
+  end;
+
+  
+resourcestring
+  SDODAS_MSG_NO_HANDLER_FOUND = 'No handler found for this type : "%s".';
+  SDODAS_MSG_INALID_PARAMS = 'Invalid parameter(s) : "%s".';
+
+implementation
+uses
+  sdo_das_utils, sdo_imp_utils;
+
+function Creator(AFactory : ISDODataFactory) : ISDODAS;
+begin
+  Result := TSDODAS.Create(AFactory) as ISDODAS;
+end;
+
+{ TSDODAS }
+
+procedure TSDODAS.AddDatasetType();
+var
+  locDatasetType : ISDOType;
+begin
+  FFactory.AddType(s_db_namespace,s_DataRowType,[tfIsOpen]);
+  FFactory.AddType(s_db_namespace,s_DataSetType,[tfIsOpen]);
+  locDatasetType := FFactory.getType(s_db_namespace,s_DataSetType);
+  FFactory.addProperty(
+    locDatasetType,s_RowCount,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]),
+    []
+  );
+  FFactory.addProperty(
+    locDatasetType,s_Row,FFactory.getType(s_db_namespace,s_DataRowType),
+    [pfIsMany,pfIsContainment]
+  );
+  FFactory.addProperty(
+    locDatasetType,s_changeSummary,sdo_namespace,s_changeSummary,[pfIsReadOnly]
+  );
+end;
+
+constructor TSDODAS.Create(AFactory: ISDODataFactory);
+begin
+  Assert(AFactory <> nil);
+  FFactory := AFactory;
+  if ( FFactory.getTypes().find(s_db_namespace,s_DataSetType) = nil ) then
+    AddDatasetType();
+  FObjectHandlerList := TObjectList.Create(True);
+end;    
+
+function TSDODAS.ExecuteQuery(
+  const ADac : TDataAccessInterface;
+  const AQuery: string;
+  const ARowType : ISDOType;
+  const AResList: ISDODataObjectList;
+  const AOptions : TSDODASOptions
+) : ISDODataObjectList;  
+begin
+  Result := ExecuteQuery(ADac,AQuery,[],ARowType,AResList,AOptions);
+end;
+
+function TSDODAS.ExecuteQuery(
+  const ADac : TDataAccessInterface;
+  const AQuery: string;         
+  const AQueryParams : array of Variant;
+  const ARowType : ISDOType;
+  const AResList: ISDODataObjectList;
+  const AOptions : TSDODASOptions
+) : ISDODataObjectList;
+var
+  ds : TDataset;
+  f : TField;
+  i, fieldCount : PtrInt;
+  objRec : ISDODataObject;
+  p : ISDOProperty;
+  pl : ISDOPropertyList;
+  locAddProp : Boolean;
+  locPropMap : array of ISDOProperty;
+begin
+  Assert(ADac <> nil);
+  Assert(ARowType <> nil);
+  Assert(AResList <> nil);
+  locAddProp := ARowType.isOpenType() and ( sdoAddProperty in AOptions );
+  if (Length(AQueryParams) = 0) then
+    ds := ADac.ExecuteDataset(AQuery)
+  else  
+    ds := ADac.ExecuteDataset(AQuery,AQueryParams);
+  try
+    if not ds.IsEmpty() then begin
+      fieldCount := ds.FieldCount;
+      SetLength(locPropMap,fieldCount);
+      pl := ARowType.getProperties();
+      for i := 0 to Pred(fieldCount) do begin
+        locPropMap[i] := pl.find(ds.Fields[i].FieldName);
+      end;
+      ds.First();
+      while not ds.Eof do begin
+        objRec := FFactory.createNew(ARowType);
+        for i := 0 to Pred(fieldCount) do begin
+          f := ds.Fields[i];
+          p := locPropMap[i];
+          if ( p = nil ) and locAddProp then begin
+            FFactory.addProperty(
+              objRec,f.FieldName,
+              FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[FieldTypeToSDOTypeMAP[f.DataType]]),
+              []
+            );
+            p := objRec.getProperty(f.FieldName);
+          end;
+          if ( p <> nil ) then
+            AssignValue(objRec,p,f);
+        end;
+        AResList.append(objRec);
+        ds.Next();
+      end;
+    end;
+  finally
+    ds.Free();
+    SetLength(locPropMap,0);
+  end;
+  Result := AResList;
+end;
+
+destructor TSDODAS.Destroy;
+begin
+  FObjectHandlerList.Free();
+  inherited;
+end;  
+
+function TSDODAS.ExecuteQuery(
+  const ADac: TDataAccessInterface;
+  const AQuery: string
+) : ISDODataObject;
+begin
+  Result := ExecuteQuery(ADac,AQuery,[]);
+end;
+
+function TSDODAS.ExecuteQuery(
+  const ADac: TDataAccessInterface;
+  const AQuery: string;     
+  const AQueryParams : array of Variant 
+) : ISDODataObject;
+var
+  dsType : ISDOType;
+  ls : ISDODataObjectList;
+begin
+  dsType := FFactory.getTypes().find(s_db_namespace,s_DataSetType);
+  if ( dsType = nil ) then begin
+    AddDatasetType();
+    dsType := FFactory.getType(s_db_namespace,s_DataSetType);
+  end;
+  Result := FFactory.createNew(dsType);
+  ls := Result.getList(s_Row);
+  ExecuteQuery(ADac,AQuery,AQueryParams,FFactory.getType(s_db_namespace,s_DataRowType),ls,[sdoAddProperty]);
+  Result.setInteger(s_RowCount,ls.size());
+end;
+
+procedure TSDODAS.RegisterObjectHandler(const ATargetObjectType: ISDOType;
+  const AHandler: ISDODASObjectHandler);
+begin
+
+end;
+
+procedure TSDODAS.UpdateDataStore(
+  const ADac : TDataAccessInterface;
+  const AChanges : ISDOChangeSummary
+);
+var
+  ls : ISDOChangedDataObjectList;
+  locSelfIntf : ISDODAS;
+  c : PtrInt;
+
+  procedure HandleUpdateType(const AChangeType : TChangeType);
+  var
+    k : PtrInt;
+    objHandler : ISDODASObjectHandler;
+    obj : ISDODataObject;
+  begin
+    for k := 0 to Pred(c) do begin
+      if ( ls.getType(k) = AChangeType ) then begin
+        obj := ls.getDataObject(k);
+        objHandler := FindObjectHandler(obj.getType());
+        if ( objHandler = nil ) then
+          raise ESDODASException.CreateFmt(SDODAS_MSG_NO_HANDLER_FOUND,[obj.getType().getURI() + '#' + obj.getType().getName()]);
+        objHandler.UpdateDataStore(locSelfIntf,obj,AChangeType);
+      end;
+    end;
+  end;
+
+begin
+  if ( AChanges = nil ) then
+    Exit;
+  ls := AChanges.getChangedDataObjects();
+  c := ls.size();
+  if ( c > 0 ) then begin
+    locSelfIntf := Self as ISDODAS;
+    HandleUpdateType(ctDelete);
+    HandleUpdateType(ctChange);
+    HandleUpdateType(ctCreate);
+  end;
+end;
+
+
+function TSDODAS.IndexOfHandler(const AType: ISDOType): Integer;
+var
+  i, c : Integer;
+begin
+  Result := -1;
+  c := FObjectHandlerList.Count;
+  if ( c > 0 ) then begin
+    for i := 0 to Pred(c) do begin
+      if TSDODASHandlerItem(FObjectHandlerList[i]).TargetType.equals(AType) then begin
+        Result := i;
+        Break;
+      end;
+    end;
+  end;
+end;
+
+function TSDODAS.FindObjectHandler(const ATargetObjectType: ISDOType): ISDODASObjectHandler;
+var
+  i : Integer;
+begin
+  i := IndexOfHandler(ATargetObjectType);
+  if ( i > -1 ) then
+    Result := TSDODASHandlerItem(FObjectHandlerList[i]).Handler
+  else
+    Result := nil;
+end;
+
+function TSDODAS.GetDataFactory() : ISDODataFactory;
+begin
+  Result := FFactory;
+end;
+
+function TSDODAS.ExecuteQuery(
+  const ADac          : TDataAccessInterface;
+  const AQuery        : string;
+  const AContainer    : ISDODataObject;
+  const ADestListName : string;
+  const AOptions      : TSDODASOptions
+): ISDODataObjectList;
+
+  procedure AddProp();
+  var
+    f : ISDODataFactory;
+  begin
+    f := GetDataFactory();
+    f.addProperty(AContainer,ADestListName,f.getType(s_db_namespace,s_DataRowType),[pfIsMany,pfIsContainment,pfIsNotNullable]);
+  end;
+
+var
+  locList : ISDODataObjectList;
+begin
+  if ( AContainer.getInstanceProperties().find(ADestListName) = nil ) then
+    AddProp();
+  locList := AContainer.getList(ADestListName);
+  Result := ExecuteQuery(
+              ADac,
+              AQuery,
+              FFactory.getType(s_db_namespace,s_DataRowType),
+              locList,
+              AOptions
+            );
+end;
+
+{ TSDODASSqlObjectHandler }
+
+constructor TSDODASSqlObjectHandler.Create(ASqlInfo: TSDODASSqlInfo);
+begin
+  if ( ASqlInfo = nil ) then
+    raise ESDODASException.CreateFmt(SDODAS_MSG_INALID_PARAMS,['ASqlInfo']);
+  inherited Create();
+  FSqlInfo := ASqlInfo;
+end;
+
+destructor TSDODASSqlObjectHandler.Destroy();
+begin
+  FSqlInfo.Free();
+  inherited;
+end;
+
+procedure TSDODASSqlObjectHandler.HandleCreate(const ADas: ISDODAS;
+  const AObject: ISDODataObject);
+begin
+
+end;
+
+procedure TSDODASSqlObjectHandler.HandleDelete(
+  const ADas : ISDODAS;
+  const AObject : ISDODataObject
+);
+begin
+
+end;
+
+procedure TSDODASSqlObjectHandler.HandleUpdate(
+  const ADas: ISDODAS;
+  const AObject: ISDODataObject
+);
+begin
+
+end;
+
+procedure TSDODASSqlObjectHandler.UpdateDataStore(
+  const ADas: ISDODAS;
+  const AObject: ISDODataObject;
+  const AUpdateKind: TChangeType
+);
+begin
+  case AUpdateKind of
+    ctCreate : HandleCreate(ADas,AObject);
+    ctChange : HandleUpdate(ADas,AObject);
+    ctDelete : HandleDelete(ADas,AObject);
+    else
+      raise ESDODASException.CreateFmt(SDODAS_MSG_INALID_PARAMS,['AUpdateKind']);
+  end;
+end;
+
+initialization
+  DefaultImplementor := {$IFDEF FPC}@{$ENDIF}Creator;
+
+finalization
+  DefaultImplementor := nil;
+  
+end.

+ 326 - 0
packages/fcl-sdo/src/das/sdo_das_utils.pas

@@ -0,0 +1,326 @@
+{
+    This file is part of the Free Pascal Class Library SDO Implementation
+    Copyright (c) 2012 by Inoussa OUEDRAOGO
+    Free Pascal development team
+
+    This unit implements some SDO DAS utilities
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+{$INCLUDE sdo_global.inc}
+unit sdo_das_utils;
+
+interface
+uses
+  SysUtils, Classes, DB,
+  sdo, sdo_das, data_acces_intf;
+
+const
+  BOOLEAN_TRUE_CHARS : set of AnsiChar = ['T','t', 'Y', 'y', 'O', 'o', '1'];
+
+  DefaultSdoType = StringType;
+
+{$IFNDEF HAS_SDO_FLOAT}
+  FloatType = DefaultSdoType;
+{$ENDIF HAS_SDO_FLOAT}
+{$IFNDEF HAS_SDO_DOUBLE}
+  DoubleType = DefaultSdoType;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFNDEF HAS_SDO_TIME}
+  TimeType = DefaultSdoType;
+{$ENDIF HAS_SDO_TIME}
+
+  FieldTypeToSDOTypeMAP : array[TFieldType] of TSDOTypeKind = (
+    StringType, StringType, ShortType, IntType, IntType,
+    //ftUnknown, ftString, ftSmallint, ftInteger, ftWord,
+    BooleanType, FloatType, CurrencyType, DoubleType, DateType, TimeType, DateTimeType,
+    //ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime,
+    BytesType, BytesType, IntType, BytesType, BytesType, BytesType, BytesType,
+    //ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic, ftFmtMemo,
+    BytesType, BytesType, BytesType, BytesType, StringType, StringType,
+    //ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar, ftWideString,
+    LongType, BytesType, BytesType, BytesType, ObjectType, BytesType, BytesType,
+    //ftLargeint, ftADT, ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob,
+    BytesType, BytesType, BytesType, StringType, TimeType, DoubleType
+    //ftVariant, ftInterface, ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd
+{$IF Declared(ftFixedWideChar)}
+    , StringType, StringType
+    //ftFixedWideChar, ftWideMemo
+{$IFEND }
+{$IF Declared(ftOraTimeStamp)}
+    , StringType, StringType
+    //ftOraTimeStamp, ftOraInterval
+{$IFEND }
+{$IF Declared(ftLongWord)}
+    , StringType, StringType, StringType, StringType, StringType, StringType, StringType,
+    //ftLongWord, ftShortint, ftByte, ftExtended, ftConnection, ftParams, ftStream,
+    StringType, StringType, StringType
+    //ftTimeStampOffset, ftObject, ftSingle
+{$IFEND }
+  );
+
+type
+
+  TSDODASHandlerItem = class
+  private
+    FHandler: ISDODASObjectHandler;
+    FTargetType: ISDOType;
+  public
+    property TargetType : ISDOType read FTargetType;
+    property Handler : ISDODASObjectHandler read FHandler;
+  end;
+
+  procedure AssignValue(
+    AObject : ISDODataObject;
+    AProp   : ISDOProperty;
+    AField  : TField
+  );
+  function GenerateInsertQuery(
+    const ARowType   : ISDOType;
+    const ATableName : string
+  ) : string;
+  function CopyToTable(
+    const ARows      : ISDODataObjectList;
+    const ATableName : string;
+    const ADac       : TDataAccessInterface
+  ) : Integer;overload;
+  procedure CopyToTable(
+    const AObject    : ISDODataObject;
+    const ATableName : string;
+    const ADac       : TDataAccessInterface
+  );overload;
+
+
+
+implementation
+uses
+  sdo_date_utils, sdo_imp_utils, sdo_linked_list;
+
+procedure AssignValue(AObject : ISDODataObject; AProp : ISDOProperty; AField : TField);
+
+  procedure AssignChar();
+  var
+    s : string;
+  begin
+    s := AField.AsString;
+    if ( Length(s) = 0 ) then
+      AObject.setCharacter(AProp,#0)
+    else
+      AObject.setCharacter(AProp,s[1]);
+  end;
+
+  procedure AssignBoolean();
+  var
+    s : string;
+  begin
+    s := AField.AsString;
+    AObject.setBoolean(AProp,(Length(s) > 0) and (s[1] in BOOLEAN_TRUE_CHARS));
+  end;
+
+  procedure AssignBlobField();
+  var
+    locStream : TMemoryStream;
+    locBlobField : TBlobField;
+    locBytes : TSDOBytes;
+    {$IFDEF DELPHI}
+      locBytes2 : TBytes;
+    {$ENDIF DELPHI}
+  begin
+    locBlobField := TBlobField(AField);
+    if (locBlobField.BlobSize = 0) then begin
+      AObject.setBytes(AProp,nil);
+    end else begin
+    {$IFDEF DELPHI}
+      if (locBlobField.BlobType = ftWideMemo) then
+        locBytes2 := TEncoding.UTF8.GetBytes(locBlobField.AsWideString)
+      else
+        locBytes2 := locBlobField.AsBytes;
+      SetLength(locBytes,Length(locBytes2));
+      if (Length(locBytes) > 0) then
+        Move(locBytes2[0],locBytes[0],Length(locBytes));
+      AObject.setBytes(AProp,locBytes);
+    {$ENDIF DELPHI}
+    {$IFDEF FPC}
+      locStream := TMemoryStream.Create();
+      try
+        locBlobField.SaveToStream(locStream);
+        locBytes := StreamToVarBytes(locStream);
+      finally
+        locStream.Free();
+      end;
+      AObject.setBytes(AProp,locBytes);
+    {$ENDIF FPC}
+    end;
+  end;
+
+begin
+  if AField.IsNull then begin
+    AObject.setNull(AProp);
+  end else begin
+    case AProp.getTypeEnum() of
+      BooleanType   :
+        begin
+          if AField.InheritsFrom(TBooleanField) then
+            AObject.setBoolean(AProp,AField.AsBoolean)
+          else
+            AssignBoolean();
+        end;
+      ByteType      : AObject.setByte(AProp,AField.AsInteger);
+      BytesType     :
+        begin
+          if AField.InheritsFrom(TBlobField) then
+            AssignBlobField()
+          else
+            AObject.setBytes(AProp, StringToVarBytes(AField.AsString));
+        end;
+      CharacterType : AssignChar();
+      CurrencyType  : AObject.setCurrency(AProp,AField.AsCurrency);
+      DateTimeType  : AObject.setDate(AProp,DateTimeToDateTimeRec(AField.AsDateTime));
+      DoubleType    : AObject.setDouble(AProp,AField.AsFloat);
+      FloatType     : AObject.setFloat(AProp,AField.AsFloat);
+      IntegerType   : AObject.setInteger(AProp,AField.AsInteger);
+      LongType      :
+        begin
+          if AField.InheritsFrom(TLargeintField) then
+            AObject.setLong(AProp,TLargeintField(AField).AsLargeInt)
+          else
+            AObject.setLong(AProp,AField.AsInteger);
+        end;
+      ShortType     : AObject.setShort(AProp,AField.AsInteger);
+      StringType  :
+        begin
+        {$IFDEF DEFAULT_UNICODE}
+          AObject.setString(AProp,AField.AsString);
+        {$ELSE DEFAULT_UNICODE}
+          AObject.setString(AProp,UTF8Decode(AField.AsString));
+        {$ENDIF DEFAULT_UNICODE}
+        end
+      else
+        raise ESDONotImplementedException.Create('TSDODAS.ExecuteQuery()>AssignValue()');
+    end;
+  end;
+end;
+
+function GenerateInsertQuery(
+  const ARowType   : ISDOType;
+  const ATableName : string
+) : string;
+var
+  locRowType : ISDOType;
+  pl : ISDOPropertyList;
+  p : ISDOProperty;
+  locInsertSQLCol, locInsertSQLVal: string;
+  k, c : Integer;
+begin
+  locRowType := ARowType;
+  pl := locRowType.getProperties();
+  locInsertSQLCol := '';
+  locInsertSQLVal := '';
+  c := 0;
+  for k := 0 to pl.getCount() - 1 do begin
+    p := pl.getItem(k);
+    if p.getType().isDataType() then begin
+      locInsertSQLCol := Format('%s, %s',[locInsertSQLCol,p.getName()]);
+      locInsertSQLVal := Format('%s, :P%d',[locInsertSQLVal,c]);
+      Inc(c);
+    end;
+  end;
+  Delete(locInsertSQLCol,1,1);
+  Delete(locInsertSQLVal,1,1);
+  Result :=
+    Format(
+      'INSERT INTO %s(%s) VALUES(%s)',
+      [Trim(ATableName),locInsertSQLCol,locInsertSQLVal]
+    );
+end;
+
+function CopyToTable(
+  const ARows      : ISDODataObjectList;
+  const ATableName : string;
+  const ADac       : TDataAccessInterface
+) : Integer;
+var
+  locRowType, locPropType : ISDOType;
+  locInsertSQLQuery: string;
+  k, kc, kp : Integer;
+  locCursor : ILinkedListCursor;
+  locRow : ISDODataObject;
+  locParams : array of Variant;
+  locRowPropList : ISDOPropertyList;
+  locIsDataType : array of record IsDataType : Boolean; Index : Integer; end;
+begin
+  Result := ARows.size();
+  if (Result = 0) then
+    exit;
+  locRowType := ARows.getDataObject(0).getType();
+  locRowPropList := locRowType.getProperties();
+  locInsertSQLQuery := GenerateInsertQuery(locRowType,ATableName);
+  kc := locRowPropList.getCount();
+  SetLength(locIsDataType,kc);
+  kp := 0;
+  for k := 0 to kc - 1 do begin
+    locPropType := locRowPropList.getItem(k).getType();
+    locIsDataType[k].IsDataType := locPropType.isDataType();
+    if locIsDataType[k].IsDataType then begin
+      locIsDataType[k].Index := kp;
+      Inc(kp);
+    end;
+  end;
+  SetLength(locParams,kp);
+  locCursor := ARows.getCursor();
+  locCursor.Reset();
+  while locCursor.MoveNext() do begin
+    locRow := ARows.getDataObject();
+    for k := 0 to kc - 1 do begin
+      if locIsDataType[k].IsDataType then
+        locParams[locIsDataType[k].Index] := locRow.getVariant(k);
+    end;
+    ADac.ExecuteNonDataset(locInsertSQLQuery,locParams);
+  end;
+end;
+
+procedure CopyToTable(
+  const AObject    : ISDODataObject;
+  const ATableName : string;
+  const ADac       : TDataAccessInterface
+);
+var
+  locRowType, locPropType : ISDOType;
+  locInsertSQLQuery: string;
+  k, kc, kp : Integer;
+  locParams : array of Variant;
+  locRowPropList : ISDOPropertyList;
+  locIsDataType : array of record IsDataType : Boolean; Index : Integer; end;
+begin
+  if (AObject = nil) then
+    exit;
+  locRowType := AObject.getType();
+  locRowPropList := locRowType.getProperties();
+  locInsertSQLQuery := GenerateInsertQuery(locRowType,ATableName);
+  kc := locRowPropList.getCount();
+  SetLength(locIsDataType,kc);
+  kp := 0;
+  for k := 0 to kc - 1 do begin
+    locPropType := locRowPropList.getItem(k).getType();
+    locIsDataType[k].IsDataType := locPropType.isDataType();
+    if locIsDataType[k].IsDataType then begin
+      locIsDataType[k].Index := kp;
+      Inc(kp);
+    end;
+  end;
+  SetLength(locParams,kp);
+  for k := 0 to kc - 1 do begin
+    if locIsDataType[k].IsDataType then
+      locParams[locIsDataType[k].Index] := AObject.getVariant(k);
+  end;
+  ADac.ExecuteNonDataset(locInsertSQLQuery,locParams);
+end;
+
+
+end.

+ 63 - 0
packages/fcl-sdo/src/das/sdo_global.inc

@@ -0,0 +1,63 @@
+{$WARNINGS OFF}
+
+  {$IFDEF FPC}
+    {$mode objfpc}{$H+}
+    {$DEFINE HAS_QWORD}
+    {$DEFINE ATT_PROC_ADDRESS}
+    {$DEFINE HAS_UNICODE}  
+    {$IF Defined(FPC_RELEASE) and (FPC_RELEASE > 0) }
+      {$define FCL_HAS_TDOMElementList}
+      {$IF Defined(FPC_VERSION) and (FPC_RELEASE >= 5) }
+        {$DEFINE HAS_CURR_TO_STR_SETTINGS}
+      {$IFEND}
+    {$IFEND}
+    {$DEFINE USE_INLINE}
+  {$ELSE}
+    {$UNDEF HAS_QWORD}
+    {$UNDEF USE_INLINE}
+    {$UNDEF ATT_PROC_ADDRESS}
+    {$DEFINE DELPHI}
+    {$DEFINE INTF_DOM}
+    {$IFDEF VER200}
+      {$DEFINE HAS_UNICODE}
+    {$ENDIF}
+    {$IFDEF VER210}
+      {$DEFINE HAS_UNICODE}
+    {$ENDIF}     
+    {$IFDEF VER220} //DelphiXE
+      {$DEFINE HAS_UNICODE}
+    {$ENDIF}
+    {$IF Defined(CompilerVersion) and (CompilerVersion >= 20)}
+      {$DEFINE HAS_UNICODE}
+    {$IFEND}
+    {$IF Defined(CompilerVersion) and (CompilerVersion < 23)}
+      {$DEFINE WINDOWS}
+    {$IFEND}
+    {$IFDEF MSWINDOWS}
+      {$DEFINE WINDOWS}
+    {$ENDIF}
+    {$IFDEF HAS_UNICODE}
+      {$DEFINE DEFAULT_UNICODE}
+    {$ENDIF}
+  {$ENDIF}
+
+{$WARNINGS ON}
+
+{$UNDEF EQUALITY_USE_SET_NULL}
+{$DEFINE TEST_GENERATE_FILE}
+
+{$DEFINE HAS_SDO_BYTES}
+{$DEFINE HAS_SDO_CHAR}
+{$DEFINE HAS_SDO_DOUBLE}
+{$DEFINE HAS_SDO_FLOAT}
+{$DEFINE HAS_SDO_LONG}
+{$DEFINE HAS_SDO_SHORT}
+{$DEFINE HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_UNICODE}
+  {$DEFINE USE_UNICODE}
+  {$IFDEF DELPHI}
+    {$DEFINE HAS_CP_STRING}
+  {$ENDIF}
+{$ENDIF}
+

+ 53 - 0
packages/fcl-sdo/tests/test_suite/projects/dunit_tests.pas

@@ -0,0 +1,53 @@
+program dunit_tests;
+
+{%File '..\..\..\sdo_global.inc'}
+
+uses
+  ActiveX,
+  Forms,
+  TestFrameWork,
+  GUITestRunner,
+  test_type in '..\test_type.pas',
+  sdo_type in '..\..\..\sdo_type.pas',
+  sdo in '..\..\..\sdo.pas',
+  sdo_property in '..\..\..\sdo_property.pas',
+  sdo_imp_utils in '..\..\..\sdo_imp_utils.pas',
+  sdo_datafactory in '..\..\..\sdo_datafactory.pas',
+  sdo_dataobject in '..\..\..\sdo_dataobject.pas',
+  sdo_field_imp in '..\..\..\sdo_field_imp.pas',
+  test_field_imp in '..\test_field_imp.pas',
+  test_dataobject in '..\test_dataobject.pas',
+  sdo_linked_list in '..\..\..\sdo_linked_list.pas',
+  sdo_types in '..\..\..\sdo_types.pas',
+  test_utils in '..\test_utils.pas',
+  sdo_dataobjectlist in '..\..\..\sdo_dataobjectlist.pas',
+  test_dataobjectlist in '..\test_dataobjectlist.pas',
+  sdo_xsd_helper in '..\..\..\sdo_xsd_helper.pas',
+  test_xsdhelper in '..\test_xsdhelper.pas',
+  sdo_serialization in '..\..\..\sdo_serialization.pas',
+  sdo_consts in '..\..\..\sdo_consts.pas',
+  test_serializer in '..\test_serializer.pas',
+  sdo_serialization_utils in '..\..\..\sdo_serialization_utils.pas',
+  sdo_serialization_xml in '..\..\..\sdo_serialization_xml.pas',
+  sdo_equalityhelper in '..\..\..\sdo_equalityhelper.pas',
+  test_equalityhelper in '..\test_equalityhelper.pas',
+  test_changesummary in '..\test_changesummary.pas',
+  sdo_changesummary in '..\..\..\sdo_changesummary.pas',
+  sdo_copyhelper in '..\..\..\sdo_copyhelper.pas',
+  test_copyhelper in '..\test_copyhelper.pas',
+  sdo_xpath_helper in '..\..\..\sdo_xpath_helper.pas',
+  test_xpathhelper in '..\test_xpathhelper.pas',
+  test_suite_utils in '..\test_suite_utils.pas',
+  sdo_convert_helper in '..\..\..\sdo_convert_helper.pas',
+  test_convert_helper in '..\test_convert_helper.pas',
+  test_property in '..\test_property.pas',
+  sdo_utils in '..\..\..\sdo_utils.pas',
+  sdo_serialization_binary in '..\..\..\sdo_serialization_binary.pas',
+  test_xsdparser in '..\test_xsdparser.pas';
+
+{$R *.res}
+
+begin
+  Application.Initialize;  
+  GUITestRunner.RunRegisteredTests();
+end.

+ 253 - 0
packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite.lpi

@@ -0,0 +1,253 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="\"/>
+    <Version Value="7"/>
+    <General>
+      <Flags>
+        <LRSInOutputDirectory Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=".exe"/>
+    </General>
+    <VersionInfo>
+      <StringTable Comments="" CompanyName="" FileDescription="" FileVersion="0.0.0.0" InternalName="" LegalCopyright="" LegalTrademarks="" OriginalFilename="" ProductName="" ProductVersion=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <CommandLineParams Value="-a"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="FCL"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="36">
+      <Unit0>
+        <Filename Value="sdo_test_suite.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_test_suite"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="..\..\..\sdo.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="..\..\..\sdo_datafactory.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_datafactory"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="..\..\..\sdo_dataobject.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_dataobject"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="..\..\..\sdo_dataobjectlist.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_dataobjectlist"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="..\..\..\sdo_field_imp.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_field_imp"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="..\..\..\sdo_imp_utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_imp_utils"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="..\..\..\sdo_linked_list.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_linked_list"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="..\..\..\sdo_property.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_property"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="..\..\..\sdo_type.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_type"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="..\test_utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_utils"/>
+      </Unit10>
+      <Unit11>
+        <Filename Value="..\test_dataobject.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_dataobject"/>
+      </Unit11>
+      <Unit12>
+        <Filename Value="..\test_dataobjectlist.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_dataobjectlist"/>
+      </Unit12>
+      <Unit13>
+        <Filename Value="..\test_field_imp.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_field_imp"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="..\test_type.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_type"/>
+      </Unit14>
+      <Unit15>
+        <Filename Value="..\test_xsdhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_xsdhelper"/>
+      </Unit15>
+      <Unit16>
+        <Filename Value="..\..\..\sdo_xsd_helper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_xsd_helper"/>
+      </Unit16>
+      <Unit17>
+        <Filename Value="..\test_serializer.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_serializer"/>
+      </Unit17>
+      <Unit18>
+        <Filename Value="..\..\..\sdo_serialization.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_serialization"/>
+      </Unit18>
+      <Unit19>
+        <Filename Value="..\..\..\sdo_serialization_xml.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_serialization_xml"/>
+      </Unit19>
+      <Unit20>
+        <Filename Value="..\..\..\sdo_equalityhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_equalityhelper"/>
+      </Unit20>
+      <Unit21>
+        <Filename Value="..\test_equalityhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_equalityhelper"/>
+      </Unit21>
+      <Unit22>
+        <Filename Value="..\test_changesummary.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_changesummary"/>
+      </Unit22>
+      <Unit23>
+        <Filename Value="..\..\..\sdo_xpath_helper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_xpath_helper"/>
+      </Unit23>
+      <Unit24>
+        <Filename Value="..\test_suite_utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_suite_utils"/>
+      </Unit24>
+      <Unit25>
+        <Filename Value="..\test_xpathhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_xpathhelper"/>
+      </Unit25>
+      <Unit26>
+        <Filename Value="..\..\..\sdo_changesummary.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_changesummary"/>
+      </Unit26>
+      <Unit27>
+        <Filename Value="..\..\..\sdo_copyhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_copyhelper"/>
+      </Unit27>
+      <Unit28>
+        <Filename Value="..\test_copyhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_copyhelper"/>
+      </Unit28>
+      <Unit29>
+        <Filename Value="..\..\..\sdo_consts.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_consts"/>
+      </Unit29>
+      <Unit30>
+        <Filename Value="..\..\..\sdo_serialization_utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_serialization_utils"/>
+      </Unit30>
+      <Unit31>
+        <Filename Value="..\..\..\sdo_types.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_types"/>
+      </Unit31>
+      <Unit32>
+        <Filename Value="..\..\..\sdo_utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_utils"/>
+      </Unit32>
+      <Unit33>
+        <Filename Value="..\..\..\sdo_convert_helper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_convert_helper"/>
+      </Unit33>
+      <Unit34>
+        <Filename Value="..\test_convert_helper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_convert_helper"/>
+      </Unit34>
+      <Unit35>
+        <Filename Value="..\test_property.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_property"/>
+      </Unit35>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="8"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="sdo_test_suite.exe"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="..\..\..\;C:\sources\wst\"/>
+      <OtherUnitFiles Value="..\;..\..\;..\..\..\;C:\sources\wst\;C:\sources\wst\ws_helper\;C:\sources\wst\wst_rtti_filter\"/>
+      <UnitOutputDirectory Value="obj"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <CStyleOperator Value="False"/>
+        <UseAnsiStrings Value="True"/>
+      </SyntaxOptions>
+    </Parsing>
+    <CodeGeneration>
+      <Checks>
+        <RangeChecks Value="True"/>
+      </Checks>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="True"/>
+        <GenerateDwarf Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+</CONFIG>

+ 33 - 0
packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite.lpr

@@ -0,0 +1,33 @@
+program sdo_test_suite;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, consoletestrunner, sdo, sdo_datafactory, sdo_dataobject,
+  sdo_dataobjectlist, sdo_field_imp, sdo_imp_utils, sdo_linked_list,
+  sdo_property, sdo_type, test_type, test_field_imp, test_dataobjectlist,
+  test_dataobject, test_utils, test_xsdhelper, test_serializer,
+  test_equalityhelper, test_changesummary, test_suite_utils, sdo_xsd_helper,
+  test_xpathhelper, sdo_xpath_helper, sdo_copyhelper, test_copyhelper,
+  sdo_consts, sdo_equalityhelper, sdo_serialization, sdo_serialization_utils,
+  sdo_types, sdo_utils, sdo_changesummary, sdo_convert_helper,
+  sdo_serialization_xml, test_convert_helper, test_property;
+
+type
+
+  { TLazTestRunner }
+
+  TMyTestRunner = class(TTestRunner)
+  protected
+  // override the protected methods of TTestRunner to customize its behavior
+  end;
+
+var
+  Application: TMyTestRunner;
+
+begin
+  Application := TMyTestRunner.Create(nil);
+  Application.Initialize;
+  Application.Run;
+  Application.Free;
+end.

+ 169 - 0
packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite_gui.lpi

@@ -0,0 +1,169 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <PathDelim Value="\"/>
+    <General>
+      <Flags>
+        <LRSInOutputDirectory Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
+    </General>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1">
+      <Item1 Name="default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <LaunchingApplication PathPlusParams="\usr\X11R6\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="3">
+      <Item1>
+        <PackageName Value="FPCUnitTestRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="LCL"/>
+      </Item2>
+      <Item3>
+        <PackageName Value="FCL"/>
+      </Item3>
+    </RequiredPackages>
+    <Units Count="15">
+      <Unit0>
+        <Filename Value="sdo_test_suite_gui.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="sdo_test_suite_gui"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="..\test_xsdhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_xsdhelper"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="..\test_changesummary.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_changesummary"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="..\test_convert_helper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_convert_helper"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="..\test_copyhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_copyhelper"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="..\test_dataobject.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_dataobject"/>
+      </Unit5>
+      <Unit6>
+        <Filename Value="..\test_dataobjectlist.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_dataobjectlist"/>
+      </Unit6>
+      <Unit7>
+        <Filename Value="..\test_equalityhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_equalityhelper"/>
+      </Unit7>
+      <Unit8>
+        <Filename Value="..\test_field_imp.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_field_imp"/>
+      </Unit8>
+      <Unit9>
+        <Filename Value="..\test_property.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_property"/>
+      </Unit9>
+      <Unit10>
+        <Filename Value="..\test_serializer.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_serializer"/>
+      </Unit10>
+      <Unit11>
+        <Filename Value="..\test_suite_utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_suite_utils"/>
+      </Unit11>
+      <Unit12>
+        <Filename Value="..\test_type.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_type"/>
+      </Unit12>
+      <Unit13>
+        <Filename Value="..\test_utils.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_utils"/>
+      </Unit13>
+      <Unit14>
+        <Filename Value="..\test_xpathhelper.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="test_xpathhelper"/>
+      </Unit14>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="9"/>
+    <PathDelim Value="\"/>
+    <Target>
+      <Filename Value="sdo_test_suite_gui"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="..\..\.."/>
+      <OtherUnitFiles Value="..;..\..;..\..\..;..\..\..\xsd;..\..\..\rtti_filter"/>
+      <UnitOutputDirectory Value="obj"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <CStyleOperator Value="False"/>
+        <UseAnsiStrings Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CompilerMessages>
+        <UseMsgFile Value="True"/>
+      </CompilerMessages>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="4" IgnoreAll="True">
+      <Item1>
+        <Name Value="ESDOPropertyNotFoundException"/>
+        <Enabled Value="False"/>
+      </Item1>
+      <Item2>
+        <Name Value="ESDOInvalidConversionException"/>
+        <Enabled Value="False"/>
+      </Item2>
+      <Item3>
+        <Name Value="ESDOIllegalArgumentException"/>
+        <Enabled Value="False"/>
+      </Item3>
+      <Item4>
+        <Name Value="ESDODuplicatedItemException"/>
+        <Enabled Value="False"/>
+      </Item4>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 19 - 0
packages/fcl-sdo/tests/test_suite/projects/sdo_test_suite_gui.lpr

@@ -0,0 +1,19 @@
+program sdo_test_suite_gui;
+
+{$mode objfpc}{$H+}
+
+uses HeapTrc, SysUtils,
+  Interfaces, Forms, GuiTestRunner, test_xsdhelper,
+  test_changesummary, test_convert_helper, test_copyhelper, test_dataobject,
+  test_dataobjectlist, test_equalityhelper, test_field_imp, test_property,
+  test_serializer, test_suite_utils, test_type, test_utils, test_xpathhelper,
+  types;
+
+begin
+  DeleteFile('heaptrace.txt');
+  SetHeapTraceOutput('heaptrace.txt');
+  Application.Initialize;
+  Application.CreateForm(TGuiTestRunner, TestRunner);
+  Application.Run;
+end.
+

+ 137 - 0
packages/fcl-sdo/tests/test_suite/projects/testrunner.pp

@@ -0,0 +1,137 @@
+program testrunner;
+
+{$mode objfpc}
+{$h+}
+
+uses HeapTrc,
+  custapp, Classes, SysUtils, fpcunit, testregistry, xmltestreport, plaintestreport,
+
+  sdo, sdo_datafactory, sdo_dataobject,
+  sdo_dataobjectlist, sdo_field_imp, sdo_imp_utils, sdo_linked_list,
+  sdo_property, sdo_type, test_type, test_field_imp, test_dataobjectlist,
+  test_dataobject, test_utils, test_xsdhelper, test_serializer,
+  test_equalityhelper, test_changesummary, test_suite_utils, sdo_xsd_helper,
+  test_xpathhelper, sdo_xpath_helper, sdo_copyhelper, test_copyhelper,
+  sdo_consts, sdo_equalityhelper, sdo_serialization, sdo_serialization_utils,
+  sdo_types, sdo_utils, sdo_changesummary, sdo_convert_helper,
+  sdo_serialization_xml, test_convert_helper, test_property, test_xsdparser;
+
+
+const
+  ShortOpts = 'alh';
+  Longopts: Array[1..5] of String = (
+    'all','list','format:','suite:','help');
+  Version = 'Version 0.2';
+
+
+type
+  TTestRunner = Class(TCustomApplication)
+  private
+    FXMLResultsWriter: TXMLResultsWriter;
+  protected
+    procedure   DoRun ; Override;
+    procedure   doTestRun(aTest: TTest); virtual;
+  public
+    constructor Create(AOwner: TComponent); override;
+    destructor  Destroy; override;
+  end;
+
+
+constructor TTestRunner.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FXMLResultsWriter := TXMLResultsWriter.Create(AOwner);
+end;
+
+
+destructor TTestRunner.Destroy;
+begin
+  FXMLResultsWriter.Free;
+end;
+
+
+procedure TTestRunner.doTestRun(aTest: TTest);
+var
+  testResult: TTestResult;
+begin
+  testResult := TTestResult.Create;
+  try
+    testResult.AddListener(FXMLResultsWriter);
+    aTest.Run(testResult);
+    FXMLResultsWriter.WriteResult(testResult);
+  finally
+    testResult.Free;
+  end;
+end;
+
+
+procedure TTestRunner.DoRun;
+var
+  I : Integer;
+  S : String;
+begin
+  S:=CheckOptions(ShortOpts,LongOpts);
+  If (S<>'') then
+    Writeln(S);
+  if HasOption('h', 'help') or (ParamCount = 0) then
+  begin
+    writeln(Title);
+    writeln(Version);
+    writeln('Usage: ');
+    writeln('-l or --list to show a list of registered tests');
+    writeln('default format is xml, add --format=latex to output the list as latex source');
+    writeln('-a or --all to run all the tests and show the results in xml format');
+    writeln('The results can be redirected to an xml file,');
+    writeln('for example: ./testrunner --all > results.xml');
+    writeln('use --suite=MyTestSuiteName to run only the tests in a single test suite class');
+  end
+  else;
+    if HasOption('l', 'list') then
+    begin
+      if HasOption('format') then
+      begin
+        if GetOptionValue('format') = 'text' then
+          writeln(GetSuiteAsPlain(GetTestRegistry))
+        else
+          writeln(GetSuiteAsXML(GetTestRegistry));
+      end
+      else
+        writeln(GetSuiteAsXML(GetTestRegistry));
+    end;
+  if HasOption('a', 'all') then
+  begin
+    doTestRun(GetTestRegistry)
+  end
+  else
+    if HasOption('suite') then
+    begin
+      S := '';
+      S:=GetOptionValue('suite');
+      if S = '' then
+        for I := 0 to GetTestRegistry.Tests.count - 1 do
+          writeln(GetTestRegistry[i].TestName)
+      else
+      for I := 0 to GetTestRegistry.Tests.count - 1 do
+        if GetTestRegistry[i].TestName = S then
+        begin
+          doTestRun(GetTestRegistry[i]);
+        end;
+    end;
+  Terminate;
+end;
+
+
+var
+  App: TTestRunner;
+
+
+begin
+  DeleteFile(sdoExpandLocalFileName('heaptrace.txt'));
+  SetHeapTraceOutput('heaptrace.txt');
+  App := TTestRunner.Create(nil);
+  App.Initialize;
+  App.Title := 'FPCUnit Console Test Case runner.';
+  App.Run;
+  App.Free;
+end.
+

+ 12466 - 0
packages/fcl-sdo/tests/test_suite/test_changesummary.pas

@@ -0,0 +1,12466 @@
+{$INCLUDE sdo_global.inc}
+unit test_changesummary;
+
+interface
+uses
+  SysUtils, Classes, Contnrs
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , test_suite_utils, sdo_types, sdo, sdo_changesummary;
+
+type
+
+  TValueSetting_Test = class(TWstBaseTest)
+  private
+    class function CreateFactory() : ISDODataFactory;
+  protected
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+  published
+    procedure create_boolean();
+    procedure create_byte();
+    procedure create_date();
+    procedure create_integer();
+    procedure create_string();
+{$IFDEF HAS_SDO_BYTES}
+    procedure create_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure create_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure create_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure create_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure create_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure create_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure create_short();
+{$ENDIF HAS_SDO_SHORT}
+  end;
+
+  (*TDicho_Test = class(TTestCase)
+  published
+    procedure find();
+    procedure build();
+  end; *)
+
+  TSDOSettingList_Test = class(TWstBaseTest)
+  private
+    class function CreateFactory() : ISDODataFactory;
+  published
+    procedure size();
+    procedure insert();
+    procedure append();
+    procedure remove();
+    procedure getItem();
+  end;
+
+  TSDOChangedDataObjectList_Test = class(TWstBaseTest)
+  private
+    class function CreateFactory() : ISDODataFactory;
+    class function CreateObject() : ISDOChangedDataObjectListEx;
+  published
+    procedure size();
+
+    procedure append();
+    procedure find();
+  end;
+
+  TChangeRecorder_Test = class(TWstBaseTest)
+  protected
+    FRecorder : TChangeRecorder;
+    FChangeSummary : ISDOChangeSummary;
+    FFactory : ISDODataFactory;
+  protected
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+    procedure InitRecorder();
+  protected
+    function CreateRecorder() : TChangeRecorder;
+    class function Create_Factory() : ISDODataFactory;
+    procedure record_int(const ADataObject : ISDODataObject; const APropName : string);
+    procedure record_bool(const ADataObject : ISDODataObject; const APropName : string);
+    procedure record_byte(const ADataObject : ISDODataObject; const APropName : string);
+{$IFDEF HAS_SDO_BYTES}
+    procedure record_bytes(const ADataObject : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_BYTES}
+    procedure record_date(const ADataObject : ISDODataObject; const APropName : string);
+    procedure record_string(const ADataObject : ISDODataObject; const APropName : string);
+    procedure record_obj(const ADataObject : ISDODataObject; const APropName : string);
+{$IFDEF HAS_SDO_CHAR}
+    procedure record_char(const ADataObject : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure record_currency(const ADataObject : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure record_double(const ADataObject : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure record_float(const ADataObject : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure record_long(const ADataObject : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure record_short(const ADataObject : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure record_list_int(const ADataObject : ISDODataObject; const APropName : string);
+  published
+    procedure multi_call_int();
+    procedure multi_call_boolean();
+    procedure multi_call_byte();
+    procedure multi_call_date();
+{$IFDEF HAS_SDO_BYTES}
+    procedure multi_call_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure multi_call_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure multi_call_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure multi_call_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure multi_call_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure multi_call_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure multi_call_short();
+{$ENDIF HAS_SDO_SHORT}
+    procedure multi_call_string();
+
+
+    procedure int_change();
+    procedure bool_change();
+    procedure byte_change();
+    procedure date_change();
+{$IFDEF HAS_SDO_BYTES}
+    procedure bytes_change();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure char_change();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure currency_change();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure double_change();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure float_change();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure long_change();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure short_change();
+{$ENDIF HAS_SDO_SHORT}
+    procedure string_change();
+
+    procedure object_change_contained_prop();
+    procedure object_change_referenced_prop();
+  end;
+
+  TSDOChangeSummary_Test = class(TWstBaseTest)
+  protected
+    FRecorder : TChangeRecorder;
+    FFactory : ISDODataFactory;
+    FFactoryX : ISDODataFactory;
+    FChangeSummary : ISDOChangeSummary;
+  protected
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+    procedure InitRecorder();
+  protected
+    function CreateRecorder() : TChangeRecorder;
+    class function Create_Factory() : ISDODataFactory;
+    class function Create_FactoryX() : ISDODataFactory;
+  private
+    procedure check_value(
+      const AObj : ISDODataObject;
+      const AProp : ISDOProperty;
+      const AValue : TValueSetting
+    );
+  published
+    procedure logging_state();
+    procedure logging_state_2();
+    procedure isCreated();
+    procedure isCreated_create_delete();
+    procedure isDeleted();
+    procedure isDeleted_nested();
+    procedure isModified();
+
+    procedure getChangedDataObjects();
+    procedure getChangedDataObjects_contained_delete();
+    procedure getChangedDataObjects_multi_value_prop();
+
+    procedure getOldValues();
+    procedure getOldValues_bool();
+    procedure getOldValues_byte();
+    procedure getOldValues_date();
+    procedure getOldValues_integer();
+    procedure getOldValues_object_prop();
+    procedure getOldValues_string();
+{$IFDEF HAS_SDO_BYTES}
+    procedure getOldValues_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure getOldValues_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure getOldValues_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure getOldValues_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure getOldValues_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure getOldValues_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure getOldValues_short();
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure getOldValue();
+    procedure getOldValue_bool();
+    procedure getOldValue_byte();
+    procedure getOldValue_date();
+    procedure getOldValue_integer();
+    procedure getOldValue_string();
+{$IFDEF HAS_SDO_BYTES}
+    procedure getOldValue_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure getOldValue_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure getOldValue_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure getOldValue_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure getOldValue_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure getOldValue_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure getOldValue_short();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure getOldValue_object_prop();
+    procedure getOldContainer();
+    procedure getOldContainmentProperty();
+
+    procedure undoChanges_simple() ;
+    procedure undoChanges_simple_bool() ;
+    procedure undoChanges_simple_byte() ;
+    procedure undoChanges_simple_date() ;
+    procedure undoChanges_simple_integer() ;
+    procedure undoChanges_simple_string() ;
+{$IFDEF HAS_SDO_BYTES}
+    procedure undoChanges_simple_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure undoChanges_simple_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure undoChanges_simple_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure undoChanges_simple_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure undoChanges_simple_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure undoChanges_simple_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure undoChanges_simple_short();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure undoChanges_simple_unset() ;
+    procedure undoChanges_simple_unset_bool() ;
+    procedure undoChanges_simple_unset_byte() ;
+    procedure undoChanges_simple_unset_date() ;
+    procedure undoChanges_simple_unset_integer() ;
+    procedure undoChanges_simple_unset_string() ;
+{$IFDEF HAS_SDO_BYTES}
+    procedure undoChanges_simple_unset_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure undoChanges_simple_unset_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure undoChanges_simple_unset_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure undoChanges_simple_unset_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure undoChanges_simple_unset_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure undoChanges_simple_unset_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure undoChanges_simple_unset_short();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure undoChanges_simple_setnull() ;
+    procedure undoChanges_simple_setnull_bool() ;
+    procedure undoChanges_simple_setnull_byte() ;
+    procedure undoChanges_simple_setnull_date() ;
+    procedure undoChanges_simple_setnull_integer() ;
+    procedure undoChanges_simple_setnull_string() ;
+{$IFDEF HAS_SDO_BYTES}
+    procedure undoChanges_simple_setnull_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure undoChanges_simple_setnull_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure undoChanges_simple_setnull_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure undoChanges_simple_setnull_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure undoChanges_simple_setnull_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure undoChanges_simple_setnull_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure undoChanges_simple_setnull_short();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure undoChanges_object_contained_startWith_OBJ_OBJ();
+    procedure undoChanges_object_contained_startWith_OBJ_OBJ_OBJ() ;
+    procedure undoChanges_object_contained_startWith_NIL_OBJ_OBJ() ;
+    procedure undoChanges_object_referenced_startWIth_OBJ_OBJ() ;
+    procedure undoChanges_object_referenced_startWith_NIL_OBJ() ;
+    procedure undoChanges_delete_contained_object();
+
+    procedure getOldXpath();
+    procedure getOldXpath_1();
+    procedure getOldValues_created_object_settinglist_is_empty();
+    procedure getOldXpath_nested_deleted_object();
+  end;
+
+  TSDODataObjectCS_Test = class(TWstBaseTest)
+  private
+    FFactory : ISDODataFactory;
+  protected
+    class function Create_Factory() : ISDODataFactory;
+  protected
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+    procedure check_bool_logging(const AObj : ISDODataObject; const APropName : string);
+    procedure check_byte_logging(const AObj : ISDODataObject; const APropName : string);
+    procedure check_date_logging(const AObj : ISDODataObject; const APropName : string);
+    procedure check_int_logging(const AObj : ISDODataObject; const APropName : string);
+    procedure check_string_logging(const AObj : ISDODataObject; const APropName : string);
+{$IFDEF HAS_SDO_BYTES}
+    procedure check_bytes_logging(const AObj : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure check_char_logging(const AObj : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure check_currency_logging(const AObj : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure check_double_logging(const AObj : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure check_float_logging(const AObj : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure check_long_logging(const AObj : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure check_short_logging(const AObj : ISDODataObject; const APropName : string);
+{$ENDIF HAS_SDO_SHORT}
+  published
+    procedure create_default_props();
+    procedure logging_bool();
+    procedure logging_byte();
+    procedure logging_date();
+    procedure logging_int();
+    procedure logging_string();
+{$IFDEF HAS_SDO_BYTES}
+    procedure logging_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure logging_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure logging_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure logging_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure logging_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure logging_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure logging_short();
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure getChangeSummary();
+  end;
+
+  TSDOChangeSummaryMultiValueProps_Test = class(TWstBaseTest)
+  private
+    FFactory : ISDODataFactory;
+  protected
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+  published
+    procedure getOldValues_bool();
+    procedure undoChanges_bool();
+    procedure undoChanges_bool_deleted();
+    procedure undoChanges_nested_bool();
+
+    procedure getOldValues_byte();
+    procedure undoChanges_byte();
+    procedure undoChanges_byte_deleted();
+    procedure undoChanges_nested_byte();
+
+    procedure getOldValues_date();
+    procedure undoChanges_date();
+    procedure undoChanges_date_deleted();
+    procedure undoChanges_nested_date();
+
+    procedure getOldValues_integer();
+    procedure undoChanges_integer();
+    procedure undoChanges_integer_deleted();
+    procedure undoChanges_nested_integer();
+
+    procedure getOldValues_objects();
+    procedure undoChanges_object();
+    procedure undoChanges_object_deleted();
+    procedure undoChanges_nested_object();
+
+    procedure getOldValues_string();
+    procedure undoChanges_string();
+    procedure undoChanges_string_deleted();
+    procedure undoChanges_nested_string();
+
+{$IFDEF HAS_SDO_BYTES}
+    procedure getOldValues_bytes();
+    procedure undoChanges_bytes();
+    procedure undoChanges_bytes_deleted();
+    procedure undoChanges_nested_bytes();
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+    procedure getOldValues_char();
+    procedure undoChanges_char();
+    procedure undoChanges_char_deleted();
+    procedure undoChanges_nested_char();
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure getOldValues_currency();
+    procedure undoChanges_currency();
+    procedure undoChanges_currency_deleted();
+    procedure undoChanges_nested_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure getOldValues_double();
+    procedure undoChanges_double();
+    procedure undoChanges_double_deleted();
+    procedure undoChanges_nested_double();
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+    procedure getOldValues_float();
+    procedure undoChanges_float();
+    procedure undoChanges_float_deleted();
+    procedure undoChanges_nested_float();
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+    procedure getOldValues_long();
+    procedure undoChanges_long();
+    procedure undoChanges_long_deleted();
+    procedure undoChanges_nested_long();
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+    procedure getOldValues_short();
+    procedure undoChanges_short();
+    procedure undoChanges_short_deleted();
+    procedure undoChanges_nested_short();
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure isDeleted();
+    procedure isDeleted_nested();
+
+    procedure getChangedDataObjects_contained_delete_multiprop_1();
+    procedure getChangedDataObjects_contained_delete_multiprop_2();
+    procedure getChangedDataObjects_contained_delete_multiprop_3();
+  end;
+
+implementation
+
+uses
+  sdo_datafactory, Math, sdo_copyhelper, sdo_equalityhelper,
+  sdo_consts, sdo_convert_helper, DateUtils, sdo_date_utils;
+
+const
+  s_uri              = 'urn-test';
+  s_type_object_A    = 'objectA';
+  s_type_object_B    = 'objectB';
+  s_type_object_C    = 'objectC';
+  s_bool_prop        = 'bool_prop';            s_bool_propList      = 'bool_prop_list';
+  s_byte_prop        = 'byte_prop';            s_byte_propList      = 'byte_prop_list';
+  s_bytes_prop       = 'bytes_prop';           s_bytes_propList     = 'bytes_prop_list';
+  s_char_prop        = 'char_prop';            s_char_propList      = 'char_prop_list';
+  s_currency_prop    = 'currency_prop';        s_currency_propList  = 'currency_prop_list';
+  s_date_prop        = 'date_prop';            s_date_propList      = 'date_prop_list';
+  s_double_prop      = 'double_prop';          s_double_propList    = 'double_prop_list';
+  s_float_prop       = 'float_prop';           s_float_propList     = 'float_prop_list';
+  s_integer_prop     = 'integer_prop';         s_integer_propList   = 'integer_prop_list';
+  s_long_prop        = 'long_prop';            s_long_propList      = 'long_prop_list';
+  s_short_prop       = 'short_prop';           s_short_propList     = 'short_prop_list';
+  s_string_prop      = 'string_prop';          s_string_propList    = 'string_prop_list';
+  s_object_prop      = 'object_prop';          s_object_propList    = 'object_prop_list';
+  s_object_ref_prop      = 'object_ref_prop';
+  s_changesummary_prop = 'change_summary_prop';
+
+  s_Employee = 'Employee';
+  s_EmployeeType = 'EmployeeType';
+  s_Department = 'Department';
+  s_location = 'location';
+  s_manager = 'manager';
+  s_name = 'name';
+  s_number = 'number';
+  s_sn = 'SN';
+
+function CastExtractor(const AList : TObjectList; const AIndex : PtrInt) : PtrInt;
+begin
+  Result := PtrInt(AList[AIndex]);
+end;
+
+function sortComparer(Item1, Item2: Pointer): Integer;
+begin
+  Result := PtrInt(Item2) - PtrInt(Item1);
+end;
+
+function SortInterfaceList(const AIL : IInterfaceList) : IInterfaceList;
+var
+  ls : TList;
+  i : PtrInt;
+begin
+  Result := TInterfaceList.Create();
+  if ( Assigned(AIL) and ( AIL.Count > 0 ) ) then begin
+    ls := TList.Create();
+    try
+      for i := 0 to Pred(AIL.Count) do begin
+        ls.Add(Pointer(AIL.Items[i] as IInterface));
+      end;
+      ls.Sort(@sortComparer);
+      for i := 0 to Pred(AIL.Count) do begin
+        Result.Add(IInterface(ls[i]));
+      end;
+    finally
+      ls.Free();
+    end;
+  end;
+end;
+
+
+{ TValueSetting_Test }
+
+procedure TValueSetting_Test.CheckEquals(expected, actual: TSDODate; msg: string; const AStrict: Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+class function TValueSetting_Test.CreateFactory() : ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}        
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+
+  Result := locFactory;
+end;
+
+procedure TValueSetting_Test.create_boolean();
+var
+  ok : Boolean;
+  boolVal : TSDOBoolean;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,boolVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(s_bool_prop) as ISDOProperty;
+  boolVal := False;
+  localObj := TValueSetting.Create(True,True,boolVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( False, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,boolVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( False, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  boolVal := False;
+  localObj := TValueSetting.Create(True,False,boolVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( boolVal, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  boolVal := True;
+  localObj := TValueSetting.Create(True,False,boolVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( boolVal, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(s_bool_propList) as ISDOProperty;
+  boolVal := True;
+  localObj := TValueSetting.Create(True,True,boolVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( False, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  boolVal := True;
+  localObj := TValueSetting.Create(False,True,boolVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( False, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  boolVal := False;
+  localObj := TValueSetting.Create(True,False,boolVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( boolVal, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  boolVal := True;
+  localObj := TValueSetting.Create(True,False,boolVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( boolVal, localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.BoolToByte(localObj.getBooleanValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.BoolToInteger(localObj.getBooleanValue()), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.BoolToString(localObj.getBooleanValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+
+procedure TValueSetting_Test.create_byte();
+var
+  ok : Boolean;
+  locVal : TSDOByte;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := 123;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(s_byte_prop) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.ByteToBool(localObj.getByteValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.ByteToString(localObj.getByteValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.ByteToBool(localObj.getByteValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.ByteToString(localObj.getByteValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.ByteToBool(localObj.getByteValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.ByteToString(localObj.getByteValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 67;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.ByteToBool(localObj.getByteValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.ByteToString(localObj.getByteValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(s_byte_propList) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.ByteToBool(localObj.getByteValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.ByteToString(localObj.getByteValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.ByteToBool(localObj.getByteValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.ByteToString(localObj.getByteValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 34;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.ByteToBool(localObj.getByteValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.ByteToString(localObj.getByteValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TValueSetting_Test.create_bytes();
+const
+  PROP_NAME = s_bytes_prop;
+  LIST_PROP_NAME = s_bytes_propList;
+  VAL_1 : array[0..2] of TSDOByte = ( 2, 24, 12 );
+  VAL_2 : array[0..5] of TSDOByte = ( 1, 07, 6, 2, 24, 12 );
+  VAL_3 : array[0..1] of TSDOByte = ( 24,6 );
+
+
+  function LocalCopy(const AValue : array of TSDOByte) : TSDOBytes;
+  begin
+    SetLength(Result,Length(AValue));
+    if ( Length(Result) > 0 ) then
+      Move(AValue[0],Result[0],Length(Result));
+  end;
+
+var
+  ok : Boolean;
+  locVal : TSDOBytes;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := LocalCopy(VAL_1);
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( nil, localObj.getBytesValue(), 'getBytesValue');
+    CheckEquals( TSDOConvertHelper.BytesToString(localObj.getBytesValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( nil, localObj.getBytesValue(), 'getBytesValue');
+    CheckEquals( TSDOConvertHelper.BytesToString(localObj.getBytesValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getBytesValue(), 'getBytesValue');
+    CheckEquals( TSDOConvertHelper.BytesToString(localObj.getBytesValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := LocalCopy(VAL_2);
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getBytesValue(), 'getBytesValue');
+    CheckEquals( TSDOConvertHelper.BytesToString(localObj.getBytesValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(LIST_PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( nil, localObj.getBytesValue(), 'getBytesValue');
+    CheckEquals( TSDOConvertHelper.BytesToString(localObj.getBytesValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( nil, localObj.getBytesValue(), 'getBytesValue');
+    CheckEquals( TSDOConvertHelper.BytesToString(localObj.getBytesValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := LocalCopy(VAL_3);
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getBytesValue(), 'getBytesValue');
+    CheckEquals( TSDOConvertHelper.BytesToString(localObj.getBytesValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TValueSetting_Test.create_char();
+const
+  PROP_NAME = s_char_prop;
+  LIST_PROP_NAME = s_char_propList;
+var
+  ok : Boolean;
+  locVal : TSDOChar;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := 'K';
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( #0, localObj.getCharacterValue(), 'getCharacterValue');
+    CheckEquals( TSDOConvertHelper.CharToBool(localObj.getCharacterValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.CharToByte(localObj.getCharacterValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.CharToInteger(localObj.getCharacterValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.CharToLong(localObj.getCharacterValue()), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.CharToShort(localObj.getCharacterValue()), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( localObj.getCharacterValue(), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( #0, localObj.getCharacterValue(), 'getCharacterValue');
+    CheckEquals( TSDOConvertHelper.CharToBool(localObj.getCharacterValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.CharToByte(localObj.getCharacterValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.CharToInteger(localObj.getCharacterValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.CharToLong(localObj.getCharacterValue()), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.CharToShort(localObj.getCharacterValue()), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( localObj.getCharacterValue(), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCharacterValue(), 'getCharacterValue');
+    CheckEquals( TSDOConvertHelper.CharToBool(localObj.getCharacterValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.CharToByte(localObj.getCharacterValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.CharToInteger(localObj.getCharacterValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.CharToLong(localObj.getCharacterValue()), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.CharToShort(localObj.getCharacterValue()), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( localObj.getCharacterValue(), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 'h';
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCharacterValue(), 'getCharacterValue');
+    CheckEquals( TSDOConvertHelper.CharToBool(localObj.getCharacterValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.CharToByte(localObj.getCharacterValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.CharToInteger(localObj.getCharacterValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.CharToLong(localObj.getCharacterValue()), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.CharToShort(localObj.getCharacterValue()), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( localObj.getCharacterValue(), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(LIST_PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( #0, localObj.getCharacterValue(), 'getCharacterValue');
+    CheckEquals( TSDOConvertHelper.CharToBool(localObj.getCharacterValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.CharToByte(localObj.getCharacterValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.CharToInteger(localObj.getCharacterValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.CharToLong(localObj.getCharacterValue()), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.CharToShort(localObj.getCharacterValue()), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( localObj.getCharacterValue(), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( #0, localObj.getCharacterValue(), 'getCharacterValue');
+    CheckEquals( TSDOConvertHelper.CharToBool(localObj.getCharacterValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.CharToByte(localObj.getCharacterValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.CharToInteger(localObj.getCharacterValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.CharToLong(localObj.getCharacterValue()), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.CharToShort(localObj.getCharacterValue()), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( localObj.getCharacterValue(), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := '1';
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCharacterValue(), 'getCharacterValue');
+    CheckEquals( TSDOConvertHelper.CharToBool(localObj.getCharacterValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.CharToByte(localObj.getCharacterValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.CharToInteger(localObj.getCharacterValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.CharToLong(localObj.getCharacterValue()), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.CharToShort(localObj.getCharacterValue()), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( localObj.getCharacterValue(), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+procedure TValueSetting_Test.create_date();
+var
+  ok : Boolean;
+  locVal : TSDODateTime;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  FillChar(locVal,SizeOf(locVal),#0);
+
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(s_date_prop) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( ZERO_DATE, localObj.getDateValue(), 'getDateValue');
+    CheckEquals( TSDOConvertHelper.DateToString(localObj.getDateValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( ZERO_DATE, localObj.getDateValue(), 'getDateValue');
+    CheckEquals( TSDOConvertHelper.DateToString(localObj.getDateValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( ZERO_DATE, localObj.getDateValue(), 'getDateValue');
+    CheckEquals( TSDOConvertHelper.DateToString(localObj.getDateValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal.Date := 39000;
+  locVal.HourOffset := 1;
+  locVal.MinuteOffset := 2;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDateValue(), 'getDateValue');
+    CheckEquals( TSDOConvertHelper.DateToString(localObj.getDateValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(s_date_propList) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( ZERO_DATE, localObj.getDateValue(), 'getDateValue');
+    CheckEquals( TSDOConvertHelper.DateToString(localObj.getDateValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( ZERO_DATE, localObj.getDateValue(), 'getDateValue');
+    CheckEquals( TSDOConvertHelper.DateToString(localObj.getDateValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDateValue(), 'getDateValue');
+    CheckEquals( TSDOConvertHelper.DateToString(localObj.getDateValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TValueSetting_Test.create_currency();
+const
+  PROP_NAME = s_currency_prop;
+  LIST_PROP_NAME = s_currency_propList;
+var
+  ok : Boolean;
+  locVal : TSDOCurrency;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := 67;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getCurrencyValue(), 'getCurrencyValue');
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getCurrencyValue(), 'getCurrencyValue');
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCurrencyValue(), 'getCurrencyValue');
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 45;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCurrencyValue(), 'getCurrencyValue');
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 1236891478.2522;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCurrencyValue(), 'getCurrencyValue');
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -225544778.8622;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCurrencyValue(), 'getCurrencyValue');
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(LIST_PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getCurrencyValue(), 'getCurrencyValue');
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getCurrencyValue(), 'getCurrencyValue');
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 99;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCurrencyValue(), 'getCurrencyValue');
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getCurrencyValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 24667733.1155;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCurrencyValue(), 'getCurrencyValue');
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -5588663211424;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getCurrencyValue(), 'getCurrencyValue');
+    CheckEquals( TSDOConvertHelper.CurrencyToString(localObj.getCurrencyValue()), localObj.getStringValue(), 'getStringValue'); 
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TValueSetting_Test.create_double();
+const
+  PROP_NAME = s_double_prop;
+  LIST_PROP_NAME = s_double_propList;
+var
+  ok : Boolean;
+  locVal : TSDODouble;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := 67;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getDoubleValue(), 'getDoubleValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getDoubleValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getDoubleValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getDoubleValue(), 'getDoubleValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getDoubleValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getDoubleValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDoubleValue(), 'getDoubleValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getDoubleValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getDoubleValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 45;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDoubleValue(), 'getDoubleValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getDoubleValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getDoubleValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 12365479;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDoubleValue(), 'getDoubleValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -225544721;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDoubleValue(), 'getDoubleValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(LIST_PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getDoubleValue(), 'getDoubleValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getDoubleValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getDoubleValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getDoubleValue(), 'getDoubleValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getDoubleValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getDoubleValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 99;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDoubleValue(), 'getDoubleValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getDoubleValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+    CheckEquals( localObj.getDoubleValue(), localObj.getFloatValue(), 'getFloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 8855224;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDoubleValue(), 'getDoubleValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -55886424;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getDoubleValue(), 'getDoubleValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getDoubleValue()), localObj.getStringValue(), 'getStringValue'); 
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TValueSetting_Test.create_float();
+const
+  PROP_NAME = s_float_prop;
+  LIST_PROP_NAME = s_float_propList;
+var
+  ok : Boolean;
+  locVal : TSDOFloat;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := 67;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getFloatValue(), 'getFloatValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getFloatValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getFloatValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getFloatValue(), 'getFloatValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getFloatValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getFloatValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getFloatValue(), 'getFloatValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getFloatValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getFloatValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 45;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getFloatValue(), 'getFloatValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getFloatValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getFloatValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 1236547891;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getFloatValue(), 'getFloatValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -2255442;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getFloatValue(), 'getFloatValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(LIST_PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getFloatValue(), 'getFloatValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getFloatValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getFloatValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getFloatValue(), 'getFloatValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getFloatValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getFloatValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 99;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getFloatValue(), 'getFloatValue');
+{$IFDEF HAS_SDO_CURRENCY}
+    CheckEquals( localObj.getFloatValue(), localObj.getCurrencyValue(), 'getCurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    CheckEquals( localObj.getFloatValue(), localObj.getDoubleValue(), 'getDoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 88552255;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getFloatValue(), 'getFloatValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -55886624;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getFloatValue(), 'getFloatValue');
+    CheckEquals( TSDOConvertHelper.FloatToString(localObj.getFloatValue()), localObj.getStringValue(), 'getStringValue'); 
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure TValueSetting_Test.create_integer();
+var
+  ok : Boolean;
+  intVal : TSDOInteger;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  intVal := 1210;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,intVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(s_integer_prop) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,intVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.IntegerToBool(localObj.getIntegerValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.IntegerToString(localObj.getIntegerValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,intVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.IntegerToBool(localObj.getIntegerValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.IntegerToString(localObj.getIntegerValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,intVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( intVal, localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.IntegerToBool(localObj.getIntegerValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.IntegerToString(localObj.getIntegerValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  intVal := 67;
+  localObj := TValueSetting.Create(True,False,intVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( intVal, localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.IntegerToBool(localObj.getIntegerValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getByteValue(), localObj.getIntegerValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.IntegerToString(localObj.getIntegerValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(s_integer_propList) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,intVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.IntegerToBool(localObj.getIntegerValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.IntegerToString(localObj.getIntegerValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,intVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.IntegerToBool(localObj.getIntegerValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.IntegerToString(localObj.getIntegerValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  intVal := 345;
+  localObj := TValueSetting.Create(True,False,intVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( intVal, localObj.getIntegerValue(), 'getIntegerValue');
+    CheckEquals( TSDOConvertHelper.IntegerToBool(localObj.getIntegerValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( TSDOConvertHelper.IntegerToString(localObj.getIntegerValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure TValueSetting_Test.create_long();
+const
+  PROP_NAME = s_long_prop;
+  LIST_PROP_NAME = s_long_propList;
+var
+  ok : Boolean;
+  locVal : TSDOLong;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := 67;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getLongValue(), 'getLongValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToChar(localObj.getLongValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToBool(localObj.getLongValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getLongValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getLongValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( localObj.getLongValue(), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getLongValue(), 'getLongValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToChar(localObj.getLongValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToBool(localObj.getLongValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getLongValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getLongValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( localObj.getLongValue(), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getLongValue(), 'getLongValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToChar(localObj.getLongValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToBool(localObj.getLongValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getLongValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getLongValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( localObj.getLongValue(), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 45;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getLongValue(), 'getLongValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToChar(localObj.getLongValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToBool(localObj.getLongValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getLongValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getLongValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( localObj.getLongValue(), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 12365478914782522;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getLongValue(), 'getLongValue');
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -22554477886221222;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getLongValue(), 'getLongValue');
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(LIST_PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getLongValue(), 'getLongValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToChar(localObj.getLongValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToBool(localObj.getLongValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getLongValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getLongValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( localObj.getLongValue(), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getLongValue(), 'getLongValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToChar(localObj.getLongValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToBool(localObj.getLongValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getLongValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getLongValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( localObj.getLongValue(), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 99;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getLongValue(), 'getLongValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToChar(localObj.getLongValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.LongToBool(localObj.getLongValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getLongValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getLongValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_SHORT}
+    CheckEquals( localObj.getLongValue(), localObj.getShortValue(), 'getShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');  
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 88552246677331155;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getLongValue(), 'getLongValue');
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');  
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -5588663211424;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getLongValue(), 'getLongValue');
+    CheckEquals( TSDOConvertHelper.LongToString(localObj.getLongValue()), localObj.getStringValue(), 'getStringValue');  
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TValueSetting_Test.create_short();
+const
+  PROP_NAME = s_short_prop;
+  LIST_PROP_NAME = s_short_propList;
+var
+  ok : Boolean;
+  locVal : TSDOShort;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  locVal := 67;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,locVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getShortValue(), 'getShortValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToChar(localObj.getShortValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToBool(localObj.getShortValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getShortValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getShortValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( localObj.getShortValue(), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getShortValue(), 'getShortValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToChar(localObj.getShortValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToBool(localObj.getShortValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getShortValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getShortValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( localObj.getShortValue(), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getShortValue(), 'getShortValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToChar(localObj.getShortValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToBool(localObj.getShortValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getShortValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getShortValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( localObj.getShortValue(), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 45;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getShortValue(), 'getShortValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToChar(localObj.getShortValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToBool(localObj.getShortValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getShortValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getShortValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( localObj.getShortValue(), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 23567;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getShortValue(), 'getShortValue');
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -22552;
+  localObj := TValueSetting.Create(True,False,locVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getShortValue(), 'getShortValue');
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(LIST_PROP_NAME) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,locVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getShortValue(), 'getShortValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToChar(localObj.getShortValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToBool(localObj.getShortValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getShortValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getShortValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( localObj.getShortValue(), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,locVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( 0, localObj.getShortValue(), 'getShortValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToChar(localObj.getShortValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToBool(localObj.getShortValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getShortValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getShortValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( localObj.getShortValue(), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 99;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getShortValue(), 'getShortValue');
+{$IFDEF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToChar(localObj.getShortValue()), localObj.getCharacterValue(), 'getCharacterValue');
+{$ENDIF HAS_SDO_CHAR}
+    CheckEquals( TSDOConvertHelper.ShortToBool(localObj.getShortValue()), localObj.getBooleanValue(), 'getBooleanValue');
+    CheckEquals( localObj.getShortValue(), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( localObj.getShortValue(), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    CheckEquals( localObj.getShortValue(), localObj.getLongValue(), 'getLongValue');
+{$ENDIF HAS_SDO_LONG}
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := 8855;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getShortValue(), 'getShortValue');
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  locVal := -11424;
+  localObj := TValueSetting.Create(True,False,locVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( locVal, localObj.getShortValue(), 'getShortValue');
+    CheckEquals( TSDOConvertHelper.ShortToString(localObj.getShortValue()), localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TValueSetting_Test.create_string();
+var
+  ok : Boolean;
+  strVal : TSDOString;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  localObj : TValueSetting;
+  prp : ISDOProperty;
+begin
+  strVal := 'sdo sample string';
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  ok := False;
+  try
+    TValueSetting.Create(False,False,strVal,nil,0);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'Invalid property parametter');
+
+  // simple value
+  prp := objectAType.getProperty(s_string_prop) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,strVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( '', localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,strVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( '', localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,strVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( strVal, localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  strVal := '123';
+  localObj := TValueSetting.Create(True,False,strVal,prp,0);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 0, localObj.getIndex(), 'getIndex' );
+    CheckEquals( strVal, localObj.getStringValue(), 'getStringValue');
+    CheckEquals( TSDOConvertHelper.StringToByte(localObj.getStringValue()), localObj.getByteValue(), 'getByteValue');
+    CheckEquals( TSDOConvertHelper.StringToInteger(localObj.getStringValue()), localObj.getIntegerValue(), 'getIntegerValue');
+{$IFDEF HAS_SDO_BYTES}
+    CheckEquals( TSDOConvertHelper.StringToBytes(localObj.getStringValue()), localObj.getBytesValue(), 'getBytesValue');
+{$ENDIF HAS_SDO_BYTES}
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  // multi value
+  prp := objectAType.getProperty(s_string_propList) as ISDOProperty;
+  localObj := TValueSetting.Create(True,True,strVal,prp,12);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 12, localObj.getIndex(), 'getIndex' );
+    CheckEquals( '', localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(False,True,strVal,prp,23);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( False, localObj.isSet(), 'isSet' );
+    CheckEquals( True, localObj.isNull(), 'isNull' );
+    CheckEquals( 23, localObj.getIndex(), 'getIndex' );
+    CheckEquals( '', localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  localObj := TValueSetting.Create(True,False,strVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( strVal, localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+
+  strVal := 'qwsdff';
+  localObj := TValueSetting.Create(True,False,strVal,prp,34);
+  try
+    CheckEquals( PtrInt(prp), PtrInt(localObj.getProperty()), 'getProperty' );
+    CheckEquals( True, localObj.isSet(), 'isSet' );
+    CheckEquals( False, localObj.isNull(), 'isNull' );
+    CheckEquals( 34, localObj.getIndex(), 'getIndex' );
+    CheckEquals( strVal, localObj.getStringValue(), 'getStringValue');
+  finally
+    FreeAndNil(localObj);
+  end;
+end;
+
+{ TSDOSettingList_Test }
+
+procedure TSDOSettingList_Test.append();
+var
+  ok : Boolean;
+  intVal : TSDOInteger;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  stg0, stg1, stg2, stg3 : TValueSetting;
+  localObj : ISDOSettingList;
+  prp : ISDOProperty;
+begin
+  intVal := 1210;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  prp := objectAType.getProperty(s_integer_prop) as ISDOProperty;
+
+  localObj := TSDOSettingList.Create();
+  ok := False;
+  try
+    localObj.append(nil);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'append(0,nil)');
+
+  stg0 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg0);
+    CheckEquals(1,localObj.size());
+    CheckSame(stg0,localObj.getItem(0));
+  localObj.append(stg0);
+    CheckEquals(1,localObj.size(),'appended twice');
+    CheckSame(stg0,localObj.getItem(0),'appended twice');
+
+  stg1 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg1);
+    CheckEquals(2,localObj.size());
+    CheckSame(stg0,localObj.getItem(0));
+    CheckSame(stg1,localObj.getItem(1));
+
+  stg2 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg2);
+    CheckEquals(3,localObj.size());
+    CheckSame(stg0,localObj.getItem(0));
+    CheckSame(stg1,localObj.getItem(1));
+    CheckSame(stg2,localObj.getItem(2));
+  localObj.append(stg2);
+    CheckEquals(3,localObj.size(),'appended twice');
+    CheckSame(stg0,localObj.getItem(0),'appended twice');
+    CheckSame(stg1,localObj.getItem(1),'appended twice');
+    CheckSame(stg2,localObj.getItem(2),'appended twice');
+
+  stg3 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg3);
+    CheckEquals(4,localObj.size());
+    CheckSame(stg0,localObj.getItem(0));
+    CheckSame(stg1,localObj.getItem(1));
+    CheckSame(stg2,localObj.getItem(2));
+    CheckSame(stg3,localObj.getItem(3));
+end;
+
+class function TSDOSettingList_Test.CreateFactory() : ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+
+  Result := locFactory;
+end;
+
+procedure TSDOSettingList_Test.getItem();
+var
+  ok : Boolean;
+  intVal : TSDOInteger;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  stg0, stg1, stg2, stg3 : TValueSetting;
+  localObj : ISDOSettingList;
+  prp : ISDOProperty;
+begin
+  intVal := 1210;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  prp := objectAType.getProperty(s_integer_prop) as ISDOProperty;
+
+  localObj := TSDOSettingList.Create();
+  ok := False;
+  try
+    localObj.getItem(0);
+  except
+    on e : ESDOIndexOutOfRangeException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'getItem(0,nil)');
+
+  stg0 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(0,stg0);
+    CheckEquals(1,localObj.size());
+    CheckSame(stg0,localObj.getItem(0));
+
+  stg1 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(0,stg1);
+    CheckEquals(2,localObj.size());
+    CheckSame(stg0,localObj.getItem(1));
+    CheckSame(stg1,localObj.getItem(0));
+
+  stg2 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(1,stg2);
+    CheckEquals(3,localObj.size());
+    CheckSame(stg0,localObj.getItem(2));
+    CheckSame(stg1,localObj.getItem(0));
+    CheckSame(stg2,localObj.getItem(1));
+
+  stg3 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert((localObj.size() - 1),stg3);
+    CheckEquals(4,localObj.size());
+    CheckSame(stg0,localObj.getItem(3));
+    CheckSame(stg1,localObj.getItem(0));
+    CheckSame(stg2,localObj.getItem(1));
+    CheckSame(stg3,localObj.getItem(2));
+
+  localObj.remove(0);
+    CheckSame(stg0,localObj.getItem(2));
+    CheckSame(stg2,localObj.getItem(0));
+    CheckSame(stg3,localObj.getItem(1));
+
+  localObj.remove(2);
+    CheckSame(stg2,localObj.getItem(0));
+    CheckSame(stg3,localObj.getItem(1));
+
+  stg0 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg0);
+    CheckSame(stg2,localObj.getItem(0));
+    CheckSame(stg3,localObj.getItem(1));
+    CheckSame(stg0,localObj.getItem(2));
+
+  localObj.remove(1);
+    CheckSame(stg2,localObj.getItem(0));
+    CheckSame(stg0,localObj.getItem(1));
+
+  localObj.remove(1);
+  localObj.remove(0);
+    ok := False;
+    try
+      localObj.getItem(0);
+    except
+      on e : ESDOIndexOutOfRangeException do
+        ok := True;
+    end;
+    CheckEquals(True,ok,'getItem(0,nil)');
+end;
+
+procedure TSDOSettingList_Test.insert();
+var
+  ok : Boolean;
+  intVal : TSDOInteger;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  stg0, stg1, stg2, stg3 : TValueSetting;
+  localObj : ISDOSettingList;
+  prp : ISDOProperty;
+begin
+  intVal := 1210;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  prp := objectAType.getProperty(s_integer_prop) as ISDOProperty;
+
+  localObj := TSDOSettingList.Create();
+  ok := False;
+  try
+    localObj.insert(0,nil);
+  except
+    on e : ESDOIllegalArgumentException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'insert(0,nil)');
+
+  stg0 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(0,stg0);
+    CheckEquals(1,localObj.size());
+    CheckSame(stg0,localObj.getItem(0));
+  localObj.insert(0,stg0);
+    CheckEquals(1,localObj.size(),'inserted twice');
+    CheckSame(stg0,localObj.getItem(0),'inserted twice');
+
+  stg1 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(0,stg1);
+    CheckEquals(2,localObj.size());
+    CheckSame(stg0,localObj.getItem(1));
+    CheckSame(stg1,localObj.getItem(0));
+
+  stg2 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(1,stg2);
+    CheckEquals(3,localObj.size());
+    CheckSame(stg0,localObj.getItem(2));
+    CheckSame(stg1,localObj.getItem(0));
+    CheckSame(stg2,localObj.getItem(1));
+  localObj.insert(1,stg2);
+    CheckEquals(3,localObj.size(),'inserted twice');
+    CheckSame(stg0,localObj.getItem(2),'inserted twice');
+    CheckSame(stg1,localObj.getItem(0),'inserted twice');
+    CheckSame(stg2,localObj.getItem(1),'inserted twice');
+
+  stg3 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert((localObj.size() - 1),stg3);
+    CheckEquals(4,localObj.size());
+    CheckSame(stg0,localObj.getItem(3));
+    CheckSame(stg1,localObj.getItem(0));
+    CheckSame(stg2,localObj.getItem(1));
+    CheckSame(stg3,localObj.getItem(2));
+end;
+
+procedure TSDOSettingList_Test.remove();
+var
+  ok : Boolean;
+  intVal : TSDOInteger;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  stg0, stg1 : TValueSetting;
+  localObj : ISDOSettingList;
+  prp : ISDOProperty;
+begin
+  intVal := 1210;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  prp := objectAType.getProperty(s_integer_prop) as ISDOProperty;
+
+  localObj := TSDOSettingList.Create();
+  ok := False;
+  try
+    localObj.remove(0);
+  except
+    on e : ESDOIndexOutOfRangeException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'remove(0,nil)');
+
+  stg0 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg0);
+  ok := False;
+  try
+    localObj.remove(1);
+  except
+    on e : ESDOIndexOutOfRangeException do
+      ok := True;
+  end;
+  CheckEquals(True,ok,'remove(1,nil)');
+
+  localObj.remove(0);
+    CheckEquals(0,localObj.size());
+    ok := False;
+    try
+      localObj.remove(0);
+    except
+      on e : ESDOIndexOutOfRangeException do
+        ok := True;
+    end;
+    CheckEquals(True,ok,'remove(0,nil)');
+
+
+  stg0 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg0);
+  stg1 := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg1);
+    ok := False;
+    try
+      localObj.remove(2);
+    except
+      on e : ESDOIndexOutOfRangeException do
+        ok := True;
+    end;
+    CheckEquals(True,ok,'remove(2,nil)');
+
+    localObj.remove(1);
+      CheckSame(stg0,localObj.getItem(0));
+        stg1 := TValueSetting.Create(True,False,intVal,prp,0);
+        localObj.append(stg1);
+        CheckSame(stg0,localObj.getItem(0));
+        CheckSame(stg1,localObj.getItem(1));
+      localObj.remove(0);
+      localObj.remove(0);
+        CheckEquals(0,localObj.size());
+end;
+
+procedure TSDOSettingList_Test.size();
+var
+  intVal : TSDOInteger;
+  fact : ISDODataFactory;
+  objectAType : ISDOType;
+  stg : TValueSetting;
+  localObj : ISDOSettingList;
+  prp : ISDOProperty;
+begin
+  intVal := 1210;
+  fact := CreateFactory();
+  objectAType := fact.getType(s_uri,s_type_object_A);
+  prp := objectAType.getProperty(s_integer_prop) as ISDOProperty;
+
+  localObj := TSDOSettingList.Create();
+  CheckEquals(0,localObj.size());
+  CheckEquals(0,localObj.size());
+
+  stg := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg);
+    CheckEquals(1,localObj.size());
+  stg := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.append(stg);
+    CheckEquals(2,localObj.size());
+  localObj.remove(1);
+    CheckEquals(1,localObj.size());
+  localObj.remove(0);
+    CheckEquals(0,localObj.size());
+
+  stg := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(0,stg);
+    CheckEquals(1,localObj.size());
+
+  stg := TValueSetting.Create(True,False,intVal,prp,0);
+  localObj.insert(0,stg);
+    CheckEquals(2,localObj.size());
+end;
+
+{ TDicho_Test }
+(*
+procedure TDicho_Test.build();
+var
+  ls : TObjectList;
+  NBR, i, j, k : PtrInt;
+  msg, order : string;
+begin
+  j := 0;
+  Randomize();
+  NBR := RandomRange(100,500);
+  ls := TObjectList.Create(False);
+  try
+    order := '';
+    for i := 1 to NBR do begin
+      while True do begin
+        j := RandomRange(0,1000);
+        if ( ls.IndexOf(TObject(j)) = -1 ) then
+          Break;
+      end;
+      CheckEquals(False,findDicho(ls,j,k,@CastExtractor));
+      ls.Insert(k,TObject(j));
+      order := order + ';' + IntToStr(j);
+    end;
+    for i := 1 to Pred(NBR) do begin
+      if ( PtrInt(ls[i-1]) > PtrInt(ls[i]) ) then begin
+        msg := '';
+        for j := 0 to Pred(NBR) do begin
+          if (j > 0) then
+            msg := msg + '; ';
+          msg := Format('%sls[%d] = %d',[msg,j,PtrInt(ls[j])]);
+        end;
+        Check(False,msg + '  ; Order = ' + order);
+      end;
+      {Check(
+        PtrInt(ls[i-1]) < PtrInt(ls[i]),
+        Format('i = %d; ls[i] = %d; ls[i-1] = %d',[i, PtrInt(ls[i]), PtrInt(ls[i-1])])
+      );}
+    end;
+  finally
+    ls.Free();
+  end;
+end;
+
+procedure TDicho_Test.find();
+var
+  offset, value, index, lngth, i : PtrInt;
+  passed : Boolean;
+  v : TObjectList;
+begin
+  v := TObjectList.Create(False);
+  try
+    for offset := 1 to 5 do begin
+      for lngth := 1 to 2049 do begin
+        v.Clear();
+        v.Capacity := lngth;
+        for i := 0 to Pred(lngth) do begin
+          v.Add(TObject(i*offset));
+        end;
+        for value := 0 to Pred(lngth) do begin
+          passed := findDicho(v,value*offset,index,@CastExtractor);
+          passed := passed and ( index = value );
+          CheckEquals(True,passed);
+        end;
+      end;
+    end;
+  finally
+    v.Free();
+  end;
+end; *)
+
+{ TSDOChangedDataObjectList_Test }
+
+procedure TSDOChangedDataObjectList_Test.append();
+var
+  localObj : ISDOChangedDataObjectListEx;
+  fact : ISDODataFactory;
+  i, j, k : PtrInt;
+  il(*, ilSorted*) : IInterfaceList;
+  obj : ISDODataObject;
+  ct : TChangeType;
+  ok : Boolean;
+  NBR_INST : PtrInt;
+begin
+  k := 0;
+  Randomize();
+  NBR_INST := RandomRange(100,1000);
+  fact := CreateFactory();
+  il := TInterfaceList.Create();
+
+  localObj := CreateObject();
+
+  for i := 0 to Pred(NBR_INST) do begin
+    ct := TChangeType( ( i mod 3 ) + 1 );
+    obj := fact.createNew(s_uri,s_type_object_A);
+    localObj.append(obj,ct);
+    il.Add(obj);
+  end;
+  {// The list is no longer sorted!
+  ilSorted := SortInterfaceList(il);
+  for i := 0 to Pred(NBR_INST) do begin
+    CheckEquals(PtrInt(ilSorted[i]),PtrInt(localObj.getDataObject(Pred(NBR_INST) - i)));
+  end; }
+  for i := 0 to Pred(NBR_INST) do begin
+    ok := False;
+    for j := 0 to Pred(NBR_INST) do begin
+      if ( il[i] = localObj.getDataObject(j) ) then begin
+        k := j;
+        ok := True;
+        Break;
+      end;
+    end;
+    CheckEquals(True, ok, 'getDataObject');
+    CheckEquals(PtrInt(TChangeType( ( i mod 3 ) + 1 )), PtrInt(Ord(localObj.getType(k))), 'getType()');
+  end;
+
+  for i := 0 to Pred(NBR_INST) do begin
+    obj := localObj.getDataObject(i);
+    ok := False;
+    try
+      localObj.append(obj,ctCreate);
+    except
+      on e : ESDODuplicatedItemException do
+        ok := True;
+    end;
+    CheckEquals(True,ok,Format('Duplicated item, i = %d',[i]));
+
+    ok := False;
+    try
+      localObj.append(obj,ctChange);
+    except
+      on e : ESDODuplicatedItemException do
+        ok := True;
+    end;
+    CheckEquals(True,ok,Format('Duplicated item, i = %d',[i]));
+
+    ok := False;
+    try
+      localObj.append(obj,ctDelete);
+    except
+      on e : ESDODuplicatedItemException do
+        ok := True;
+    end;
+    CheckEquals(True,ok,Format('Duplicated item, i = %d',[i]));
+  end;
+
+  { The list is no longer sorted!
+  for i := 0 to Pred(NBR_INST - 1) do begin
+    obj := localObj.getDataObject(i);
+    CheckEquals(True,PtrInt(obj) < PtrInt(localObj.getDataObject(i+1)));
+  end;
+  for i := ( 0 + 1 ) to Pred(NBR_INST) do begin
+    obj := localObj.getDataObject(i);
+    CheckEquals(True,PtrInt(obj) > PtrInt(localObj.getDataObject(i-1)));
+  end;}
+end;
+
+class function TSDOChangedDataObjectList_Test.CreateFactory() : ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+
+  Result := locFactory;
+end;
+
+class function TSDOChangedDataObjectList_Test.CreateObject() : ISDOChangedDataObjectListEx;
+begin
+  Result := TSDOChangedDataObjectList.Create();
+end;
+
+procedure TSDOChangedDataObjectList_Test.find();
+var
+  localObj : ISDOChangedDataObjectListEx;
+  fact : ISDODataFactory;
+  i, j : PtrInt;
+  il: IInterfaceList;
+  obj : ISDODataObject;
+  NBR_INST : PtrInt;
+begin
+  Randomize();
+  NBR_INST := RandomRange(100,1000);
+  fact := CreateFactory();
+  il := TInterfaceList.Create();
+
+  localObj := CreateObject();
+
+  for i := 0 to Pred(NBR_INST) do begin
+    obj := fact.createNew(s_uri,s_type_object_A);
+    localObj.append(obj,TChangeType( ( i mod 3 ) + 1 ));
+    il.Add(obj);
+  end;
+
+  for i := 0 to Pred(NBR_INST) do begin
+    CheckEquals(True,localObj.find(il[i] as ISDODataObject,j));
+    Check(j >= 0);
+    Check(j < NBR_INST);
+  end;
+end;
+
+procedure TSDOChangedDataObjectList_Test.size();
+var
+  localObj : ISDOChangedDataObjectListEx;
+  fact : ISDODataFactory;
+  il : IInterfaceList;
+begin
+  fact := CreateFactory();
+  localObj := CreateObject();
+
+  CheckEquals(0,localObj.size());
+  CheckEquals(0,localObj.size());
+
+  il := TInterfaceList.Create();
+  il.Add(fact.createNew(s_uri,s_type_object_A));
+  localObj.append(il[il.Count - 1] as ISDODataObject,ctDelete);
+    CheckEquals(1,localObj.size());
+  il.Add(fact.createNew(s_uri,s_type_object_A));
+  localObj.append(il[il.Count - 1] as ISDODataObject,ctCreate);
+    CheckEquals(2,localObj.size());
+  il.Add(fact.createNew(s_uri,s_type_object_A));
+  localObj.append(il[il.Count - 1] as ISDODataObject,ctChange);
+    CheckEquals(3,localObj.size());
+end;
+
+{ TChangeRecorder_Test }
+
+procedure TChangeRecorder_Test.bool_change();
+const
+  LOCAL_PROP = s_bool_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_bool(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setBoolean(LOCAL_PROP,False);
+    record_bool(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setBoolean(LOCAL_PROP,True);
+    record_bool(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_bool(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setBoolean(LOCAL_PROP,False);
+    record_bool(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_bool(locObj,LOCAL_PROP);
+end;
+
+procedure TChangeRecorder_Test.byte_change();
+const
+  LOCAL_PROP = s_byte_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_byte(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setByte(LOCAL_PROP,123);
+    record_byte(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setByte(LOCAL_PROP,76);
+    record_byte(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_byte(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setByte(LOCAL_PROP,123);
+    record_byte(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_byte(locObj,LOCAL_PROP);
+end;
+
+procedure TChangeRecorder_Test.CheckEquals(expected, actual: TSDODate;
+  msg: string; const AStrict: Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+function TChangeRecorder_Test.CreateRecorder() : TChangeRecorder;
+var
+  ls : ISDOChangedDataObjectList;
+begin
+  ls := TSDOChangedDataObjectList.Create();
+  FChangeSummary := TSDOChangeSummary.Create(ls);
+  Result := TChangeRecorder.Create(ls, FChangeSummary);
+end;
+
+function IndexOf(const AObject : ISDODataObject; const AList : ISDOChangedDataObjectList) : PtrInt;
+var
+  i : PtrInt;
+begin
+  Result := -1;
+  for i := 0 to Pred(AList.size()) do begin
+    if ( AList.getDataObject(i) = AObject ) then begin
+      Result := i;
+      Break;
+    end;
+  end;
+end;
+
+class function TChangeRecorder_Test.Create_Factory() : ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locFactory.AddType(AUri,s_type_object_B,[]);
+    locFactory.AddType(AUri,s_type_object_C,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_object_prop,AUri,s_type_object_B,[pfIsContainment]);
+        locFactory.addProperty(locObj,s_object_ref_prop,AUri,s_type_object_C,[]);
+  end;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+
+  Result := locFactory;
+end;
+
+procedure TChangeRecorder_Test.date_change();
+const
+  LOCAL_PROP = s_date_prop;
+  VAL_1 : TSDODate = ( Date : 39000; HourOffset : 1; MinuteOffset : 2; );
+  VAL_2 : TSDODate = ( Date : 45678; HourOffset : 9; MinuteOffset : 10; );
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_date(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDate(LOCAL_PROP,VAL_1);
+    record_date(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDate(LOCAL_PROP,VAL_2);
+    record_date(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_date(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDate(LOCAL_PROP,VAL_1);
+    record_date(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_date(locObj,LOCAL_PROP);
+end;
+
+procedure TChangeRecorder_Test.InitRecorder();
+begin
+  FreeAndNil(FRecorder);
+  FChangeSummary := nil;
+  FRecorder := CreateRecorder();
+end;
+
+procedure TChangeRecorder_Test.int_change();
+const
+  LOCAL_PROP = s_integer_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_int(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setInteger(LOCAL_PROP,1210);
+    record_int(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setInteger(LOCAL_PROP,-76);
+    record_int(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_int(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setInteger(LOCAL_PROP,1210);
+    record_int(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_int(locObj,LOCAL_PROP);
+end;
+
+procedure TChangeRecorder_Test.multi_call_boolean();
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(s_bool_prop);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setBoolean(locProp,False);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.multi_call_byte();
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(s_byte_prop);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setByte(locProp,78);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.multi_call_date();
+const
+  VAL_1 : TSDODate = ( Date : 39000; HourOffset : 1; MinuteOffset : 2; );
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(s_date_prop);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setDate(locProp,VAL_1);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.multi_call_int();
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(s_integer_prop);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setInteger(locProp,1210);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.multi_call_string();
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(s_string_prop);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setString(locProp,'qwerty#azerty');
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TChangeRecorder_Test.record_char(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOChar;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getCharacter(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getCharacter(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getCharacter(locProp), locSetting.getCharacterValue());
+end;
+
+procedure TChangeRecorder_Test.multi_call_char();
+const
+  LOCAL_PROP = s_char_prop;
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(LOCAL_PROP);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setCharacter(locProp,TSDOChar(78));
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.char_change();
+const
+  LOCAL_PROP = s_char_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_char(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setCharacter(LOCAL_PROP,TSDOChar(123));
+    record_char(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setCharacter(LOCAL_PROP,TSDOChar(76));
+    record_char(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_char(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setCharacter(LOCAL_PROP,TSDOChar(123));
+    record_char(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_char(locObj,LOCAL_PROP);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TChangeRecorder_Test.record_bytes(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOBytes;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getBytes(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getBytes(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getBytes(locProp), locSetting.getBytesValue());
+end;
+
+procedure TChangeRecorder_Test.multi_call_bytes();
+const
+  LOCAL_PROP = s_bytes_prop;
+var
+  VAL_1 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(TSDOByte);
+    VAL_1 := v;
+  end;  
+  
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  SetConstants();
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(LOCAL_PROP);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setBytes(locProp,VAL_1);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.bytes_change();
+const
+  LOCAL_PROP = s_bytes_prop;
+var
+  VAL_1, VAL_2, VAL_3 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(TSDOByte);
+    VAL_1 := v;
+    v := nil;    
+
+    VAL_2 := nil;
+
+    SetLength(v,20);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(TSDOByte);
+    VAL_3 := v; 
+  end;
+  
+var
+  locObj : ISDODataObject;
+begin
+  SetConstants();
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_bytes(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setBytes(LOCAL_PROP,VAL_1);
+    record_bytes(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setBytes(LOCAL_PROP,VAL_2);
+    record_bytes(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_bytes(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setBytes(LOCAL_PROP,VAL_3);
+    record_bytes(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_bytes(locObj,LOCAL_PROP);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TChangeRecorder_Test.record_currency(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOCurrency;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getCurrency(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getCurrency(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getCurrency(locProp), locSetting.getCurrencyValue());
+end;
+
+procedure TChangeRecorder_Test.multi_call_currency();
+const
+  LOCAL_PROP = s_currency_prop;
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(LOCAL_PROP);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setCurrency(locProp,7886556852);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.currency_change();
+const
+  LOCAL_PROP = s_currency_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_currency(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setCurrency(LOCAL_PROP,123963258741);
+    record_currency(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setCurrency(LOCAL_PROP,7614785236654);
+    record_currency(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_currency(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setCurrency(LOCAL_PROP,123321652);
+    record_currency(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_currency(locObj,LOCAL_PROP);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TChangeRecorder_Test.record_double(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDODouble;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getDouble(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getDouble(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getDouble(locProp), locSetting.getDoubleValue());
+end;
+
+procedure TChangeRecorder_Test.multi_call_double();
+const
+  LOCAL_PROP = s_double_prop;
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(LOCAL_PROP);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setDouble(locProp,7886556852);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.double_change();
+const
+  LOCAL_PROP = s_double_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_double(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDouble(LOCAL_PROP,123963258741);
+    record_double(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDouble(LOCAL_PROP,7614785236654);
+    record_double(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_double(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDouble(LOCAL_PROP,123321652);
+    record_double(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_double(locObj,LOCAL_PROP);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TChangeRecorder_Test.record_float(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOFloat;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getFloat(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getFloat(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getFloat(locProp), locSetting.getFloatValue());
+end;
+
+procedure TChangeRecorder_Test.multi_call_float();
+const
+  LOCAL_PROP = s_float_prop;
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(LOCAL_PROP);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setFloat(locProp,7886556852);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.float_change();
+const
+  LOCAL_PROP = s_float_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_float(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setFloat(LOCAL_PROP,123963258741);
+    record_float(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setFloat(LOCAL_PROP,7614785236654);
+    record_float(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_float(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setFloat(LOCAL_PROP,123321652);
+    record_float(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_float(locObj,LOCAL_PROP);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TChangeRecorder_Test.record_long(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOLong;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getLong(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getLong(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getLong(locProp), locSetting.getLongValue());
+end;
+
+procedure TChangeRecorder_Test.multi_call_long();
+const
+  LOCAL_PROP = s_long_prop;
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(LOCAL_PROP);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setLong(locProp,TSDOLong(78865235820256852));
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.long_change();
+const
+  LOCAL_PROP = s_long_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_long(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setLong(LOCAL_PROP,TSDOLong(123963258741));
+    record_long(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setLong(LOCAL_PROP,TSDOLong(761478523699123654));
+    record_long(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_long(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setLong(LOCAL_PROP,TSDOLong(1233216549874741225));
+    record_long(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_long(locObj,LOCAL_PROP);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TChangeRecorder_Test.record_short(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOShort;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getShort(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getShort(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getShort(locProp), locSetting.getShortValue());
+end;
+
+procedure TChangeRecorder_Test.multi_call_short();
+const
+  LOCAL_PROP = s_short_prop;
+var
+  locObj : ISDODataObject;
+  locProp : ISDOProperty;
+  locChangeInfo : TDataObjectChangeInfo;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locProp := locObj.getProperty(LOCAL_PROP);
+
+  FRecorder.recordChange(locObj,locProp);
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  locObj.setShort(locProp,TSDOShort(7882));
+  i := IndexOf(locObj,FRecorder.Store);
+  Check( ( i >= 0 ) );
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+
+  FRecorder.recordChange(locObj,locProp);
+  FRecorder.recordChange(locObj,locProp);
+  CheckEquals(1,locChangeInfo.ChangeList.size());
+end;
+
+procedure TChangeRecorder_Test.short_change();
+const
+  LOCAL_PROP = s_short_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_short(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setShort(LOCAL_PROP,TSDOShort(1239));
+    record_short(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setShort(LOCAL_PROP,TSDOShort(-7614));
+    record_short(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_short(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setShort(LOCAL_PROP,TSDOShort(1225));
+    record_short(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_short(locObj,LOCAL_PROP);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TChangeRecorder_Test.object_change_contained_prop();
+const
+  LOCAL_PROP = s_object_prop;
+  LOCAL_PROP_CLASS = s_type_object_B;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDataObject(LOCAL_PROP,FFactory.createNew(s_uri,LOCAL_PROP_CLASS));
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDataObject(LOCAL_PROP,nil);
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDataObject(LOCAL_PROP,FFactory.createNew(s_uri,LOCAL_PROP_CLASS));
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_obj(locObj,LOCAL_PROP);
+end;
+
+procedure TChangeRecorder_Test.object_change_referenced_prop();
+const
+  LOCAL_PROP = s_object_ref_prop;
+  LOCAL_PROP_CLASS = s_type_object_C;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDataObject(LOCAL_PROP,FFactory.createNew(s_uri,LOCAL_PROP_CLASS));
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDataObject(LOCAL_PROP,nil);
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setDataObject(LOCAL_PROP,FFactory.createNew(s_uri,LOCAL_PROP_CLASS));
+    record_obj(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_obj(locObj,LOCAL_PROP);
+end;
+
+procedure TChangeRecorder_Test.record_bool(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOBoolean;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getBoolean(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getBoolean(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getBoolean(locProp), locSetting.getBooleanValue());
+end;
+
+procedure TChangeRecorder_Test.record_byte(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOByte;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getByte(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getByte(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getByte(locProp), locSetting.getByteValue());
+end;
+
+procedure TChangeRecorder_Test.record_date(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDODateTime;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getDate(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getDate(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getDate(locProp), locSetting.getDateValue());
+end;
+
+procedure TChangeRecorder_Test.record_int(
+  const ADataObject : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOInteger;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getInteger(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getInteger(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getInteger(locProp), locSetting.getIntegerValue());
+end;
+
+procedure TChangeRecorder_Test.record_list_int(   
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+{var
+  locProp : ISDOProperty;
+  locValueList : ISDODataObjectList;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;}
+begin
+  {locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+  CheckEquals(True, locProp.isMany());
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getInteger(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getInteger(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getInteger(locProp), locSetting.getIntegerValue());}
+end;
+
+procedure TChangeRecorder_Test.record_obj(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : ISDODataObject;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getDataObject(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(PtrUInt(locValue),PtrUInt(ADataObject.getDataObject(APropName)), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(PtrUInt(ADataObject.getDataObject(locProp)), PtrUInt(locSetting.getDataObjectValue()));
+end;
+
+procedure TChangeRecorder_Test.record_string(
+  const ADataObject: ISDODataObject;
+  const APropName: string
+);
+var
+  locProp : ISDOProperty;
+  locValue : TSDOString;
+  locSetting : TValueSetting;
+  i : PtrInt;
+  locListX : ISDOChangedDataObjectListEx;
+  locChangeInfo : TDataObjectChangeInfo;
+begin
+  locProp := ADataObject.getProperty(APropName);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locProp),Format('Invalid property : "%s"',[APropName]));
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  CheckEquals(-1,i);
+
+  locValue := ADataObject.getString(APropName);
+  FRecorder.recordChange(ADataObject,locProp);
+  CheckEquals(locValue,ADataObject.getString(APropName), 'The change recorder should not modify the object.');
+
+  i := IndexOf(ADataObject,FRecorder.Store);
+  Check( ( i >= 0 ) );
+
+  locListX := FRecorder.Store as ISDOChangedDataObjectListEx;
+  locChangeInfo := locListX.getInfo(i);
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo));
+  CheckEquals(PtrUInt(ADataObject), PtrUInt(locChangeInfo.DataObject));
+  CheckEquals(Ord(ctChange), Ord(locChangeInfo.ChangeType));
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locChangeInfo.ChangeList));
+
+  CheckEquals(1, locChangeInfo.ChangeList.size());
+  locSetting := locChangeInfo.ChangeList.getItem(0);
+  CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+  CheckEquals(ADataObject.isNull(locProp), locSetting.isNull());
+  CheckEquals(ADataObject.isSet(locProp), locSetting.isSet());
+  CheckEquals(ADataObject.getString(locProp), locSetting.getStringValue());
+end;
+
+procedure TChangeRecorder_Test.SetUp();
+begin
+  inherited;
+  FRecorder := CreateRecorder();
+  FFactory := Create_Factory();
+end;
+
+procedure TChangeRecorder_Test.string_change();
+const
+  LOCAL_PROP = s_string_prop;
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+
+  record_string(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setString(LOCAL_PROP,RandomString(RandomRange(0,1000)));
+    record_string(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setString(LOCAL_PROP,'');
+    record_string(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setNull(LOCAL_PROP);
+    record_string(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.setString(LOCAL_PROP,RandomString(RandomRange(0,1000)));
+    record_string(locObj,LOCAL_PROP);
+
+  InitRecorder();
+  locObj.unset(LOCAL_PROP);
+    record_string(locObj,LOCAL_PROP);
+end;
+
+procedure TChangeRecorder_Test.TearDown();
+begin
+  FFactory := nil;
+  FreeAndNil(FRecorder);
+  inherited;
+end;
+
+{ TSDOChangeSummary_Test }
+
+class function TSDOChangeSummary_Test.Create_Factory() : ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[]);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+
+  Result := locFactory;
+end;
+
+function TSDOChangeSummary_Test.CreateRecorder(): TChangeRecorder;
+var
+  ls : ISDOChangedDataObjectList;
+begin
+  ls := TSDOChangedDataObjectList.Create();
+  FChangeSummary := TSDOChangeSummary.Create(ls);
+  Result := TChangeRecorder.Create(ls, FChangeSummary);
+end;
+
+procedure TSDOChangeSummary_Test.InitRecorder();
+begin
+  FChangeSummary := nil;
+  FreeAndNil(FRecorder);
+  FRecorder := CreateRecorder();
+  //FChangeSummary := TSDOChangeSummary.Create(FRecorder.Store);
+end;
+
+procedure TSDOChangeSummary_Test.SetUp();
+begin
+  inherited;
+  FRecorder := CreateRecorder();
+  FFactory := Create_Factory();
+  FFactoryX := Create_FactoryX();
+  InitRecorder();
+end;
+
+procedure TSDOChangeSummary_Test.TearDown();
+begin
+  FChangeSummary := nil;
+  FreeAndNil(FRecorder);
+  FFactoryX := nil;
+  FFactory := nil;
+  inherited;
+end;
+
+procedure TSDOChangeSummary_Test.logging_state();
+begin
+  CheckEquals(False,FChangeSummary.isLogging(),'By default, the logging should b OFF');
+
+  FChangeSummary.endLogging();
+    CheckEquals(False,FChangeSummary.isLogging());
+  FChangeSummary.endLogging();
+    FChangeSummary.endLogging();
+    CheckEquals(False,FChangeSummary.isLogging());
+
+  FChangeSummary.beginLogging();
+    CheckEquals(True,FChangeSummary.isLogging());
+  FChangeSummary.beginLogging();
+  FChangeSummary.beginLogging();
+    CheckEquals(True,FChangeSummary.isLogging());
+
+  FChangeSummary.endLogging();
+    CheckEquals(False,FChangeSummary.isLogging());
+
+  FChangeSummary.beginLogging();
+    CheckEquals(True,FChangeSummary.isLogging());
+end;
+
+procedure TSDOChangeSummary_Test.isCreated();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(False,FChangeSummary.isCreated(nil));
+  CheckEquals(False,FChangeSummary.isCreated(locObj));
+  FRecorder.recordCreation(locObj);
+    CheckEquals(True,FChangeSummary.isCreated(locObj));
+
+  //-------------------------
+  InitRecorder();
+  FChangeSummary.beginLogging();
+  CheckEquals(False,FChangeSummary.isCreated(locObj));
+  FRecorder.recordChange(locObj,locObj.getProperty(s_integer_prop));
+    CheckEquals(False,FChangeSummary.isCreated(locObj));
+
+  //-------------------------
+  InitRecorder();
+  FChangeSummary.beginLogging();
+  CheckEquals(False,FChangeSummary.isCreated(locObj));
+  FRecorder.recordDeletion(locObj);
+    CheckEquals(False,FChangeSummary.isCreated(locObj));
+end;
+
+procedure TSDOChangeSummary_Test.isModified();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(False,FChangeSummary.isModified(nil));
+  CheckEquals(False,FChangeSummary.isModified(locObj));
+  FRecorder.recordChange(locObj,locObj.getProperty(s_integer_prop));
+    CheckEquals(True,FChangeSummary.isModified(locObj));
+
+  //-------------------------
+  InitRecorder();
+  FChangeSummary.beginLogging();
+  CheckEquals(False,FChangeSummary.isModified(locObj));
+  FRecorder.recordCreation(locObj);
+    CheckEquals(False,FChangeSummary.isModified(locObj));
+
+  //-------------------------
+  InitRecorder();
+  FChangeSummary.beginLogging();
+  CheckEquals(False,FChangeSummary.isModified(locObj));
+  FRecorder.recordDeletion(locObj);
+    CheckEquals(False,FChangeSummary.isModified(locObj));
+end;
+
+procedure TSDOChangeSummary_Test.isDeleted();
+var
+  locObj : ISDODataObject;
+  ls : ISDOChangedDataObjectList;
+  i, c, locFoundIdx : PtrInt;
+  locFound : Boolean;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.setInteger(s_integer_prop,RandomRange(-1210,1210));
+  locObj.getList(s_integer_propList).append(RandomRange(-1210,1210));
+  locObj.getList(s_integer_propList).append(RandomRange(-1210,1210));
+  locObj.setString(s_string_prop,RandomString(1000));
+  locObj.getList(s_string_propList).append(RandomString(1210));
+  locObj.getList(s_string_propList).append(RandomString(1210));
+
+  FChangeSummary.beginLogging();
+    CheckEquals(False,FChangeSummary.isDeleted(nil));
+    CheckEquals(False,FChangeSummary.isDeleted(locObj));
+    FRecorder.recordDeletion(locObj);
+      CheckEquals(True,FChangeSummary.isDeleted(locObj));
+      ls := FChangeSummary.getChangedDataObjects();
+      Check( ls.size() >  0 );
+      c := ls.size();
+      locFoundIdx := -1;
+      locFound := False;
+      for i := 0 to Pred(c) do begin
+        if ( ls.getType(i) = ctDelete ) and ( locObj = ls.getDataObject(i) ) then begin
+          locFoundIdx := i;
+          locFound := True;
+          Break;
+        end;
+      end;
+      CheckEquals(True,locFound);
+      if ( locFoundIdx < Pred(c) ) then begin
+        locFound := False;
+        for i := Succ(locFoundIdx) to Pred(c) do begin
+          if ( ls.getType(i) = ctDelete ) and ( locObj = ls.getDataObject(i) ) then begin
+            locFound := True;
+            Break;
+          end;
+        end;
+        CheckEquals(False, locFound, 'There should be _only one copy_ of the deleted object.');
+      end;
+end;
+
+procedure TSDOChangeSummary_Test.getChangedDataObjects();
+const LOCAL_PROP = s_integer_prop;
+var
+  ls : ISDOChangedDataObjectList;
+  vobj : array of ISDODataObject;
+  vct  : array of TChangeType;
+  l, i, j : PtrInt;
+  locProp : ISDOProperty;
+begin
+  ls := FChangeSummary.getChangedDataObjects();
+  CheckNotEquals(PtrUInt(nil),PtrUInt(ls));
+  CheckEquals(0,ls.size());
+
+  l := RandomRange(0,1000);
+  if ( l > 0 ) then begin
+    SetLength(vobj,l);
+    try
+      SetLength(vct,l);
+      for i := 0 to Pred(l) do begin
+        vobj[i] := FFactory.createNew(s_uri,s_type_object_A);
+        vobj[i].setInteger(s_integer_prop,i + 1);
+        vct[i] := TChangeType(RandomRange(Ord(ctCreate),Ord(ctDelete)));
+      end;
+      locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP);
+      for i := 0 to Pred(l) do begin
+        case vct[i] of
+          ctCreate   : FRecorder.recordCreation(vobj[i]);
+          ctChange   : FRecorder.recordChange(vobj[i],vobj[i].getProperty(s_integer_prop));
+          ctDelete   : FRecorder.recordDeletion(vobj[i]);
+        end;
+      end;
+
+      ls := FChangeSummary.getChangedDataObjects();
+      CheckEquals(l,ls.size());
+      for i := 0 to Pred(l) do begin
+        j := IndexOf(vobj[i],ls);
+        Check( ( j >= 0 ) );
+        CheckEquals(Ord(vct[i]), Ord(ls.getType(j)));
+      end;
+    finally
+      SetLength(vct,0);
+      SetLength(vobj,0);
+    end;
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues();
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locPropInt, locPropString : ISDOProperty;
+begin
+  locPropInt := FFactory.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactory.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setInteger(locPropInt,1210);
+  FRecorder.recordChange(locObjA,locPropInt);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setInteger(locPropInt,1210);
+  FRecorder.recordChange(locObjB,locPropInt);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+
+  locObjA.setString(locPropString,RandomString(1000));
+  FRecorder.recordChange(locObjA,locPropString);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(2,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+
+  locObjB.setString(locPropString,RandomString(1000));
+  FRecorder.recordChange(locObjB,locPropString);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(2,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(2,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue();
+var
+  locObjA, locObjB : ISDODataObject;
+  locPropInt, locPropString : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locPropInt := FFactory.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactory.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locPropInt)));
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locPropString)));
+
+  locObjA.setInteger(locPropInt,1210);
+  FRecorder.recordChange(locObjA,locPropInt);
+    locSetting := FChangeSummary.getOldValue(locObjA,locPropInt);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locPropInt), PtrUInt(locSetting.getProperty()));
+    CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locPropString)));
+
+  locObjB.setInteger(locPropInt,1210);
+  FRecorder.recordChange(locObjB,locPropInt);
+    locSetting := FChangeSummary.getOldValue(locObjB,locPropInt);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locPropInt), PtrUInt(locSetting.getProperty()));
+    CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjB,locPropString)));
+
+
+  locObjA.setString(locPropString,RandomString(1000));
+  FRecorder.recordChange(locObjA,locPropString);
+    locSetting := FChangeSummary.getOldValue(locObjA,locPropInt);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropInt), PtrUInt(locSetting.getProperty()));
+    locSetting := FChangeSummary.getOldValue(locObjA,locPropString);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropString), PtrUInt(locSetting.getProperty()));
+
+
+  locObjB.setString(locPropString,RandomString(1000));
+  FRecorder.recordChange(locObjB,locPropString);
+    locSetting := FChangeSummary.getOldValue(locObjB,locPropInt);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropInt), PtrUInt(locSetting.getProperty()));
+    locSetting := FChangeSummary.getOldValue(locObjB,locPropString);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropString), PtrUInt(locSetting.getProperty()));
+end;
+
+type TAccesMode = ( amShallow, amDeep );
+function find(
+  const ADataObject : ISDODataObject;
+  const AList : ISDOChangedDataObjectList;
+  const ACompareMode : TAccesMode
+) : Integer;
+var
+  i, c : PtrInt;
+begin
+  Result := -1;
+  c := AList.size();
+  if ( c > 0 ) then begin
+    if ( ACompareMode = amShallow ) then begin
+      for i := 0 to Pred(c) do begin
+        if TSDOEqualityHelper.equalShallow(ADataObject,AList.getDataObject(i)) then begin
+          Result := i;
+          Break;
+        end;
+      end;
+    end else begin
+      for i := 0 to Pred(c) do begin
+        if TSDOEqualityHelper.equal(ADataObject,AList.getDataObject(i)) then begin
+          Result := i;
+          Break;
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.getOldContainer();
+var
+  locA, locB, locB1, locC : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locCS := locA.getChangeSummary();
+    locCS.beginLogging();
+  locB := FFactoryX.createNew(s_uri,s_type_object_B);
+  locB1 := FFactoryX.createNew(s_uri,s_type_object_B);
+  locC := FFactoryX.createNew(s_uri,s_type_object_C);
+
+  CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locA)));
+  CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locB)));
+  CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locC)));
+
+  locA.setDataObject(s_object_prop,locB);
+    CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locA)));
+    CheckEquals(PtrUInt(locA), PtrUInt(locCS.getOldContainer(locB)));
+    CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locC)));
+
+  locA.setDataObject(s_object_prop,locB1);
+    CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locA)));
+    CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locB)), '"locB" should no longer be referenced by the ChangeSummary at this stade( create + delete = 0 ).');
+    CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locC)));
+
+    locB1.setDataObject(s_object_prop,locC);
+      CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locA)));
+      CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locB)), '"locB" should no longer be referenced by the ChangeSummary at this stade( create + delete = 0 ).');
+      CheckEquals(PtrUInt(locB1), PtrUInt(locCS.getOldContainer(locC)));
+    locB1.setDataObject(s_object_prop,nil);
+      CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locA)));
+      CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locB)), '"locB" should no longer be referenced by the ChangeSummary at this stade( create + delete = 0 ).');
+      CheckEquals(PtrUInt(nil), PtrUInt(locCS.getOldContainer(locC)), '"locC" should no longer be referenced by the ChangeSummary at this stade( create + delete = 0 ).');
+
+end;
+
+procedure TSDOChangeSummary_Test.getOldContainmentProperty();
+
+  procedure Check_dont_have_old_prop(const ADataObject : ISDODataObject; const ACS : ISDOChangeSummary);
+  var
+    ok : Boolean;
+  begin
+    ok := False;
+    try
+      ACS.getOldContainmentProperty(ADataObject);
+    except
+      on e : ESDOInvalidStateOperationException do
+        ok := True;
+    end;
+    Check(ok, 'this object should not have a Old Containment Property.');
+  end;
+
+var
+  locA, locB, locB1, locC : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locCS := locA.getChangeSummary();
+    locCS.beginLogging();
+  locB := FFactoryX.createNew(s_uri,s_type_object_B);
+  locB1 := FFactoryX.createNew(s_uri,s_type_object_B);
+  locC := FFactoryX.createNew(s_uri,s_type_object_C);
+
+  Check_dont_have_old_prop(locA,locCS);
+  Check_dont_have_old_prop(locB,locCS);
+  Check_dont_have_old_prop(locC,locCS);
+
+  locA.setDataObject(s_object_prop,locB);
+    Check_dont_have_old_prop(locA,locCS);
+    Check_dont_have_old_prop(locC,locCS);
+
+  locA.setDataObject(s_object_prop,locB1);
+    Check_dont_have_old_prop(locA,locCS);
+    Check_dont_have_old_prop(locB,locCS);
+    Check_dont_have_old_prop(locC,locCS);
+
+    locB1.setDataObject(s_object_prop,locC);
+      Check_dont_have_old_prop(locA,locCS);
+      Check_dont_have_old_prop(locB,locCS);
+    locB1.setDataObject(s_object_prop,nil);
+      Check_dont_have_old_prop(locA,locCS);
+      Check_dont_have_old_prop(locB,locCS);
+      Check_dont_have_old_prop(locC,locCS);
+end;
+
+class function TSDOChangeSummary_Test.Create_FactoryX(): ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_Objects(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_C,[]);
+    locObj := locFactory.getType(AUri,s_type_object_C);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+
+    locFactory.AddType(AUri,s_type_object_B,[]);
+    locObj := locFactory.getType(AUri,s_type_object_B);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locFactory.addProperty(locObj,s_object_prop,s_uri,s_type_object_C,[pfIsContainment]);
+
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], [pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], [pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_object_prop,s_uri,s_type_object_B,[pfIsContainment]);
+      locFactory.addProperty(locObj,s_object_ref_prop,s_uri,s_type_object_B,[]);
+      locFactory.addProperty(locObj,s_changesummary_prop,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  end;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_Objects(s_uri);
+
+  Result := locFactory;
+end;
+
+procedure TSDOChangeSummary_Test.isDeleted_nested();
+  procedure Check_DeletedObject(const AObj : ISDODataObject; const AList : ISDOChangedDataObjectList);
+  var
+    i, c, locFoundIdx : PtrInt;
+    locFound : Boolean;
+  begin
+    Check( AList.size() >  0 );
+    c := AList.size();
+    locFoundIdx := -1;
+    locFound := False;
+    for i := 0 to Pred(c) do begin
+      if ( AList.getType(i) = ctDelete ) and ( AObj = AList.getDataObject(i) ) then begin
+        locFoundIdx := i;
+        locFound := True;
+        Break;
+      end;
+    end;
+    CheckEquals(True,locFound);
+    if ( locFoundIdx < Pred(c) ) then begin
+      locFound := False;
+      for i := Succ(locFoundIdx) to Pred(c) do begin
+        if ( AList.getType(i) = ctDelete ) and ( AObj = AList.getDataObject(i) ) then begin
+          locFound := True;
+          Break;
+        end;
+      end;
+      CheckEquals(False, locFound, 'There should be _only one copy_ of the deleted object.');
+    end;
+  end;
+
+
+var
+  locA, locB, locC : ISDODataObject;
+  ls : ISDOChangedDataObjectList;
+begin
+  locC := FFactoryX.createNew(s_uri,s_type_object_C);
+    locC.setInteger(s_integer_prop,RandomRange(-12345,12456));
+    locC.setString(s_string_prop,RandomString(1000));
+  locB := FFactoryX.createNew(s_uri,s_type_object_B);
+    locB.setInteger(s_integer_prop,RandomRange(-12345,12456));
+    locB.setString(s_string_prop,RandomString(1000));
+    locB.setDataObject(s_object_prop,locC);
+  locA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locA.setInteger(s_integer_prop,RandomRange(-1210,1210));
+    locA.getList(s_integer_propList).append(RandomRange(-1210,1210));
+    locA.getList(s_integer_propList).append(RandomRange(-1210,1210));
+    locA.setString(s_string_prop,RandomString(1000));
+    locA.getList(s_string_propList).append(RandomString(1210));
+    locA.getList(s_string_propList).append(RandomString(1210));
+    locA.setDataObject(s_object_prop,locB);
+
+  FChangeSummary.beginLogging();
+
+    CheckEquals(False,FChangeSummary.isDeleted(locA));
+    CheckEquals(False,FChangeSummary.isDeleted(locB));
+    CheckEquals(False,FChangeSummary.isDeleted(locC));
+
+    FRecorder.recordDeletion(locB);
+      ls := FChangeSummary.getChangedDataObjects();
+      Check_DeletedObject(locB,ls);
+
+    FRecorder.recordDeletion(locA);
+      CheckEquals(True,FChangeSummary.isDeleted(locA));
+      CheckEquals(True,FChangeSummary.isDeleted(locB));
+      CheckEquals(True,FChangeSummary.isDeleted(locC));
+      ls := FChangeSummary.getChangedDataObjects();
+      Check_DeletedObject(locA,ls);
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple();
+var
+  locObjA : ISDODataObject;
+  locPropBool, locPropInt, locPropString : ISDOProperty;
+  locSettingBool, locSettingInt, locSettingString : TValueSetting;
+  ibuffer : TSDOInteger;
+  sbuffer : TSDOString;
+  bbuffer : TSDOBoolean;
+  locCS : ISDOChangeSummary;
+begin
+  locPropBool := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_bool_prop);
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+    locObjA.setString(locPropString,RandomString(1000));
+    locSettingBool := nil;
+    locSettingInt := nil;
+    locSettingString := nil;
+  try
+    bbuffer := locObjA.getBoolean(locPropBool);
+      locSettingBool := TValueSetting.Create(locObjA.isSet(locPropBool),locObjA.isNull(locPropBool),bbuffer,locPropBool,0);
+    ibuffer := locObjA.getInteger(locPropInt);
+      locSettingInt := TValueSetting.Create(locObjA.isSet(locPropInt),locObjA.isNull(locPropInt),ibuffer,locPropInt,0);
+    sbuffer := locObjA.getString(locPropString);
+      locSettingString := TValueSetting.Create(locObjA.isSet(locPropString),locObjA.isNull(locPropString),sbuffer,locPropString,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+        locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+        locObjA.setString(locPropString,RandomString(1000));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locPropBool,locSettingBool);
+        check_value(locObjA,locPropInt,locSettingInt);
+        check_value(locObjA,locPropString,locSettingString);
+
+    FreeAndNil(locSettingBool);
+    FreeAndNil(locSettingInt);
+    FreeAndNil(locSettingString);
+    bbuffer := locObjA.getBoolean(locPropBool);
+      locSettingBool := TValueSetting.Create(locObjA.isSet(locPropBool),locObjA.isNull(locPropBool),bbuffer,locPropBool,0);
+    ibuffer := locObjA.getInteger(locPropInt);
+      locSettingInt := TValueSetting.Create(locObjA.isSet(locPropInt),locObjA.isNull(locPropInt),ibuffer,locPropInt,0);
+    sbuffer := locObjA.getString(locPropString);
+      locSettingString := TValueSetting.Create(locObjA.isSet(locPropString),locObjA.isNull(locPropString),sbuffer,locPropString,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+          locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+        locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+          locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+        locObjA.setString(locPropString,RandomString(1000));
+          locObjA.setString(locPropString,RandomString(1000));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locPropBool,locSettingBool);
+        check_value(locObjA,locPropInt,locSettingInt);
+        check_value(locObjA,locPropString,locSettingString);
+  finally
+    FreeAndNil(locSettingBool);
+    FreeAndNil(locSettingInt);
+    FreeAndNil(locSettingString);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_object_contained_startWith_OBJ_OBJ();
+var
+  locObjA, locB, locBB, locA1, locB1 : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(s_bool_prop,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+    locObjA.setByte(s_byte_prop,RandomRange(Low(TSDOByte),High(TSDOByte)));
+    locObjA.setInteger(s_integer_prop,RandomRange(-1210,1210));
+    locObjA.setString(s_string_prop,RandomString(1000));
+    locB := FFactoryX.createNew(s_uri,s_type_object_B);
+      locB.setBoolean(locB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+      locB.setByte(s_byte_prop,RandomRange(Low(TSDOByte),High(TSDOByte)));
+      locB.setInteger(locB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+      locB.setString(locB.getProperty(s_string_prop),RandomString(1210));
+    locObjA.setDataObject(s_object_prop,locB);
+  locBB := FFactoryX.createNew(s_uri,s_type_object_B);
+    locBB.setBoolean(locBB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+    locBB.setByte(s_byte_prop,RandomRange(Low(TSDOByte),High(TSDOByte)));
+    locBB.setInteger(locBB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+    locBB.setString(locBB.getProperty(s_string_prop),RandomString(1210));
+
+  locA1 := TSDOCopyHelper.copy(locObjA);
+  locB1 := TSDOCopyHelper.copy(locB);
+
+  locCS := locObjA.getChangeSummary();
+    locCS.beginLogging();
+      locObjA.setBoolean(s_bool_prop,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+      locObjA.setByte(s_byte_prop,RandomRange(Low(TSDOByte),High(TSDOByte)));
+      locObjA.setInteger(s_integer_prop,RandomRange(-1210,1210));
+      locObjA.setString(s_string_prop,RandomString(1000));
+        locB.setBoolean(locB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+        locB.setByte(s_byte_prop,RandomRange(Low(TSDOByte),High(TSDOByte)));
+        locB.setInteger(locB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+        locB.setString(locB.getProperty(s_string_prop),RandomString(1210));
+      locObjA.setDataObject(s_object_prop,locBB);
+    locCS.endLogging();
+    locCS.undoChanges();
+      CheckEquals(0,locCS.getChangedDataObjects().size());
+      Check(TSDOEqualityHelper.equal(locObjA,locA1));
+      Check(TSDOEqualityHelper.equal(locObjA.getDataObject(s_object_prop),locB1));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_object_contained_startWith_NIL_OBJ_OBJ();
+var
+  locObjA, locB, locBB, locA1, locB1 : ISDODataObject;
+  locPropBool, locPropInt, locPropString, locPropObj_propB : ISDOProperty;
+  locCS : ISDOChangeSummary;
+begin
+  locPropBool := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_bool_prop);
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locPropObj_propB := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+  locB := FFactoryX.createNew(s_uri,s_type_object_B);
+
+  locA1 := TSDOCopyHelper.copy(locObjA);
+  locB1 := TSDOCopyHelper.copy(locB);
+
+  locCS := locObjA.getChangeSummary();
+  locCS.beginLogging();
+      locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+      locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+      locObjA.setString(locPropString,RandomString(1000));
+
+        locB.setBoolean(locB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+        locB.setInteger(locB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+        locB.setString(locB.getProperty(s_string_prop),RandomString(1210));
+      locObjA.setDataObject(locPropObj_propB,locB);
+    locBB := locObjA.createDataObject(s_object_prop);
+      locBB.setBoolean(locBB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+      locBB.setInteger(locBB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+      locBB.setString(locBB.getProperty(s_string_prop),RandomString(1210));
+
+  locCS.endLogging();
+  locCS.undoChanges();
+      CheckEquals(0,locCS.getChangedDataObjects().size());
+      Check(TSDOEqualityHelper.equal(locObjA,locA1));
+      Check(TSDOEqualityHelper.equal(locObjA.getDataObject(locPropObj_propB),nil));
+end;
+
+procedure TSDOChangeSummary_Test.getOldXpath();
+var
+  locObjA, locB, locC, locBB : ISDODataObject;
+  locPropObj_propB : ISDOProperty;
+  locCS : ISDOChangeSummary;
+begin
+  locPropObj_propB := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+  locB := FFactoryX.createNew(s_uri,s_type_object_B);
+
+  locCS := locObjA.getChangeSummary();
+  locCS.beginLogging();
+    CheckEquals('',locCS.getOldXpath(locObjA));
+    CheckEquals('',locCS.getOldXpath(locB));
+    locObjA.setDataObject(locPropObj_propB,locB);
+      CheckEquals('',locCS.getOldXpath(locObjA));
+      CheckEquals('',locCS.getOldXpath(locB));
+      locBB := locObjA.createDataObject(locPropObj_propB);
+        CheckEquals('',locCS.getOldXpath(locObjA));
+        CheckEquals('',locCS.getOldXpath(locB));
+        CheckEquals('',locCS.getOldXpath(locBB));
+        locC := locBB.createDataObject(s_object_prop);
+          CheckEquals('',locCS.getOldXpath(locC));
+          locBB.setDataObject(s_object_prop,nil);
+          CheckEquals('',locCS.getOldXpath(locB));
+          CheckEquals('',locCS.getOldXpath(locC));
+end;
+
+procedure TSDOChangeSummary_Test.logging_state_2();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+    FRecorder.recordCreation(locObj);
+      Check(FChangeSummary.getChangedDataObjects().size() > 0);
+  FChangeSummary.endLogging();
+    Check(FChangeSummary.getChangedDataObjects().size() > 0);
+    FChangeSummary.beginLogging();
+      CheckEquals(0,FChangeSummary.getChangedDataObjects().size(), 'After beginLoggin->endLogging->begginLoggin the changes list must be empty');
+end;
+
+procedure TSDOChangeSummary_Test.check_value(
+  const AObj: ISDODataObject;
+  const AProp: ISDOProperty;
+  const AValue: TValueSetting
+);
+begin
+  CheckEquals(AValue.isSet(), AObj.isSet(AProp));
+  CheckEquals(AValue.isNull(), AObj.isNull(AProp));
+  if not AValue.isNull() then begin
+    case AProp.getTypeEnum() of
+      BooleanType  : CheckEquals(AValue.getBooleanValue(), AObj.getBoolean(AProp));
+      ByteType     : CheckEquals(AValue.getByteValue(), AObj.getByte(AProp));
+{$IFDEF HAS_SDO_BYTES}
+      BytesType    : CheckEquals(AValue.getBytesValue(), AObj.getBytes(AProp));
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType: CheckEquals(AValue.getCharacterValue(), AObj.getCharacter(AProp));
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      CurrencyType : CheckEquals(AValue.getCurrencyValue(), AObj.getCurrency(AProp));
+{$ENDIF HAS_SDO_CURRENCY}
+      DateTimeType : CheckEquals(AValue.getDateValue(), AObj.getDate(AProp));
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType   : CheckEquals(AValue.getDoubleValue(), AObj.getDouble(AProp));
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType    : CheckEquals(AValue.getFloatValue(), AObj.getFloat(AProp));
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType  : CheckEquals(AValue.getIntegerValue(), AObj.getInteger(AProp));
+{$IFDEF HAS_SDO_LONG}
+      LongType     : CheckEquals(AValue.getLongValue(), AObj.getLong(AProp));
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType    : CheckEquals(AValue.getShortValue(), AObj.getShort(AProp));
+{$ENDIF HAS_SDO_SHORT}
+      ObjectType   : Check(TSDOEqualityHelper.equal(AValue.getDataObjectValue(),AObj.getDataObject(AProp)));
+      StringType   : CheckEquals(AValue.getStringValue(), AObj.getString(AProp));
+      else
+        Assert(False,'NOT implemented.');
+    end;
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset();
+var
+  locObjA : ISDODataObject;
+  locPropBool, locPropInt, locPropString : ISDOProperty;
+  locSettingBool, locSettingInt, locSettingString : TValueSetting;
+  ibuffer : TSDOInteger;
+  sbuffer : TSDOString;
+  bbuffer : TSDOBoolean;
+  locCS : ISDOChangeSummary;
+begin
+  locPropBool := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_bool_prop);
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+    locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+    locObjA.setString(locPropString,RandomString(1000));
+    locSettingBool := nil;
+    locSettingInt := nil;
+    locSettingString := nil;
+  try
+    bbuffer := locObjA.getBoolean(locPropBool);
+      locSettingBool := TValueSetting.Create(locObjA.isSet(locPropBool),locObjA.isNull(locPropBool),bbuffer,locPropBool,0);
+    ibuffer := locObjA.getInteger(locPropInt);
+      locSettingInt := TValueSetting.Create(locObjA.isSet(locPropInt),locObjA.isNull(locPropInt),ibuffer,locPropInt,0);
+    sbuffer := locObjA.getString(locPropString);
+      locSettingString := TValueSetting.Create(locObjA.isSet(locPropString),locObjA.isNull(locPropString),sbuffer,locPropString,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locPropBool);
+        locObjA.unset(locPropInt);
+        locObjA.unset(locPropString);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locPropBool,locSettingBool);
+        check_value(locObjA,locPropInt,locSettingInt);
+        check_value(locObjA,locPropString,locSettingString);
+  finally
+    FreeAndNil(locSettingBool);
+    FreeAndNil(locSettingInt);
+    FreeAndNil(locSettingString);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull();
+var
+  locObjA : ISDODataObject;
+  locPropBool, locPropInt, locPropString : ISDOProperty;
+  locSettingBool, locSettingInt, locSettingString : TValueSetting;
+  ibuffer : TSDOInteger;
+  sbuffer : TSDOString;
+  bbuffer : TSDOBoolean;
+  locCS : ISDOChangeSummary;
+begin
+  locPropBool := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_bool_prop);
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+    locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+    locObjA.setString(locPropString,RandomString(1000));
+    locSettingBool := nil;
+    locSettingInt := nil;
+    locSettingString := nil;
+  try
+    bbuffer := locObjA.getBoolean(locPropBool);
+      locSettingBool := TValueSetting.Create(locObjA.isSet(locPropBool),locObjA.isNull(locPropBool),bbuffer,locPropBool,0);
+    ibuffer := locObjA.getInteger(locPropInt);
+      locSettingInt := TValueSetting.Create(locObjA.isSet(locPropInt),locObjA.isNull(locPropInt),ibuffer,locPropInt,0);
+    sbuffer := locObjA.getString(locPropString);
+      locSettingString := TValueSetting.Create(locObjA.isSet(locPropString),locObjA.isNull(locPropString),sbuffer,locPropString,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locPropBool);
+        locObjA.setNull(locPropInt);
+        locObjA.setNull(locPropString);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locPropBool,locSettingBool);
+        check_value(locObjA,locPropInt,locSettingInt);
+        check_value(locObjA,locPropString,locSettingString);
+  finally
+    FreeAndNil(locSettingBool);
+    FreeAndNil(locSettingInt);
+    FreeAndNil(locSettingString);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_object_prop();
+var
+  locObj1, locObj2 : ISDODataObject;
+  locPropCont, locPropRef : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locPropCont := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_prop);
+  locPropRef := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_ref_prop);
+  locObj1 := FFactoryX.createNew(s_uri,s_type_object_A);
+  locObj2 := FFactoryX.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObj1,locPropCont)));
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObj1,locPropRef)));
+
+  locObj1.setDataObject(locPropCont,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObj1,locPropCont);
+    locSetting := FChangeSummary.getOldValue(locObj1,locPropCont);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locPropCont), PtrUInt(locSetting.getProperty()));
+    CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObj1,locPropRef)));
+
+  locObj2.setDataObject(locPropCont,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObj2,locPropCont);
+    locSetting := FChangeSummary.getOldValue(locObj2,locPropCont);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locPropCont), PtrUInt(locSetting.getProperty()));
+    CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObj2,locPropRef)));
+
+  locObj1.setDataObject(locPropRef,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObj1,locPropRef);
+    locSetting := FChangeSummary.getOldValue(locObj1,locPropCont);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropCont), PtrUInt(locSetting.getProperty()));
+    locSetting := FChangeSummary.getOldValue(locObj1,locPropRef);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropRef), PtrUInt(locSetting.getProperty()));
+
+  locObj2.setDataObject(locPropRef,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObj2,locPropRef);
+    locSetting := FChangeSummary.getOldValue(locObj2,locPropCont);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropCont), PtrUInt(locSetting.getProperty()));
+    locSetting := FChangeSummary.getOldValue(locObj2,locPropRef);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+      CheckEquals(PtrUInt(locPropRef), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues_object_prop();
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locPropInt, locPropString, locPropObjCont, locPropObjRef : ISDOProperty;
+begin
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locPropObjCont := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_prop);
+  locPropObjRef := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_ref_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+  locObjB := FFactoryX.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setInteger(locPropInt,1210);
+  FRecorder.recordChange(locObjA,locPropInt);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setInteger(locPropInt,1210);
+  FRecorder.recordChange(locObjB,locPropInt);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+
+  locObjA.setString(locPropString,RandomString(1000));
+  FRecorder.recordChange(locObjA,locPropString);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(2,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+
+  locObjB.setString(locPropString,RandomString(1000));
+  FRecorder.recordChange(locObjB,locPropString);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(2,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(2,ls.size());
+
+  locObjA.setDataObject(locPropObjCont,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObjA,locPropObjCont);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(3,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(2,ls.size());
+
+  locObjB.setDataObject(locPropObjCont,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObjB,locPropObjCont);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(3,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(3,ls.size());
+
+  locObjA.setDataObject(locPropObjRef,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObjA,locPropObjRef);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(4,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(3,ls.size());
+
+  locObjB.setDataObject(locPropObjRef,FFactoryX.createNew(s_uri,s_type_object_B));
+  FRecorder.recordChange(locObjB,locPropObjRef);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(4,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(4,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_object_referenced_startWIth_OBJ_OBJ();
+var
+  locObjA, locB, locBB, locA1, locB1 : ISDODataObject;
+  locPropBool, locPropInt, locPropString, locPropObj_propB : ISDOProperty;
+  locCS : ISDOChangeSummary;
+begin
+  locPropBool := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_bool_prop);
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locPropObj_propB := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_ref_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+    locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+    locObjA.setString(locPropString,RandomString(1000));
+    locB := (*the object must be in the containment tree*)
+               locObjA.createDataObject(s_object_prop);
+      locB.setBoolean(locB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+      locB.setInteger(locB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+      locB.setString(locB.getProperty(s_string_prop),RandomString(1210));
+    (* This is necessary because locObjA.createDataObject(s_object_prop) is for "s_object_prop" not for "s_object_ref_prop"*)
+    locObjA.setDataObject(locPropObj_propB,locB);
+  locBB := FFactoryX.createNew(s_uri,s_type_object_B);
+    locBB.setBoolean(locBB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+    locBB.setInteger(locBB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+    locBB.setString(locBB.getProperty(s_string_prop),RandomString(1210));
+
+  locA1 := TSDOCopyHelper.copy(locObjA);
+  locB1 := TSDOCopyHelper.copy(locB);
+
+  locCS := locObjA.getChangeSummary();
+    locCS.beginLogging();
+      locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+      locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+      locObjA.setString(locPropString,RandomString(1000));
+      locObjA.setDataObject(locPropObj_propB,locBB);
+    locCS.endLogging();
+    locCS.undoChanges();
+      CheckEquals(0,locCS.getChangedDataObjects().size());
+      //Check(TSDOEqualityHelper.equal(locObjA,locA1));
+      CheckEquals(PtrUInt(locObjA.getDataObject(s_object_prop)), PtrUInt(locObjA.getDataObject(locPropObj_propB)));
+      //Check(TSDOEqualityHelper.equal(locObjA.getDataObject(locPropObj_propB),locB1));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_object_referenced_startWith_NIL_OBJ();
+var
+  locObjA, locB, locBB, locA1, locB1 : ISDODataObject;
+  locPropBool, locPropInt, locPropString, locPropObj_propB : ISDOProperty;
+  locCS : ISDOChangeSummary;
+begin
+  locPropBool := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_bool_prop);
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locPropObj_propB := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_ref_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+  locBB := (*the object must be in the containment tree*)
+             locObjA.createDataObject(s_object_prop);
+
+  locA1 := TSDOCopyHelper.copy(locObjA);
+  locB1 := TSDOCopyHelper.copy(locB);
+
+  locCS := locObjA.getChangeSummary();
+  locCS.beginLogging();
+      locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+      locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+      locObjA.setString(locPropString,RandomString(1000));
+      locObjA.setDataObject(locPropObj_propB,locB);
+    locObjA.setDataObject(locPropObj_propB,locBB);
+  locCS.endLogging();
+  locCS.undoChanges();
+      CheckEquals(0,locCS.getChangedDataObjects().size());
+      Check(TSDOEqualityHelper.equal(locObjA,locA1));
+      Check(TSDOEqualityHelper.equal(locObjA.getDataObject(locPropObj_propB),nil));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_object_contained_startWith_OBJ_OBJ_OBJ();
+var
+  locObjA, locB, locBB, locA1, locB1 : ISDODataObject;
+  locPropBool, locPropInt, locPropString, locPropObj_propB : ISDOProperty;
+  locCS : ISDOChangeSummary;
+begin
+  locPropBool := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_bool_prop);
+  locPropInt := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_integer_prop);
+  locPropString := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_string_prop);
+  locPropObj_propB := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+    locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+    locObjA.setString(locPropString,RandomString(1000));
+    locB := FFactoryX.createNew(s_uri,s_type_object_B);
+      locB.setBoolean(locB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+      locB.setInteger(locB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+      locB.setString(locB.getProperty(s_string_prop),RandomString(1210));
+    locObjA.setDataObject(locPropObj_propB,locB);
+  locBB := FFactoryX.createNew(s_uri,s_type_object_B);
+    locBB.setBoolean(locBB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+    locBB.setInteger(locBB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+    locBB.setString(locBB.getProperty(s_string_prop),RandomString(1210));
+
+  locA1 := TSDOCopyHelper.copy(locObjA);
+  locB1 := TSDOCopyHelper.copy(locB);
+
+  locCS := locObjA.getChangeSummary();
+    locCS.beginLogging();
+      locObjA.setBoolean(locPropBool,( ( RandomRange(0,1000) mod 2 ) = 0 ) );
+      locObjA.setInteger(locPropInt,RandomRange(-1210,1210));
+      locObjA.setString(locPropString,RandomString(1000));
+        {locB.setBoolean(locB.getProperty(s_bool_prop),( ( RandomRange(0,1000) mod 2 ) = 0 ));
+        locB.setInteger(locB.getProperty(s_integer_prop),RandomRange(-1210,1210));
+        locB.setString(locB.getProperty(s_string_prop),RandomString(1210)); }
+      locObjA.setDataObject(locPropObj_propB,locBB);
+      locObjA.createDataObject(locPropObj_propB);
+    locCS.endLogging();
+    locCS.undoChanges();
+      CheckEquals(0,locCS.getChangedDataObjects().size());
+      Check(TSDOEqualityHelper.equal(locObjA,locA1));
+      Check(TSDOEqualityHelper.equal(locObjA.getDataObject(locPropObj_propB),locB1));
+end;
+
+procedure TSDOChangeSummary_Test.isCreated_create_delete();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(False,FChangeSummary.isCreated(nil));
+  CheckEquals(False,FChangeSummary.isCreated(locObj));
+  FRecorder.recordCreation(locObj);
+    CheckEquals(True,FChangeSummary.isCreated(locObj));
+  FRecorder.recordDeletion(locObj);
+    CheckEquals(False,FChangeSummary.isDeleted(locObj));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_delete_contained_object();
+var
+  locA, locB0, locB1, locC0, locC1 : ISDODataObject;
+  locCopyA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locA.setString(s_string_prop,RandomString(1000));
+    locB0 := locA.createDataObject(s_object_prop);
+      locB0.setString(s_string_prop,RandomString(1000));
+      locC0 := locB0.createDataObject(s_object_prop);
+        locC0.setString(s_string_prop,RandomString(1000));
+
+  locCopyA := TSDOCopyHelper.copy(locA);
+
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locB1 := locA.createDataObject(s_object_prop);
+      locB1.setString(s_string_prop,RandomString(1000));
+      locC1 := locB1.createDataObject(s_object_prop);
+        locC1.setString(s_string_prop,RandomString(1000));
+  locCS.endLogging();
+  locCS.undoChanges();
+      CheckEquals(0,locCS.getChangedDataObjects().size());
+      Check(TSDOEqualityHelper.equal(locCopyA,locA));
+end;
+
+procedure TSDOChangeSummary_Test.getOldXpath_1();
+var
+  locObjA, locB, locBB : ISDODataObject;
+  locPropObj_propB : ISDOProperty;
+  locCS : ISDOChangeSummary;
+begin
+  locPropObj_propB := FFactoryX.getType(s_uri,s_type_object_A).getProperty(s_object_prop);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+  locB := FFactoryX.createNew(s_uri,s_type_object_B);
+    locObjA.setDataObject(locPropObj_propB,locB);
+
+  locCS := locObjA.getChangeSummary();
+  locCS.beginLogging();
+    CheckEquals('',locCS.getOldXpath(locObjA));
+    CheckEquals('',locCS.getOldXpath(locB));
+    locBB := locObjA.createDataObject(locPropObj_propB);
+      CheckEquals('',locCS.getOldXpath(locObjA));
+      CheckEquals(locPropObj_propB.getName(),locCS.getOldXpath(locB));
+      CheckEquals('',locCS.getOldXpath(locBB));
+      locObjA.createDataObject(locPropObj_propB);
+        CheckEquals(locPropObj_propB.getName(),locCS.getOldXpath(locB));
+end;
+
+procedure TSDOChangeSummary_Test.getOldXpath_nested_deleted_object();
+var
+  locFac : ISDODataFactory;
+  locA, locB, locBB, locC, locD : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+  locFac.AddType(s_uri,'c',[]);
+  locFac.AddType(s_uri,'d',[]);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ac',s_uri,'c',[]);
+    locFac.addProperty(s_uri,'a','p_ad',s_uri,'d',[]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+      locFac.addProperty(s_uri,'b','p_bc',s_uri,'c',[pfIsContainment]);
+        locFac.addProperty(s_uri,'c','p_cd',s_uri,'d',[pfIsContainment]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locB := locA.createDataObject('p_ab');
+      locC := locB.createDataObject('p_bc');
+      locD := locC.createDataObject('p_cd');
+
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locBB := locA.createDataObject('p_ab');
+    CheckEquals('p_ab',locCS.getOldXpath(locB));
+    CheckEquals('p_ab/p_bc',locCS.getOldXpath(locC));
+    CheckEquals('p_ab/p_bc/p_cd',locCS.getOldXpath(locD));
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues_created_object_settinglist_is_empty();
+var
+  locA, locB : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locA := FFactoryX.createNew(s_uri,s_type_object_A);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locB := locA.createDataObject(s_object_prop);
+    locB.setInteger(s_integer_prop,1210);
+    locB.setString(s_string_prop, 'kis');
+    CheckEquals(0, locCS.getOldValues(locB).size());
+end;
+
+procedure TSDOChangeSummary_Test.getChangedDataObjects_contained_delete;
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC, locD : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  i : PtrInt;
+  ls : ISDOChangedDataObjectList;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+  locFac.AddType(s_uri,'c',[]);
+  locFac.AddType(s_uri,'d',[]);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+      locFac.addProperty(s_uri,'b','p_bc',s_uri,'c',[pfIsContainment]);
+        locFac.addProperty(s_uri,'c','p_cd',s_uri,'d',[pfIsContainment]);
+          locFac.addProperty(s_uri,'d','p_int',sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+
+  locA := locFac.createNew(s_uri,'a');
+  locCS := locA.getChangeSummary();
+  locCS.endLogging();
+    locB := locA.createDataObject('p_ab');
+      locC := locB.createDataObject('p_bc');
+        locD := locC.createDataObject('p_cd');
+  locCS.beginLogging();
+    locD.setInteger('p_int',1210);
+    locA.setDataObject('p_ab',nil);
+
+  ls := locCS.getChangedDataObjects();
+  i := IndexOf(locD,ls);
+  Check( ( i < 0 ) or ( Ord(ls.getType(i)) = Ord(ctDelete) ) );
+  Check(locCS.isDeleted(locD));
+end;
+
+procedure TSDOChangeSummary_Test.getChangedDataObjects_multi_value_prop;
+var
+  locFac : ISDODataFactory;
+  locA, locB : ISDODataObject;
+  locLs : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  i : PtrInt;
+  ls : ISDOChangedDataObjectList;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+      locFac.addProperty(s_uri,'b','p_int',sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+
+  locA := locFac.createNew(s_uri,'a');
+  locCS := locA.getChangeSummary();
+  locCS.endLogging();
+    locLs := locA.getList('p_ab');
+    for i := 1 to 5 do begin
+      locB := locFac.createNew(s_uri,'b');
+      locB.setInteger('p_int',i);
+      locLs.append(locB);
+    end;
+  locCS.beginLogging();
+    locLs.delete(2);
+    locLs.delete(0);
+
+  ls := locCS.getChangedDataObjects();
+  CheckEquals(3, ls.size());
+  CheckEquals(Ord(ctChange), Ord(ls.getType(0)), 'a');
+  CheckEquals(Ord(ctDelete), Ord(ls.getType(1)), 'a.p_ab[2]');
+  CheckEquals(Ord(ctDelete), Ord(ls.getType(2)), 'a.p_ab[3]');
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_bool();
+const
+  LOCAL_PROP_NAME = s_bool_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOBoolean;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(locProp,False);
+    locSetting := nil;
+  try
+    buffer := locObjA.getBoolean(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setBoolean(locProp,True);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getBoolean(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setBoolean(locProp,True);
+          locObjA.setBoolean(locProp,False);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_byte();
+const
+  LOCAL_PROP_NAME = s_byte_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOByte;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setByte(locProp,RandomRange(Low(TSDOByte),High(TSDOByte)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getByte(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setByte(locProp,RandomRange(Low(TSDOByte),High(TSDOByte)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getByte(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setByte(locProp,RandomRange(Low(TSDOByte),High(TSDOByte)));
+          locObjA.setByte(locProp,RandomRange(Low(TSDOByte),High(TSDOByte)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_bool();
+const
+  LOCAL_PROP_NAME = s_bool_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOBoolean;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(locProp,True);
+    locSetting := nil;
+  try
+    buffer := locObjA.getBoolean(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_byte();
+const
+  LOCAL_PROP_NAME = s_byte_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOByte;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setByte(locProp,RandomRange(Low(TSDOByte),High(TSDOByte)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getByte(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_integer();
+const
+  LOCAL_PROP_NAME = s_integer_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOInteger;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setInteger(locProp,456789);
+    locSetting := nil;
+  try
+    buffer := locObjA.getInteger(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_string();
+const
+  LOCAL_PROP_NAME = s_string_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOString;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setString(locProp,'X-PASCAL');
+    locSetting := nil;
+  try
+    buffer := locObjA.getString(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_bool();
+const
+  LOCAL_PROP_NAME = s_bool_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOBoolean;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBoolean(locProp,True);
+    locSetting := nil;
+  try
+    buffer := locObjA.getBoolean(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_byte();
+const
+  LOCAL_PROP_NAME = s_byte_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOByte;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setByte(locProp,RandomRange(Low(TSDOByte),High(TSDOByte)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getByte(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_integer();
+const
+  LOCAL_PROP_NAME = s_integer_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOInteger;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setInteger(locProp,78910);
+    locSetting := nil;
+  try
+    buffer := locObjA.getInteger(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_string();
+const
+  LOCAL_PROP_NAME = s_string_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOString;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setString(locProp,'FGHJKLM');
+    locSetting := nil;
+  try
+    buffer := locObjA.getString(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues_bool();
+const
+  VAL_1 : TSDOBoolean = False;
+  PROP_NAME = s_bool_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setBoolean(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setBoolean(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues_byte();
+const
+  VAL_1 : TSDOByte = 123;
+  PROP_NAME = s_byte_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setByte(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setByte(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_bool();
+const
+  VAL_1 : TSDOBoolean = True;
+  VAL_2 : TSDOBoolean = False;
+  PROP_NAME = s_bool_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setBoolean(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setBoolean(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_byte();
+const
+  VAL_1 : TSDOByte = 123;
+  VAL_2 : TSDOByte = 78;
+  PROP_NAME = s_byte_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setByte(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setByte(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues_date();
+const
+  VAL_1 : TSDODateTime = ( Date : 39000; HourOffset : 5; MinuteOffset : 6; );
+  VAL_2 : TSDODateTime = ( Date : 34567; HourOffset : 8; MinuteOffset : 9; );
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(s_date_prop);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setDate(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setDate(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues_integer();
+const
+  VAL_1 : TSDOInteger = 123456;
+  PROP_NAME = s_integer_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setInteger(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setInteger(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValues_string();
+const
+  VAL_1 : TSDOString = 'sdo.standart.AZERTY';
+  PROP_NAME = s_string_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setString(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setString(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOChangeSummary_Test.getOldValues_bytes();
+const
+  PROP_NAME = s_bytes_prop;
+var
+  VAL_1 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(TSDOByte);
+    VAL_1 := v;
+  end;  
+  
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  SetConstants();
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setBytes(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setBytes(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_bytes();
+const
+  PROP_NAME = s_bytes_prop;
+var
+  VAL_1, VAL_2 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(TSDOByte);
+    VAL_1 := v;
+    v := nil;    
+
+    SetLength(v,20);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(TSDOByte);
+    VAL_2 := v;
+  end;  
+  
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  SetConstants();
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setBytes(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setBytes(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_bytes();
+const
+  LOCAL_PROP_NAME = s_bytes_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOBytes;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBytes(locProp,RandomBytes(100));
+    locSetting := nil;
+  try
+    buffer := locObjA.getBytes(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setBytes(locProp,RandomBytes(100));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getBytes(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setBytes(locProp,RandomBytes(100));
+          locObjA.setBytes(locProp,RandomBytes(100));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_bytes();
+const
+  LOCAL_PROP_NAME = s_bytes_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOBytes;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBytes(locProp,RandomBytes(100));
+    locSetting := nil;
+  try
+    buffer := locObjA.getBytes(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_bytes();
+const
+  LOCAL_PROP_NAME = s_bytes_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOBytes;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setBytes(locProp,RandomBytes(100));
+    locSetting := nil;
+  try
+    buffer := locObjA.getBytes(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOChangeSummary_Test.getOldValues_char();
+const
+  VAL_1 : TSDOChar = 'c';
+  PROP_NAME = s_char_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setCharacter(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setCharacter(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_char();
+const
+  VAL_1 : TSDOChar = 'd';
+  VAL_2 : TSDOChar = 'i';
+  PROP_NAME = s_char_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setCharacter(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setCharacter(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_char();
+const
+  LOCAL_PROP_NAME = s_char_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOChar;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setCharacter(locProp,TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+    locSetting := nil;
+  try
+    buffer := locObjA.getCharacter(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setCharacter(locProp,TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getCharacter(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setCharacter(locProp,TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+          locObjA.setCharacter(locProp,TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_char();
+const
+  LOCAL_PROP_NAME = s_char_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOChar;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setCharacter(locProp,TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+    locSetting := nil;
+  try
+    buffer := locObjA.getCharacter(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_char();
+const
+  LOCAL_PROP_NAME = s_char_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOChar;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setCharacter(locProp,TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+    locSetting := nil;
+  try
+    buffer := locObjA.getCharacter(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOChangeSummary_Test.getOldValues_currency();
+const
+  VAL_1 : TSDOCurrency = 1238527419247;
+  PROP_NAME = s_currency_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setCurrency(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setCurrency(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_currency();
+const
+  VAL_1 : TSDOCurrency = 98765432178225;
+  VAL_2 : TSDOCurrency = -4587412254554;
+  PROP_NAME = s_currency_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setCurrency(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setCurrency(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_currency();
+const
+  LOCAL_PROP_NAME = s_currency_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOCurrency;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setCurrency(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getCurrency(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setCurrency(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getCurrency(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setCurrency(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+          locObjA.setCurrency(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_currency();
+const
+  LOCAL_PROP_NAME = s_currency_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOCurrency;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setCurrency(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getCurrency(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_currency();
+const
+  LOCAL_PROP_NAME = s_currency_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOCurrency;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setCurrency(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getCurrency(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOChangeSummary_Test.getOldValues_double();
+const
+  VAL_1 : TSDODouble = 1238527419247;
+  PROP_NAME = s_double_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setDouble(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setDouble(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_double();
+const
+  VAL_1 : TSDODouble = 9876543211478225;
+  VAL_2 : TSDODouble = -4587412282254554;
+  PROP_NAME = s_double_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setDouble(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setDouble(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_double();
+const
+  LOCAL_PROP_NAME = s_double_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDODouble;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setDouble(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getDouble(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setDouble(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getDouble(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setDouble(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+          locObjA.setDouble(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_double();
+const
+  LOCAL_PROP_NAME = s_double_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDODouble;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setDouble(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getDouble(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_double();
+const
+  LOCAL_PROP_NAME = s_double_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDODouble;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setDouble(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getDouble(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOChangeSummary_Test.getOldValues_float();
+const
+  VAL_1 : TSDOFloat = 1238527419247;
+  PROP_NAME = s_float_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setFloat(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setFloat(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_float();
+const
+  VAL_1 : TSDOFloat = 9876543211478225;
+  VAL_2 : TSDOFloat = -4587412282254554;
+  PROP_NAME = s_float_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setFloat(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setFloat(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_float();
+const
+  LOCAL_PROP_NAME = s_float_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOFloat;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setFloat(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getFloat(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setFloat(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getFloat(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setFloat(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+          locObjA.setFloat(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_float();
+const
+  LOCAL_PROP_NAME = s_float_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOFloat;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setFloat(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getFloat(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_float();
+const
+  LOCAL_PROP_NAME = s_float_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOFloat;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setFloat(locProp,test_suite_utils.RandomRange(Low(Word),High(Word)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getFloat(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOChangeSummary_Test.getOldValues_long();
+const
+  VAL_1 : TSDOLong = 123852741963654247;
+  PROP_NAME = s_long_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setLong(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setLong(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_long();
+const
+  VAL_1 : TSDOLong = 9876543211478225;
+  VAL_2 : TSDOLong = -4587412282254554;
+  PROP_NAME = s_long_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setLong(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setLong(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_long();
+const
+  LOCAL_PROP_NAME = s_long_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOLong;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setLong(locProp,test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getLong(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setLong(locProp,test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getLong(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setLong(locProp,test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+          locObjA.setLong(locProp,test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_long();
+const
+  LOCAL_PROP_NAME = s_long_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOLong;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setLong(locProp,test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getLong(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_long();
+const
+  LOCAL_PROP_NAME = s_long_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOLong;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setLong(locProp,test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getLong(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOChangeSummary_Test.getOldValues_short();
+const
+  VAL_1 : TSDOShort = 12385;
+  PROP_NAME = s_short_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  ls : ISDOSettingList;
+  locProp : ISDOProperty;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  ls := FChangeSummary.getOldValues(locObjA);
+  CheckEquals(0, ls.size());
+  ls := FChangeSummary.getOldValues(locObjB);
+  CheckEquals(0, ls.size());
+
+  locObjA.setShort(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+  locObjB.setShort(locProp,VAL_1);
+  FRecorder.recordChange(locObjB,locProp);
+    ls := FChangeSummary.getOldValues(locObjA);
+    CheckEquals(1,ls.size());
+
+    ls := FChangeSummary.getOldValues(locObjB);
+    CheckEquals(1,ls.size());
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_short();
+const
+  VAL_1 : TSDOShort = 9876;
+  VAL_2 : TSDOShort = -4587;
+  PROP_NAME = s_short_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setShort(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setShort(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_short();
+const
+  LOCAL_PROP_NAME = s_short_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOShort;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setShort(locProp,RandomRange(Low(TSDOShort),High(TSDOShort)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getShort(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setShort(locProp,RandomRange(Low(TSDOShort),High(TSDOShort)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getShort(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setShort(locProp,RandomRange(Low(TSDOShort),High(TSDOShort)));
+          locObjA.setShort(locProp,RandomRange(Low(TSDOShort),High(TSDOShort)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_short();
+const
+  LOCAL_PROP_NAME = s_short_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOShort;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setShort(locProp,RandomRange(Low(TSDOShort),High(TSDOShort)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getShort(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_short();
+const
+  LOCAL_PROP_NAME = s_short_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOShort;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setShort(locProp,RandomRange(Low(TSDOShort),High(TSDOShort)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getShort(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOChangeSummary_Test.getOldValue_date();
+const
+  VAL_1 : TSDODateTime = ( Date : 39000; HourOffset : 5; MinuteOffset : 6; );
+  VAL_2 : TSDODateTime = ( Date : 34567; HourOffset : 8; MinuteOffset : 9; );
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(s_date_prop);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setDate(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setDate(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_Integer();
+const
+  VAL_1 : TSDOInteger = 123456;
+  VAL_2 : TSDOInteger = -987;
+  PROP_NAME = s_integer_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setInteger(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setInteger(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.getOldValue_string();
+const
+  VAL_1 : TSDOString = 'Inoussa.O';
+  VAL_2 : TSDOString = 'SDO.AZERTY';
+  PROP_NAME = s_string_prop;
+var
+  locObjA, locObjB : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+begin
+  locProp := FFactory.getType(s_uri,s_type_object_A).getProperty(PROP_NAME);
+  locObjA := FFactory.createNew(s_uri,s_type_object_A);
+  locObjB := FFactory.createNew(s_uri,s_type_object_A);
+  FChangeSummary.beginLogging();
+
+  CheckEquals(PtrUInt(nil), PtrUInt(FChangeSummary.getOldValue(locObjA,locProp)));
+
+  locObjA.setString(locProp,VAL_1);
+  FRecorder.recordChange(locObjA,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjA,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+
+  locObjB.setString(locProp,VAL_2);
+  FRecorder.recordChange(locObjB,locProp);
+    locSetting := FChangeSummary.getOldValue(locObjB,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locSetting.getProperty()));
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_date();
+const
+  LOCAL_PROP_NAME = s_date_prop;
+  VAL_1 : TSDODateTime = ( Date : 39000; HourOffset : 5; MinuteOffset : 6; );
+  VAL_2 : TSDODateTime = ( Date : 34567; HourOffset : 8; MinuteOffset : 9; );
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDODateTime;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setDate(locProp,VAL_1);
+    locSetting := nil;
+  try
+    buffer := locObjA.getDate(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setDate(locProp,VAL_2);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getDate(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setDate(locProp,VAL_1);
+          locObjA.setDate(locProp,VAL_2);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_integer();
+const
+  LOCAL_PROP_NAME = s_integer_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOInteger;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setInteger(locProp,RandomRange(-978456,123456));
+    locSetting := nil;
+  try
+    buffer := locObjA.getInteger(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setInteger(locProp,RandomRange(-978456,123456));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getInteger(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setInteger(locProp,RandomRange(-978456,123456));
+          locObjA.setInteger(locProp,RandomRange(-978456,123456));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_string();
+const
+  LOCAL_PROP_NAME = s_string_prop;
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDOString;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setString(locProp,RandomString(RandomRange(0,1000)));
+    locSetting := nil;
+  try
+    buffer := locObjA.getString(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setString(locProp,RandomString(RandomRange(0,1000)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+
+    FreeAndNil(locSetting);
+    buffer := locObjA.getString(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setString(locProp,RandomString(RandomRange(0,1000)));
+          locObjA.setString(locProp,RandomString(RandomRange(0,1000)));
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.CheckEquals(expected, actual: TSDODate; msg: string; const AStrict: Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_unset_date();
+const
+  LOCAL_PROP_NAME = s_date_prop;
+  VAL_1 : TSDODateTime = ( Date : 39000; HourOffset : 5; MinuteOffset : 6; );
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDODateTime;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setDate(locProp,VAL_1);
+    locSetting := nil;
+  try
+    buffer := locObjA.getDate(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.unset(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+procedure TSDOChangeSummary_Test.undoChanges_simple_setnull_date();
+const
+  LOCAL_PROP_NAME = s_date_prop;
+  VAL_1 : TSDODateTime = ( Date : 39000; HourOffset : 5; MinuteOffset : 6; );
+var
+  locObjA : ISDODataObject;
+  locProp : ISDOProperty;
+  locSetting : TValueSetting;
+  buffer : TSDODateTime;
+  locCS : ISDOChangeSummary;
+begin
+  locProp := FFactoryX.getType(s_uri,s_type_object_A).getProperty(LOCAL_PROP_NAME);
+  locObjA := FFactoryX.createNew(s_uri,s_type_object_A);
+    locObjA.setDate(locProp,VAL_1);
+    locSetting := nil;
+  try
+    buffer := locObjA.getDate(locProp);
+      locSetting := TValueSetting.Create(locObjA.isSet(locProp),locObjA.isNull(locProp),buffer,locProp,0);
+
+    locCS := locObjA.getChangeSummary();
+      locCS.beginLogging();
+        locObjA.setNull(locProp);
+      locCS.endLogging();
+      locCS.undoChanges();
+        CheckEquals(0,locCS.getChangedDataObjects().size());
+        check_value(locObjA,locProp,locSetting);
+  finally
+    FreeAndNil(locSetting);
+  end;
+end;
+
+{ TSDODataObjectCS_Test }
+type
+  TValueState = record
+    IsSet : Boolean;
+    IsNull : Boolean;
+    Value : TValueBuffer;
+  end;
+
+procedure TSDODataObjectCS_Test.CheckEquals(expected, actual: TSDODate;
+  msg: string; const AStrict: Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+procedure TSDODataObjectCS_Test.check_bool_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOBoolean;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := ( ( RandomRange(Low(TSDOByte),High(TSDOByte)) mod 2 ) = 0);
+
+  locOldState.Value.BooleanValue := AObj.getBoolean(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setBoolean(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.BooleanValue,locSetting.getBooleanValue(),'getBooleanValue');
+
+  locNewValue := ( ( RandomRange(Low(Byte),High(Byte)) mod 2 ) = 0);
+  AObj.setBoolean(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.BooleanValue,locSetting.getBooleanValue(),'getBooleanValue');
+end;
+
+procedure TSDODataObjectCS_Test.check_byte_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOByte;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := RandomRange(Low(TSDOByte),High(TSDOByte));
+
+  locOldState.Value.ByteValue := AObj.getByte(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setByte(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.ByteValue,locSetting.getByteValue(),'getByteValue');
+
+  locNewValue := RandomRange(Low(TSDOByte),High(TSDOByte));
+  AObj.setByte(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.ByteValue,locSetting.getByteValue(),'getByteValue');
+end;
+
+procedure TSDODataObjectCS_Test.check_date_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDODateTime;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue.Date := 39123.45;
+  locNewValue.HourOffset := 2;
+  locNewValue.MinuteOffset := 3;
+
+  locOldState.Value.DateValue := AObj.getDate(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setDate(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.DateValue,locSetting.getDateValue(),'getDateValue');
+
+  locNewValue.Date := 45000;
+  locNewValue.HourOffset := -5;
+  locNewValue.MinuteOffset := 0;
+  AObj.setDate(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.DateValue,locSetting.getDateValue(),'getDateValue');
+end;
+
+procedure TSDODataObjectCS_Test.check_int_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOInteger;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := RandomRange(-121076,121076);
+
+  locOldState.Value.IntegerValue := AObj.getInteger(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setInteger(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.IntegerValue,locSetting.getIntegerValue(),'getIntegerValue');
+
+  locNewValue := RandomRange(-121076,121076);
+  AObj.setInteger(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.IntegerValue,locSetting.getIntegerValue(),'getIntegerValue');
+end;
+
+procedure TSDODataObjectCS_Test.check_string_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOString;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := RandomString(RandomRange(10,1000));
+
+  New(locOldState.Value.StringValue);
+  try
+    locOldState.Value.StringValue^ := AObj.getString(locProp);
+    locOldState.IsSet := AObj.isSet(locProp);
+    locOldState.IsNull := AObj.isNull(locProp);
+    AObj.setString(locProp,locNewValue);
+      locSetting := locCS.getOldValue(AObj,locProp);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+      CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+      CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+      CheckEquals(locOldState.Value.StringValue^,locSetting.getStringValue(),'getStringValue');
+
+    locNewValue := RandomString(RandomRange(10,1000));
+    AObj.setString(locProp,locNewValue);  // the recorder should keep the first recorded old values
+      locSetting := locCS.getOldValue(AObj,locProp);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+      CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+      CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+      CheckEquals(locOldState.Value.StringValue^,locSetting.getStringValue(),'getStringValue');
+  finally
+    Dispose(locOldState.Value.StringValue);
+  end;
+end;
+
+procedure TSDODataObjectCS_Test.create_default_props();
+var
+  locObj : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locCS := locObj.getChangeSummary();
+
+  CheckNotEquals(PtrUInt(nil),PtrUInt(locCS), 'getChangeSummary()');
+  CheckEquals(False, locCS.isLogging());
+end;
+
+class function TSDODataObjectCS_Test.Create_Factory(): ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_Objects(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_C,[]);
+    locObj := locFactory.getType(AUri,s_type_object_C);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+
+    locFactory.AddType(AUri,s_type_object_B,[]);
+    locObj := locFactory.getType(AUri,s_type_object_B);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locFactory.addProperty(locObj,s_object_prop,s_uri,s_type_object_C,[pfIsContainment]);
+
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], [pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], [pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_object_prop,s_uri,s_type_object_B,[pfIsContainment]);
+      locFactory.addProperty(locObj,s_object_ref_prop,s_uri,s_type_object_B,[]);
+      locFactory.addProperty(locObj,s_changesummary_prop,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  end;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_Objects(s_uri);
+
+  Result := locFactory;
+end;
+
+procedure TSDODataObjectCS_Test.getChangeSummary();
+var
+  locA, locB, locC : ISDODataObject;
+begin
+  locA := FFactory.createNew(s_uri,s_type_object_A);
+  locB := FFactory.createNew(s_uri,s_type_object_B);
+  locC := FFactory.createNew(s_uri,s_type_object_C);
+
+  CheckNotEquals(PtrUInt(nil), PtrUInt(locA.getChangeSummary()));
+  CheckEquals(PtrUInt(nil), PtrUInt(locB.getChangeSummary()));
+  CheckEquals(PtrUInt(nil), PtrUInt(locB.getChangeSummary()));
+
+  locA.setDataObject(s_object_prop,locB);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locA.getChangeSummary()));
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locB.getChangeSummary()));
+    CheckEquals(PtrUInt(nil), PtrUInt(locC.getChangeSummary()));
+
+    locB.setDataObject(s_object_prop,locC);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locA.getChangeSummary()));
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locB.getChangeSummary()));
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locC.getChangeSummary()));
+end;
+
+procedure TSDODataObjectCS_Test.logging_bool();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_bool_logging(locObj,s_bool_prop);
+end;
+
+procedure TSDODataObjectCS_Test.logging_byte();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_byte_logging(locObj,s_byte_prop);
+end;
+
+procedure TSDODataObjectCS_Test.logging_date();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_date_logging(locObj,s_date_prop);
+end;
+
+procedure TSDODataObjectCS_Test.logging_int();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_int_logging(locObj,s_integer_prop);
+end;
+
+procedure TSDODataObjectCS_Test.logging_string();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_string_logging(locObj,s_string_prop);
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDODataObjectCS_Test.check_bytes_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOBytes;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := RandomBytes(100);
+
+  New(locOldState.Value.BytesValue);
+  try
+    locOldState.Value.BytesValue^ := AObj.getBytes(locProp);
+    locOldState.IsSet := AObj.isSet(locProp);
+    locOldState.IsNull := AObj.isNull(locProp);
+    AObj.setBytes(locProp,locNewValue);
+      locSetting := locCS.getOldValue(AObj,locProp);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+      CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+      CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+      CheckEquals(locOldState.Value.BytesValue^,locSetting.getBytesValue(),'getBytesValue');
+
+    locNewValue := RandomBytes(100);
+    AObj.setBytes(locProp,locNewValue);  // the recorder should keep the first recorded old values
+      locSetting := locCS.getOldValue(AObj,locProp);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+      CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+      CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+      CheckEquals(locOldState.Value.BytesValue^,locSetting.getBytesValue(),'getBytesValue');
+  finally
+    Dispose(locOldState.Value.BytesValue);
+  end;
+end;
+
+procedure TSDODataObjectCS_Test.logging_bytes();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_bytes_logging(locObj,s_bytes_prop);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDODataObjectCS_Test.check_char_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOChar;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+
+  locOldState.Value.CharValue := AObj.getCharacter(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setCharacter(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.CharValue,locSetting.getCharacterValue(),'getCharacterValue');
+
+  locNewValue := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  AObj.setCharacter(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.CharValue,locSetting.getCharacterValue(),'getCharacterValue');
+end;
+
+procedure TSDODataObjectCS_Test.logging_char();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_char_logging(locObj,s_char_prop);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDODataObjectCS_Test.check_currency_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOCurrency;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := test_suite_utils.RandomRange(Low(Word),High(Word));
+
+  locOldState.Value.CurrencyValue := AObj.getCurrency(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setCurrency(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.CurrencyValue,locSetting.getCurrencyValue(),'getCurrencyValue');
+
+  locNewValue := test_suite_utils.RandomRange(Low(Word),High(Word));
+  AObj.setCurrency(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.CurrencyValue,locSetting.getCurrencyValue(),'getCurrencyValue');
+end;
+
+procedure TSDODataObjectCS_Test.logging_currency();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_currency_logging(locObj,s_currency_prop);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDODataObjectCS_Test.check_double_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDODouble;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := test_suite_utils.RandomRange(Low(Word),High(Word));
+
+  locOldState.Value.DoubleValue := AObj.getDouble(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setDouble(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.DoubleValue,locSetting.getDoubleValue(),'getDoubleValue');
+
+  locNewValue := test_suite_utils.RandomRange(Low(Word),High(Word));
+  AObj.setDouble(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.DoubleValue,locSetting.getDoubleValue(),'getDoubleValue');
+end;
+
+procedure TSDODataObjectCS_Test.logging_double();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_double_logging(locObj,s_double_prop);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDODataObjectCS_Test.check_float_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOFloat;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := test_suite_utils.RandomRange(Low(Word),High(Word));
+
+  locOldState.Value.FloatValue := AObj.getFloat(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setFloat(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.FloatValue,locSetting.getFloatValue(),'getFloatValue');
+
+  locNewValue := test_suite_utils.RandomRange(Low(Word),High(Word));
+  AObj.setFloat(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.FloatValue,locSetting.getFloatValue(),'getFloatValue');
+end;
+
+procedure TSDODataObjectCS_Test.logging_float();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_float_logging(locObj,s_float_prop);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDODataObjectCS_Test.check_long_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOLong;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+
+  locOldState.Value.LongValue := AObj.getLong(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setLong(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.LongValue,locSetting.getLongValue(),'getLongValue');
+
+  locNewValue := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+  AObj.setLong(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.LongValue,locSetting.getLongValue(),'getLongValue');
+end;
+
+procedure TSDODataObjectCS_Test.logging_long();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_long_logging(locObj,s_long_prop);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDODataObjectCS_Test.check_short_logging(
+  const AObj : ISDODataObject;
+  const APropName : string
+);
+var
+  locProp : ISDOProperty;
+  locCS : ISDOChangeSummary;
+  locSetting : TValueSetting;
+  locNewValue : TSDOShort;
+  locOldState : TValueState;
+begin
+  locProp := AObj.getProperty(APropName);
+  locCS := AObj.getChangeSummary();
+  locNewValue := RandomRange(Low(TSDOShort),High(TSDOShort));
+
+  locOldState.Value.ShortValue := AObj.getShort(locProp);
+  locOldState.IsSet := AObj.isSet(locProp);
+  locOldState.IsNull := AObj.isNull(locProp);
+  AObj.setShort(locProp,locNewValue);
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.ShortValue,locSetting.getShortValue(),'getShortValue');
+
+  locNewValue := RandomRange(Low(TSDOShort),High(TSDOShort));
+  AObj.setShort(locProp,locNewValue);  // the recorder should keep the first recorded old values
+    locSetting := locCS.getOldValue(AObj,locProp);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locSetting), 'getOldValue()');
+    CheckEquals(locOldState.IsSet,locSetting.isSet,'isSet');
+    CheckEquals(locOldState.IsNull,locSetting.isNull,'ISNull');
+    CheckEquals(locOldState.Value.ShortValue,locSetting.getShortValue(),'getShortValue');
+end;
+
+procedure TSDODataObjectCS_Test.logging_short();
+var
+  locObj : ISDODataObject;
+begin
+  locObj := FFactory.createNew(s_uri,s_type_object_A);
+  locObj.getChangeSummary().beginLogging();
+
+  check_short_logging(locObj,s_short_prop);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDODataObjectCS_Test.SetUp();
+begin
+  inherited;
+  FFactory := Create_Factory();
+end;
+
+procedure TSDODataObjectCS_Test.TearDown();
+begin
+  FFactory := nil;
+  inherited;
+end;
+
+{ TSDOChangeSummaryMultiValueProps_Test }
+
+procedure TSDOChangeSummaryMultiValueProps_Test.CheckEquals(expected,
+  actual: TSDODate; msg: string; const AStrict: Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getChangedDataObjects_contained_delete_multiprop_1();
+var
+  locFac : ISDODataFactory;
+  locPL, locPJ0, locPJ1, locP1, locP2, locP3 : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  i : PtrInt;
+  ls : ISDOChangedDataObjectList;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'ProjectList',[]);
+  locFac.AddType(s_uri,'ProjectType',[]);
+  locFac.AddType(s_uri,'Person',[]);
+    locFac.addProperty(s_uri,'ProjectList','Project',s_uri,'ProjectType',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'ProjectList',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+      locFac.addProperty(s_uri,'ProjectType','Member',s_uri,'Person',[pfIsContainment,pfIsMany]);
+        locFac.addProperty(s_uri,'Person','Manager',s_uri,'Person',[]);
+          locFac.addProperty(s_uri,'Person','Name',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+
+  locPL := locFac.createNew(s_uri,'ProjectList');
+  locCS := locPL.getChangeSummary();
+  locCS.endLogging();
+    locPJ0 := locPL.createDataObject('Project');
+    locPL.getList('Project').append(locPJ0);
+    locPJ1 := locPL.createDataObject('Project');
+    locPL.getList('Project').append(locPJ1);
+      locP1 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP1);
+        locP1.setString('Name', 'P1 person');
+      locP2 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP2);
+        locP2.setString('Name', 'P2 person');
+        locP2.setDataObject('Manager', locPJ1.getDataObject('Member[Name="P1 person"]'));
+      locP3 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP3);
+        locP3.setString('Name', 'P3 person');
+        locP1.setDataObject('Manager', locPJ1.getDataObject('Member[Name="P3 person"]'));
+
+  locCS.beginLogging();
+    //locPJ2 := locPL
+    locPL.getList('Project').delete(1);
+
+  ls := locCS.getChangedDataObjects();
+  i := IndexOf(locP1,ls);
+  Check( ( i < 0 ) or ( Ord(ls.getType(i)) = Ord(ctDelete) ) );
+  Check(locCS.isDeleted(locPJ1));
+
+  i := IndexOf(locP2,ls);
+  Check( ( i < 0 ) or ( Ord(ls.getType(i)) = Ord(ctDelete) ) );
+  Check(locCS.isDeleted(locPJ1));
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getChangedDataObjects_contained_delete_multiprop_2;
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  ls : ISDOChangedDataObjectList;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+  locFac.AddType(s_uri,'c',[]);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'b','p_bc',s_uri,'c',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+  locCS := locA.getChangeSummary();
+  locCS.endLogging();
+    locB := locA.createDataObject('p_ab');
+  locCS.beginLogging();
+    locC := locFac.createNew(s_uri,'c');
+    locB.getList('p_bc').append(locC);
+  locA.setDataObject('p_ab',nil);
+
+  ls := locCS.getChangedDataObjects();
+  CheckEquals(2, ls.size());
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getChangedDataObjects_contained_delete_multiprop_3();
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  ls : ISDOChangedDataObjectList;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+  locFac.AddType(s_uri,'c',[]);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'b','p_bc',s_uri,'c',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+  locCS := locA.getChangeSummary();
+  locCS.endLogging();
+    locB := locA.createDataObject('p_ab');
+    locA.getList('p_ab').append(locB);
+  locCS.beginLogging();
+    locC := locFac.createNew(s_uri,'c');
+    locB.getList('p_bc').append(locC);
+  locA.getList('p_ab').delete(0);
+
+  ls := locCS.getChangedDataObjects();
+  CheckEquals(2, ls.size());
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_bool();
+const
+  LOCAL_PROP = s_bool_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOBoolean;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := ( ( RandomRange(-1234,56789) mod 3 ) = 0 );
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.setBoolean(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getBooleanValue(), Format('i = %d; getBooleanValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_byte;
+const
+  LOCAL_PROP = s_byte_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOByte;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomRange(Low(TSDOByte),High(TSDOByte));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.setByte(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getByteValue(), Format('i = %d; getByteValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_date();
+const
+  LOCAL_PROP = s_date_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDODateTime;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomDate();
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(RandomDate());
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDate());
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+      vls.setDate(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDate());
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getDateValue(), Format('i = %d; getDateValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_integer;
+const
+  LOCAL_PROP = s_integer_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOInteger;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomRange(-1234,56789);
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(RandomRange(-1234,56789));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(-1234,56789));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+      vls.setInteger(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(-1234,56789));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getIntegerValue(), Format('i = %d; getIntegerValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_objects();
+const
+  LOCAL_PROP = s_Employee;
+
+  function create_factory () : ISDODataFactory;
+  var
+    locFac : ISDODataFactory;
+  begin
+    locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_EmployeeType,[]);
+      locFac.addProperty(s_uri, s_EmployeeType,'name',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locFac.addProperty(s_uri, s_EmployeeType,'SN',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.AddType(s_uri,s_Department,[]);
+      locFac.addProperty(s_uri,s_Department,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locFac.addProperty(s_uri,s_Department,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locFac.addProperty(s_uri,s_Department,s_Employee,s_uri,s_EmployeeType,[pfIsMany,pfIsContainment]);
+      locFac.addProperty(s_uri,s_Department,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+    Result := locFac;
+  end;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+  function create_employee(
+    const AFac : ISDODataFactory;
+    const AName, ASN : TSDOString
+  ) : ISDODataObject;
+  begin
+    Result := AFac.createNew(s_uri, s_EmployeeType);
+    Result.setString(s_name, AName);
+    Result.setString(s_sn, ASN);
+  end;
+
+  procedure check_employee_equal(const A, B : ISDODataObject; const AMsgPrefix : string);
+  begin
+    Check(
+      ( ( A = nil ) and ( B = nil ) ) or
+      ( ( A <> nil ) and ( B <> nil ) ),
+      AMsgPrefix
+    );
+    if ( A <> nil ) then begin
+      CheckEquals(A.getString(s_name), B.getString(s_name), Format('%s %s',[AMsgPrefix, s_name]));
+      CheckEquals(A.getString(s_sn), B.getString(s_sn), Format('%s %s',[AMsgPrefix, s_sn]));
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of ISDODataObject;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  locFac := create_factory();
+  x := locFac.createNew(s_uri,s_Department);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100)));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(create_employee(locFac, 'sdo', '001'));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.setDataObject(RandomRange(0, ( vls.size() - 1 ) ), create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        check_employee_equal(vvals[i],s.getDataObjectValue(), Format('Object[%d]',[i]));
+        CheckEquals(True, TSDOEqualityHelper.equal(vvals[i],s.getDataObjectValue()), Format('i = %d; getDataObjectValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_string();
+const
+  LOCAL_PROP = s_string_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOString;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomString(RandomRange(0,100));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(RandomString(RandomRange(0,100)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomString(RandomRange(0,100)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+      vls.setString(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomString(RandomRange(0,100)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getStringValue(), Format('i = %d; getStringValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.isDeleted();
+var
+  f : ISDODataFactory;
+  a, b0, b1, b2 : ISDODataObject;
+  ls : ISDODataObjectList;
+  cs : ISDOChangeSummary;
+begin
+  f := TSDODataFactory.Create();
+  f.AddType(s_uri,'a',[]);
+  f.AddType(s_uri,'b',[]);
+  f.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsMany,pfIsContainment]);
+  f.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  a := f.createNew(s_uri,'a');
+  ls := a.getList('p_ab');
+  cs := a.getChangeSummary();
+  cs.endLogging();
+    b0 := a.createDataObject('p_ab');
+    ls.append(b0);
+  cs.beginLogging();
+    b1 := a.createDataObject('p_ab');
+    ls.append(b1);
+    b2 := a.createDataObject('p_ab');
+    ls.append(b2);
+    ls.delete(1);
+      CheckEquals(False, cs.isDeleted(b0));
+      CheckEquals(False, cs.isDeleted(b1), 'Because it has been created when the cs where ON');
+      CheckEquals(False, cs.isDeleted(b2));
+    ls.delete(0);
+      CheckEquals(True, cs.isDeleted(b0));
+      CheckEquals(False, cs.isDeleted(b1), 'Because it has been created when the cs where ON');
+      CheckEquals(False, cs.isDeleted(b2));
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.isDeleted_nested();
+var
+  f : ISDODataFactory;
+  a, b0, b1, b2 : ISDODataObject;
+  c01, c02 : ISDODataObject;
+  ls : ISDODataObjectList;
+  cs : ISDOChangeSummary;
+begin
+  f := TSDODataFactory.Create();
+  f.AddType(s_uri,'a',[]);
+  f.AddType(s_uri,'b',[]);
+  f.AddType(s_uri,'c',[]);
+  f.addProperty(s_uri,'b','p_bc',s_uri,'c',[pfIsMany,pfIsContainment]);
+  f.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsMany,pfIsContainment]);
+  f.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  a := f.createNew(s_uri,'a');
+  ls := a.getList('p_ab');
+  cs := a.getChangeSummary();
+  cs.endLogging();
+    b0 := a.createDataObject('p_ab');
+    ls.append(b0);
+      c01 := b0.createDataObject('p_bc'); b0.getList('p_bc').append(c01);
+      c02 := b0.createDataObject('p_bc'); b0.getList('p_bc').append(c02);
+  cs.beginLogging();
+    b1 := a.createDataObject('p_ab'); ls.append(b1);
+    b2 := a.createDataObject('p_ab'); ls.append(b2);
+
+    ls.delete(1);
+      CheckEquals(False, cs.isDeleted(b0));
+      CheckEquals(False, cs.isDeleted(b1), 'Because it has been created when the cs where ON');
+      CheckEquals(False, cs.isDeleted(b2));
+    ls.delete(0);
+      CheckEquals(True, cs.isDeleted(b0));
+      CheckEquals(False, cs.isDeleted(b1), 'Because it has been created when the cs where ON');
+      CheckEquals(False, cs.isDeleted(b2));
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.SetUp();
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+  end;
+
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+  FFactory := locFactory;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.TearDown();
+begin
+  FFactory := nil;
+  inherited;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_bool();
+const
+  LOCAL_PROP = s_bool_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOBoolean;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := ( RandomRange(-1234,56789) mod 3 ) = 0;
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.setBoolean(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getBoolean(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_bool_deleted;
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(True);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(True);
+    locA.getList('p_ab').append(False);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(True);
+    locA.getList('p_ab').append(False);
+    locA.getList('p_ab').append(False);
+    locA.getList('p_ab').append(True);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_byte();
+const
+  LOCAL_PROP = s_byte_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOByte;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomRange(Low(TSDOByte),High(TSDOByte));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.setByte(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getByte(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_byte_deleted();
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOByte(123));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOByte(23));
+    locA.getList('p_ab').append(TSDOByte(45));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOByte(12));
+    locA.getList('p_ab').append(TSDOByte(23));
+    locA.getList('p_ab').append(TSDOByte(45));
+    locA.getList('p_ab').append(TSDOByte(67));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_date();
+const
+  LOCAL_PROP = s_date_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDODateTime;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomDate();
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(RandomDate());
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDate());
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+      vls.setDate(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDate());
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getDate(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_date_deleted();
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(RandomDate());
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(RandomDate());
+    locA.getList('p_ab').append(RandomDate());
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(RandomDate());
+    locA.getList('p_ab').append(RandomDate());
+    locA.getList('p_ab').append(RandomDate());
+    locA.getList('p_ab').append(RandomDate());
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_integer();
+const
+  LOCAL_PROP = s_integer_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOInteger;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomRange(-1234,56789);
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(RandomRange(-1234,56789));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(-1234,56789));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+      vls.setInteger(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(-1234,56789));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getInteger(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_integer_deleted();
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(1210);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(23);
+    locA.getList('p_ab').append(45);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(12);
+    locA.getList('p_ab').append(23);
+    locA.getList('p_ab').append(45);
+    locA.getList('p_ab').append(67);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_bool();
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOBoolean;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOBoolean;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[IntegerType], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[BooleanType], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[BooleanType], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setInteger('p_i', RandomRange(-1234,56789));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := ( RandomRange(-1234,56789) mod 3 ) = 0;
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := ( RandomRange(-1234,56789) mod 3 ) = 0;
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.setBoolean(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.setBoolean(RandomRange(0, ( vls.size() - 1 ) ), ( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.append(( RandomRange(-1234,56789) mod 3 ) = 0);
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getBoolean(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getBoolean(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_byte();
+const
+  PROP_TYPE = ByteType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOByte;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOByte;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setByte('p_i', RandomRange(Low(TSDOByte),High(TSDOByte)));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomRange(Low(TSDOByte),High(TSDOByte));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomRange(Low(TSDOByte),High(TSDOByte));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.setByte(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.setByte(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.append(RandomRange(Low(TSDOByte),High(TSDOByte)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getByte(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getByte(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_date();
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDODateTime;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDODateTime;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[DateTimeType], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[DateTimeType], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[DateTimeType], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setDate('p_i', RandomDate());
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomDate();
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomDate();
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(RandomDate());
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDate());
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+        vls.setDate(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDate());
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDate());
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDate());
+        vls.setDate(RandomRange(0, ( vls.size() - 1 ) ), RandomDate());
+        vls.append(RandomDate());
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getDate(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getDate(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_integer();
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOInteger;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOInteger;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[IntegerType], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[IntegerType], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[IntegerType], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setInteger('p_i', RandomRange(-1234,56789));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomRange(-1234,56789);
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomRange(-1234,56789);
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(RandomRange(-1234,56789));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(-1234,56789));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+        vls.setInteger(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(-1234,56789));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(-1234,56789));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(-1234,56789));
+        vls.setInteger(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(-1234,56789));
+        vls.append(RandomRange(-1234,56789));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getInteger(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getInteger(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_object();
+
+  function create_e1(const AFac : ISDODataFactory) : ISDODataObject;
+  begin
+    Result := AFac.createNew(s_uri, 'e_1');
+    Result.setString('p_e1', RandomString(RandomRange(0,100)));
+  end;
+
+  function create_e2(const AFac : ISDODataFactory) : ISDODataObject;
+  begin
+    Result := AFac.createNew(s_uri, 'e_2');
+    Result.setString('p_e2', RandomString(RandomRange(0,100)));
+  end;
+
+  procedure check_e1_equal(const A, B : ISDODataObject; const AMsgPrefix : string);
+  begin
+    Check(
+      ( ( A = nil ) and ( B = nil ) ) or
+      ( ( A <> nil ) and ( B <> nil ) ),
+      AMsgPrefix
+    );
+    if ( A <> nil ) then begin
+      CheckEquals(True, TSDOEqualityHelper.equal(A.getDataObject('p_e1'), B.getDataObject('p_e1')), Format('%s %s',[AMsgPrefix, s_name]));
+    end;
+  end;
+
+  procedure check_e2_equal(const A, B : ISDODataObject; const AMsgPrefix : string);
+  begin
+    Check(
+      ( ( A = nil ) and ( B = nil ) ) or
+      ( ( A <> nil ) and ( B <> nil ) ),
+      AMsgPrefix
+    );
+    if ( A <> nil ) then begin
+      CheckEquals(True, TSDOEqualityHelper.equal(A.getDataObject('p_e2'), B.getDataObject('p_e2')), Format('%s %s',[AMsgPrefix, s_name]));
+    end;
+  end;
+
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of ISDODataObject;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of ISDODataObject;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'e_1', []);
+    f.AddType(s_uri, 'e_2', []);
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'e_1', 'p_e1', sdo_namespace, SDOTypeDefaultTypeNames[StringType], []);
+    f.addProperty(s_uri, 'e_2', 'p_e2', sdo_namespace, SDOTypeDefaultTypeNames[StringType], []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[IntegerType], []);
+    f.addProperty(s_uri, 'a', 'p_li', s_uri, 'e_1', [pfIsMany,pfIsContainment]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', s_uri, 'e_2', [pfIsMany,pfIsContainment]);
+  x := f.createNew(s_uri,'a');
+    x.setInteger('p_i', RandomRange(-1234,56789));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := create_e1(f);
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := create_e2(f);
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(create_e1(f));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(create_e1(f));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), create_e1(f));
+        vls.setDataObject(RandomRange(0, ( vls.size() - 1 ) ), create_e1(f));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(create_e1(f));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), create_e2(f));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(create_e2(f));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(create_e2(f));
+        vls.setDataObject(RandomRange(0, ( vls.size() - 1 ) ), create_e2(f));
+        vls.append(create_e2(f));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          check_e1_equal(vvals_a[i], vls.getDataObject(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          check_e2_equal(vvals_b[i], vls.getDataObject(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_string();
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOString;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOString;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[IntegerType], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[StringType], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[stringType], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setInteger('p_i', RandomRange(-1234,56789));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomString(RandomRange(0,100));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomString(RandomRange(0,100));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(RandomString(RandomRange(0,100)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomString(RandomRange(0,100)));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+        vls.setString(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomString(RandomRange(0,100)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomString(RandomRange(0,100)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomString(RandomRange(0,100)));
+        vls.setString(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+        vls.append(RandomString(RandomRange(0,100)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getString(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getString(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_bytes();
+const
+  LOCAL_PROP = s_bytes_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOBytes;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomBytes(RandomRange(0,200));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.appendBytes(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.appendBytes(RandomBytes(RandomRange(0,200)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendBytes(RandomBytes(RandomRange(0,200)));
+      vls.insertBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+      vls.setBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendBytes(RandomBytes(RandomRange(0,200)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getBytesValue(), Format('i = %d; getBytesValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_bytes();
+const
+  LOCAL_PROP = s_bytes_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOBytes;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomBytes(RandomRange(0,200));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.appendBytes(vvals[i]);
+
+    cs.beginLogging();
+      vls.appendBytes(RandomBytes(RandomRange(0,200)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendBytes(RandomBytes(RandomRange(0,200)));
+      vls.insertBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+      vls.setBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendBytes(RandomBytes(RandomRange(0,200)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getBytes(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_bytes_deleted();
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').appendBytes(RandomBytes(RandomRange(0,200)));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').appendBytes(RandomBytes(RandomRange(0,200)));
+    locA.getList('p_ab').appendBytes(RandomBytes(RandomRange(0,200)));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').appendBytes(RandomBytes(RandomRange(0,200)));
+    locA.getList('p_ab').appendBytes(RandomBytes(RandomRange(0,200)));
+    locA.getList('p_ab').appendBytes(RandomBytes(RandomRange(0,200)));
+    locA.getList('p_ab').appendBytes(RandomBytes(RandomRange(0,200)));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_bytes();
+const
+  PROP_TYPE = BytesType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOBytes;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOBytes;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setBytes('p_i', RandomBytes(RandomRange(0,200)));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomBytes(RandomRange(0,200));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomBytes(RandomRange(0,200));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.appendBytes(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.appendBytes(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.appendBytes(RandomBytes(RandomRange(0,200)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendBytes(RandomBytes(RandomRange(0,200)));
+        vls.insertBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+        vls.setBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendBytes(RandomBytes(RandomRange(0,200)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insertBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendBytes(RandomBytes(RandomRange(0,200)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendBytes(RandomBytes(RandomRange(0,200)));
+        vls.setBytes(RandomRange(0, ( vls.size() - 1 ) ), RandomBytes(RandomRange(0,200)));
+        vls.appendBytes(RandomBytes(RandomRange(0,200)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getBytes(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getBytes(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_char();
+const
+  LOCAL_PROP = s_char_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOChar;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.setCharacter(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getCharacterValue(), Format('i = %d; getCharacterValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_char();
+const
+  LOCAL_PROP = s_char_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOChar;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.setCharacter(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getCharacter(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_char_deleted();
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOChar('z'));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOChar('d'));
+    locA.getList('p_ab').append(TSDOChar('f'));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOChar('w'));
+    locA.getList('p_ab').append(TSDOChar(#0));
+    locA.getList('p_ab').append(TSDOChar('5'));
+    locA.getList('p_ab').append(TSDOChar('n'));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_char();
+const
+  PROP_TYPE = CharacterType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOChar;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOChar;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setCharacter('p_i', TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.setCharacter(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.setCharacter(RandomRange(0, ( vls.size() - 1 ) ), TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.append(TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar)))));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getCharacter(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getCharacter(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_currency;
+const
+  LOCAL_PROP = s_currency_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOCurrency;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := test_suite_utils.RandomRange(Low(Word),High(Word));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.appendCurrency(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.insertCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.setCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getCurrencyValue(), Format('i = %d; getCurrencyValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_currency();
+const
+  LOCAL_PROP = s_currency_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOCurrency;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := test_suite_utils.RandomRange(Low(Word),High(Word));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.appendCurrency(vvals[i]);
+
+    cs.beginLogging();
+      vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.insertCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.setCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getCurrency(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_currency_deleted();
+const
+  CURRENCY_CONT_ARRAY : array[0..6] of TSDOCurrency = (
+    123963244, 23852215, -52245, 1252222, -11122123, -24245, 522552
+  );
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').appendCurrency(CURRENCY_CONT_ARRAY[0]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').appendCurrency(CURRENCY_CONT_ARRAY[1]);
+    locA.getList('p_ab').appendCurrency(CURRENCY_CONT_ARRAY[2]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').appendCurrency(CURRENCY_CONT_ARRAY[3]);
+    locA.getList('p_ab').appendCurrency(CURRENCY_CONT_ARRAY[4]);
+    locA.getList('p_ab').appendCurrency(CURRENCY_CONT_ARRAY[5]);
+    locA.getList('p_ab').appendCurrency(CURRENCY_CONT_ARRAY[6]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_currency();
+const
+  PROP_TYPE = CurrencyType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOCurrency;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOCurrency;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setCurrency('p_i', test_suite_utils.RandomRange(Low(Word),High(Word)));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := test_suite_utils.RandomRange(Low(Word),High(Word));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := test_suite_utils.RandomRange(Low(Word),High(Word));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.appendCurrency(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.appendCurrency(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.insertCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.setCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insertCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.setCurrency(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.appendCurrency(test_suite_utils.RandomRange(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getCurrency(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getCurrency(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_double;
+const
+  LOCAL_PROP = s_double_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDODouble;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomDouble(Low(Word),High(Word));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(RandomDouble(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDouble(Low(Word),High(Word)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+      vls.setDouble(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDouble(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getDoubleValue(), Format('i = %d; getDoubleValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_double();
+const
+  LOCAL_PROP = s_double_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDODouble;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomDouble(Low(Word),High(Word));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(RandomDouble(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDouble(Low(Word),High(Word)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+      vls.setDouble(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomDouble(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getDouble(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_double_deleted();
+const
+  DOUBLE_CONT_ARRAY : array[0..6] of TSDODouble = (
+    123963244, 23852215, -52245, 1252222, -11122123, -24245, 522552
+  );
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(DOUBLE_CONT_ARRAY[0]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(DOUBLE_CONT_ARRAY[1]);
+    locA.getList('p_ab').append(DOUBLE_CONT_ARRAY[2]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(DOUBLE_CONT_ARRAY[3]);
+    locA.getList('p_ab').append(DOUBLE_CONT_ARRAY[4]);
+    locA.getList('p_ab').append(DOUBLE_CONT_ARRAY[5]);
+    locA.getList('p_ab').append(DOUBLE_CONT_ARRAY[6]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_double();
+const
+  PROP_TYPE = DoubleType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDODouble;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDODouble;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setDouble('p_i', RandomDouble(Low(Word),High(Word)));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomDouble(Low(Word),High(Word));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomDouble(Low(Word),High(Word));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(RandomDouble(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDouble(Low(Word),High(Word)));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+        vls.setDouble(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDouble(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDouble(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomDouble(Low(Word),High(Word)));
+        vls.setDouble(RandomRange(0, ( vls.size() - 1 ) ), RandomDouble(Low(Word),High(Word)));
+        vls.append(RandomDouble(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getDouble(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getDouble(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_float;
+const
+  LOCAL_PROP = s_float_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOFloat;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomFloat(Low(Word),High(Word));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(RandomFloat(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomFloat(Low(Word),High(Word)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+      vls.setFloat(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomFloat(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getFloatValue(), Format('i = %d; getFloatValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_float();
+const
+  LOCAL_PROP = s_float_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOFloat;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomFloat(Low(Word),High(Word));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(RandomFloat(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomFloat(Low(Word),High(Word)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+      vls.setFloat(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomFloat(Low(Word),High(Word)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getFloat(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_float_deleted();
+const
+  FLOAT_CONT_ARRAY : array[0..6] of TSDOFloat = (
+    123963244, 23852215, -52245, 1252222, -11122123, -24245, 522552
+  );
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(FLOAT_CONT_ARRAY[0]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(FLOAT_CONT_ARRAY[1]);
+    locA.getList('p_ab').append(FLOAT_CONT_ARRAY[2]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(FLOAT_CONT_ARRAY[3]);
+    locA.getList('p_ab').append(FLOAT_CONT_ARRAY[4]);
+    locA.getList('p_ab').append(FLOAT_CONT_ARRAY[5]);
+    locA.getList('p_ab').append(FLOAT_CONT_ARRAY[6]);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_float();
+const
+  PROP_TYPE = FloatType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOFloat;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOFloat;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setFloat('p_i', RandomFloat(Low(Word),High(Word)));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomFloat(Low(Word),High(Word));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomFloat(Low(Word),High(Word));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(RandomFloat(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomFloat(Low(Word),High(Word)));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+        vls.setFloat(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomFloat(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomFloat(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomFloat(Low(Word),High(Word)));
+        vls.setFloat(RandomRange(0, ( vls.size() - 1 ) ), RandomFloat(Low(Word),High(Word)));
+        vls.append(RandomFloat(Low(Word),High(Word)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getFloat(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getFloat(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_long;
+const
+  LOCAL_PROP = s_long_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOLong;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.setLong(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getLongValue(), Format('i = %d; getLongValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_long();
+const
+  LOCAL_PROP = s_long_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOLong;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.setLong(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getLong(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_long_deleted();
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOLong(123963244));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOLong(23852215));
+    locA.getList('p_ab').append(TSDOLong(-52245));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOLong(1252222));
+    locA.getList('p_ab').append(TSDOLong(-11122123));
+    locA.getList('p_ab').append(TSDOLong(-24245));
+    locA.getList('p_ab').append(TSDOLong(522552));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_long();
+const
+  PROP_TYPE = LongType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOLong;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOLong;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setLong('p_i', test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.setLong(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.setLong(RandomRange(0, ( vls.size() - 1 ) ), test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.append(test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getLong(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getLong(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOChangeSummaryMultiValueProps_Test.getOldValues_short;
+const
+  LOCAL_PROP = s_short_propList;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  ls : ISDOSettingList;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOShort;
+  vvals_length, i : PtrInt;
+  s : TValueSetting;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomRange(Low(TSDOShort),High(TSDOShort));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.setShort(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      ls := cs.getOldValues(x);
+      CheckNotEquals(PtrUInt(nil), PtrUInt(ls));
+      CheckEquals(vvals_length, ls.size(), 'ls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        s := ls.getItem(i);
+        CheckEquals(PtrUInt(x.getProperty(LOCAL_PROP)), PtrUInt(s.getProperty()), Format('i = %d; getProperty',[i]));
+        CheckEquals(i, s.getIndex(), Format('i = %d; getIndex',[i]));
+        CheckEquals(True, s.isSet(), Format('i = %d; isSet',[i]));
+        CheckEquals(False, s.isNull(), Format('i = %d; isNull',[i]));
+        CheckEquals(vvals[i], s.getShortValue(), Format('i = %d; getShortValue',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_short();
+const
+  LOCAL_PROP = s_short_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOShort;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomRange(Low(TSDOShort),High(TSDOShort));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.setShort(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getShort(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_short_deleted();
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOShort(1239));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOShort(2385));
+    locA.getList('p_ab').append(TSDOShort(-5225));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(TSDOShort(125));
+    locA.getList('p_ab').append(TSDOShort(-1113));
+    locA.getList('p_ab').append(TSDOShort(-245));
+    locA.getList('p_ab').append(TSDOShort(5222));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_nested_short();
+const
+  PROP_TYPE = ShortType;
+var
+  f : ISDODataFactory;
+  x, y : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals_a : array of TSDOShort;
+  vvals_a_length, i : PtrInt;
+  vvals_b : array of TSDOShort;
+  vvals_b_length : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+    f.AddType(s_uri, 'a', []);
+    f.AddType(s_uri, 'b', []);
+    f.addProperty(s_uri, 'a', 'p_i', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], []);
+    f.addProperty(s_uri, 'a', 'p_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+    f.addProperty(s_uri, 'a', 'p_ab', s_uri, 'b', [pfIsContainment]);
+    f.addProperty(s_uri, 'a', s_changesummary_prop, sdo_namespace, SDOTypeDefaultTypeNames[ChangeSummaryType], [pfIsReadOnly]);
+    f.addProperty(s_uri, 'b', 'p_b_li', sdo_namespace, SDOTypeDefaultTypeNames[PROP_TYPE], [pfIsMany]);
+  x := f.createNew(s_uri,'a');
+    x.setShort('p_i', RandomRange(Low(TSDOShort),High(TSDOShort)));
+    y := x.createDataObject('p_ab');
+  cs := x.getChangeSummary();
+
+  vvals_a_length := RandomRange(1,100);
+  vvals_b_length := RandomRange(1,100);
+  SetLength(vvals_a,vvals_a_length);
+  try
+    for i := 0 to Pred(vvals_a_length) do
+      vvals_a[i] := RandomRange(Low(TSDOShort),High(TSDOShort));
+    SetLength(vvals_b,vvals_b_length);
+    for i := 0 to Pred(vvals_b_length) do
+      vvals_b[i] := RandomRange(Low(TSDOShort),High(TSDOShort));
+
+    vls := x.getList('p_li');
+      for i := 0 to Pred(vvals_a_length) do
+        vls.append(vvals_a[i]);
+    vls := y.getList('p_b_li');
+      for i := 0 to Pred(vvals_b_length) do
+        vls.append(vvals_b[i]);
+
+    cs.beginLogging();
+      vls := x.getList('p_li');
+        vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.setShort(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls := y.getList('p_b_li');
+        vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.setShort(RandomRange(0, ( vls.size() - 1 ) ), RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.append(RandomRange(Low(TSDOShort),High(TSDOShort)));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+        vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      vls := x.getList('p_li');
+        CheckEquals(vvals_a_length, vls.size(), 'x, vls.size()');
+        for i := 0 to Pred(vvals_a_length) do begin
+          CheckEquals(vvals_a[i], vls.getShort(i), Format('x, Index = %d',[i]));
+        end;
+      vls := y.getList('p_b_li');
+        CheckEquals(vvals_b_length, vls.size(), 'y, vls.size()');
+        for i := 0 to Pred(vvals_b_length) do begin
+          CheckEquals(vvals_b[i], vls.getShort(i), Format('y, Index = %d',[i]));
+        end;
+
+  finally
+    SetLength(vvals_b,0);
+    SetLength(vvals_a,0);
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_object;
+const
+  LOCAL_PROP = s_Employee;
+
+  function create_factory () : ISDODataFactory;
+  var
+    locFac : ISDODataFactory;
+  begin
+    locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_EmployeeType,[]);
+      locFac.addProperty(s_uri, s_EmployeeType,'name',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locFac.addProperty(s_uri, s_EmployeeType,'SN',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.AddType(s_uri,s_Department,[]);
+      locFac.addProperty(s_uri,s_Department,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locFac.addProperty(s_uri,s_Department,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locFac.addProperty(s_uri,s_Department,s_Employee,s_uri,s_EmployeeType,[pfIsMany,pfIsContainment]);
+      locFac.addProperty(s_uri,s_Department,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+    Result := locFac;
+  end;
+
+  procedure check_empty_list(const AList : ISDOSettingList);
+  begin
+    CheckNotEquals(PtrUInt(nil), PtrUInt(AList));
+    CheckEquals(0, AList.size());
+  end;
+
+  function create_employee(
+    const AFac : ISDODataFactory;
+    const AName, ASN : TSDOString
+  ) : ISDODataObject;
+  begin
+    Result := AFac.createNew(s_uri, s_EmployeeType);
+    Result.setString(s_name, AName);
+    Result.setString(s_sn, ASN);
+  end;
+
+  procedure check_employee_equal(const A, B : ISDODataObject; const AMsgPrefix : string);
+  begin
+    Check(
+      ( ( A = nil ) and ( B = nil ) ) or
+      ( ( A <> nil ) and ( B <> nil ) ),
+      AMsgPrefix
+    );
+    if ( A <> nil ) then begin
+      CheckEquals(A.getString(s_name), B.getString(s_name), Format('%s %s',[AMsgPrefix, s_name]));
+      CheckEquals(A.getString(s_sn), B.getString(s_sn), Format('%s %s',[AMsgPrefix, s_sn]));
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of ISDODataObject;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  locFac := create_factory();
+  x := locFac.createNew(s_uri,s_Department);
+  cs := x.getChangeSummary();
+  check_empty_list(cs.getOldValues(x));
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100)));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+      check_empty_list(cs.getOldValues(x));
+
+    cs.beginLogging();
+      vls.append(create_employee(locFac, 'sdo', '001'));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.setDataObject(RandomRange(0, ( vls.size() - 1 ) ), create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), create_employee(locFac, RandomString(RandomRange(0,100)), RandomString(RandomRange(0,100))));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        check_employee_equal(vvals[i],vls.getDataObject(i), Format('Object[%d]',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_object_deleted;
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(locA.createDataObject('p_ab'));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(locA.createDataObject('p_ab'));
+    locA.getList('p_ab').append(locA.createDataObject('p_ab'));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append(locA.createDataObject('p_ab'));
+    locA.getList('p_ab').append(locA.createDataObject('p_ab'));
+    locA.getList('p_ab').append(locA.createDataObject('p_ab'));
+    locA.getList('p_ab').append(locA.createDataObject('p_ab'));
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_string();
+const
+  LOCAL_PROP = s_string_propList;
+var
+  x : ISDODataObject;
+  cs : ISDOChangeSummary;
+  vls : ISDODataObjectList;
+  vvals : array of TSDOString;
+  vvals_length, i : PtrInt;
+begin
+  Randomize();
+  x := FFactory.createNew(s_uri,s_type_object_A);
+  cs := x.getChangeSummary();
+
+  vvals_length := RandomRange(1,100);
+  SetLength(vvals,vvals_length);
+  try
+    for i := 0 to Pred(vvals_length) do
+      vvals[i] := RandomString(RandomRange(0,100));
+    vls := x.getList(LOCAL_PROP);
+      for i := 0 to Pred(vvals_length) do
+        vls.append(vvals[i]);
+
+    cs.beginLogging();
+      vls.append(RandomString(RandomRange(0,100)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomString(RandomRange(0,100)));
+      vls.insert(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+      vls.setString(RandomRange(0, ( vls.size() - 1 ) ), RandomString(RandomRange(0,100)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.append(RandomString(RandomRange(0,100)));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+      vls.delete(RandomRange(0, ( vls.size() - 1 ) ));
+    cs.undoChanges();
+      CheckEquals(0, cs.getChangedDataObjects().size, 'cs.getChangedDataObjects().size');
+      CheckEquals(vvals_length, vls.size(), 'vls.size()');
+      for i := 0 to Pred(vvals_length) do begin
+        CheckEquals(vvals[i], vls.getString(i), Format('Index = %d',[i]));
+      end;
+  finally
+    SetLength(vvals,0);
+  end;
+end;
+
+procedure TSDOChangeSummaryMultiValueProps_Test.undoChanges_string_deleted;
+var
+  locFac : ISDODataFactory;
+  locA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+    locFac.addProperty(s_uri,'a','p_ab',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append('azerty');
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(0);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append('sdo');
+    locA.getList('p_ab').append('fpc');
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(1);
+  locCS.getOldValues(locA);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.getList('p_ab').append('Delphi');
+    locA.getList('p_ab').append('Lazarus');
+    locA.getList('p_ab').append('WST');
+    locA.getList('p_ab').append('OI');
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.getList('p_ab').delete(3);
+  locCS.getOldValues(locA);
+end;
+
+initialization
+  RegisterTest('ChangeSummary',TValueSetting_Test.Suite);
+  RegisterTest('ChangeSummary',TSDOSettingList_Test.Suite);
+  //RegisterTest('ChangeSummary', TDicho_Test.Suite);
+  RegisterTest('ChangeSummary', TSDOChangedDataObjectList_Test.Suite);
+  RegisterTest('ChangeSummary', TChangeRecorder_Test.Suite);
+  RegisterTest('ChangeSummary', TSDOChangeSummary_Test.Suite);
+  RegisterTest('ChangeSummary', TSDODataObjectCS_Test.Suite);
+  RegisterTest('ChangeSummary', TSDOChangeSummaryMultiValueProps_Test.Suite);
+
+end.

+ 611 - 0
packages/fcl-sdo/tests/test_suite/test_convert_helper.pas

@@ -0,0 +1,611 @@
+{$INCLUDE sdo_global.inc}
+unit test_convert_helper;
+
+interface
+uses
+  SysUtils, Classes
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , test_suite_utils, sdo, sdo_types, sdo_convert_helper ;
+
+type
+
+  TSDOConvertHelper_Test = class(TWstBaseTest)
+  protected
+    class function getObject() : TSDOConvertHelperClass;
+  published
+    procedure BoolToByte();
+    procedure BoolToInteger();
+    procedure BoolToLong();
+    procedure BoolToShort();
+    procedure BoolToString();
+
+    procedure ByteToBool();
+    procedure ByteToChar();
+    procedure ByteToString();
+
+    procedure BytesToString();
+
+    procedure CharToBool();
+    procedure CharToByte();
+    procedure CharToInteger();
+    procedure CharToLong();
+    procedure CharToShort();
+
+    procedure IntegerToBool();
+    procedure IntegerToChar();
+    procedure IntegerToString();
+
+    procedure LongToBool();
+    procedure LongToChar();
+    procedure LongToString();
+
+    procedure ShortToBool();
+    procedure ShortToChar();
+    procedure ShortToString();
+
+    procedure StringToBool();
+    procedure StringToByte();
+    procedure StringToBytes();
+    procedure StringToDate();
+    procedure StringToInteger();
+    procedure StringToLong();
+    procedure StringToShort();
+
+    procedure FloatToString();
+    procedure FloatToBool();
+
+    procedure DateToString();
+  end;
+
+implementation
+
+{ TSDOConvertHelper_Test }
+
+procedure TSDOConvertHelper_Test.BoolToByte();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(1, locObj.BoolToByte(True), 'true');
+  CheckEquals(0, locObj.BoolToByte(False), 'false');
+end;
+
+procedure TSDOConvertHelper_Test.BoolToInteger();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(1, locObj.BoolToInteger(True), 'true');
+  CheckEquals(0, locObj.BoolToInteger(False), 'false');
+end;
+
+procedure TSDOConvertHelper_Test.BoolToLong();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(1, locObj.BoolToLong(True), 'true');
+  CheckEquals(0, locObj.BoolToLong(False), 'false');
+end;
+
+procedure TSDOConvertHelper_Test.BoolToShort();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(1, locObj.BoolToShort(True), 'true');
+  CheckEquals(0, locObj.BoolToShort(False), 'false');
+end;
+
+procedure TSDOConvertHelper_Test.BoolToString();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals('1', locObj.BoolToString(True), 'true');
+  CheckEquals('0', locObj.BoolToString(False), 'false');
+end;
+
+procedure TSDOConvertHelper_Test.ByteToBool();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(True, locObj.ByteToBool(123));
+  CheckEquals(False, locObj.ByteToBool(0));
+  CheckEquals(True, locObj.ByteToBool(1));
+  CheckEquals(True, locObj.ByteToBool(2));
+  CheckEquals(True, locObj.ByteToBool(34));
+end;
+
+procedure TSDOConvertHelper_Test.ByteToChar();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(TSDOChar(#123), locObj.ByteToChar(123));
+  CheckEquals(TSDOChar(#0), locObj.ByteToChar(0));
+  CheckEquals(TSDOChar(#1), locObj.ByteToChar(1));
+  CheckEquals(TSDOChar(#56), locObj.ByteToChar(56));
+end;
+
+procedure TSDOConvertHelper_Test.ByteToString();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals('123', locObj.ByteToString(123));
+  CheckEquals('0', locObj.ByteToString(0));
+  CheckEquals('1', locObj.ByteToString(1));
+  CheckEquals('56', locObj.ByteToString(56));
+end;
+
+procedure TSDOConvertHelper_Test.DateToString();
+const
+  sDATE_1 = '1976-10-12T23:34:56Z';
+  sDATE_2 = '0987-06-12T20:34:56Z';
+var
+  d : TSDODate;
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  //'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
+  FillChar(d,SizeOf(d),#0);
+  d.Date := EncodeDate(1976,10,12) + EncodeTime(23,34,56,0);
+  CheckEquals(sDATE_1, locObj.DateToString(d));
+
+  FillChar(d,SizeOf(d),#0);
+  d.Date := EncodeDate(987,06,12) - EncodeTime(20,34,56,0);
+  CheckEquals(sDATE_2, locObj.DateToString(d));
+
+  FillChar(d,SizeOf(d),#0);
+  d.Date := EncodeDate(2002,10,10) + EncodeTime(12,0,0,0);
+  d.HourOffset := 5;
+  CheckEquals('2002-10-10T07:00:00Z', locObj.DateToString(d));
+end;
+
+procedure TSDOConvertHelper_Test.FloatToBool();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(True, locObj.FloatToBool(1));
+  CheckEquals(False, locObj.FloatToBool(0));
+
+  CheckEquals(True, locObj.FloatToBool(123));
+  CheckEquals(True, locObj.FloatToBool(-43));
+  CheckEquals(True, locObj.FloatToBool(123456789));
+end;
+
+procedure TSDOConvertHelper_Test.FloatToString;
+begin
+
+end;
+
+class function TSDOConvertHelper_Test.getObject() : TSDOConvertHelperClass;
+begin
+  Result := TSDOConvertHelper;
+end;
+
+procedure TSDOConvertHelper_Test.CharToBool();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(True, locObj.CharToBool('8'));
+  CheckEquals(False, locObj.CharToBool(#0));
+  CheckEquals(True, locObj.CharToBool(#1));
+  CheckEquals(True, locObj.CharToBool('T'));
+end;
+
+procedure TSDOConvertHelper_Test.CharToByte();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(Ord(TSDOChar('8')), locObj.CharToByte('8'));
+  CheckEquals(0, locObj.CharToByte(#0));
+  CheckEquals(1, locObj.CharToByte(#1));
+  CheckEquals(Ord(TSDOChar('T')), locObj.CharToByte('T'));
+end;
+
+procedure TSDOConvertHelper_Test.CharToInteger();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(Ord(TSDOChar('8')), locObj.CharToInteger('8'));
+  CheckEquals(0, locObj.CharToInteger(#0));
+  CheckEquals(1, locObj.CharToInteger(#1));
+  CheckEquals(Ord(TSDOChar('T')), locObj.CharToInteger('T'));
+end;
+
+procedure TSDOConvertHelper_Test.CharToLong();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(Ord(TSDOChar('8')), locObj.CharToLong('8'));
+  CheckEquals(0, locObj.CharToLong(#0));
+  CheckEquals(1, locObj.CharToLong(#1));
+  CheckEquals(Ord(TSDOChar('T')), locObj.CharToLong('T'));
+end;
+
+procedure TSDOConvertHelper_Test.CharToShort();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(Ord(TSDOChar('8')), locObj.CharToShort('8'));
+  CheckEquals(0, locObj.CharToShort(#0));
+  CheckEquals(1, locObj.CharToShort(#1));
+  CheckEquals(Ord(TSDOChar('T')), locObj.CharToShort('T'));
+end;
+
+procedure TSDOConvertHelper_Test.IntegerToBool();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(True, locObj.IntegerToBool(-789));
+  CheckEquals(False, locObj.IntegerToBool(0));
+  CheckEquals(True, locObj.IntegerToBool(1));
+  CheckEquals(True, locObj.IntegerToBool(-1));
+  CheckEquals(True, locObj.IntegerToBool(123));
+end;
+
+procedure TSDOConvertHelper_Test.IntegerToChar();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(TSDOChar(0), locObj.IntegerToChar(0));
+  CheckEquals(TSDOChar(12), locObj.IntegerToChar(12));
+  CheckEquals(TSDOChar(123), locObj.IntegerToChar(123));
+  CheckEquals(TSDOChar(TSDOInteger(-52)), locObj.IntegerToChar(-52));
+  CheckEquals(TSDOChar(12345), locObj.IntegerToChar(12345));
+end;
+
+procedure TSDOConvertHelper_Test.IntegerToString();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals('-123456', locObj.IntegerToString(-123456));
+  CheckEquals('0', locObj.IntegerToString(0));
+  CheckEquals('1', locObj.IntegerToString(1));
+  CheckEquals('123456', locObj.IntegerToString(123456));
+end;
+
+procedure TSDOConvertHelper_Test.LongToBool();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(True, locObj.LongToBool(-789));
+  CheckEquals(False, locObj.LongToBool(0));
+  CheckEquals(True, locObj.LongToBool(1));
+  CheckEquals(True, locObj.LongToBool(-1));
+  CheckEquals(True, locObj.LongToBool(123));
+end;
+
+procedure TSDOConvertHelper_Test.LongToChar();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(TSDOChar(0), locObj.LongToChar(0));
+  CheckEquals(TSDOChar(12), locObj.LongToChar(12));
+  CheckEquals(TSDOChar(123), locObj.LongToChar(123));
+  CheckEquals(TSDOChar(TSDOLong(-52)), locObj.LongToChar(-52));
+  CheckEquals(TSDOChar(TSDOLong(123456)), locObj.LongToChar(123456));
+end;
+
+procedure TSDOConvertHelper_Test.LongToString();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals('-123456', locObj.LongToString(-123456));
+  CheckEquals('0', locObj.LongToString(0));
+  CheckEquals('1', locObj.LongToString(1));
+  CheckEquals('123456', locObj.LongToString(123456));
+end;
+
+procedure TSDOConvertHelper_Test.ShortToBool();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(True, locObj.ShortToBool(-789));
+  CheckEquals(False, locObj.ShortToBool(0));
+  CheckEquals(True, locObj.ShortToBool(1));
+  CheckEquals(True, locObj.ShortToBool(-1));
+  CheckEquals(True, locObj.ShortToBool(123));
+end;
+
+procedure TSDOConvertHelper_Test.ShortToChar();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals(TSDOChar(0), locObj.ShortToChar(0));
+  CheckEquals(TSDOChar(12), locObj.ShortToChar(12));
+  CheckEquals(TSDOChar(123), locObj.ShortToChar(123));
+  CheckEquals(TSDOChar(TSDOShort(-52)), locObj.ShortToChar(-52));
+  CheckEquals(TSDOChar(TSDOShort(12345)), locObj.ShortToChar(12345));
+end;
+
+procedure TSDOConvertHelper_Test.ShortToString();
+var
+  locObj : TSDOConvertHelperClass;
+begin
+  locObj := getObject();
+  CheckEquals('-1234', locObj.ShortToString(-1234));
+  CheckEquals('0', locObj.ShortToString(0));
+  CheckEquals('1', locObj.ShortToString(1));
+  CheckEquals('1234', locObj.ShortToString(1234));
+end;
+
+procedure TSDOConvertHelper_Test.StringToBool();
+var
+  locObj : TSDOConvertHelperClass;
+
+  procedure check_invalid(const AString : TSDOString);
+  var
+    Ok : boolean;
+  begin
+    ok := False;
+    try
+      locObj.StringToBool(AString);
+    except
+      on e : ESDOInvalidConversionException do
+        ok := True;
+    end;
+    Check(ok,Format('This conversion should fail : "%s".',[AString]));
+  end;
+
+begin
+  locObj := getObject();
+  CheckEquals(False, locObj.StringToBool('0'));
+  CheckEquals(False, locObj.StringToBool('false'));
+  CheckEquals(False, locObj.StringToBool('FaLsE'));
+  CheckEquals(True, locObj.StringToBool('1'));
+  CheckEquals(True, locObj.StringToBool('True'));
+  check_invalid('');
+  check_invalid('xxxxx');
+  check_invalid('falsexxx');
+  check_invalid('truessss');
+end;
+
+procedure TSDOConvertHelper_Test.StringToByte();
+var
+  locObj : TSDOConvertHelperClass;
+
+  procedure check_invalid(const AString : TSDOString);
+  var
+    Ok : boolean;
+  begin
+    ok := False;
+    try
+      locObj.StringToByte(AString);
+    except
+      on e : ESDOInvalidConversionException do
+        ok := True;
+    end;
+    Check(ok,Format('This conversion should fail : "%s".',[AString]));
+  end;
+
+begin
+  locObj := getObject();
+  CheckEquals(123, locObj.StringToByte('123'));
+  CheckEquals(0, locObj.StringToByte('0'));
+  CheckEquals(1, locObj.StringToByte('1'));
+  CheckEquals(45, locObj.StringToByte('45'));
+  check_invalid('');
+  check_invalid('xxxxx');
+  check_invalid('1235dd');
+  check_invalid('a2522');
+end;
+
+procedure TSDOConvertHelper_Test.StringToDate();
+var
+  locObj : TSDOConvertHelperClass;
+
+  procedure check_invalid(const AString : TSDOString);
+  var
+    Ok : boolean;
+  begin
+    ok := False;
+    try
+      locObj.StringToDate(AString);
+    except
+      on e : ESDOInvalidConversionException do
+        ok := True;
+    end;
+    Check(ok,Format('This conversion should fail : "%s".',[AString]));
+  end;
+
+var
+  s : string;
+  d : TSDODate;
+  y,m,dy : Word;
+  hh,mn,ss, ssss : Word;
+begin
+  locObj := getObject();
+  //'-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
+  s := '1976-10-12T23:34:56Z';
+  d := locObj.StringToDate(s);
+    DecodeDate(d.Date,y,m,dy);
+      CheckEquals(y,1976,'Year');
+      CheckEquals(m,10,'Month');
+      CheckEquals(dy,12,'Day');
+    DecodeTime(d.Date,hh,mn,ss,ssss);
+      CheckEquals(hh,23,'Hour');
+      CheckEquals(mn,34,'Minute');
+      CheckEquals(ss,56,'Second');
+    CheckEquals(0,d.HourOffset,'HourOffset');
+    CheckEquals(0,d.MinuteOffset,'MinuteOffset');
+
+  s := '1976-10-12T23:34:56+12:34';
+  d := locObj.StringToDate(s);
+    DecodeDate(d.Date,y,m,dy);
+      CheckEquals(y,1976,'Year');
+      CheckEquals(m,10,'Month');
+      CheckEquals(dy,12,'Day');
+    DecodeTime(d.Date,hh,mn,ss,ssss);
+      CheckEquals(hh,23,'Hour');
+      CheckEquals(mn,34,'Minute');
+      CheckEquals(ss,56,'Second');
+    CheckEquals(12,d.HourOffset,'HourOffset');
+    CheckEquals(34,d.MinuteOffset,'MinuteOffset');
+
+  check_invalid('azerty');
+  check_invalid('123');  
+end;
+
+procedure TSDOConvertHelper_Test.StringToInteger();
+var
+  locObj : TSDOConvertHelperClass;
+
+  procedure check_invalid(const AString : TSDOString);
+  var
+    Ok : boolean;
+  begin
+    ok := False;
+    try
+      locObj.StringToInteger(AString);
+    except
+      on e : ESDOInvalidConversionException do
+        ok := True;
+    end;
+    Check(ok,Format('This conversion should fail : "%s".',[AString]));
+  end;
+
+begin
+  locObj := getObject();
+  CheckEquals(-123456, locObj.StringToInteger('-123456'));
+  CheckEquals(0, locObj.StringToInteger('0'));
+  CheckEquals(1, locObj.StringToInteger('1'));
+  CheckEquals(123456, locObj.StringToInteger('123456'));
+  check_invalid('');
+  check_invalid('xxxxx');
+  check_invalid('1235dd');
+  check_invalid('a2522');
+end;
+
+procedure TSDOConvertHelper_Test.StringToLong();
+var
+  locObj : TSDOConvertHelperClass;
+
+  procedure check_invalid(const AString : TSDOString);
+  var
+    Ok : boolean;
+  begin
+    ok := False;
+    try
+      locObj.StringToLong(AString);
+    except
+      on e : ESDOInvalidConversionException do
+        ok := True;
+    end;
+    Check(ok,Format('This conversion should fail : "%s".',[AString]));
+  end;
+
+begin
+  locObj := getObject();
+  CheckEquals(-123456, locObj.StringToLong('-123456'));
+  CheckEquals(0, locObj.StringToLong('0'));
+  CheckEquals(1, locObj.StringToLong('1'));
+  Check(Int64(High(LongWord)) + 10 = locObj.StringToLong(IntToStr(Int64(High(LongWord)) + 10)));
+  check_invalid('');
+  check_invalid('xxxxx');
+  check_invalid('1235dd');
+  check_invalid('a2522');
+end;
+
+procedure TSDOConvertHelper_Test.StringToShort();
+var
+  locObj : TSDOConvertHelperClass;
+
+  procedure check_invalid(const AString : TSDOString);
+  var
+    Ok : boolean;
+  begin
+    ok := False;
+    try
+      locObj.StringToShort(AString);
+    except
+      on e : ESDOInvalidConversionException do
+        ok := True;
+    end;
+    Check(ok,Format('This conversion should fail : "%s".',[AString]));
+  end;
+
+begin
+  locObj := getObject();
+  CheckEquals(-1234, locObj.StringToShort('-1234'));
+  CheckEquals(0, locObj.StringToShort('0'));
+  CheckEquals(1, locObj.StringToShort('1'));
+  CheckEquals(1234, locObj.StringToShort('1234'));
+  check_invalid('');
+  check_invalid('xxxxx');
+  check_invalid('1235dd');
+  check_invalid('a2522');
+end;
+
+procedure TSDOConvertHelper_Test.BytesToString();
+const
+  LEN = 1000;
+var
+  locObj : TSDOConvertHelperClass;
+  buff : TSDOBytes;
+  strBuff : TSDOString;
+  ansiStrBuff : AnsiString;
+  i : Integer;
+begin
+  locObj := getObject();
+  SetLength(buff,LEN);
+  for i := 0 to Pred(LEN) do
+    buff[i] := ( i mod High(TSDOByte) );
+
+  CheckEquals('', locObj.BytesToString(nil));
+
+  SetLength(ansiStrBuff,LEN * 2);
+  BinToHex(PAnsiChar(buff),PAnsiChar(ansiStrBuff),LEN);
+  strBuff := ansiStrBuff;
+  CheckEquals(strBuff,locObj.BytesToString(buff));
+end;
+
+procedure TSDOConvertHelper_Test.StringToBytes();
+const
+  LEN = 1000;
+var
+  locObj : TSDOConvertHelperClass;
+  buff, calcBuff : TSDOBytes;
+  strBuff : TSDOString;
+  ansiStrBuff : AnsiString;
+  i : Integer;
+begin
+  locObj := getObject();
+  SetLength(buff,LEN);
+  for i := 0 to Pred(LEN) do
+    buff[i] := ( i mod High(TSDOByte) );
+  SetLength(ansiStrBuff,LEN * 2);
+  BinToHex(PAnsiChar(buff),PAnsiChar(ansiStrBuff),LEN);
+  strBuff := ansiStrBuff;
+
+  CheckEquals(PtrUInt(nil), PtrUInt(locObj.StringToBytes('')));
+  calcBuff := locObj.StringToBytes(strBuff);
+  Check(CompareMem(Pointer(buff),Pointer(calcBuff),LEN));
+end;
+
+initialization
+  RegisterTest('Helpers',TSDOConvertHelper_Test.Suite);
+
+end.

+ 779 - 0
packages/fcl-sdo/tests/test_suite/test_copyhelper.pas

@@ -0,0 +1,779 @@
+{$INCLUDE sdo_global.inc}
+unit test_copyhelper;
+
+interface
+uses
+  SysUtils, Classes//, Dialogs
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , sdo, sdo_types, sdo_copyhelper, sdo_equalityhelper, test_suite_utils ;
+
+type
+
+  TSDOCopyHelper_Test = class(TWstBaseTest)
+  private
+    FFactory : ISDODataFactory;
+  private
+    function CreateFactory() : ISDODataFactory;
+    function CreateCopyHelper() : TSDOCopyHelperClass;
+    function createObjA(const AUri : string; const AFact : ISDODataFactory) : ISDODataObject;
+    function createObjB(const AUri : string; const AFact : ISDODataFactory) : ISDODataObject;
+    function createObjC(const AUri : string; const AFact : ISDODataFactory) : ISDODataObject;
+  protected
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+  published
+    procedure shallow_copy_nil_obj();
+    procedure shallow_copy_empty_obj();
+    procedure shallow_copy();
+    procedure shallow_copy_cursorPos();
+
+    procedure copy_nil_obj();
+    procedure copy_empty_obj();
+    procedure copy();
+    procedure copy_cursorPos();
+  end;
+
+implementation
+uses sdo_datafactory, sdo_linked_list;
+
+const
+  s_uri              = 'urn-test';
+  s_type_object_A    = 'objectA';
+  s_type_object_B    = 'objectB';
+  s_type_object_C    = 'objectC';
+  s_type_object_D    = 'objectD';
+  s_bool_prop        = 'bool_prop';            s_bool_propList      = 'bool_prop_list';
+  s_byte_prop        = 'byte_prop';            s_byte_propList      = 'byte_prop_list';
+  s_bytes_prop       = 'bytes_prop';           s_bytes_propList     = 'bytes_prop_list';
+  s_char_prop        = 'char_prop';            s_char_propList      = 'char_prop_list';
+  s_currency_prop    = 'currency_prop';        s_currency_propList  = 'currency_prop_list';
+  s_date_prop        = 'date_prop';            s_date_propList      = 'date_prop_list';
+  s_double_prop      = 'double_prop';          s_double_propList    = 'double_prop_list';
+  s_float_prop       = 'float_prop';           s_float_propList     = 'float_prop_list';
+  s_integer_prop     = 'integer_prop';         s_integer_propList   = 'integer_prop_list';
+  s_long_prop        = 'long_prop';            s_long_propList      = 'long_prop_list';
+  s_short_prop       = 'short_prop';           s_short_propList     = 'short_prop_list';
+  s_string_prop      = 'string_prop';          s_string_propList    = 'string_prop_list';
+  s_object_prop      = 'object_prop';          s_object_propList    = 'object_prop_list';
+  s_object_ref_prop      = 'object_ref_prop';
+
+  CURRENCY_CONT_ARRAY : array[0..3] of TSDOCurrency = (
+    123456789.3258, 0, -1478369.9876, -5869.9831
+  );
+  
+  DOUBLE_CONT_ARRAY : array[0..3] of TSDODouble = (
+    123456789.3258942121, 0, -147258369.987654321, -58369.98321
+  );
+
+  FLOAT_CONT_ARRAY : array[0..3] of TSDOFloat = (
+    -123789.325121, -96321.558, 0, 83629.5851
+  );
+
+{ TSDOCopyHelper_Test }
+
+procedure TSDOCopyHelper_Test.copy();
+var
+  locA, locB, locC, locD : ISDODataObject;
+  locA1, locB1, locC1, locD1 : ISDODataObject;
+begin
+  locA := createObjA(s_uri,FFactory);
+  locB := createObjB(s_uri,FFactory);
+  locC := createObjC(s_uri,FFactory);
+  locD := FFactory.createNew(s_uri,s_type_object_D);
+
+  locA1 := TSDOCopyHelper.copyShallow(locA);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locA,locA1));
+
+  locB1 := TSDOCopyHelper.copyShallow(locB);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locB,locB1));
+
+  locC1 := TSDOCopyHelper.copyShallow(locC);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locC,locC1));
+
+  locD1 := TSDOCopyHelper.copyShallow(locD);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locD,locD1));
+end;
+
+procedure TSDOCopyHelper_Test.copy_empty_obj();
+var
+  locA, locB, locC, locD : ISDODataObject;
+  locA1, locB1, locC1, locD1 : ISDODataObject;
+begin
+  locA := FFactory.createNew(s_uri,s_type_object_A);
+  locB := FFactory.createNew(s_uri,s_type_object_B);
+  locC := FFactory.createNew(s_uri,s_type_object_C);
+  locD := FFactory.createNew(s_uri,s_type_object_D);
+
+  locA1 := TSDOCopyHelper.copyShallow(locA);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locA,locA1));
+
+  locB1 := TSDOCopyHelper.copyShallow(locB);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locB,locB1));
+
+  locC1 := TSDOCopyHelper.copyShallow(locC);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locC,locC1));
+
+  locD1 := TSDOCopyHelper.copyShallow(locD);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locD,locD1));
+end;
+
+procedure TSDOCopyHelper_Test.copy_nil_obj();
+var
+  locX : ISDODataObject;
+begin
+  locX := CreateCopyHelper().copy(nil);
+  CheckEquals(PtrUInt(nil), PtrUInt(locX));
+end;
+
+function TSDOCopyHelper_Test.CreateCopyHelper() : TSDOCopyHelperClass;
+begin
+  Result := TSDOCopyHelper;
+end;
+
+function TSDOCopyHelper_Test.CreateFactory() : ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY} 
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}        
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+
+  procedure Add_ObjectB();
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(s_uri,s_type_object_B,[]);
+    locObj := locFactory.getType(s_uri,s_type_object_B);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY} 
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+
+      locFactory.addProperty(locObj,s_object_prop,s_uri,s_type_object_A,[pfIsContainment]);
+      locFactory.addProperty(locObj,s_object_ref_prop,s_uri,s_type_object_A,[]);
+      locFactory.addProperty(locObj,s_object_propList,s_uri,s_type_object_A,[pfIsMany,pfIsContainment]);
+  end;
+
+  procedure Add_ObjectC();
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(s_uri,s_type_object_C,[]);
+    locObj := locFactory.getType(s_uri,s_type_object_C);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}        
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}        
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+
+  procedure Add_ObjectD();
+  begin
+    locFactory.AddType(s_uri,s_type_object_D,[]);
+  end;
+
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+  Add_ObjectB();
+  Add_ObjectC();
+  Add_ObjectD();
+  Result := locFactory;
+end;
+
+function TSDOCopyHelper_Test.createObjA(const AUri: string; const AFact: ISDODataFactory): ISDODataObject;
+const
+  VAL_1 : TSDODate = ( Date : 35000; HourOffset : 3; MinuteOffset : 4; );
+  VAL_2 : TSDODate = ( Date : 40000; HourOffset : 0; MinuteOffset : 0; );
+  VAL_3 : TSDODate = ( Date : 38000; HourOffset : 5; MinuteOffset : 45; );
+  VAL_4 : TSDODate = ( Date : 39000; HourOffset : 6; MinuteOffset : 55; );
+var
+  VAL_1_BYTES, VAL_2_BYTES, VAL_3_BYTES, VAL_4_BYTES : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(TSDOByte);
+    VAL_1_BYTES := v;
+    v := nil;    
+
+    VAL_2_BYTES := nil;
+
+    SetLength(v,20);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(TSDOByte);
+    VAL_3_BYTES := v;
+    v := nil;  
+
+    SetLength(v,30);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(TSDOByte);
+    VAL_4_BYTES := v;
+    v := nil;
+  end;
+
+var
+  ls : ISDODataObjectList;
+begin
+  SetConstants();
+  Result := AFact.createNew(AUri,s_type_object_A);
+  Result.setBoolean(s_bool_prop,True);
+  Result.setByte(s_byte_prop,123);
+{$IFDEF HAS_SDO_BYTES}
+  Result.setBytes(s_bytes_prop,VAL_1_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+  Result.setCharacter(s_char_prop,'x');
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  Result.setCurrency(s_currency_prop,123.4567);
+{$ENDIF HAS_SDO_CURRENCY}
+  Result.setDate(s_date_prop,VAL_1);
+{$IFDEF HAS_SDO_DOUBLE}
+  Result.setDouble(s_double_prop,78.3654);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  Result.setFloat(s_float_prop,-159.753);
+{$ENDIF HAS_SDO_FLOAT}
+  Result.setInteger(s_integer_prop,1210);
+{$IFDEF HAS_SDO_LONG}
+  Result.setLong(s_long_prop,123456789987654321);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  Result.setShort(s_short_prop,6541);
+{$ENDIF HAS_SDO_SHORT}
+  Result.setString(s_string_prop,'inoussa wst fpc');
+
+  ls := Result.getList(s_bool_propList);
+    ls.append(True);
+    ls.append(True);
+    ls.append(False);
+    ls.append(True);
+    ls.append(False);
+
+  ls := Result.getList(s_byte_propList);
+    ls.append(TSDOByte(1));
+    ls.append(TSDOByte(2));
+    ls.append(TSDOByte(3));
+
+{$IFDEF HAS_SDO_BYTES}
+  ls := Result.getList(s_bytes_propList);
+    ls.appendBytes(VAL_1_BYTES);
+    ls.appendBytes(VAL_2_BYTES);
+    ls.appendBytes(VAL_3_BYTES);
+    ls.appendBytes(VAL_4_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  ls := Result.getList(s_char_propList);
+    ls.append(TSDOChar('a'));
+    ls.append(TSDOChar('b'));
+    ls.append(TSDOChar('p'));
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  ls := Result.getList(s_currency_propList);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[0]);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[1]);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[2]);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[3]);
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+  ls := Result.getList(s_double_propList);
+    ls.append(DOUBLE_CONT_ARRAY[0]);
+    ls.append(DOUBLE_CONT_ARRAY[1]);
+    ls.append(DOUBLE_CONT_ARRAY[2]);
+    ls.append(DOUBLE_CONT_ARRAY[3]);
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  ls := Result.getList(s_float_propList);
+    ls.append(FLOAT_CONT_ARRAY[0]);
+    ls.append(FLOAT_CONT_ARRAY[1]);
+    ls.append(FLOAT_CONT_ARRAY[2]);
+    ls.append(FLOAT_CONT_ARRAY[3]);
+{$ENDIF HAS_SDO_FLOAT}
+
+  ls := Result.getList(s_date_propList);
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+    ls.append(VAL_3);
+    ls.append(VAL_4);
+
+  ls := Result.getList(s_integer_propList);
+    ls.append(TSDOInteger(12));
+    ls.append(TSDOInteger(10));
+    ls.append(TSDOInteger(76));
+    ls.append(TSDOInteger(-123));
+    ls.append(TSDOInteger(0));
+
+{$IFDEF HAS_SDO_LONG}
+  ls := Result.getList(s_long_propList);
+    ls.append(TSDOLong(748159623849516236));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3692581479137842655));
+    ls.append(TSDOLong(112233445566778899));
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  ls := Result.getList(s_short_propList);
+    ls.append(TSDOLong(7481));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3655));
+    ls.append(TSDOLong(8899));
+{$ENDIF HAS_SDO_ShORT}
+
+  ls := Result.getList(s_string_propList);
+    ls.append(TSDOString('object'));
+    ls.append(TSDOString(''));
+    ls.append(TSDOString('pascal'));
+    ls.append(TSDOString('Lazarus'));
+    ls.append(TSDOString('Delphi'));
+end;
+
+function TSDOCopyHelper_Test.createObjB(const AUri: string; const AFact: ISDODataFactory): ISDODataObject;
+const
+  VAL_1 : TSDODate = ( Date : 45678; HourOffset : 3; MinuteOffset : 4; );
+  VAL_2 : TSDODate = ( Date : 41234; HourOffset : 0; MinuteOffset : 0; );
+  VAL_3 : TSDODate = ( Date : 38976; HourOffset : 5; MinuteOffset : 45; );
+  VAL_4 : TSDODate = ( Date : 39254; HourOffset : 6; MinuteOffset : 55; );
+var
+  VAL_1_BYTES, VAL_2_BYTES, VAL_3_BYTES, VAL_4_BYTES : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,5);
+    for k := 0 to High(v) do
+      v[k] := k mod High(TSDOByte);
+    VAL_1_BYTES := v;
+    v := nil;    
+
+    VAL_2_BYTES := nil;
+
+    SetLength(v,23);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(TSDOByte);
+    VAL_3_BYTES := v;
+    v := nil;  
+
+    SetLength(v,35);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(TSDOByte);
+    VAL_4_BYTES := v;
+    v := nil;
+  end;
+
+var
+  ls : ISDODataObjectList;
+begin
+  SetConstants();
+  Result := AFact.createNew(AUri,s_type_object_B);
+  Result.setBoolean(s_bool_prop,True);
+  Result.setByte(s_byte_prop,123);
+{$IFDEF HAS_SDO_BYTES}
+  Result.setBytes(s_bytes_prop,VAL_1_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+  Result.setCharacter(s_char_prop,'l');
+{$ENDIF HAS_SDO_CHAR}
+  Result.setDate(s_date_prop,VAL_2);
+{$IFDEF HAS_SDO_DOUBLE}
+  Result.setDouble(s_double_prop,8521.0255);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  Result.setFloat(s_float_prop,-5852.655753);
+{$ENDIF HAS_SDO_FLOAT}
+  Result.setInteger(s_integer_prop,1210);
+{$IFDEF HAS_SDO_LONG}
+  Result.setLong(s_long_prop,123456789987654321);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  Result.setShort(s_short_prop,6541);
+{$ENDIF HAS_SDO_SHORT}
+  Result.setString(s_string_prop,'inoussa wst fpc');
+
+  ls := Result.getList(s_bool_propList);
+    ls.append(True);
+    ls.append(True);
+    ls.append(False);
+    ls.append(True);
+    ls.append(False);
+
+  ls := Result.getList(s_byte_propList);
+    ls.append(1);
+    ls.append(2);
+    ls.append(3);
+
+{$IFDEF HAS_SDO_BYTES}
+  ls := Result.getList(s_bytes_propList);
+    ls.appendBytes(VAL_1_BYTES);
+    ls.appendBytes(VAL_2_BYTES);
+    ls.appendBytes(VAL_3_BYTES);
+    ls.appendBytes(VAL_4_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  ls := Result.getList(s_char_propList);
+    ls.append(TSDOChar('a'));
+    ls.append(TSDOChar('b'));
+    ls.append(TSDOChar('p'));
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  ls := Result.getList(s_currency_propList);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[0]);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[1]);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[2]);
+    ls.appendCurrency(CURRENCY_CONT_ARRAY[3]);
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+  ls := Result.getList(s_double_propList);
+    ls.append(DOUBLE_CONT_ARRAY[0]);
+    ls.append(DOUBLE_CONT_ARRAY[1]);
+    ls.append(DOUBLE_CONT_ARRAY[2]);
+    ls.append(DOUBLE_CONT_ARRAY[3]);
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  ls := Result.getList(s_float_propList);
+    ls.append(FLOAT_CONT_ARRAY[0]);
+    ls.append(FLOAT_CONT_ARRAY[1]);
+    ls.append(FLOAT_CONT_ARRAY[2]);
+    ls.append(FLOAT_CONT_ARRAY[3]);
+{$ENDIF HAS_SDO_FLOAT}
+
+  ls := Result.getList(s_date_propList);
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+    ls.append(VAL_3);
+    ls.append(VAL_4);
+        
+  ls := Result.getList(s_integer_propList);
+    ls.append(12);
+    ls.append(10);
+    ls.append(76);
+    ls.append(-123);
+    ls.append(0);
+
+{$IFDEF HAS_SDO_LONG}
+  ls := Result.getList(s_long_propList);
+    ls.append(TSDOLong(7481596238495162375));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3692581479137842655));
+    ls.append(TSDOLong(112233445566778899));
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  ls := Result.getList(s_short_propList);
+    ls.append(TSDOLong(7481));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3655));
+    ls.append(TSDOLong(8899));
+{$ENDIF HAS_SDO_ShORT}
+
+  ls := Result.getList(s_string_propList);
+    ls.append('object');
+    ls.append('');
+    ls.append('pascal');
+    ls.append('Lazarus');
+    ls.append('Delphi');
+
+  Result.setDataObject(s_object_prop,AFact.createNew(s_uri,s_type_object_A));
+    Result.getDataObject(s_object_prop).setString(s_string_prop,'B->A->' + s_string_prop);
+  Result.setDataObject(s_object_ref_prop,AFact.createNew(s_uri,s_type_object_A));
+    Result.getDataObject(s_object_ref_prop).setString(s_string_prop,'ref B->A->' + s_string_prop);
+  ls := Result.getList(s_object_propList);
+    ls.append(AFact.createNew(AUri,s_type_object_A));
+    ls.append(AFact.createNew(AUri,s_type_object_A));
+    ls.getCursor().MoveFirst();
+      ls.getDataObject().setString(s_string_prop,'B->A[0]->' + s_string_prop);
+    ls.getCursor().MoveNext();
+      ls.getDataObject().setString(s_string_prop,'B->A[1]->' + s_string_prop);
+end;
+
+function TSDOCopyHelper_Test.createObjC(const AUri: string; const AFact: ISDODataFactory): ISDODataObject;
+const
+  VAL_1 : TSDODate = ( Date : 38678; HourOffset : 3; MinuteOffset : 4; );
+  VAL_2 : TSDODate = ( Date : 39234; HourOffset : 0; MinuteOffset : 0; );
+  VAL_3 : TSDODate = ( Date : 40976; HourOffset : 5; MinuteOffset : 45; );
+  VAL_4 : TSDODate = ( Date : 41254; HourOffset : 6; MinuteOffset : 55; );
+var
+  ls : ISDODataObjectList;
+begin
+  Result := AFact.createNew(AUri,s_type_object_A);
+  Result.setBoolean(s_bool_prop,True);
+  Result.setByte(s_byte_prop,123);
+  Result.setDate(s_date_prop,VAL_3);
+  Result.setInteger(s_integer_prop,1210);
+  Result.setString(s_string_prop,'inoussa wst fpc');
+
+  ls := Result.getList(s_bool_propList);
+    ls.append(True);
+    ls.append(True);
+    ls.append(False);
+    ls.append(True);
+    ls.append(False);
+
+  ls := Result.getList(s_byte_propList);
+    ls.append(1);
+    ls.append(2);
+    ls.append(3);
+
+  ls := Result.getList(s_date_propList);
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+    ls.append(VAL_3);
+    ls.append(VAL_4);    
+        
+  ls := Result.getList(s_integer_propList);
+    ls.append(12);
+    ls.append(10);
+    ls.append(76);
+    ls.append(-123);
+    ls.append(0);
+
+  ls := Result.getList(s_string_propList);
+    ls.append('object');
+    ls.append('');
+    ls.append('pascal');
+    ls.append('Lazarus');
+    ls.append('Delphi');
+end;
+
+procedure TSDOCopyHelper_Test.shallow_copy_cursorPos();
+var
+  x, y : ISDODataObject;
+  lsB, lsI : ISDODataObjectList;
+  bmB, bmI : TLinkedListBookmark;
+begin
+  x := createObjA(s_uri, FFactory);
+    lsB := x.getList(s_bool_propList);
+      lsB.getCursor().MoveFirst();
+      lsB.getCursor().MoveNext();
+      lsB.getCursor().MoveNext();
+    lsI := x.getList(s_integer_propList);
+      lsI.getCursor().MoveLast();
+      lsI.getCursor().MovePrevious();
+    bmB := lsB.getCursor().GetBookmark();
+    bmI := lsI.getCursor().GetBookmark();
+
+  y := TSDOCopyHelper.copyShallow(x);
+    CheckEquals(bmB,lsB.getCursor().GetBookmark());
+    CheckEquals(bmI,lsI.getCursor().GetBookmark());
+end;
+
+procedure TSDOCopyHelper_Test.SetUp();
+begin
+  inherited;
+  FFactory := CreateFactory();
+end;
+
+procedure TSDOCopyHelper_Test.shallow_copy();
+var
+  locA, locB, locC, locD : ISDODataObject;
+  locA1, locB1, locC1, locD1 : ISDODataObject;
+begin
+  locA := createObjA(s_uri,FFactory);
+  locB := createObjB(s_uri,FFactory);
+  locC := createObjC(s_uri,FFactory);
+  locD := FFactory.createNew(s_uri,s_type_object_D);
+
+  locA1 := TSDOCopyHelper.copyShallow(locA);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locA,locA1));
+
+  locB1 := TSDOCopyHelper.copyShallow(locB);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locB,locB1));
+
+  locC1 := TSDOCopyHelper.copyShallow(locC);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locC,locC1));
+
+  locD1 := TSDOCopyHelper.copyShallow(locD);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locD,locD1));
+end;
+
+procedure TSDOCopyHelper_Test.shallow_copy_empty_obj();
+var
+  locA, locB, locC, locD : ISDODataObject;
+  locA1, locB1, locC1, locD1 : ISDODataObject;
+begin
+  locA := FFactory.createNew(s_uri,s_type_object_A);
+  locB := FFactory.createNew(s_uri,s_type_object_B);
+  locC := FFactory.createNew(s_uri,s_type_object_C);
+  locD := FFactory.createNew(s_uri,s_type_object_D);
+
+  locA1 := TSDOCopyHelper.copyShallow(locA);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locA,locA1));
+
+  locB1 := TSDOCopyHelper.copyShallow(locB);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locB,locB1));
+
+  locC1 := TSDOCopyHelper.copyShallow(locC);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locC,locC1));
+
+  locD1 := TSDOCopyHelper.copyShallow(locD);
+    CheckEquals(True, TSDOEqualityHelper.equalShallow(locD,locD1));
+end;
+
+procedure TSDOCopyHelper_Test.shallow_copy_nil_obj();
+var
+  locX : ISDODataObject;
+begin
+  locX := CreateCopyHelper().copy(nil);
+  CheckEquals(PtrUInt(nil), PtrUInt(locX));
+end;
+
+procedure TSDOCopyHelper_Test.TearDown();
+begin
+  FFactory := nil;
+  inherited;
+end;
+
+procedure TSDOCopyHelper_Test.copy_cursorPos();
+var
+  x, y : ISDODataObject;
+  lsB, lsI : ISDODataObjectList;
+  bmB, bmI : TLinkedListBookmark;
+begin
+  x := createObjA(s_uri, FFactory);
+    lsB := x.getList(s_bool_propList);
+      lsB.getCursor().MoveFirst();
+      lsB.getCursor().MoveNext();
+      lsB.getCursor().MoveNext();
+    lsI := x.getList(s_integer_propList);
+      lsI.getCursor().MoveLast();
+      lsI.getCursor().MovePrevious();
+    bmB := lsB.getCursor().GetBookmark();
+    bmI := lsI.getCursor().GetBookmark();
+
+  y := TSDOCopyHelper.copyShallow(x);
+    CheckEquals(bmB,lsB.getCursor().GetBookmark());
+    CheckEquals(bmI,lsI.getCursor().GetBookmark());
+end;
+
+initialization
+  RegisterTest('Helpers',TSDOCopyHelper_Test.Suite);
+
+end.

+ 6626 - 0
packages/fcl-sdo/tests/test_suite/test_dataobject.pas

@@ -0,0 +1,6626 @@
+{$INCLUDE sdo_global.inc}
+unit test_dataobject;
+
+interface
+uses SysUtils
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , test_suite_utils, sdo, sdo_type, sdo_types, sdo_field_imp ;
+
+type
+
+  TSDOBaseDataObject_Test = class(TWstBaseTest)
+  private
+    FFactory : ISDODataFactory;
+  protected
+    class function is_open_type() : Boolean;virtual;abstract;
+    class function Create_Factory() : ISDODataFactory;
+    class function GetTestSuitePath() : string;
+    function Create_Object() : ISDODataObject;
+    procedure check_xpath_value(
+      const AExpected : TSDOInteger;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+    procedure check_xpath_value(
+      const AExpected : TSDOByte;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+    procedure check_xpath_value(
+      const AExpected : TSDOBoolean;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+    procedure check_xpath_value(
+      const AExpected : TSDODateTime;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+    procedure check_xpath_value(
+      const AExpected : TSDOString;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$IFDEF HAS_SDO_BYTES}
+    procedure check_xpath_value(
+      const AExpected : TSDOBytes;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure check_xpath_value(
+      const AExpected : TSDOChar;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure check_xpath_value_currency(
+      const AExpected : TSDOCurrency;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure check_xpath_value(
+      const AExpected : TSDODouble;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure check_xpath_value(
+      const AExpected : TSDOFloat;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure check_xpath_value(
+      const AExpected : TSDOLong;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure check_xpath_value(
+      const AExpected : TSDOShort;
+      const AObject : ISDODataObject;
+      const AXPath : string
+    );overload;
+{$ENDIF HAS_SDO_SHORT}
+  protected
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+  public
+    procedure CheckEquals(expected, actual: TSDODateTime; msg: string = ''; const AStrict : Boolean = True); overload;
+  published
+    procedure IsInstanceOf();
+    procedure object_destroy_order();
+    procedure object_getChangeSummary();
+    procedure object_getChangeSummary_multiprop();
+    procedure object_setDataObject_cycle_containment();
+    procedure object_setDataObject_ref();
+    procedure object_setDataObject_ref_nil();
+    procedure object_setDataObject_ref_nil_nested();
+    procedure object_setDataObject_ref_unset();
+    procedure object_setDataObject_ref_unset_nested();
+    procedure object_setDataObject_ref_setnull();
+    procedure object_setDataObject_ref_setnull_nested();
+
+
+    procedure boolean_procs();
+    procedure byte_procs();
+    procedure integer_procs();
+    procedure string_procs();
+    procedure object_procs();
+    procedure date_procs();
+{$IFDEF HAS_SDO_BYTES}
+    procedure bytes_procs();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure char_procs();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure currency_procs();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure double_procs();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure float_procs();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure long_procs();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure short_procs();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure byte_multivalue();
+    procedure date_multivalue();
+    procedure integer_multivalue();
+    procedure object_ref_multivalue();
+    procedure object_cont_multivalue();
+{$IFDEF HAS_SDO_BYTES}
+    procedure bytes_multivalue();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure char_multivalue();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure currency_multivalue();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure double_multivalue();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure float_multivalue();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure long_multivalue();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure short_multivalue();
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure integer_unset_isset();
+    procedure boolean_unset_isset();
+    procedure byte_unset_isset();
+    procedure string_unset_isset();
+    procedure object_unset_isset();
+    procedure date_unset_isset();
+{$IFDEF HAS_SDO_BYTES}
+    procedure bytes_unset_isset();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure char_unset_isset();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure currency_unset_isset();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure double_unset_isset();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure float_unset_isset();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure long_unset_isset();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure short_unset_isset();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure integer_setnull_isnull();
+    procedure boolean_setnull_isnull();
+    procedure byte_setnull_isnull();
+    procedure string_setnull_isnull();
+    procedure date_setnull_isnull();
+{$IFDEF HAS_SDO_BYTES}
+    procedure bytes_setnull_isnull();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure char_setnull_isnull();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure currency_setnull_isnull();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure double_setnull_isnull();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure float_setnull_isnull();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure long_setnull_isnull();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure short_setnull_isnull();
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure property_default_value_integer();
+    procedure property_default_value_bool();
+    procedure property_default_value_byte();
+    procedure property_default_value_string();
+    procedure property_default_value_date();
+{$IFDEF HAS_SDO_BYTES}
+    procedure property_default_value_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure property_default_value_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure property_default_value_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure property_default_value_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure property_default_value_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure property_default_value_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure property_default_value_short();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure property_default_value_unset_integer();
+    procedure property_default_value_unset_bool();
+    procedure property_default_value_unset_byte();
+    procedure property_default_value_unset_string();
+    procedure property_default_value_unset_date();
+{$IFDEF HAS_SDO_BYTES}
+    procedure property_default_value_unset_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure property_default_value_unset_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure property_default_value_unset_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure property_default_value_unset_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure property_default_value_unset_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure property_default_value_unset_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure property_default_value_unset_short();
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure get_bool_xpath();
+    procedure get_byte_xpath();
+    procedure get_date_xpath();
+    procedure get_integer_xpath();
+    procedure get_string_xpath();
+{$IFDEF HAS_SDO_BYTES}
+    procedure get_bytes_xpath();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure get_char_xpath();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure get_currency_xpath();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure get_double_xpath();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure get_float_xpath();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure get_long_xpath();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure get_short_xpath();
+{$ENDIF HAS_SDO_SHORT}
+  end;
+
+  TSDODataObject_Test = class(TSDOBaseDataObject_Test)
+  protected
+    class function is_open_type() : Boolean;override;
+  end;
+
+  TSDOOpenedDataObject_Test = class(TSDOBaseDataObject_Test)
+  protected
+    class function is_open_type() : Boolean;override;
+    procedure check_property(
+      const APropList : ISDOPropertyList;
+      const AName : string;
+      const AType : ISDOType;
+      const AFlags : TPropertyFlags
+    );
+  published
+    procedure addProperty();
+    procedure addProperty_error();
+    procedure addProperty_byte();
+    procedure addProperty_date();
+{$IFDEF HAS_SDO_BYTES}
+    procedure addProperty_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure addProperty_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure addProperty_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure addProperty_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure addProperty_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure addProperty_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure addProperty_short();
+{$ENDIF HAS_SDO_SHORT}
+
+
+    procedure addProperty_multi_value();
+    procedure addProperty_multi_value_byte();
+    procedure addProperty_multi_value_date();
+{$IFDEF HAS_SDO_BYTES}
+    procedure addProperty_multi_value_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure addProperty_multi_value_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure addProperty_multi_value_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure addProperty_multi_value_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure addProperty_multi_value_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure addProperty_multi_value_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure addProperty_multi_value_short();
+{$ENDIF HAS_SDO_SHORT}
+
+    procedure implicit_add_property();
+    procedure implicit_add_property_byte();
+    procedure implicit_add_property_date();
+{$IFDEF HAS_SDO_BYTES}
+    procedure implicit_add_property_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure implicit_add_property_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure implicit_add_property_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure implicit_add_property_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure implicit_add_property_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure implicit_add_property_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure implicit_add_property_short();
+{$ENDIF HAS_SDO_SHORT}
+  end;
+
+  TObserver_Test = class(TTestCase)
+  published
+    procedure ObserverInfo_create();
+
+    procedure ObserverList_add_find();
+  end;
+
+implementation
+
+uses
+  sdo_datafactory, Math, sdo_linked_list, sdo_dataobject,
+  sdo_consts, DateUtils, sdo_date_utils;
+
+const s_URI_1  = 'uri:1'; s_URI_3 = 'uri:3';
+      s_TYPE_1 = 'type1'; s_TYPE_2 = 'type2'; s_TYPE_3 = 'type3'; s_TYPE_4 = 'type4';
+      s_PROP_BOOL_1 = 'propboolean1';
+        s_PROP_BOOL_2 = 'propboolean2';
+        s_PROP_BOOL_3 = 'propboolean3';
+      s_PROP_BYTE_1 = 'propbyte1';
+        s_PROP_BYTE_2 = 'propbyte2';
+        s_PROP_BYTE_3 = 'propbyte3';
+      s_PROP_BYTES_1 = 'propbytes1';
+        s_PROP_BYTES_2 = 'propbytes2';
+        s_PROP_BYTES_3 = 'propbytes3';
+      s_PROP_CHAR_1 = 'propchar1';
+        s_PROP_CHAR_2 = 'propchar2';
+        s_PROP_CHAR_3 = 'propchar3';
+      s_PROP_CURRENCY_1 = 'propcurrency1';
+        s_PROP_CURRENCY_2 = 'propcurrency2';
+        s_PROP_CURRENCY_3 = 'propcurrency3';
+      s_PROP_DATE_1 = 'propdate1';
+        s_PROP_DATE_2 = 'propdate2';
+        s_PROP_DATE_3 = 'propdate3';
+      s_PROP_DOUBLE_1 = 'propdouble1';
+        s_PROP_DOUBLE_2 = 'propdouble2';
+        s_PROP_DOUBLE_3 = 'propdouble3';
+      s_PROP_FLOAT_1 = 'propfloat1';
+        s_PROP_FLOAT_2 = 'propfloat2';
+        s_PROP_FLOAT_3 = 'propfloat3';
+      s_PROP_INTEGER_1 = 'proplong1';
+        s_PROP_INTEGER_2 = 'proplong2';
+        s_PROP_INTEGER_3 = 'proplong3';
+      s_PROP_LONG_1 = 'propinteger1';
+        s_PROP_LONG_2 = 'propinteger2';
+        s_PROP_LONG_3 = 'propinteger3';
+      s_PROP_SHORT_1 = 'propshort1';
+        s_PROP_SHORT_2 = 'propshort2';
+        s_PROP_SHORT_3 = 'propshort3';
+      s_PROP_STR_1 = 'propStr1';
+        s_PROP_STR_2 = 'propStr2';
+        s_PROP_STR_3 = 'propStr3';
+      s_PROP_OBJ_CONT = 'propobj_cont';
+        s_PROP_OBJ_REF = 'propobj_ref';
+        s_PROP_OBJ_CONT_LIST = 'propobj_cont_list';
+        s_PROP_OBJ_REF_LIST = 'propobj_ref_list';
+
+      s_PROP_BOOL_A = 'propbooleanA';
+        s_PROP_BOOL_B = 'propbooleanB';
+      s_PROP_BYTE_A = 'propbyteA';
+        s_PROP_BYTE_B = 'propbyteB';
+      s_PROP_BYTES_A = 'propbytesA';
+        s_PROP_BYTES_B = 'propbytesB';
+      s_PROP_CHAR_A = 'propcharA';
+        s_PROP_CHAR_B = 'propcharB';
+      s_PROP_CURRENCY_A = 'propcurrencyA';
+        s_PROP_CURRENCY_B = 'propcurrencyB';
+      s_PROP_DATE_A = 'propdateA';
+        s_PROP_DATE_B = 'propdateB';
+      s_PROP_DOUBLE_A = 'propdoubleA';
+        s_PROP_DOUBLE_B = 'propdoubleB';
+      s_PROP_FLOAT_A = 'propfloatA';
+        s_PROP_FLOAT_B = 'propfloatB';
+      s_PROP_INTEGER_A = 'propintegerA';
+        s_PROP_INTEGER_B = 'propintegerB';
+      s_PROP_LONG_A = 'proplongA';
+        s_PROP_LONG_B = 'proplongB';
+      s_PROP_SHORT_A = 'propshortA';
+        s_PROP_SHORT_B = 'propshortB';
+      s_PROP_STR_A = 'propStrA';
+        s_PROP_STR_B = 'propStrB';
+
+{ TSDOBaseDataObject_Test }
+
+function TSDOBaseDataObject_Test.Create_Object() : ISDODataObject;
+begin
+  Result := FFactory.createNew(s_URI_1,s_TYPE_1);
+end;
+
+class function TSDOBaseDataObject_Test.Create_Factory() : ISDODataFactory;
+var
+  typ, typ2, typ3 : ISDOType;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  Result := TSDODataFactory.Create();
+  Result.AddType(s_URI_1,s_TYPE_1,tfg);
+  Result.AddType(s_URI_1,s_TYPE_2,tfg);
+  Result.AddType(s_URI_3,s_TYPE_3,tfg);
+  Result.AddType(s_URI_1,s_TYPE_4,tfg);
+  typ := Result.getType(s_URI_1,s_TYPE_1);
+    Result.addProperty(typ,s_PROP_BOOL_1,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ,s_PROP_BYTE_1,sdo_namespace,'Byte',[]);
+{$IFDEF HAS_SDO_BYTES}
+    Result.addProperty(typ,s_PROP_BYTES_1,sdo_namespace,'Bytes',[]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    Result.addProperty(typ,s_PROP_CHAR_1,sdo_namespace,'Character',[]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    Result.addProperty(typ,s_PROP_CURRENCY_1,sdo_namespace,'Currency',[]);
+{$ENDIF HAS_SDO_CURRENCY}
+    Result.addProperty(typ,s_PROP_DATE_1,sdo_namespace,'Date',[]);
+{$IFDEF HAS_SDO_DOUBLE}
+    Result.addProperty(typ,s_PROP_DOUBLE_1,sdo_namespace,'Double',[]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    Result.addProperty(typ,s_PROP_FLOAT_1,sdo_namespace,'Float',[]);
+{$ENDIF HAS_SDO_FLOAT}
+    Result.addProperty(typ,s_PROP_INTEGER_1,sdo_namespace,'Integer',[]);
+{$IFDEF HAS_SDO_LONG}
+    Result.addProperty(typ,s_PROP_LONG_1,sdo_namespace,'Long',[]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    Result.addProperty(typ,s_PROP_SHORT_1,sdo_namespace,'Short',[]);
+{$ENDIF HAS_SDO_SHORT}
+    Result.addProperty(typ,s_PROP_STR_1,sdo_namespace,'String',[]);
+
+    Result.addProperty(typ,s_PROP_BOOL_2,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ,s_PROP_BYTE_2,sdo_namespace,'Byte',[]);
+{$IFDEF HAS_SDO_BYTES}
+    Result.addProperty(typ,s_PROP_BYTES_2,sdo_namespace,'Bytes',[]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    Result.addProperty(typ,s_PROP_CHAR_2,sdo_namespace,'Character',[]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    Result.addProperty(typ,s_PROP_CURRENCY_2,sdo_namespace,'Currency',[]);
+{$ENDIF HAS_SDO_CURRENCY}
+    Result.addProperty(typ,s_PROP_DATE_2,sdo_namespace,'Date',[]);
+{$IFDEF HAS_SDO_DOUBLE}
+    Result.addProperty(typ,s_PROP_DOUBLE_2,sdo_namespace,'Double',[]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    Result.addProperty(typ,s_PROP_FLOAT_2,sdo_namespace,'Float',[]);
+{$ENDIF HAS_SDO_FLOAT}
+    Result.addProperty(typ,s_PROP_INTEGER_2,sdo_namespace,'Integer',[]);
+{$IFDEF HAS_SDO_LONG}
+    Result.addProperty(typ,s_PROP_LONG_2,sdo_namespace,'Long',[]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    Result.addProperty(typ,s_PROP_SHORT_2,sdo_namespace,'Short',[]);
+{$ENDIF HAS_SDO_SHORT}
+    Result.addProperty(typ,s_PROP_STR_2,sdo_namespace,'String',[]);
+    Result.addProperty(typ,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+    Result.addProperty(typ,s_PROP_OBJ_REF,s_URI_1,s_TYPE_2,[]);
+    Result.addProperty(typ,s_PROP_OBJ_CONT_LIST,s_URI_1,s_TYPE_2,[pfIsMany,pfIsContainment]);
+    Result.addProperty(typ,s_PROP_OBJ_REF_LIST,s_URI_1,s_TYPE_2,[pfIsMany]);
+
+    Result.addProperty(typ,s_PROP_BOOL_3,sdo_namespace,'Boolean',[pfIsMany]);
+    Result.addProperty(typ,s_PROP_BYTE_3,sdo_namespace,'Byte',[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+    Result.addProperty(typ,s_PROP_BYTES_3,sdo_namespace,'Bytes',[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    Result.addProperty(typ,s_PROP_CHAR_3,sdo_namespace,'Character',[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    Result.addProperty(typ,s_PROP_CURRENCY_3,sdo_namespace,'Currency',[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+    Result.addProperty(typ,s_PROP_DATE_3,sdo_namespace,'Date',[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+    Result.addProperty(typ,s_PROP_DOUBLE_3,sdo_namespace,'Double',[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    Result.addProperty(typ,s_PROP_FLOAT_3,sdo_namespace,'Float',[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+    Result.addProperty(typ,s_PROP_INTEGER_3,sdo_namespace,'Integer',[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+    Result.addProperty(typ,s_PROP_LONG_3,sdo_namespace,'Long',[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    Result.addProperty(typ,s_PROP_SHORT_3,sdo_namespace,'Short',[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+    Result.addProperty(typ,s_PROP_STR_3,sdo_namespace,'String',[pfIsMany]);
+
+  typ2 := Result.getType(s_URI_1,s_TYPE_2);
+    Result.addProperty(typ2,s_PROP_BOOL_A,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ2,s_PROP_BYTE_A,sdo_namespace,'Byte',[]);
+{$IFDEF HAS_SDO_BYTES}
+    Result.addProperty(typ2,s_PROP_BYTES_A,sdo_namespace,'Bytes',[]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    Result.addProperty(typ2,s_PROP_CHAR_A,sdo_namespace,'Character',[]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    Result.addProperty(typ2,s_PROP_CURRENCY_A,sdo_namespace,'Currency',[]);
+{$ENDIF HAS_SDO_CURRENCY}
+    Result.addProperty(typ2,s_PROP_DATE_A,sdo_namespace,'Date',[]);
+{$IFDEF HAS_SDO_DOUBLE}
+    Result.addProperty(typ2,s_PROP_DOUBLE_A,sdo_namespace,'Double',[]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    Result.addProperty(typ2,s_PROP_FLOAT_A,sdo_namespace,'Float',[]);
+{$ENDIF HAS_SDO_FLOAT}
+    Result.addProperty(typ2,s_PROP_INTEGER_A,sdo_namespace,'Integer',[]);
+{$IFDEF HAS_SDO_LONG}
+    Result.addProperty(typ2,s_PROP_LONG_A,sdo_namespace,'Long',[]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    Result.addProperty(typ2,s_PROP_SHORT_A,sdo_namespace,'Short',[]);
+{$ENDIF HAS_SDO_SHORT}
+    Result.addProperty(typ2,s_PROP_STR_A,sdo_namespace,'String',[]);
+    Result.addProperty(typ2,s_PROP_OBJ_CONT,s_URI_3,s_TYPE_3,[pfIsContainment]);
+
+  typ3 := Result.getType(s_URI_3,s_TYPE_3);
+    Result.addProperty(typ3,s_PROP_BOOL_2,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ3,s_PROP_BYTE_2,sdo_namespace,'Byte',[]);
+{$IFDEF HAS_SDO_BYTES}
+    Result.addProperty(typ3,s_PROP_BYTES_2,sdo_namespace,'Bytes',[]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    Result.addProperty(typ3,s_PROP_CHAR_2,sdo_namespace,'Character',[]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    Result.addProperty(typ3,s_PROP_CURRENCY_2,sdo_namespace,'Currency',[]);
+{$ENDIF HAS_SDO_CURRENCY}
+    Result.addProperty(typ3,s_PROP_DATE_2,sdo_namespace,'Date',[]);
+{$IFDEF HAS_SDO_DOUBLE}
+    Result.addProperty(typ3,s_PROP_DOUBLE_2,sdo_namespace,'Double',[]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    Result.addProperty(typ3,s_PROP_FLOAT_2,sdo_namespace,'Float',[]);
+{$ENDIF HAS_SDO_FLOAT}
+    Result.addProperty(typ3,s_PROP_INTEGER_2,sdo_namespace,'Integer',[]);
+{$IFDEF HAS_SDO_LONG}
+    Result.addProperty(typ3,s_PROP_LONG_2,sdo_namespace,'Long',[]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    Result.addProperty(typ3,s_PROP_SHORT_2,sdo_namespace,'Short',[]);
+{$ENDIF HAS_SDO_SHORT}
+    Result.addProperty(typ3,s_PROP_STR_2,sdo_namespace,'String',[]);
+    Result.addProperty(typ3,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_4,[pfIsContainment]);
+end;
+
+class function TSDOBaseDataObject_Test.GetTestSuitePath() : string;
+begin
+  Result := 'object';
+end;
+
+procedure TSDOBaseDataObject_Test.SetUp();
+begin
+  inherited;
+  FFactory := Create_Factory();
+end;
+
+procedure TSDOBaseDataObject_Test.TearDown();
+begin
+  FFactory := nil;
+  inherited;
+end;
+
+procedure TSDOBaseDataObject_Test.boolean_procs();
+const VAL_1 = True; VAL_2 = False;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setBoolean(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getBoolean(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setBoolean(obj.getProperty(s_PROP_BOOL_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setBoolean(obj.getProperty(s_PROP_BOOL_1),VAL_1);
+  CheckEquals(VAL_1,obj.getBoolean(obj.getProperty(s_PROP_BOOL_1)));
+  CheckEquals(VAL_1,obj.getBoolean(s_PROP_BOOL_1));
+  CheckEquals(VAL_1,obj.getBoolean(obj.getPropertyIndex(obj.getProperty(s_PROP_BOOL_1))));
+
+  obj.setBoolean(obj.getProperty(s_PROP_BOOL_1),VAL_2);
+  CheckEquals(VAL_2,obj.getBoolean(obj.getProperty(s_PROP_BOOL_1)));
+  CheckEquals(VAL_2,obj.getBoolean(s_PROP_BOOL_1));
+  CheckEquals(VAL_2,obj.getBoolean(obj.getPropertyIndex(obj.getProperty(s_PROP_BOOL_1))));
+
+  obj.setBoolean(obj.getProperty(s_PROP_BOOL_2),VAL_1);
+  CheckEquals(VAL_1,obj.getBoolean(obj.getProperty(s_PROP_BOOL_2)));
+  CheckEquals(VAL_1,obj.getBoolean(s_PROP_BOOL_2));
+  CheckEquals(VAL_1,obj.getBoolean(obj.getPropertyIndex(obj.getProperty(s_PROP_BOOL_2))));
+
+  obj.setBoolean(obj.getProperty(s_PROP_BOOL_2),VAL_2);
+  CheckEquals(VAL_2,obj.getBoolean(obj.getProperty(s_PROP_BOOL_2)));
+  CheckEquals(VAL_2,obj.getBoolean(s_PROP_BOOL_2));
+  CheckEquals(VAL_2,obj.getBoolean(obj.getPropertyIndex(obj.getProperty(s_PROP_BOOL_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.integer_procs();
+const VAL_1 = 1210; VAL_2 = -97456; VAL_3 = 0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setInteger(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getInteger(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setInteger(obj.getProperty(s_PROP_INTEGER_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setInteger(obj.getProperty(s_PROP_INTEGER_1),VAL_1);
+  CheckEquals(VAL_1,obj.getInteger(obj.getProperty(s_PROP_INTEGER_1)));
+  CheckEquals(VAL_1,obj.getInteger(s_PROP_INTEGER_1));
+  CheckEquals(VAL_1,obj.getInteger(obj.getPropertyIndex(obj.getProperty(s_PROP_INTEGER_1))));
+
+  obj.setInteger(obj.getProperty(s_PROP_INTEGER_1),VAL_2);
+  CheckEquals(VAL_2,obj.getInteger(obj.getProperty(s_PROP_INTEGER_1)));
+  CheckEquals(VAL_2,obj.getInteger(s_PROP_INTEGER_1));
+  CheckEquals(VAL_2,obj.getInteger(obj.getPropertyIndex(obj.getProperty(s_PROP_INTEGER_1))));
+
+  obj.setInteger(obj.getProperty(s_PROP_INTEGER_1),VAL_3);
+  CheckEquals(VAL_3,obj.getInteger(obj.getProperty(s_PROP_INTEGER_1)));
+  CheckEquals(VAL_3,obj.getInteger(s_PROP_INTEGER_1));
+  CheckEquals(VAL_3,obj.getInteger(obj.getPropertyIndex(obj.getProperty(s_PROP_INTEGER_1))));
+
+
+  obj.setInteger(obj.getProperty(s_PROP_INTEGER_2),VAL_1);
+  CheckEquals(VAL_1,obj.getInteger(obj.getProperty(s_PROP_INTEGER_2)));
+  CheckEquals(VAL_1,obj.getInteger(s_PROP_INTEGER_2));
+  CheckEquals(VAL_1,obj.getInteger(obj.getPropertyIndex(obj.getProperty(s_PROP_INTEGER_2))));
+
+  obj.setInteger(obj.getProperty(s_PROP_INTEGER_2),VAL_2);
+  CheckEquals(VAL_2,obj.getInteger(obj.getProperty(s_PROP_INTEGER_2)));
+  CheckEquals(VAL_2,obj.getInteger(s_PROP_INTEGER_2));
+  CheckEquals(VAL_2,obj.getInteger(obj.getPropertyIndex(obj.getProperty(s_PROP_INTEGER_2))));
+
+  obj.setInteger(obj.getProperty(s_PROP_INTEGER_2),VAL_3);
+  CheckEquals(VAL_3,obj.getInteger(obj.getProperty(s_PROP_INTEGER_2)));
+  CheckEquals(VAL_3,obj.getInteger(s_PROP_INTEGER_2));
+  CheckEquals(VAL_3,obj.getInteger(obj.getPropertyIndex(obj.getProperty(s_PROP_INTEGER_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.string_procs();
+const VAL_1 = 'klmhgf[]1210'; VAL_2 = ''; VAL_3 = 'wxyz';
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setString(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setString(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  obj.setString(obj.getProperty(s_PROP_STR_1),VAL_1);
+  CheckEquals(VAL_1,obj.getString(obj.getProperty(s_PROP_STR_1)));
+  CheckEquals(VAL_1,obj.getString(s_PROP_STR_1));
+  CheckEquals(VAL_1,obj.getString(obj.getPropertyIndex(obj.getProperty(s_PROP_STR_1))));
+
+  obj.setString(obj.getProperty(s_PROP_STR_1),VAL_2);
+  CheckEquals(VAL_2,obj.getString(obj.getProperty(s_PROP_STR_1)));
+  CheckEquals(VAL_2,obj.getString(s_PROP_STR_1));
+  CheckEquals(VAL_2,obj.getString(obj.getPropertyIndex(obj.getProperty(s_PROP_STR_1))));
+
+  obj.setString(obj.getProperty(s_PROP_STR_1),VAL_3);
+  CheckEquals(VAL_3,obj.getString(obj.getProperty(s_PROP_STR_1)));
+  CheckEquals(VAL_3,obj.getString(s_PROP_STR_1));
+  CheckEquals(VAL_3,obj.getString(obj.getPropertyIndex(obj.getProperty(s_PROP_STR_1))));
+
+
+  obj.setString(obj.getProperty(s_PROP_STR_2),VAL_1);
+  CheckEquals(VAL_1,obj.getString(obj.getProperty(s_PROP_STR_2)));
+  CheckEquals(VAL_1,obj.getString(s_PROP_STR_2));
+  CheckEquals(VAL_1,obj.getString(obj.getPropertyIndex(obj.getProperty(s_PROP_STR_2))));
+
+  obj.setString(obj.getProperty(s_PROP_STR_2),VAL_2);
+  CheckEquals(VAL_2,obj.getString(obj.getProperty(s_PROP_STR_2)));
+  CheckEquals(VAL_2,obj.getString(s_PROP_STR_2));
+  CheckEquals(VAL_2,obj.getString(obj.getPropertyIndex(obj.getProperty(s_PROP_STR_2))));
+
+  obj.setString(obj.getProperty(s_PROP_STR_2),VAL_3);
+  CheckEquals(VAL_3,obj.getString(obj.getProperty(s_PROP_STR_2)));
+  CheckEquals(VAL_3,obj.getString(s_PROP_STR_2));
+  CheckEquals(VAL_3,obj.getString(obj.getPropertyIndex(obj.getProperty(s_PROP_STR_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.object_procs();
+var
+  ok : Boolean;
+  obj1, obj2, obj2_2, obj3 : ISDODataObject;
+  p1, p2 : ISDOProperty;
+begin
+  obj1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  Check(nil = obj1.getDataObject(s_PROP_OBJ_CONT));
+
+  obj3 := FFactory.createNew(s_URI_3,s_TYPE_3);
+
+  ok := False;
+  try
+    obj1.setDataObject(s_PROP_OBJ_CONT,obj3);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'incomptatible types.');
+
+  ok := False;
+  try
+    obj1.getContainmentProperty();
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'Containment property.');
+
+  Check(nil = obj1.getDataObject(s_PROP_OBJ_CONT));
+
+  obj2 := obj1.createDataObject(s_PROP_OBJ_CONT);
+    Check(nil <> obj2);
+    Check(nil <> obj1.getDataObject(s_PROP_OBJ_CONT));
+    Check(obj2 = obj1.getDataObject(s_PROP_OBJ_CONT));
+    Check(obj1 = obj2.getContainer());
+    p1 := obj1.getProperty(s_PROP_OBJ_CONT) as ISDOProperty;
+    p2 := obj2.getContainmentProperty() as ISDOProperty;
+    Check( p1 = p2 );
+    ok := False;
+    try
+      obj1.setDataObject(s_PROP_OBJ_CONT,obj3);
+    except
+      on e : ESDOIllegalArgumentException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'incomptatible types.');
+    Check(obj2 = obj1.getDataObject(s_PROP_OBJ_CONT), 'A failed action must not modify data');
+    Check(obj1 = obj2.getContainer(), 'A failed action must not modify data');
+    p1 := obj1.getProperty(s_PROP_OBJ_CONT) as ISDOProperty;
+    p2 := obj2.getContainmentProperty() as ISDOProperty;
+    Check( p1 = p2 , 'A failed action must not modify data');
+
+
+  obj1.setDataObject(s_PROP_OBJ_CONT,obj2);
+    Check(nil = obj3.getDataObject(s_PROP_OBJ_CONT));
+    Check(nil <> obj1.getDataObject(s_PROP_OBJ_CONT));
+    Check(obj2 = obj1.getDataObject(s_PROP_OBJ_CONT));
+    Check(obj1 = obj2.getContainer());
+    p1 := obj1.getProperty(s_PROP_OBJ_CONT) as ISDOProperty;
+    p2 := obj2.getContainmentProperty() as ISDOProperty;
+    Check( p1 = p2 );
+
+  obj2_2 := FFactory.createNew(s_URI_1,s_TYPE_2);
+  obj1.setDataObject(s_PROP_OBJ_REF,obj2_2);
+    Check(nil = obj2_2.getContainer());
+    Check(nil <> obj1.getDataObject(s_PROP_OBJ_REF));
+    Check(obj2_2 = obj1.getDataObject(s_PROP_OBJ_REF));
+
+  ok := False;
+  try
+    obj2_2.getContainmentProperty();
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'Containment property.');
+end;
+
+procedure TSDOBaseDataObject_Test.integer_multivalue();
+const LOCAL_PROP = s_PROP_INTEGER_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOInteger;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := Random(200000000);
+      if ( ( k mod 5 ) = 0 ) then
+        val_list[k] := - val_list[k];
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getInteger(),'append() <> getInteger()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.integer_unset_isset();
+const
+  LOCAL_PROP = s_PROP_INTEGER_1;
+  LOCAL_PROP_ARRAY = s_PROP_INTEGER_3;
+  VAL_1  = 1210;  VAL_2 = 76;
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setInteger(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getIntegerDefault(),obj.getInteger(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setInteger(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.boolean_unset_isset();
+const
+  LOCAL_PROP = s_PROP_BOOL_1;
+  LOCAL_PROP_ARRAY = s_PROP_BOOL_3;
+  VAL_1  = True;  VAL_2 = False;
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setBoolean(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.setBoolean(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.string_unset_isset();
+const
+  LOCAL_PROP = s_PROP_STR_1;
+  LOCAL_PROP_ARRAY = s_PROP_STR_3;
+  VAL_1  = 'wwssxx';  VAL_2 = '';
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setString(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.setString(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.object_unset_isset();
+const
+  LOCAL_PROP = s_PROP_OBJ_CONT;
+  LOCAL_PROP_ARRAY = s_PROP_OBJ_CONT_LIST;
+var
+  obj, VAL_A, VAL_B : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP + ' 1');
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  VAL_A := obj.createDataObject(LOCAL_PROP);
+  VAL_B := obj.createDataObject(LOCAL_PROP);
+
+  obj.setDataObject(LOCAL_PROP, VAL_A);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP + ' 4');
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP + ' 5');
+    obj.setDataObject(LOCAL_PROP, VAL_B);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP + ' 6');
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP + ' 7');
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+  ls.append(obj.createDataObject(LOCAL_PROP_ARRAY));
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(0,ls.size());
+    ls.append(obj.createDataObject(LOCAL_PROP_ARRAY));
+    ls.append(obj.createDataObject(LOCAL_PROP_ARRAY));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.integer_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_INTEGER_1;
+  LOCAL_PROP_ARRAY = s_PROP_INTEGER_3;
+  VAL_1  = 1210;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setInteger(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(0,obj.getInteger(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.boolean_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_BOOL_1;
+  LOCAL_PROP_ARRAY = s_PROP_BOOL_3;
+  VAL_1  = True; VAL_2 = False;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setBoolean(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(False,obj.getBoolean(LOCAL_PROP),LOCAL_PROP);
+
+  obj.setBoolean(LOCAL_PROP, VAL_2);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(False,obj.getBoolean(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.string_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_STR_1;
+  LOCAL_PROP_ARRAY = s_PROP_STR_3;
+  VAL_1  = 'wwssxx';  VAL_2 = '';
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setString(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setString(LOCAL_PROP, VAL_2);
+      CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      obj.setNull(LOCAL_PROP);
+        CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_ref_nil();
+var
+  locA, locA1, locB : ISDODataObject;
+begin
+  locA := FFactory.createNew(s_URI_1,s_TYPE_1);
+    locB := locA.createDataObject(s_PROP_OBJ_CONT);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locB));
+    CheckEquals(PtrUInt(locB), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+  locA1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+    locA1.setDataObject(s_PROP_OBJ_REF,locB);
+    CheckEquals(PtrUInt(locB), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+    CheckEquals(PtrUInt(locB), PtrUInt(locA1.getDataObject(s_PROP_OBJ_REF)));
+
+    locA.setDataObject(s_PROP_OBJ_CONT,nil);
+      CheckEquals(PtrUInt(nil), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+      CheckEquals(PtrUInt(nil), PtrUInt(locA1.getDataObject(s_PROP_OBJ_REF)), 'This reference should be NIL because the object has been deleted by his container.');
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_ref_unset();
+var
+  locA, locA1, locB : ISDODataObject;
+begin
+  locA := FFactory.createNew(s_URI_1,s_TYPE_1);
+    locB := locA.createDataObject(s_PROP_OBJ_CONT);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locB));
+    CheckEquals(PtrUInt(locB), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+  locA1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+    locA1.setDataObject(s_PROP_OBJ_REF,locB);
+    CheckEquals(PtrUInt(locB), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+    CheckEquals(PtrUInt(locB), PtrUInt(locA1.getDataObject(s_PROP_OBJ_REF)));
+
+    locA.unset(s_PROP_OBJ_CONT);
+      CheckEquals(PtrUInt(nil), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+      CheckEquals(PtrUInt(nil), PtrUInt(locA1.getDataObject(s_PROP_OBJ_REF)), 'This reference should be NIL because the object has been deleted by his container.');
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_ref_setnull();
+var
+  locA, locA1, locB : ISDODataObject;
+begin
+  locA := FFactory.createNew(s_URI_1,s_TYPE_1);
+    locB := locA.createDataObject(s_PROP_OBJ_CONT);
+    CheckNotEquals(PtrUInt(nil), PtrUInt(locB));
+    CheckEquals(PtrUInt(locB), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+  locA1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+    locA1.setDataObject(s_PROP_OBJ_REF,locB);
+    CheckEquals(PtrUInt(locB), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+    CheckEquals(PtrUInt(locB), PtrUInt(locA1.getDataObject(s_PROP_OBJ_REF)));
+
+    locA.setNull(s_PROP_OBJ_CONT);
+      CheckEquals(PtrUInt(nil), PtrUInt(locA.getDataObject(s_PROP_OBJ_CONT)));
+      CheckEquals(PtrUInt(nil), PtrUInt(locA1.getDataObject(s_PROP_OBJ_REF)), 'This reference should be NIL because the object has been deleted by his container.');
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_ref_nil_nested();
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC, locD : ISDODataObject;
+
+  procedure InitAndCreateObject();
+  begin
+    locA := nil;
+    locB := nil;
+    locC := nil;
+    locD := nil;
+    locA := locFac.createNew(s_URI_1,'A');
+      locB := locA.createDataObject('Pab');
+        locC := locB.createDataObject('Pbc');
+          locD := locC.createDataObject('Pcd');
+      locA.setDataObject('Pad_ref',locD);
+  end;
+
+var
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_URI_1,'A',tfg);
+    locFac.AddType(s_URI_1,'B',tfg);
+    locFac.AddType(s_URI_1,'C',tfg);
+    locFac.AddType(s_URI_1,'D',tfg);
+      locFac.addProperty(s_URI_1,'A','Pab',s_URI_1,'B',[pfIsContainment]);        //  <<-- Containment
+        locFac.addProperty(s_URI_1,'B','Pbc',s_URI_1,'C',[pfIsContainment]);      //  <<-- Containment
+          locFac.addProperty(s_URI_1,'C','Pcd',s_URI_1,'D',[pfIsContainment]);    //  <<-- Containment
+      locFac.addProperty(s_URI_1,'A','Pad_ref',s_URI_1,'D',[]);       //  <<-- Reference
+
+  InitAndCreateObject();
+    locC.setDataObject('Pcd',nil);
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+
+  InitAndCreateObject();
+    locB.setDataObject('Pbc',nil);
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+
+  InitAndCreateObject();
+    locA.setDataObject('Pab',nil);
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_ref_setnull_nested;
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC, locD : ISDODataObject;
+
+  procedure InitAndCreateObject();
+  begin
+    locA := nil;
+    locB := nil;
+    locC := nil;
+    locD := nil;
+    locA := locFac.createNew(s_URI_1,'A');
+      locB := locA.createDataObject('Pab');
+        locC := locB.createDataObject('Pbc');
+          locD := locC.createDataObject('Pcd');
+      locA.setDataObject('Pad_ref',locD);
+  end;
+
+var
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_URI_1,'A',tfg);
+    locFac.AddType(s_URI_1,'B',tfg);
+    locFac.AddType(s_URI_1,'C',tfg);
+    locFac.AddType(s_URI_1,'D',tfg);
+      locFac.addProperty(s_URI_1,'A','Pab',s_URI_1,'B',[pfIsContainment]);        //  <<-- Containment
+        locFac.addProperty(s_URI_1,'B','Pbc',s_URI_1,'C',[pfIsContainment]);      //  <<-- Containment
+          locFac.addProperty(s_URI_1,'C','Pcd',s_URI_1,'D',[pfIsContainment]);    //  <<-- Containment
+      locFac.addProperty(s_URI_1,'A','Pad_ref',s_URI_1,'D',[]);       //  <<-- Reference
+
+  InitAndCreateObject();
+    locC.setNull('Pcd');
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+
+  InitAndCreateObject();
+    locB.setNull('Pbc');
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+
+  InitAndCreateObject();
+    locA.setNull('Pab');
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_ref_unset_nested;
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC, locD : ISDODataObject;
+
+  procedure InitAndCreateObject();
+  begin
+    locA := nil;
+    locB := nil;
+    locC := nil;
+    locD := nil;
+    locA := locFac.createNew(s_URI_1,'A');
+      locB := locA.createDataObject('Pab');
+        locC := locB.createDataObject('Pbc');
+          locD := locC.createDataObject('Pcd');
+      locA.setDataObject('Pad_ref',locD);
+  end;
+
+var
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_URI_1,'A',tfg);
+    locFac.AddType(s_URI_1,'B',tfg);
+    locFac.AddType(s_URI_1,'C',tfg);
+    locFac.AddType(s_URI_1,'D',tfg);
+      locFac.addProperty(s_URI_1,'A','Pab',s_URI_1,'B',[pfIsContainment]);       //  <<-- Containment
+        locFac.addProperty(s_URI_1,'B','Pbc',s_URI_1,'C',[pfIsContainment]);     //  <<-- Containment
+          locFac.addProperty(s_URI_1,'C','Pcd',s_URI_1,'D',[pfIsContainment]);    //  <<-- Containment
+      locFac.addProperty(s_URI_1,'A','Pad_ref',s_URI_1,'D',[]);       //  <<-- Reference
+
+  InitAndCreateObject();
+    locC.unset('Pcd');
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+
+  InitAndCreateObject();
+    locB.unset('Pbc');
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+
+  InitAndCreateObject();
+    locA.unset('Pab');
+    CheckEquals(PtrUInt(0), PtrUInt(locA.getDataObject('Pad_ref')));
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_cycle_containment();
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC : ISDODataObject;
+  ok : Boolean;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_URI_1,'X',tfg);
+    locFac.AddType(s_URI_1,'A',tfg);
+      locFac.setBaseType(s_URI_1,'A',s_URI_1,'X');
+    locFac.AddType(s_URI_1,'B',tfg);
+    locFac.AddType(s_URI_1,'C',tfg);
+      locFac.addProperty(s_URI_1,'A','p_ab',s_URI_1,'B',[pfIsContainment]);
+      locFac.addProperty(s_URI_1,'B','p_bc',s_URI_1,'C',[pfIsContainment]);
+      locFac.addProperty(s_URI_1,'C','p_ca',sdo_namespace,SDOTypeDefaultTypeNames[ObjectType],[pfIsContainment]);
+
+  locA := locFac.createNew(s_URI_1,'A');
+    locB := locA.createDataObject('p_ab');
+      locC := locB.createDataObject('p_bc');
+        ok := False;
+        try
+          locC.setDataObject('p_ca',locA);
+        except
+          on  e : ESDOCycleContainmentException do
+            ok := True
+        end;
+        Check(ok,'Cycle Containment.');
+end;
+
+procedure TSDOBaseDataObject_Test.IsInstanceOf();
+var
+  locFac : ISDODataFactory;
+  locO : ISDODataObjectEx;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_URI_1,'A',tfg);
+    locFac.AddType(s_URI_1,'A_B_1',tfg);
+      locFac.setBaseType(s_URI_1,'A_B_1',s_URI_1,'A');
+    locFac.AddType(s_URI_1,'A_B_2',tfg);
+      locFac.setBaseType(s_URI_1,'A_B_2',s_URI_1,'A');
+      locFac.AddType(s_URI_1,'A_B_2_C',tfg);
+        locFac.setBaseType(s_URI_1,'A_B_2_C',s_URI_1,'A_B_2');
+        locFac.AddType(s_URI_1,'A_B_2_C_D',tfg);
+          locFac.setBaseType(s_URI_1,'A_B_2_C_D',s_URI_1,'A_B_2_C');
+  locFac.AddType(s_URI_1,'B',tfg);
+  locFac.AddType(s_URI_1,'C',tfg);
+
+  locO := locFac.createNew(s_URI_1,'A') as ISDODataObjectEx;
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'B')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_1')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C_D')));
+
+  locO := locFac.createNew(s_URI_1,'A_B_1') as ISDODataObjectEx;
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A')));
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_1')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'B')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C_D')));
+
+  locO := locFac.createNew(s_URI_1,'A_B_2') as ISDODataObjectEx;
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A')));
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'B')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_1')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C_D')));
+
+  locO := locFac.createNew(s_URI_1,'A_B_2_C') as ISDODataObjectEx;
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A')));
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2')));
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'B')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_1')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C_D')));
+
+  locO := locFac.createNew(s_URI_1,'A_B_2_C_D') as ISDODataObjectEx;
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A')));
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2')));
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C')));
+    CheckEquals(True, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_2_C_D')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'B')));
+    CheckEquals(False, locO.IsInstanceOf(locFac.getType(s_URI_1,'A_B_1')));
+
+end;
+
+procedure TSDOBaseDataObject_Test.object_setDataObject_ref();
+const
+  s_uri = 'u';
+var
+  locFac : ISDODataFactory;
+  a, b : ISDODataObject;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',tfg);
+  locFac.AddType(s_uri,'b',tfg);
+  locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[]);
+
+  a := locFac.createNew(s_uri,'a');
+  b := locFac.createNew(s_uri,'b');
+  a.setDataObject('p_ab',b);
+end;
+
+procedure TSDOBaseDataObject_Test.get_integer_xpath();
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_INTEGER_1,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_INTEGER_2,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,s_PROP_INTEGER_A,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,s_PROP_INTEGER_B,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOInteger;
+begin
+  o1_val_1 := RandomRange(-12345,12345);
+  o1_val_2 := RandomRange(-12345,12345);
+  o2_val_A := RandomRange(-12345,12345);
+  o2_val_B := RandomRange(-12345,12345);
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setInteger(s_PROP_INTEGER_1,o1_val_1);
+  o1.setInteger(s_PROP_INTEGER_2,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setInteger(s_PROP_INTEGER_A,o2_val_A);
+      o2.setInteger(s_PROP_INTEGER_B,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,s_PROP_INTEGER_1);
+  check_xpath_value(o1_val_2, o1, s_PROP_INTEGER_2);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,s_PROP_INTEGER_A]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,s_PROP_INTEGER_B]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',s_PROP_INTEGER_1]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',s_PROP_INTEGER_2]));
+end;
+
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOInteger;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getInteger(AXPath), AXPath);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_integer();
+const
+  VAL_1 : TSDOInteger = 1210;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_INTEGER_1,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_INTEGER_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getInteger(locProp), 'getInteger');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_integer();
+const
+  VAL_1 = 1210; VAL_2 = 789;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_INTEGER_1,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_INTEGER_1);
+        locProp.setDefault(TSDOInteger(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setInteger(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getInteger(locProp), 'getInteger');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getInteger(locProp), 'getInteger');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_bool();
+const
+  VAL_1 = True;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_BOOL_1,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_BOOL_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getBoolean(locProp), 'getBoolean');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_bool();
+const
+  VAL_1 = True; VAL_2 = False;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_BOOL_1,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_BOOL_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setBoolean(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getBoolean(locProp), 'getBoolean');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getBoolean(locProp), 'getBoolean');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_string();
+const
+  VAL_1 = 'Kiswendsida O.';
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_STR_1,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_STR_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getString(locProp), 'getString');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_string;
+const
+  VAL_1 = 'O. A. Kiswensida'; VAL_2 = 'sssszzeerrff';
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_STR_1,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_STR_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setString(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getString(locProp), 'getString');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getString(locProp), 'getString');
+end;
+
+procedure TSDOBaseDataObject_Test.object_ref_multivalue();
+const LOCAL_PROP = s_PROP_OBJ_REF_LIST;
+var
+  val_list : array of ISDODataObject;
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  local_array_len, i : PtrInt;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+  xtraObj : ISDODataObject;
+begin
+  Randomize();
+  local_array_len := RandomRange(0,100);
+  SetLength(val_list,local_array_len);
+  try
+    for i := 0 to Pred(local_array_len) do
+      val_list[i] := FFactory.createNew(s_URI_1,s_TYPE_2);
+    obj := Create_Object();
+
+    ok := False;
+    try
+      ls := obj.getList(s_PROP_BOOL_1);
+    except
+      on e : ESDOIllegalArgumentException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+    ls := obj.getList(LOCAL_PROP);
+      Check(ls <> nil);
+    ls1 := obj.getList(LOCAL_PROP);
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+    ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+    ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+    ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+    ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+    CheckEquals(0,ls.size(),'Size');
+    for i := 0 to Pred(local_array_len) do begin
+      ls.append(val_list[i]);
+    end;
+
+    crs := ls.getCursor();
+    Check(crs <> nil,'ls.getCursor()');
+    crs.Reset();
+    CheckEquals(local_array_len,ls.size(),'Size');
+    for i := 0 to Pred(local_array_len) do begin
+      crs.MoveNext();
+      CheckEquals(PtrUInt(val_list[i]),PtrUInt(ls.getDataObject()),Format('append(%d) <> getDataObject(%d)',[i,i]));
+      CheckEquals(PtrUInt(nil),PtrUInt(ls.getDataObject().getContainer()),Format('nil <> getDataObject(%d).getContainer()',[i]));
+    end;
+
+    xtraObj := FFactory.createNew(s_URI_3,s_TYPE_3);
+    ok := False;
+    try
+      ls.append(xtraObj);
+    except
+      on e : ESDOIllegalArgumentException do
+        ok := True;
+    end;
+    Check(ok, 'Adding an different object type.');
+  finally
+    SetLength(val_list,0);
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.object_cont_multivalue();
+const LOCAL_PROP = s_PROP_OBJ_CONT_LIST;
+var
+  val_list : array of ISDODataObject;
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  local_array_len, i : PtrInt;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+  xtraObj : ISDODataObject;
+begin
+  Randomize();
+  local_array_len := RandomRange(0,100);
+  SetLength(val_list,local_array_len);
+  try
+    for i := 0 to Pred(local_array_len) do
+      val_list[i] := FFactory.createNew(s_URI_1,s_TYPE_2);
+    obj := Create_Object();
+
+    ok := False;
+    try
+      ls := obj.getList(s_PROP_BOOL_1);
+    except
+      on e : ESDOIllegalArgumentException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+    ls := obj.getList(LOCAL_PROP);
+      Check(ls <> nil);
+    ls1 := obj.getList(LOCAL_PROP);
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+    ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+    ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+    ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+    ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+      CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+    CheckEquals(0,ls.size(),'Size');
+    for i := 0 to Pred(local_array_len) do begin
+      ls.append(val_list[i]);
+    end;
+
+    crs := ls.getCursor();
+    Check(crs <> nil,'ls.getCursor()');
+    crs.Reset();
+    CheckEquals(local_array_len,ls.size(),'Size');
+    for i := 0 to Pred(local_array_len) do begin
+      crs.MoveNext();
+      CheckEquals(PtrUInt(val_list[i]),PtrUInt(ls.getDataObject()),Format('append(%d) <> getDataObject(%d)',[i,i]));
+      CheckEquals(PtrUInt(obj),PtrUInt(ls.getDataObject().getContainer()),Format('obj <> getDataObject(%d).getContainer()',[i]));
+    end;
+
+    xtraObj := FFactory.createNew(s_URI_3,s_TYPE_3);
+    ok := False;
+    try
+      ls.append(xtraObj);
+    except
+      on e : ESDOIllegalArgumentException do
+        ok := True;
+    end;
+    Check(ok, 'Adding an different object type.');
+  finally
+    SetLength(val_list,0);
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.object_destroy_order();
+var
+  locFac : ISDODataFactory;
+  locA, locB : ISDODataObject;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_URI_1,'a',[]);
+  locFac.AddType(s_URI_1,'b',[]);
+    locFac.addProperty(s_URI_1,'a','p_ab',s_URI_1,'b',[]);
+
+  locA := locFac.createNew(s_URI_1,'a');
+  locB := locFac.createNew(s_URI_1,'b');
+  locA.setDataObject('p_ab', locB);
+  locA := nil;
+  locB := nil;
+end;
+
+procedure TSDOBaseDataObject_Test.object_getChangeSummary();
+var
+  locFac : ISDODataFactory;
+  locA, locB_Ref, locB_Cont : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_URI_1,'a',[]);
+  locFac.AddType(s_URI_1,'b',[]);
+    locFac.addProperty(s_URI_1,'a','p_ab_ref',s_URI_1,'b',[]);
+    locFac.addProperty(s_URI_1,'a','p_ab_cont',s_URI_1,'b',[pfIsContainment]);
+    locFac.addProperty(s_URI_1,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_URI_1,'a');
+  locB_Cont := locFac.createNew(s_URI_1,'b');
+  locB_Ref := locFac.createNew(s_URI_1,'b');
+  locCS := locA.getChangeSummary();
+
+  CheckNotEquals(PtrUInt(nil), PtrUInt(locCS));
+  CheckEquals(PtrUInt(nil), PtrUInt(locB_Cont.getChangeSummary()));
+  CheckEquals(PtrUInt(nil), PtrUInt(locB_Ref.getChangeSummary()));
+
+  locA.setDataObject('p_ab_cont', locB_Cont);
+    CheckEquals(PtrUInt(locCS), PtrUInt(locB_Cont.getChangeSummary()));
+  locA.setDataObject('p_ab_cont', nil);
+    CheckEquals(PtrUInt(nil), PtrUInt(locB_Cont.getChangeSummary()));
+
+  locA.setDataObject('p_ab_ref', locB_Ref);
+    CheckEquals(PtrUInt(nil), PtrUInt(locB_Cont.getChangeSummary()));
+  locA.setDataObject('p_ab_ref', nil);
+    CheckEquals(PtrUInt(nil), PtrUInt(locB_Ref.getChangeSummary()));
+end;
+
+procedure TSDOBaseDataObject_Test.object_getChangeSummary_multiprop();
+var
+  locFac : ISDODataFactory;
+  locA, locB_Ref, locB_Cont : ISDODataObject;
+  locCS : ISDOChangeSummary;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_URI_1,'a',[]);
+  locFac.AddType(s_URI_1,'b',[]);
+    locFac.addProperty(s_URI_1,'a','p_ab_ref',s_URI_1,'b',[pfIsMany]);
+    locFac.addProperty(s_URI_1,'a','p_ab_cont',s_URI_1,'b',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_URI_1,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+  locA := locFac.createNew(s_URI_1,'a');
+  locB_Cont := locFac.createNew(s_URI_1,'b');
+  locB_Ref := locFac.createNew(s_URI_1,'b');
+  locCS := locA.getChangeSummary();
+
+  CheckNotEquals(PtrUInt(nil), PtrUInt(locCS));
+  CheckEquals(PtrUInt(nil), PtrUInt(locB_Cont.getChangeSummary()));
+  CheckEquals(PtrUInt(nil), PtrUInt(locB_Ref.getChangeSummary()));
+
+  locA.getList('p_ab_cont').append(locB_Cont);
+    CheckEquals(PtrUInt(locCS), PtrUInt(locB_Cont.getChangeSummary()));
+  locA.getList('p_ab_cont').delete(0);
+    CheckEquals(PtrUInt(nil), PtrUInt(locB_Cont.getChangeSummary()));
+
+  locA.getList('p_ab_ref').append(locB_Ref);
+    CheckEquals(PtrUInt(nil), PtrUInt(locB_Cont.getChangeSummary()));
+  locA.getList('p_ab_ref').delete(0);
+    CheckEquals(PtrUInt(nil), PtrUInt(locB_Ref.getChangeSummary()));
+end;
+
+procedure TSDOBaseDataObject_Test.byte_procs();
+const VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 56; VAL_3 : TSDOByte = 0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setByte(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getByte(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setByte(obj.getProperty(s_PROP_BYTE_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setByte(obj.getProperty(s_PROP_BYTE_1),VAL_1);
+  CheckEquals(VAL_1,obj.getByte(obj.getProperty(s_PROP_BYTE_1)));
+  CheckEquals(VAL_1,obj.getByte(s_PROP_BYTE_1));
+  CheckEquals(VAL_1,obj.getByte(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTE_1))));
+
+  obj.setByte(obj.getProperty(s_PROP_BYTE_1),VAL_2);
+  CheckEquals(VAL_2,obj.getByte(obj.getProperty(s_PROP_BYTE_1)));
+  CheckEquals(VAL_2,obj.getByte(s_PROP_BYTE_1));
+  CheckEquals(VAL_2,obj.getByte(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTE_1))));
+
+  obj.setByte(obj.getProperty(s_PROP_BYTE_1),VAL_3);
+  CheckEquals(VAL_3,obj.getByte(obj.getProperty(s_PROP_BYTE_1)));
+  CheckEquals(VAL_3,obj.getByte(s_PROP_BYTE_1));
+  CheckEquals(VAL_3,obj.getByte(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTE_1))));
+
+
+  obj.setByte(obj.getProperty(s_PROP_BYTE_2),VAL_1);
+  CheckEquals(VAL_1,obj.getByte(obj.getProperty(s_PROP_BYTE_2)));
+  CheckEquals(VAL_1,obj.getByte(s_PROP_BYTE_2));
+  CheckEquals(VAL_1,obj.getByte(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTE_2))));
+
+  obj.setByte(obj.getProperty(s_PROP_BYTE_2),VAL_2);
+  CheckEquals(VAL_2,obj.getByte(obj.getProperty(s_PROP_BYTE_2)));
+  CheckEquals(VAL_2,obj.getByte(s_PROP_BYTE_2));
+  CheckEquals(VAL_2,obj.getByte(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTE_2))));
+
+  obj.setByte(obj.getProperty(s_PROP_BYTE_2),VAL_3);
+  CheckEquals(VAL_3,obj.getByte(obj.getProperty(s_PROP_BYTE_2)));
+  CheckEquals(VAL_3,obj.getByte(s_PROP_BYTE_2));
+  CheckEquals(VAL_3,obj.getByte(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTE_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.byte_multivalue();
+const LOCAL_PROP = s_PROP_BYTE_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOByte;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := Random(High(TSDOByte));
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getByte(),'append() <> getByte()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.byte_unset_isset();
+const
+  LOCAL_PROP = s_PROP_BYTE_1;
+  LOCAL_PROP_ARRAY = s_PROP_BYTE_3;
+  VAL_1 : TSDOByte = 12;  VAL_2 : TSDOByte = 76;
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setByte(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getByteDefault(),obj.getByte(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setByte(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.byte_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_BYTE_1;
+  LOCAL_PROP_ARRAY = s_PROP_BYTE_3;
+  VAL_1 : TSDOByte = 12;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setByte(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(0,obj.getByte(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_byte();
+const
+  VAL_1 : TSDOByte = 12;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_BYTE_1,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_BYTE_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getByte(locProp), 'getByte');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_byte();
+const
+  VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 89;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_BYTE_1,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_BYTE_1);
+        locProp.setDefault(TSDOByte(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setByte(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getByte(locProp), 'getByte');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getByte(locProp), 'getByte');
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOBaseDataObject_Test.bytes_procs();
+var
+      VAL_1, VAL_2, VAL_3 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil; 
+
+    VAL_2 := nil;    
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3 := v;     
+  end;
+
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  SetConstants();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setBytes(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getBytes(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setBytes(obj.getProperty(s_PROP_BYTES_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setBytes(obj.getProperty(s_PROP_BYTES_1),VAL_1);
+  CheckEquals(VAL_1,obj.getBytes(obj.getProperty(s_PROP_BYTES_1)));
+  CheckEquals(VAL_1,obj.getBytes(s_PROP_BYTES_1));
+  CheckEquals(VAL_1,obj.getBytes(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTES_1))));
+
+  obj.setBytes(obj.getProperty(s_PROP_BYTES_1),VAL_2);
+  CheckEquals(VAL_2,obj.getBytes(obj.getProperty(s_PROP_BYTES_1)));
+  CheckEquals(VAL_2,obj.getBytes(s_PROP_BYTES_1));
+  CheckEquals(VAL_2,obj.getBytes(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTES_1))));
+
+  obj.setBytes(obj.getProperty(s_PROP_BYTES_1),VAL_3);
+  CheckEquals(VAL_3,obj.getBytes(obj.getProperty(s_PROP_BYTES_1)));
+  CheckEquals(VAL_3,obj.getBytes(s_PROP_BYTES_1));
+  CheckEquals(VAL_3,obj.getBytes(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTES_1))));
+
+
+  obj.setBytes(obj.getProperty(s_PROP_BYTES_2),VAL_1);
+  CheckEquals(VAL_1,obj.getBytes(obj.getProperty(s_PROP_BYTES_2)));
+  CheckEquals(VAL_1,obj.getBytes(s_PROP_BYTES_2));
+  CheckEquals(VAL_1,obj.getBytes(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTES_2))));
+
+  obj.setBytes(obj.getProperty(s_PROP_BYTES_2),VAL_2);
+  CheckEquals(VAL_2,obj.getBytes(obj.getProperty(s_PROP_BYTES_2)));
+  CheckEquals(VAL_2,obj.getBytes(s_PROP_BYTES_2));
+  CheckEquals(VAL_2,obj.getBytes(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTES_2))));
+
+  obj.setBytes(obj.getProperty(s_PROP_BYTES_2),VAL_3);
+  CheckEquals(VAL_3,obj.getBytes(obj.getProperty(s_PROP_BYTES_2)));
+  CheckEquals(VAL_3,obj.getBytes(s_PROP_BYTES_2));
+  CheckEquals(VAL_3,obj.getBytes(obj.getPropertyIndex(obj.getProperty(s_PROP_BYTES_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.bytes_multivalue();
+const LOCAL_PROP = s_PROP_BYTES_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOBytes;
+
+  procedure PrepareArray();
+  var
+    k, h : Integer;
+    e : TSDOBytes;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      e := nil;
+      SetLength(e,RandomRange(0,1000));
+      if ( Length(e) > 0 ) then begin
+        for h := Low(e) to High(e) do
+          e[h] := RandomRange(Low(Byte),High(Byte));
+      end;
+      val_list[k] := e;
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.appendBytes(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getBytes(),'append() <> getBytes()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.bytes_unset_isset();
+const
+  LOCAL_PROP = s_PROP_BYTES_1;
+  LOCAL_PROP_ARRAY = s_PROP_BYTES_3;
+var
+  VAL_1, VAL_2 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;    
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_2 := v;     
+  end;  
+  
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  SetConstants();
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setBytes(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getBytesDefault(),obj.getBytes(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setBytes(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.appendBytes(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.appendBytes(VAL_1);
+    ls.appendBytes(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.bytes_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_BYTES_1;
+  LOCAL_PROP_ARRAY = s_PROP_BYTES_3;  
+var
+  VAL_1 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+  end;  
+  
+var
+  obj : ISDODataObject;
+begin
+  SetConstants();
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setBytes(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(TSDOBytes(nil),obj.getBytes(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_bytes();
+var
+  VAL_1 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+  end;  
+  
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  SetConstants();
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_BYTES_1,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_BYTES_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getBytes(locProp), 'getBytes');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_bytes();
+var
+  VAL_1, VAL_2 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;    
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_2 := v;     
+  end; 
+  
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  SetConstants();
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_BYTES_1,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_BYTES_1);
+        locProp.setDefault(TSDOBytes(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setBytes(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getBytes(locProp), 'getBytes');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getBytes(locProp), 'getBytes');
+end;
+
+procedure TSDOBaseDataObject_Test.get_bytes_xpath();
+const
+  LOCAL_PROP_TYPE = BytesType;
+  LOCAL_PROP_1_NAME = s_PROP_BYTES_1;
+  LOCAL_PROP_2_NAME = s_PROP_BYTES_2;
+  LOCAL_PROP_A_NAME = s_PROP_BYTES_A;
+  LOCAL_PROP_B_NAME = s_PROP_BYTES_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    o1_val_1 := v;
+    v := nil;
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    o1_val_2 := v;
+    
+    o2_val_A := nil;
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    o2_val_B := v;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+begin
+  SetConstants();
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setBytes(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setBytes(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setBytes(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setBytes(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOBaseDataObject_Test.char_procs();
+const 
+  LOCAL_PROP_1 = s_PROP_CHAR_1;
+  LOCAL_PROP_2 = s_PROP_CHAR_2;
+  LOCAL_PROP_3 = s_PROP_CHAR_3;
+  VAL_1 : TSDOChar = 'W'; VAL_2 : TSDOChar = 's'; VAL_3 : TSDOChar = #0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setCharacter(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getCharacter(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setCharacter(obj.getProperty(LOCAL_PROP_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setCharacter(obj.getProperty(LOCAL_PROP_1),VAL_1);
+  CheckEquals(VAL_1,obj.getCharacter(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_1,obj.getCharacter(LOCAL_PROP_1));
+  CheckEquals(VAL_1,obj.getCharacter(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setCharacter(obj.getProperty(LOCAL_PROP_1),VAL_2);
+  CheckEquals(VAL_2,obj.getCharacter(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_2,obj.getCharacter(LOCAL_PROP_1));
+  CheckEquals(VAL_2,obj.getCharacter(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setCharacter(obj.getProperty(LOCAL_PROP_1),VAL_3);
+  CheckEquals(VAL_3,obj.getCharacter(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_3,obj.getCharacter(LOCAL_PROP_1));
+  CheckEquals(VAL_3,obj.getCharacter(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+
+  obj.setCharacter(obj.getProperty(LOCAL_PROP_2),VAL_1);
+  CheckEquals(VAL_1,obj.getCharacter(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_1,obj.getCharacter(LOCAL_PROP_2));
+  CheckEquals(VAL_1,obj.getCharacter(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setCharacter(obj.getProperty(LOCAL_PROP_2),VAL_2);
+  CheckEquals(VAL_2,obj.getCharacter(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_2,obj.getCharacter(LOCAL_PROP_2));
+  CheckEquals(VAL_2,obj.getCharacter(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setCharacter(obj.getProperty(LOCAL_PROP_2),VAL_3);
+  CheckEquals(VAL_3,obj.getCharacter(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_3,obj.getCharacter(LOCAL_PROP_2));
+  CheckEquals(VAL_3,obj.getCharacter(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.char_multivalue();
+const LOCAL_PROP = s_PROP_CHAR_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOChar;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getCharacter(),'append() <> getCharacter()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.char_unset_isset();
+const
+  LOCAL_PROP = s_PROP_CHAR_1;
+  LOCAL_PROP_ARRAY = s_PROP_CHAR_3;
+  VAL_1 : TSDOChar = 'k';  VAL_2 : TSDOChar = 'x';
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setCharacter(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getCharacterDefault(),obj.getCharacter(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setCharacter(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.char_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_CHAR_1;
+  LOCAL_PROP_ARRAY = s_PROP_CHAR_3;
+  VAL_1 : TSDOChar = 'z';
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setCharacter(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(#0,obj.getCharacter(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_char();
+const
+  VAL_1 : TSDOChar = 'q';
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_CHAR_1,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_CHAR_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getCharacter(locProp), 'getCharacter');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_char();
+const
+  VAL_1 : TSDOChar = 'e'; VAL_2 : TSDOChar = 'r';
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_CHAR_1,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_CHAR_1);
+        locProp.setDefault(TSDOChar(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setCharacter(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getCharacter(locProp), 'getCharacter');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getCharacter(locProp), 'getCharacter');
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOBaseDataObject_Test.currency_procs();
+const 
+  LOCAL_PROP_1 = s_PROP_CURRENCY_1;
+  LOCAL_PROP_2 = s_PROP_CURRENCY_2;
+  LOCAL_PROP_3 = s_PROP_CURRENCY_3;
+  VAL_1 : TSDOCurrency = 12345678.9101; VAL_2 : TSDOCurrency = -9879879.8765; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setCurrency(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getCurrency(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setCurrency(obj.getProperty(LOCAL_PROP_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setCurrency(obj.getProperty(LOCAL_PROP_1),VAL_1);
+  CheckEquals(VAL_1,obj.getCurrency(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_1,obj.getCurrency(LOCAL_PROP_1));
+  CheckEquals(VAL_1,obj.getCurrency(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setCurrency(obj.getProperty(LOCAL_PROP_1),VAL_2);
+  CheckEquals(VAL_2,obj.getCurrency(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_2,obj.getCurrency(LOCAL_PROP_1));
+  CheckEquals(VAL_2,obj.getCurrency(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setCurrency(obj.getProperty(LOCAL_PROP_1),VAL_3);
+  CheckEquals(VAL_3,obj.getCurrency(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_3,obj.getCurrency(LOCAL_PROP_1));
+  CheckEquals(VAL_3,obj.getCurrency(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+
+  obj.setCurrency(obj.getProperty(LOCAL_PROP_2),VAL_1);
+  CheckEquals(VAL_1,obj.getCurrency(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_1,obj.getCurrency(LOCAL_PROP_2));
+  CheckEquals(VAL_1,obj.getCurrency(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setCurrency(obj.getProperty(LOCAL_PROP_2),VAL_2);
+  CheckEquals(VAL_2,obj.getCurrency(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_2,obj.getCurrency(LOCAL_PROP_2));
+  CheckEquals(VAL_2,obj.getCurrency(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setCurrency(obj.getProperty(LOCAL_PROP_2),VAL_3);
+  CheckEquals(VAL_3,obj.getCurrency(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_3,obj.getCurrency(LOCAL_PROP_2));
+  CheckEquals(VAL_3,obj.getCurrency(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.currency_multivalue();
+const LOCAL_PROP = s_PROP_CURRENCY_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOCurrency;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+      if ( ( k mod 3 ) = 0 ) then
+        val_list[k] := val_list[k] + High(TSDOInteger)
+      else if ( ( k mod 4 ) = 0 ) then
+        val_list[k] := val_list[k] - High(TSDOInteger)
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.appendCurrency(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getCurrency(),'appendCurrency() <> getCurrency()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.currency_unset_isset();
+const
+  LOCAL_PROP = s_PROP_CURRENCY_1;
+  LOCAL_PROP_ARRAY = s_PROP_CURRENCY_3;
+  VAL_1 : TSDOCurrency = 12345678.9101; VAL_2 : TSDOCurrency = -9879879.8765; 
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setCurrency(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getCurrencyDefault(),obj.getCurrency(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setCurrency(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.appendCurrency(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.appendCurrency(VAL_1);
+    ls.appendCurrency(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.currency_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_CURRENCY_1;
+  LOCAL_PROP_ARRAY = s_PROP_CURRENCY_3;
+  VAL_1 : TSDOCurrency = 8529637418529.6341;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setCurrency(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(0,obj.getCurrency(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_currency();
+const
+  VAL_1 : TSDOCurrency = 987654321741.8563;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_CURRENCY_1,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_CURRENCY_1);
+        locProp.setDefaultCurrency(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEqualsCurrency(VAL_1, locA.getCurrency(locProp), 'getCurrency');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_currency();
+const
+  VAL_1 : TSDOCurrency = 7481592639867.5321; VAL_2 : TSDOCurrency = -193742865123.6574;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_CURRENCY_1,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_CURRENCY_1);
+        locProp.setDefaultCurrency(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setCurrency(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEqualsCurrency(VAL_2, locA.getCurrency(locProp), 'getCurrency');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEqualsCurrency(VAL_1, locA.getCurrency(locProp), 'getCurrency');
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOBaseDataObject_Test.double_procs();
+const 
+  LOCAL_PROP_1 = s_PROP_DOUBLE_1;
+  LOCAL_PROP_2 = s_PROP_DOUBLE_2;
+  LOCAL_PROP_3 = s_PROP_DOUBLE_3;
+  VAL_1 : TSDODouble = 12345678.91011; VAL_2 : TSDODouble = -9879879.87654; VAL_3 : TSDODouble = 0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setDouble(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getDouble(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setDouble(obj.getProperty(LOCAL_PROP_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setDouble(obj.getProperty(LOCAL_PROP_1),VAL_1);
+  CheckEquals(VAL_1,obj.getDouble(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_1,obj.getDouble(LOCAL_PROP_1));
+  CheckEquals(VAL_1,obj.getDouble(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setDouble(obj.getProperty(LOCAL_PROP_1),VAL_2);
+  CheckEquals(VAL_2,obj.getDouble(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_2,obj.getDouble(LOCAL_PROP_1));
+  CheckEquals(VAL_2,obj.getDouble(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setDouble(obj.getProperty(LOCAL_PROP_1),VAL_3);
+  CheckEquals(VAL_3,obj.getDouble(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_3,obj.getDouble(LOCAL_PROP_1));
+  CheckEquals(VAL_3,obj.getDouble(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+
+  obj.setDouble(obj.getProperty(LOCAL_PROP_2),VAL_1);
+  CheckEquals(VAL_1,obj.getDouble(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_1,obj.getDouble(LOCAL_PROP_2));
+  CheckEquals(VAL_1,obj.getDouble(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setDouble(obj.getProperty(LOCAL_PROP_2),VAL_2);
+  CheckEquals(VAL_2,obj.getDouble(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_2,obj.getDouble(LOCAL_PROP_2));
+  CheckEquals(VAL_2,obj.getDouble(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setDouble(obj.getProperty(LOCAL_PROP_2),VAL_3);
+  CheckEquals(VAL_3,obj.getDouble(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_3,obj.getDouble(LOCAL_PROP_2));
+  CheckEquals(VAL_3,obj.getDouble(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.double_multivalue();
+const LOCAL_PROP = s_PROP_DOUBLE_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDODouble;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+      if ( ( k mod 3 ) = 0 ) then
+        val_list[k] := val_list[k] + High(TSDOInteger)
+      else if ( ( k mod 4 ) = 0 ) then
+        val_list[k] := val_list[k] - High(TSDOInteger)
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getDouble(),'append() <> getDouble()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.double_unset_isset();
+const
+  LOCAL_PROP = s_PROP_DOUBLE_1;
+  LOCAL_PROP_ARRAY = s_PROP_DOUBLE_3;
+  VAL_1 : TSDODouble = 12345678.91011; VAL_2 : TSDODouble = -9879879.87654; 
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setDouble(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getDoubleDefault(),obj.getDouble(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setDouble(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.double_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_DOUBLE_1;
+  LOCAL_PROP_ARRAY = s_PROP_DOUBLE_3;
+  VAL_1 : TSDODouble = 8529637418529.63741;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setDouble(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(0,obj.getDouble(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_double();
+const
+  VAL_1 : TSDODouble = 987654321741.852963;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_DOUBLE_1,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_DOUBLE_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getDouble(locProp), 'getDouble');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_double();
+const
+  VAL_1 : TSDODouble = 7481592639867.53421; VAL_2 : TSDODouble = -193742865123.6549874;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_DOUBLE_1,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_DOUBLE_1);
+        locProp.setDefault(TSDODouble(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setDouble(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getDouble(locProp), 'getDouble');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getDouble(locProp), 'getDouble');
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOBaseDataObject_Test.float_procs();
+const 
+  LOCAL_PROP_1 = s_PROP_FLOAT_1;
+  LOCAL_PROP_2 = s_PROP_FLOAT_2;
+  LOCAL_PROP_3 = s_PROP_FLOAT_3;
+  VAL_1 : TSDOFloat = 12345678.91011; VAL_2 : TSDOFloat = -9879879.87654; VAL_3 : TSDOFloat = 0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setFloat(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getFloat(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setFloat(obj.getProperty(LOCAL_PROP_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setFloat(obj.getProperty(LOCAL_PROP_1),VAL_1);
+  CheckEquals(VAL_1,obj.getFloat(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_1,obj.getFloat(LOCAL_PROP_1));
+  CheckEquals(VAL_1,obj.getFloat(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setFloat(obj.getProperty(LOCAL_PROP_1),VAL_2);
+  CheckEquals(VAL_2,obj.getFloat(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_2,obj.getFloat(LOCAL_PROP_1));
+  CheckEquals(VAL_2,obj.getFloat(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setFloat(obj.getProperty(LOCAL_PROP_1),VAL_3);
+  CheckEquals(VAL_3,obj.getFloat(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_3,obj.getFloat(LOCAL_PROP_1));
+  CheckEquals(VAL_3,obj.getFloat(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+
+  obj.setFloat(obj.getProperty(LOCAL_PROP_2),VAL_1);
+  CheckEquals(VAL_1,obj.getFloat(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_1,obj.getFloat(LOCAL_PROP_2));
+  CheckEquals(VAL_1,obj.getFloat(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setFloat(obj.getProperty(LOCAL_PROP_2),VAL_2);
+  CheckEquals(VAL_2,obj.getFloat(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_2,obj.getFloat(LOCAL_PROP_2));
+  CheckEquals(VAL_2,obj.getFloat(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setFloat(obj.getProperty(LOCAL_PROP_2),VAL_3);
+  CheckEquals(VAL_3,obj.getFloat(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_3,obj.getFloat(LOCAL_PROP_2));
+  CheckEquals(VAL_3,obj.getFloat(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.float_multivalue();
+const LOCAL_PROP = s_PROP_FLOAT_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOFloat;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+      if ( ( k mod 3 ) = 0 ) then
+        val_list[k] := val_list[k] + High(TSDOInteger)
+      else if ( ( k mod 4 ) = 0 ) then
+        val_list[k] := val_list[k] - High(TSDOInteger)
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getFloat(),'append() <> getFloat()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.float_unset_isset();
+const
+  LOCAL_PROP = s_PROP_FLOAT_1;
+  LOCAL_PROP_ARRAY = s_PROP_FLOAT_3;
+  VAL_1 : TSDOFloat = 12345678.91011; VAL_2 : TSDOFloat = -9879879.87654; 
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setFloat(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getFloatDefault(),obj.getFloat(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setFloat(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.float_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_FLOAT_1;
+  LOCAL_PROP_ARRAY = s_PROP_FLOAT_3;
+  VAL_1 : TSDOFloat = 8529637418529.63741;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setFloat(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(0,obj.getFloat(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_float();
+const
+  VAL_1 : TSDOFloat = 987654321741.852963;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_FLOAT_1,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_FLOAT_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getFloat(locProp), 'getFloat');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_float();
+const
+  VAL_1 : TSDOFloat = 7481592639867.53421; VAL_2 : TSDOFloat = -193742865123.6549874;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_FLOAT_1,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_FLOAT_1);
+        locProp.setDefault(TSDOFloat(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setFloat(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getFloat(locProp), 'getFloat');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getFloat(locProp), 'getFloat');
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOBaseDataObject_Test.long_procs();
+const 
+  LOCAL_PROP_1 = s_PROP_LONG_1;
+  LOCAL_PROP_2 = s_PROP_LONG_2;
+  LOCAL_PROP_3 = s_PROP_LONG_3;
+  VAL_1 : TSDOLong = 1234567891011; VAL_2 : TSDOLong = -987987987654; VAL_3 : TSDOLong = 0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setLong(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getLong(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setLong(obj.getProperty(LOCAL_PROP_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setLong(obj.getProperty(LOCAL_PROP_1),VAL_1);
+  CheckEquals(VAL_1,obj.getLong(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_1,obj.getLong(LOCAL_PROP_1));
+  CheckEquals(VAL_1,obj.getLong(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setLong(obj.getProperty(LOCAL_PROP_1),VAL_2);
+  CheckEquals(VAL_2,obj.getLong(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_2,obj.getLong(LOCAL_PROP_1));
+  CheckEquals(VAL_2,obj.getLong(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setLong(obj.getProperty(LOCAL_PROP_1),VAL_3);
+  CheckEquals(VAL_3,obj.getLong(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_3,obj.getLong(LOCAL_PROP_1));
+  CheckEquals(VAL_3,obj.getLong(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+
+  obj.setLong(obj.getProperty(LOCAL_PROP_2),VAL_1);
+  CheckEquals(VAL_1,obj.getLong(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_1,obj.getLong(LOCAL_PROP_2));
+  CheckEquals(VAL_1,obj.getLong(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setLong(obj.getProperty(LOCAL_PROP_2),VAL_2);
+  CheckEquals(VAL_2,obj.getLong(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_2,obj.getLong(LOCAL_PROP_2));
+  CheckEquals(VAL_2,obj.getLong(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setLong(obj.getProperty(LOCAL_PROP_2),VAL_3);
+  CheckEquals(VAL_3,obj.getLong(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_3,obj.getLong(LOCAL_PROP_2));
+  CheckEquals(VAL_3,obj.getLong(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.long_multivalue();
+const LOCAL_PROP = s_PROP_LONG_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOLong;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+      if ( ( k mod 3 ) = 0 ) then
+        val_list[k] := val_list[k] + High(TSDOInteger)
+      else if ( ( k mod 4 ) = 0 ) then
+        val_list[k] := val_list[k] - High(TSDOInteger)
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getLong(),'append() <> getLong()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.long_unset_isset();
+const
+  LOCAL_PROP = s_PROP_LONG_1;
+  LOCAL_PROP_ARRAY = s_PROP_LONG_3;
+  VAL_1 : TSDOLong = 123456789125525;  VAL_2 : TSDOLong = -123987321654987;
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setLong(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getLongDefault(),obj.getLong(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setLong(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.long_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_LONG_1;
+  LOCAL_PROP_ARRAY = s_PROP_LONG_3;
+  VAL_1 : TSDOLong = 852963741852963741;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setLong(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(0,obj.getLong(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_long();
+const
+  VAL_1 : TSDOLong = 987654321741852963;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_LONG_1,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_LONG_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getLong(locProp), 'getLong');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_long();
+const
+  VAL_1 : TSDOLong = 748159263986753421; VAL_2 : TSDOLong = -1937428651236549874;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_LONG_1,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_LONG_1);
+        locProp.setDefault(TSDOLong(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setLong(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getLong(locProp), 'getLong');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getLong(locProp), 'getLong');
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOBaseDataObject_Test.short_procs();
+const
+  LOCAL_PROP_1 = s_PROP_SHORT_1;
+  LOCAL_PROP_2 = s_PROP_SHORT_2;
+  LOCAL_PROP_3 = s_PROP_SHORT_3;
+  VAL_1 : TSDOShort = 4567; VAL_2 : TSDOShort = -9856; VAL_3 : TSDOShort = 0;
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setShort(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getShort(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setShort(obj.getProperty(LOCAL_PROP_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setShort(obj.getProperty(LOCAL_PROP_1),VAL_1);
+  CheckEquals(VAL_1,obj.getShort(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_1,obj.getShort(LOCAL_PROP_1));
+  CheckEquals(VAL_1,obj.getShort(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setShort(obj.getProperty(LOCAL_PROP_1),VAL_2);
+  CheckEquals(VAL_2,obj.getShort(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_2,obj.getShort(LOCAL_PROP_1));
+  CheckEquals(VAL_2,obj.getShort(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+  obj.setShort(obj.getProperty(LOCAL_PROP_1),VAL_3);
+  CheckEquals(VAL_3,obj.getShort(obj.getProperty(LOCAL_PROP_1)));
+  CheckEquals(VAL_3,obj.getShort(LOCAL_PROP_1));
+  CheckEquals(VAL_3,obj.getShort(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_1))));
+
+
+  obj.setShort(obj.getProperty(LOCAL_PROP_2),VAL_1);
+  CheckEquals(VAL_1,obj.getShort(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_1,obj.getShort(LOCAL_PROP_2));
+  CheckEquals(VAL_1,obj.getShort(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setShort(obj.getProperty(LOCAL_PROP_2),VAL_2);
+  CheckEquals(VAL_2,obj.getShort(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_2,obj.getShort(LOCAL_PROP_2));
+  CheckEquals(VAL_2,obj.getShort(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+
+  obj.setShort(obj.getProperty(LOCAL_PROP_2),VAL_3);
+  CheckEquals(VAL_3,obj.getShort(obj.getProperty(LOCAL_PROP_2)));
+  CheckEquals(VAL_3,obj.getShort(LOCAL_PROP_2));
+  CheckEquals(VAL_3,obj.getShort(obj.getPropertyIndex(obj.getProperty(LOCAL_PROP_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.short_multivalue();
+const LOCAL_PROP = s_PROP_SHORT_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDOShort;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k] := RandomRange(Low(TSDOShort),High(TSDOShort));
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_BOOL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_BOOL_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getShort(),'append() <> getShort()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.short_unset_isset();
+const
+  LOCAL_PROP = s_PROP_SHORT_1;
+  LOCAL_PROP_ARRAY = s_PROP_SHORT_3;
+  VAL_1 : TSDOShort = 789;  VAL_2 : TSDOShort = -654;
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setShort(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getShortDefault(),obj.getShort(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setShort(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.short_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_SHORT_1;
+  LOCAL_PROP_ARRAY = s_PROP_SHORT_3;
+  VAL_1 : TSDOShort = 1597;
+var
+  obj : ISDODataObject;
+begin
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setShort(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(0,obj.getShort(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_short();
+const
+  VAL_1 : TSDOShort = 6547;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_SHORT_1,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_SHORT_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getShort(locProp), 'getShort');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_short();
+const
+  VAL_1 : TSDOShort = 20123; VAL_2 : TSDOShort = -5648;
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_SHORT_1,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_SHORT_1);
+        locProp.setDefault(TSDOShort(VAL_1));
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setShort(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getShort(locProp), 'getShort');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getShort(locProp), 'getShort');
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOBytes;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getBytes(AXPath), AXPath);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOChar;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getCharacter(AXPath), AXPath);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOBaseDataObject_Test.check_xpath_value_currency(
+  const AExpected: TSDOCurrency;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEqualsCurrency(AExpected,AObject.getCurrency(AXPath), 0.0001, AXPath);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDODouble;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getDouble(AXPath), 0.0001, AXPath);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOFloat;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getFloat(AXPath), 0.0001, AXPath);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOLong;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getLong(AXPath), AXPath);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOShort;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getShort(AXPath), AXPath);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOByte;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getByte(AXPath), AXPath);
+end;
+
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDODateTime;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getDate(AXPath), AXPath, False);
+end;
+
+procedure TSDOBaseDataObject_Test.get_byte_xpath();
+const
+  LOCAL_PROP_TYPE = ByteType;
+  LOCAL_PROP_1_NAME = s_PROP_BYTE_1;
+  LOCAL_PROP_2_NAME = s_PROP_BYTE_2;
+  LOCAL_PROP_A_NAME = s_PROP_BYTE_A;
+  LOCAL_PROP_B_NAME = s_PROP_BYTE_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOByte;
+begin
+  o1_val_1 := RandomRange(Low(TSDOByte),High(TSDOByte));
+  o1_val_2 := RandomRange(Low(TSDOByte),High(TSDOByte));
+  o2_val_A := RandomRange(Low(TSDOByte),High(TSDOByte));
+  o2_val_B := RandomRange(Low(TSDOByte),High(TSDOByte));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setByte(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setByte(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setByte(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setByte(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOBaseDataObject_Test.get_char_xpath();
+const
+  LOCAL_PROP_TYPE = CharacterType;
+  LOCAL_PROP_1_NAME = s_PROP_CHAR_1;
+  LOCAL_PROP_2_NAME = s_PROP_CHAR_2;
+  LOCAL_PROP_A_NAME = s_PROP_CHAR_A;
+  LOCAL_PROP_B_NAME = s_PROP_CHAR_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOChar;
+begin
+  o1_val_1 := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  o1_val_2 := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  o2_val_A := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  o2_val_B := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setCharacter(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setCharacter(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setCharacter(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setCharacter(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOBaseDataObject_Test.get_currency_xpath();
+const
+  LOCAL_PROP_TYPE = CurrencyType;
+  LOCAL_PROP_1_NAME = s_PROP_CURRENCY_1;
+  LOCAL_PROP_2_NAME = s_PROP_CURRENCY_2;
+  LOCAL_PROP_A_NAME = s_PROP_CURRENCY_A;
+  LOCAL_PROP_B_NAME = s_PROP_CURRENCY_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOCurrency;
+begin
+  o1_val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o1_val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_A := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_B := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setCurrency(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setCurrency(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setCurrency(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setCurrency(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value_currency(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value_currency(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value_currency(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value_currency(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value_currency(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value_currency(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOBaseDataObject_Test.get_double_xpath();
+const
+  LOCAL_PROP_TYPE = DoubleType;
+  LOCAL_PROP_1_NAME = s_PROP_DOUBLE_1;
+  LOCAL_PROP_2_NAME = s_PROP_DOUBLE_2;
+  LOCAL_PROP_A_NAME = s_PROP_DOUBLE_A;
+  LOCAL_PROP_B_NAME = s_PROP_DOUBLE_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDODouble;
+begin
+  o1_val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o1_val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_A := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_B := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setDouble(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setDouble(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setDouble(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setDouble(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOBaseDataObject_Test.get_float_xpath();
+const
+  LOCAL_PROP_TYPE = FloatType;
+  LOCAL_PROP_1_NAME = s_PROP_FLOAT_1;
+  LOCAL_PROP_2_NAME = s_PROP_FLOAT_2;
+  LOCAL_PROP_A_NAME = s_PROP_FLOAT_A;
+  LOCAL_PROP_B_NAME = s_PROP_FLOAT_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOFloat;
+begin
+  o1_val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o1_val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_A := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_B := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setFloat(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setFloat(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setFloat(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setFloat(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure TSDOBaseDataObject_Test.get_date_xpath();
+const
+  LOCAL_PROP_TYPE = DateTimeType;
+  LOCAL_PROP_1_NAME = s_PROP_DATE_1;
+  LOCAL_PROP_2_NAME = s_PROP_DATE_2;
+  LOCAL_PROP_A_NAME = s_PROP_DATE_A;
+  LOCAL_PROP_B_NAME = s_PROP_DATE_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDODateTime;
+begin
+  o1_val_1 := RandomDate();
+  o1_val_2 := RandomDate();
+  o2_val_A := RandomDate();
+  o2_val_B := RandomDate();
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setDate(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setDate(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setDate(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setDate(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOBaseDataObject_Test.get_long_xpath();
+const
+  LOCAL_PROP_TYPE = LongType;
+  LOCAL_PROP_1_NAME = s_PROP_LONG_1;
+  LOCAL_PROP_2_NAME = s_PROP_LONG_2;
+  LOCAL_PROP_A_NAME = s_PROP_LONG_A;
+  LOCAL_PROP_B_NAME = s_PROP_LONG_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOLong;
+begin
+  o1_val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o1_val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_A := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  o2_val_B := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setLong(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setLong(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setLong(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setLong(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOBaseDataObject_Test.get_short_xpath();
+const
+  LOCAL_PROP_TYPE = ShortType;
+  LOCAL_PROP_1_NAME = s_PROP_SHORT_1;
+  LOCAL_PROP_2_NAME = s_PROP_SHORT_2;
+  LOCAL_PROP_A_NAME = s_PROP_SHORT_A;
+  LOCAL_PROP_B_NAME = s_PROP_SHORT_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOShort;
+begin
+  o1_val_1 := RandomRange(Low(TSDOShort),High(TSDOShort));
+  o1_val_2 := RandomRange(Low(TSDOShort),High(TSDOShort));
+  o2_val_A := RandomRange(Low(TSDOShort),High(TSDOShort));
+  o2_val_B := RandomRange(Low(TSDOShort),High(TSDOShort));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setShort(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setShort(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setShort(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setShort(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOBoolean;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getBoolean(AXPath), AXPath);
+end;
+
+procedure TSDOBaseDataObject_Test.get_bool_xpath();
+const
+  LOCAL_PROP_TYPE = BooleanType;
+  LOCAL_PROP_1_NAME = s_PROP_BOOL_1;
+  LOCAL_PROP_2_NAME = s_PROP_BOOL_2;
+  LOCAL_PROP_A_NAME = s_PROP_BOOL_A;
+  LOCAL_PROP_B_NAME = s_PROP_BOOL_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOBoolean;
+begin
+  o1_val_1 := ( RandomRange(-1234,56789) mod 3 ) = 0;
+  o1_val_2 := ( RandomRange(-1234,56789) mod 3 ) = 0;
+  o2_val_A := ( RandomRange(-1234,56789) mod 3 ) = 0;
+  o2_val_B := ( RandomRange(-1234,56789) mod 3 ) = 0;
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setBoolean(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setBoolean(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setBoolean(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setBoolean(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+
+procedure TSDOBaseDataObject_Test.check_xpath_value(
+  const AExpected: TSDOString;
+  const AObject: ISDODataObject;
+  const AXPath: string
+);
+begin
+  CheckEquals(AExpected,AObject.getString(AXPath), AXPath);
+end;
+
+procedure TSDOBaseDataObject_Test.get_string_xpath();
+const
+  LOCAL_PROP_TYPE = StringType;
+  LOCAL_PROP_1_NAME = s_PROP_STR_1;
+  LOCAL_PROP_2_NAME = s_PROP_STR_2;
+  LOCAL_PROP_A_NAME = s_PROP_STR_A;
+  LOCAL_PROP_B_NAME = s_PROP_STR_B;
+
+  function local_create_factory() : ISDODataFactory;
+  var
+    res : ISDODataFactory;
+    tfg : TTypeFlags;
+  begin
+    tfg := [];
+    if is_open_type() then
+      Include(tfg,tfIsOpen);
+    res := TSDODataFactory.Create() as ISDODataFactory;
+    res.AddType(s_URI_1,s_TYPE_1,tfg);
+    res.AddType(s_URI_1,s_TYPE_2,tfg);
+    res.AddType(s_URI_1,s_TYPE_3,tfg);
+
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_1_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,LOCAL_PROP_2_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[pfIsContainment]);
+
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_A_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+    res.addProperty(s_URI_1,s_TYPE_2,LOCAL_PROP_B_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LOCAL_PROP_TYPE],[]);
+
+    Result := res;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  o1, o2 : ISDODataObject;
+  o1_val_1, o1_val_2, o2_val_A, o2_val_B : TSDOString;
+begin
+  o1_val_1 := RandomString(RandomRange(0,1000));
+  o1_val_2 := RandomString(RandomRange(0,1000));
+  o2_val_A := RandomString(RandomRange(0,1000));
+  o2_val_B := RandomString(RandomRange(0,1000));
+  locFac := local_create_factory();
+  o1 := locFac.createNew(s_URI_1,s_TYPE_1);
+  o1.setString(LOCAL_PROP_1_NAME,o1_val_1);
+  o1.setString(LOCAL_PROP_2_NAME,o1_val_2);
+    o2 := O1.createDataObject(s_PROP_OBJ_CONT);
+      o2.setString(LOCAL_PROP_A_NAME,o2_val_A);
+      o2.setString(LOCAL_PROP_B_NAME,o2_val_B);
+
+  check_xpath_value(o1_val_1, o1,LOCAL_PROP_1_NAME);
+  check_xpath_value(o1_val_2, o1, LOCAL_PROP_2_NAME);
+  check_xpath_value(o2_val_A, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_A_NAME]));
+  check_xpath_value(o2_val_B, o1, Format('%s/%s',[s_PROP_OBJ_CONT,LOCAL_PROP_B_NAME]));
+  check_xpath_value(o1_val_1, o2, Format('%s/%s',['..',LOCAL_PROP_1_NAME]));
+  check_xpath_value(o1_val_2, o2, Format('%s/%s',['..',LOCAL_PROP_2_NAME]));
+end;
+
+procedure TSDOBaseDataObject_Test.date_procs();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_3)^ := d;
+  end;
+
+var
+  obj : ISDODataObject;
+  ok : Boolean;
+begin
+  SetConstants();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    obj.setDate(obj.getProperty('qsdc'),VAL_1);
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.getDate(obj.getProperty('qsdc'));
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOPropertyNotFoundException.');
+
+  ok := False;
+  try
+    obj.setDate(obj.getProperty(s_PROP_DATE_3),VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Expect ESDOIllegalArgumentException.');
+
+  obj.setDate(obj.getProperty(s_PROP_DATE_1),VAL_1);
+  CheckEquals(VAL_1,obj.getDate(obj.getProperty(s_PROP_DATE_1)));
+  CheckEquals(VAL_1,obj.getDate(s_PROP_DATE_1));
+  CheckEquals(VAL_1,obj.getDate(obj.getPropertyIndex(obj.getProperty(s_PROP_DATE_1))));
+
+  obj.setDate(obj.getProperty(s_PROP_DATE_1),VAL_2);
+  CheckEquals(VAL_2,obj.getDate(obj.getProperty(s_PROP_DATE_1)));
+  CheckEquals(VAL_2,obj.getDate(s_PROP_DATE_1));
+  CheckEquals(VAL_2,obj.getDate(obj.getPropertyIndex(obj.getProperty(s_PROP_DATE_1))));
+
+  obj.setDate(obj.getProperty(s_PROP_DATE_1),VAL_3);
+  CheckEquals(VAL_3,obj.getDate(obj.getProperty(s_PROP_DATE_1)));
+  CheckEquals(VAL_3,obj.getDate(s_PROP_DATE_1));
+  CheckEquals(VAL_3,obj.getDate(obj.getPropertyIndex(obj.getProperty(s_PROP_DATE_1))));
+
+
+  obj.setDate(obj.getProperty(s_PROP_DATE_2),VAL_1);
+  CheckEquals(VAL_1,obj.getDate(obj.getProperty(s_PROP_DATE_2)));
+  CheckEquals(VAL_1,obj.getDate(s_PROP_DATE_2));
+  CheckEquals(VAL_1,obj.getDate(obj.getPropertyIndex(obj.getProperty(s_PROP_DATE_2))));
+
+  obj.setDate(obj.getProperty(s_PROP_DATE_2),VAL_2);
+  CheckEquals(VAL_2,obj.getDate(obj.getProperty(s_PROP_DATE_2)));
+  CheckEquals(VAL_2,obj.getDate(s_PROP_DATE_2));
+  CheckEquals(VAL_2,obj.getDate(obj.getPropertyIndex(obj.getProperty(s_PROP_DATE_2))));
+
+  obj.setDate(obj.getProperty(s_PROP_DATE_2),VAL_3);
+  CheckEquals(VAL_3,obj.getDate(obj.getProperty(s_PROP_DATE_2)));
+  CheckEquals(VAL_3,obj.getDate(s_PROP_DATE_2));
+  CheckEquals(VAL_3,obj.getDate(obj.getPropertyIndex(obj.getProperty(s_PROP_DATE_2))));
+end;
+
+procedure TSDOBaseDataObject_Test.CheckEquals(expected, actual: TSDODate;
+  msg: string; const AStrict: Boolean
+);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.date_multivalue();
+const LOCAL_PROP = s_PROP_DATE_3; LOCAL_ARRAY_LEN = 100;
+var
+  val_list : array[0..Pred(LOCAL_ARRAY_LEN)] of TSDODate;
+
+  procedure PrepareArray();
+  var
+    k : Integer;
+  begin
+    Randomize();
+    for k := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+      val_list[k].Date := EncodeDateTime(
+                            RandomRange(1900,2009),RandomRange(1,12),RandomRange(1,28),
+                            RandomRange(1,23),RandomRange(0,59),RandomRange(0,59), RandomRange(0,999)
+                          );
+      val_list[k].HourOffset := RandomRange(0,10);
+      val_list[k].MinuteOffset := RandomRange(0,59);
+    end;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls, ls1 : ISDODataObjectList;
+  i : Integer;
+  crs : ILinkedListCursor;
+  ok : Boolean;
+begin
+  PrepareArray();
+  obj := Create_Object();
+
+  ok := False;
+  try
+    ls := obj.getList(s_PROP_DATE_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,Format('"%s" is not a multivalue property.',[s_PROP_DATE_1]));
+
+  ls := obj.getList(LOCAL_PROP);
+    Check(ls <> nil);
+  ls1 := obj.getList(LOCAL_PROP);
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Name)');
+
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+  ls1 := obj.getList(obj.getType().getPropertyIndex(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Index)');
+
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+  ls1 := obj.getList(obj.getType().getProperty(LOCAL_PROP));
+    CheckEquals(PtrInt(ls),PtrInt(ls1), 'getList(Name) <> getList(Property)');
+
+  CheckEquals(0,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    ls.append(val_list[i]);
+  end;
+
+  crs := ls.getCursor();
+  Check(crs <> nil,'ls.getCursor()');
+  crs.Reset();
+  CheckEquals(LOCAL_ARRAY_LEN,ls.size(),'Size');
+  for i := 0 to Pred(LOCAL_ARRAY_LEN) do begin
+    crs.MoveNext();
+    CheckEquals(val_list[i],ls.getDate(),'append() <> getByte()');
+  end;
+end;
+
+procedure TSDOBaseDataObject_Test.date_unset_isset();
+const
+  LOCAL_PROP = s_PROP_DATE_1;
+  LOCAL_PROP_ARRAY = s_PROP_DATE_3;
+  VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+  VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_2)^ := d;
+  end;
+
+var
+  obj : ISDODataObject;
+  ls : ISDODataObjectList;
+begin
+  SetConstants();
+  obj := Create_Object();
+
+  CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 1');
+
+  obj.setDate(LOCAL_PROP, VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+    obj.unset(LOCAL_PROP);
+      CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(obj.getProperty(LOCAL_PROP).getDateDefault(),obj.getDate(LOCAL_PROP),'"unSet" should restore the default value');
+    obj.setDate(LOCAL_PROP, VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+      obj.unset(LOCAL_PROP);
+        CheckEquals(False,obj.isSet(LOCAL_PROP),LOCAL_PROP);
+
+  ls := obj.getList(LOCAL_PROP_ARRAY);
+  Check(ls <> nil);
+  CheckEquals(0,ls.size());
+  CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 2');
+  ls.append(VAL_1);
+    CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 3');
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 4');
+      CheckEquals(0,ls.size());
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 5');
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(True,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 6');
+      CheckEquals(2,ls.size());
+    obj.unset(LOCAL_PROP_ARRAY);
+      CheckEquals(PtrInt(ls),PtrInt(obj.getList(LOCAL_PROP_ARRAY)));
+      CheckEquals(False,obj.isSet(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY + ' 7');
+      CheckEquals(0,ls.size());
+end;
+
+procedure TSDOBaseDataObject_Test.date_setnull_isnull();
+const
+  LOCAL_PROP = s_PROP_DATE_1;
+  LOCAL_PROP_ARRAY = s_PROP_DATE_3;
+  VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+var
+  obj : ISDODataObject;
+begin
+  PSDODate(@VAL_1)^.Date := Now();
+  obj := Create_Object();
+
+  // these _does_ depend on the property's default
+  CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+  CheckEquals(False,obj.isNull(LOCAL_PROP_ARRAY),LOCAL_PROP_ARRAY);
+
+  obj.setDate(LOCAL_PROP, VAL_1);
+    CheckEquals(False,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+    obj.setNull(LOCAL_PROP);
+      CheckEquals(True,obj.isNull(LOCAL_PROP),LOCAL_PROP);
+      CheckEquals(ZERO_DATE,obj.getDate(LOCAL_PROP),LOCAL_PROP);
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_date();
+const
+  VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  PSDODate(@VAL_1)^.Date := Now();
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_DATE_1,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_DATE_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  CheckEquals(VAL_1, locA.getDate(locProp), 'getDate');
+  CheckEquals(False, locA.isSet(locProp), 'isSet');
+end;
+
+procedure TSDOBaseDataObject_Test.property_default_value_unset_date();
+const
+  VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+  VAL_2 : TSDODate = ( Date : 0; HourOffset : 3; MinuteOffset : 4; );
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  tfg : TTypeFlags;
+begin
+  PSDODate(@VAL_1)^.Date := Now();
+  PSDODate(@VAL_2)^.Date := Date() - 100;
+  tfg := [];
+  if is_open_type() then
+    Include(tfg,tfIsOpen);
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,tfg);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_DATE_1,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[]);
+      locProp := locFactory.getType(s_URI_1,s_TYPE_1).getProperty(s_PROP_DATE_1);
+        locProp.setDefault(VAL_1);
+
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+  locA.setDate(locProp, VAL_2);
+    CheckEquals(True, locA.isSet(locProp), 'isSet');
+    CheckEquals(VAL_2, locA.getDate(locProp), 'getDate');
+    locA.unset(locProp);
+      CheckEquals(False, locA.isSet(locProp), 'isSet');
+      CheckEquals(VAL_1, locA.getDate(locProp), 'getDate');
+end;
+
+{ TObserver_Test }
+
+procedure TObserver_Test.ObserverInfo_create();
+var
+  locFactory : ISDODataFactory;
+  locA : ISDODataObject;
+  locProp : ISDOProperty;
+  locRef : TObserverInfo;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,[]);
+    locFactory.AddType(s_URI_1,s_TYPE_2,[]);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_REF,s_URI_1,s_TYPE_2,[]);
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+    locProp := locA.getProperty(s_PROP_OBJ_REF);
+  locRef := TObserverInfo.Create(locA,locProp);
+  try
+    CheckEquals(PtrUInt(locA), PtrUInt(locRef.GetDataObject()));
+    CheckEquals(PtrUInt(locProp), PtrUInt(locRef.GetRefProperty()));
+  finally
+    FreeAndNil(locRef);
+  end;
+end;
+
+procedure TObserver_Test.ObserverList_add_find();
+var
+  locFactory : ISDODataFactory;
+  locA, locB : ISDODataObject;
+  locProp, locPropB : ISDOProperty;
+  locRef : TObserverInfo;
+  locRefList : TDataObjectObserverList;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+    locFactory.AddType(s_URI_1,s_TYPE_1,[]);
+    locFactory.AddType(s_URI_1,s_TYPE_2,[]);
+    locFactory.AddType(s_URI_1,s_TYPE_3,[]);
+      locFactory.addProperty(s_URI_1,s_TYPE_1,s_PROP_OBJ_REF,s_URI_1,s_TYPE_2,[]);
+      locFactory.addProperty(s_URI_1,s_TYPE_2,s_PROP_OBJ_REF,s_URI_1,s_TYPE_3,[]);
+  locA := locFactory.createNew(s_URI_1,s_TYPE_1);
+    locProp := locA.getProperty(s_PROP_OBJ_REF);
+  locRefList := TDataObjectObserverList.Create();
+  try
+    CheckEquals(0, locRefList.GetCount());
+    locRef := locRefList.Find(locA,locProp);
+    CheckEquals(PtrUInt(0), PtrUInt(locRef));
+
+    locRefList.Add(locA,locProp);
+      CheckEquals(1, locRefList.GetCount());
+      locRef := locRefList.Find(locA,locProp);
+      CheckNotEquals(PtrUInt(0), PtrUInt(locRef));
+      CheckEquals(PtrUInt(locA), PtrUInt(locRef.GetDataObject()));
+      CheckEquals(PtrUInt(locProp), PtrUInt(locRef.GetRefProperty()));
+      CheckEquals(PtrUInt(locRef), PtrUInt(locRefList.GetItem(0)));
+
+      locRefList.Add(locA,locProp);
+        CheckEquals(PtrUInt(locRef), PtrUInt(locRefList.Find(locA,locProp)));
+        CheckEquals(1, locRefList.GetCount());
+
+      locB := locFactory.createNew(s_URI_1,s_TYPE_2);
+      locPropB := locB.getProperty(s_PROP_OBJ_REF);
+      locRefList.Add(locB,locPropB);
+        CheckEquals(2, locRefList.GetCount());
+        locRef := locRefList.Find(locA,locProp);
+          CheckNotEquals(PtrUInt(0), PtrUInt(locRef));
+          CheckEquals(PtrUInt(locA), PtrUInt(locRef.GetDataObject()));
+          CheckEquals(PtrUInt(locProp), PtrUInt(locRef.GetRefProperty()));
+        locRef := locRefList.Find(locB,locPropB);
+          CheckNotEquals(PtrUInt(0), PtrUInt(locRef));
+          CheckEquals(PtrUInt(locB), PtrUInt(locRef.GetDataObject()));
+          CheckEquals(PtrUInt(locPropB), PtrUInt(locRef.GetRefProperty()));
+
+  finally
+    FreeAndNil(locRefList);
+  end;
+end;
+
+{ TSDODataObject_Test }
+
+class function TSDODataObject_Test.is_open_type() : Boolean;
+begin
+  Result := False;
+end;
+
+{ TSDOOpenedDataObject_Test }
+
+procedure TSDOOpenedDataObject_Test.addProperty();
+const
+  s_open_bool = 'open_bool_prop';
+  s_open_byte = 'open_byte_prop';
+  s_open_int = 'open_int_prop';
+  s_open_str = 'open_str_prop';
+  s_open_obj = 'open_obj_prop';
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_b : TSDOBoolean;
+  val_byte : TSDOByte;
+  val_i : TSDOInteger;
+  val_s : TSDOString;
+  val_o : ISDODataObject;
+  val_open_bool : TSDOBoolean;
+  val_open_byte : TSDOByte;
+  val_open_int : TSDOInteger;
+  val_open_str : TSDOString;
+  val_open_obj : ISDODataObject;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_b := ( ( RandomRange(-123,456) mod 3 ) = 0 );
+  val_byte := RandomRange(Low(TSDOByte),High(TSDOByte));
+  val_i := RandomRange(-123,456);
+  val_s := RandomString(123);
+  val_o := FFactory.createNew(s_URI_1,s_TYPE_2);
+  val_open_bool := ( ( RandomRange(-1234,4567) mod 2 ) = 0 );
+  val_open_byte := RandomRange(Low(TSDOByte),High(TSDOByte));
+  val_open_int := RandomRange(-12345,678910);
+  val_open_str := RandomString(1234);
+  val_open_obj := FFactory.createNew(s_URI_1,s_TYPE_2);
+
+  locO := Create_Object();
+    locO.setBoolean(s_PROP_BOOL_1,val_b);
+    locO.setByte(s_PROP_BYTE_1,val_byte);
+    locO.setInteger(s_PROP_INTEGER_1,val_i);
+    locO.setString(s_PROP_STR_1,val_s);
+    locO.setDataObject(s_PROP_OBJ_CONT,val_o);
+  locOX := locO as ISDODataObjectEx;
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_int,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_int, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]), []);
+    locO.setInteger(s_open_int,val_open_int);
+      CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+      CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+      CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+      CheckEquals(PtrUInt(val_o), PtrUInt(locO.getDataObject(s_PROP_OBJ_CONT)), s_PROP_OBJ_CONT);
+      CheckEquals(val_open_int, locO.getInteger(s_open_int), s_open_int);
+
+    locOX.addProperty(s_open_bool,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]),[]);
+      CheckEquals( ( staticPropCount + 2), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_bool, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]), []);
+    locOX.addProperty(s_open_str,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),[]);
+      CheckEquals( ( staticPropCount + 3), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_str, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]), []);
+    locO.setBoolean(s_open_bool,val_open_bool);
+    locO.setString(s_open_str,val_open_str);
+      CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+      CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+      CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+      CheckEquals(PtrUInt(val_o), PtrUInt(locO.getDataObject(s_PROP_OBJ_CONT)), s_PROP_OBJ_CONT);
+      CheckEquals(val_open_str, locO.getString(s_open_str), s_open_str);
+
+    locOX.addProperty(s_open_obj,FFactory.getType(s_URI_1,s_TYPE_2),[]);
+      CheckEquals( ( staticPropCount + 4), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_obj, FFactory.getType(s_URI_1,s_TYPE_2), []);
+    locO.setDataObject(s_open_obj,val_open_obj);
+      CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+      CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+      CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+      CheckEquals(PtrUInt(val_o), PtrUInt(locO.getDataObject(s_PROP_OBJ_CONT)), s_PROP_OBJ_CONT);
+      CheckEquals(val_open_bool, locO.getBoolean(s_open_bool), s_open_bool);
+      CheckEquals(val_open_int, locO.getInteger(s_open_int), s_open_int);
+      CheckEquals(val_open_str, locO.getString(s_open_str), s_open_str);
+      CheckEquals(PtrUInt(val_open_obj), PtrUInt(locO.getDataObject(s_open_obj)), s_open_obj);
+
+    locOX.addProperty(s_open_byte,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ByteType]),[]);
+      CheckEquals( ( staticPropCount + 5), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_byte, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ByteType]), []);
+    locO.setByte(s_open_byte,val_open_byte);
+      CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+      CheckEquals(val_byte, locO.getByte(s_PROP_BYTE_1), s_PROP_BYTE_1);
+      CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+      CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+      CheckEquals(PtrUInt(val_o), PtrUInt(locO.getDataObject(s_PROP_OBJ_CONT)), s_PROP_OBJ_CONT);
+      CheckEquals(val_open_int, locO.getInteger(s_open_int), s_open_int);
+      CheckEquals(val_open_byte, locO.getByte(s_open_byte), s_open_byte);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_byte();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_BYTE_1;
+  prop_type = ByteType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDOByte;
+  val_open : TSDOByte;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := RandomRange(Low(TSDOByte),High(TSDOByte));
+  val_open := RandomRange(Low(TSDOByte),High(TSDOByte));
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setByte(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setByte(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getByte(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getByte(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_date();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_DATE_1;
+  prop_type = DateTimeType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDODateTime;
+  val_open : TSDODateTime;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := RandomDate();
+  val_open := RandomDate();
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setDate(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setDate(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getDate(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getDate(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_error();
+const
+  s_open_bool = 'open_bool_prop';
+  s_open_byte = 'open_byte_prop';
+  s_open_int = 'open_int_prop';
+  s_open_str = 'open_str_prop';
+  s_open_obj = 'open_obj_prop';
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+
+  procedure check_add_2_time(const AName : string; const AType : ISDOType; const AFlags : TPropertyFlags);
+  var
+    ok : boolean;
+  begin
+    locOX.addProperty(AName,AType,AFlags);
+    ok := False;
+    try
+      locOX.addProperty(AName,AType,AFlags);
+    except
+      on e : ESDODuplicatedItemException do
+        ok := True;
+    end;
+    CheckEquals(True, ok);
+  end;
+
+begin
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    check_add_2_time(s_open_int,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]),[]);
+    check_add_2_time(s_open_bool,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]),[]);
+    check_add_2_time(s_open_byte,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ByteType]),[]);
+    check_add_2_time(s_open_str,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),[]);
+    check_add_2_time(s_open_obj,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]),[]);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value();
+const
+  s_open_bool = 'open_bool_prop';
+  s_open_int = 'open_int_prop';
+  s_open_str = 'open_str_prop';
+  s_open_obj_cont = 'open_obj_prop_cont';
+  s_open_obj_ref = 'open_obj_prop_ref';
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_b : TSDOBoolean;
+  val_i : TSDOInteger;
+  val_s : TSDOString;
+  val_open_bool : array of TSDOBoolean;
+  val_open_int : array of TSDOInteger;
+  val_open_str : array of TSDOString;
+  val_open_obj_cont, val_open_obj_ref : array of ISDODataObject;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_b := ( ( RandomRange(-123,456) mod 3 ) = 0 );
+  val_i := RandomRange(-123,456);
+  val_s := RandomString(123);
+  c := RandomRange(1,100);
+  SetLength(val_open_bool,c);
+  for i := 0 to Pred(Length(val_open_bool)) do
+    val_open_bool[i] := ( ( RandomRange(-1234,4567) mod 3 ) = 0 );
+  c := RandomRange(1,100);
+  SetLength(val_open_int,c);
+  for i := 0 to Pred(Length(val_open_int)) do
+    val_open_int[i] := RandomRange(-1234, 546789);
+  c := RandomRange(1,100);
+  SetLength(val_open_str,c);
+  for i := 0 to Pred(Length(val_open_str)) do
+    val_open_str[i] := RandomString(RandomRange(0,100));
+  c := RandomRange(1,100);
+  SetLength(val_open_obj_cont,c);
+  for i := 0 to Pred(Length(val_open_obj_cont)) do
+    val_open_obj_cont[i] := FFactory.createNew(s_URI_1,s_TYPE_2);
+  c := RandomRange(1,100);
+  SetLength(val_open_obj_ref,c);
+  for i := 0 to Pred(Length(val_open_obj_ref)) do
+    val_open_obj_ref[i] := FFactory.createNew(s_URI_1,s_TYPE_2);
+
+  try
+    locO := Create_Object();
+      locO.setBoolean(s_PROP_BOOL_1,val_b);
+      locO.setInteger(s_PROP_INTEGER_1,val_i);
+      locO.setString(s_PROP_STR_1,val_s);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_int,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_int, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]), [pfIsMany]);
+      ls := locO.getList(s_open_int);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_int)');
+        for i := 0 to Pred(Length(val_open_int)) do
+          ls.append(val_open_int[i]);
+        CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+        CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+        CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+        for i := 0 to Pred(Length(val_open_int)) do
+          CheckEquals(val_open_int[i], ls.getInteger(i), s_open_int);
+
+      locOX.addProperty(s_open_bool,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 2), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_bool, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]), [pfIsMany]);
+      locOX.addProperty(s_open_str,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 3), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_str, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]), [pfIsMany]);
+      locOX.addProperty(s_open_obj_cont,FFactory.getType(s_URI_1,s_TYPE_2),[pfIsMany,pfIsContainment]);
+        CheckEquals( ( staticPropCount + 4), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_obj_cont, FFactory.getType(s_URI_1,s_TYPE_2), [pfIsMany,pfIsContainment]);
+      locOX.addProperty(s_open_obj_ref,FFactory.getType(s_URI_1,s_TYPE_2),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 5), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_obj_ref, FFactory.getType(s_URI_1,s_TYPE_2), [pfIsMany]);
+
+      ls := locO.getList(s_open_bool);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_bool)');
+        for i := 0 to Pred(Length(val_open_bool)) do
+          ls.append(val_open_bool[i]);
+      ls := locO.getList(s_open_str);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_str)');
+        for i := 0 to Pred(Length(val_open_str)) do
+          ls.append(val_open_str[i]);
+      ls := locO.getList(s_open_obj_cont);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_obj_cont)');
+        for i := 0 to Pred(Length(val_open_obj_cont)) do
+          ls.append(val_open_obj_cont[i]);
+      ls := locO.getList(s_open_obj_ref);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_obj_ref)');
+        for i := 0 to Pred(Length(val_open_obj_ref)) do
+          ls.append(val_open_obj_ref[i]);
+
+        CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+        CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+        CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+        ls := locO.getList(s_open_bool);
+          CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_bool)');
+          for i := 0 to Pred(Length(val_open_bool)) do
+            CheckEquals(val_open_bool[i], ls.getBoolean(i), s_open_bool);
+        ls := locO.getList(s_open_int);
+          CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_int)');
+          for i := 0 to Pred(Length(val_open_int)) do
+            CheckEquals(val_open_int[i], ls.getInteger(i), s_open_int);
+        ls := locO.getList(s_open_str);
+          CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_str)');
+          for i := 0 to Pred(Length(val_open_str)) do
+            CheckEquals(val_open_str[i], ls.getString(i), s_open_str);
+        ls := locO.getList(s_open_obj_ref);
+          CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_obj_ref)');
+          for i := 0 to Pred(Length(val_open_obj_ref)) do begin
+            CheckEquals(PtrUInt(val_open_obj_ref[i]), PtrUInt(ls.getDataObject(i)), s_open_obj_ref);
+            CheckEquals(PtrUInt(nil), PtrUInt(ls.getDataObject(i).getContainer()), 'Containment, s_open_obj_ref');
+          end;
+        ls := locO.getList(s_open_obj_cont);
+          CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_obj_cont)');
+          for i := 0 to Pred(Length(val_open_obj_cont)) do begin
+            CheckEquals(PtrUInt(val_open_obj_cont[i]), PtrUInt(ls.getDataObject(i)), s_open_obj_cont);
+            CheckEquals(PtrUInt(locO), PtrUInt(ls.getDataObject(i).getContainer()), 'Containment, s_open_obj_cont');
+          end;
+
+  finally
+    SetLength(val_open_obj_cont,0);
+    SetLength(val_open_obj_ref,0);
+    SetLength(val_open_str,0);
+    SetLength(val_open_int,0);
+    SetLength(val_open_bool,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_byte();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_BYTE_1;
+  item_data_type = ByteType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDOByte;
+  val_open : array of TSDOByte;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOByte),High(TSDOByte));
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := RandomRange(Low(TSDOByte),High(TSDOByte));
+
+  try
+    locO := Create_Object();
+      locO.setByte(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.append(val_open[i]);
+        CheckEquals(val_static, locO.getByte(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getByte(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_date();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_DATE_1;
+  item_data_type = DateTimeType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDODateTime;
+  val_open : array of TSDODateTime;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := RandomDate();
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := RandomDate();
+
+  try
+    locO := Create_Object();
+      locO.setDate(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.append(val_open[i]);
+        CheckEquals(val_static, locO.getDate(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getDate(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.check_property(
+  const APropList: ISDOPropertyList; const AName: string;
+  const AType: ISDOType; const AFlags: TPropertyFlags
+);
+var
+  pp : ISDOProperty;
+begin
+  pp := APropList.find(AName);
+  CheckNotEquals(PtrUInt(nil), PtrUInt(pp), Format('Property not found : "%s".',[AName]));
+  CheckEquals(AName, pp.getName());
+  Check(AType.equals(pp.getType()), Format('Property type differs : "%s".',[AName]));
+  CheckEquals((pfIsMany in AFlags), pp.isMany(), Format('Property isMany differs : "%s".',[AName]));
+  CheckEquals((pfIsReadOnly in AFlags), pp.isReadOnly(), Format('Property isReadOnly differs : "%s".',[AName]));
+  CheckEquals((pfIsContainment in AFlags), pp.isContainment(), Format('Property isContainment differs : "%s".',[AName]));
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property();
+const
+  s_open_bool = 'open_bool_prop';
+  s_open_int = 'open_int_prop';
+  s_open_str = 'open_str_prop';
+  s_open_obj_cont = 'open_obj_prop_cont';
+  s_open_obj_ref = 'open_obj_prop_ref';
+var
+  locO : ISDODataObject;
+  val_b : TSDOBoolean;
+  val_i : TSDOInteger;
+  val_s : TSDOString;
+  val_o : ISDODataObject;
+  val_open_bool : TSDOBoolean;
+  val_open_int : TSDOInteger;
+  val_open_str : TSDOString;
+  val_open_obj_cont, val_open_obj_ref : ISDODataObject;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_b := ( ( RandomRange(-123,456) mod 3 ) = 0 );
+  val_i := RandomRange(-123,456);
+  val_s := RandomString(123);
+  val_o := FFactory.createNew(s_URI_1,s_TYPE_2);
+  val_open_bool := ( ( RandomRange(-1234,4567) mod 2 ) = 0 );
+  val_open_int := RandomRange(-12345,678910);
+  val_open_str := RandomString(1234);
+  val_open_obj_cont := FFactory.createNew(s_URI_1,s_TYPE_2);
+  val_open_obj_ref := val_o;
+
+  locO := Create_Object();
+    locO.setBoolean(s_PROP_BOOL_1,val_b);
+    locO.setInteger(s_PROP_INTEGER_1,val_i);
+    locO.setString(s_PROP_STR_1,val_s);
+    locO.setDataObject(s_PROP_OBJ_CONT,val_o);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setInteger(s_open_int,val_open_int);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_int, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]), []);
+      CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+      CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+      CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+      CheckEquals(PtrUInt(val_o), PtrUInt(locO.getDataObject(s_PROP_OBJ_CONT)), s_PROP_OBJ_CONT);
+      CheckEquals(val_open_int, locO.getInteger(s_open_int), s_open_int);
+
+    locO.setBoolean(s_open_bool,val_open_bool);
+      CheckEquals( ( staticPropCount + 2), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_bool, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]), []);
+    locO.setString(s_open_str,val_open_str);
+      CheckEquals( ( staticPropCount + 3), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_str, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]), []);
+    locO.setDataObject(s_open_obj_cont,val_open_obj_cont);
+      CheckEquals( ( staticPropCount + 4), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_obj_cont, FFactory.getType(s_URI_1,s_TYPE_2), [pfIsContainment]);
+    locO.setDataObject(s_open_obj_ref,val_open_obj_ref);
+      CheckEquals( ( staticPropCount + 5), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_obj_ref, FFactory.getType(s_URI_1,s_TYPE_2), []);
+
+      CheckEquals(val_b, locO.getBoolean(s_PROP_BOOL_1), s_PROP_BOOL_1);
+      CheckEquals(val_i, locO.getInteger(s_PROP_INTEGER_1), s_PROP_INTEGER_1);
+      CheckEquals(val_s, locO.getString(s_PROP_STR_1), s_PROP_STR_1);
+      CheckEquals(PtrUInt(val_o), PtrUInt(locO.getDataObject(s_PROP_OBJ_CONT)), s_PROP_OBJ_CONT);
+      CheckEquals(val_open_bool, locO.getBoolean(s_open_bool), s_open_bool);
+      CheckEquals(val_open_int, locO.getInteger(s_open_int), s_open_int);
+      CheckEquals(val_open_str, locO.getString(s_open_str), s_open_str);
+      CheckEquals(PtrUInt(val_open_obj_cont), PtrUInt(locO.getDataObject(s_open_obj_cont)), s_open_obj_cont);
+      CheckEquals(PtrUInt(val_open_obj_ref), PtrUInt(locO.getDataObject(s_open_obj_ref)), s_open_obj_ref);
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_byte();
+const
+  s_static_prop = s_PROP_BYTE_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static : TSDOByte;
+  val_open : TSDOByte;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOByte),High(TSDOByte));
+  val_open := RandomRange(Low(TSDOByte),High(TSDOByte));
+
+  locO := Create_Object();
+    locO.setByte(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setByte(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ByteType]), []);
+      CheckEquals(val_static, locO.getByte(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getByte(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_date();
+const
+  s_static_prop = s_PROP_DATE_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static, val_open : TSDODateTime;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := RandomDate();
+  val_open := RandomDate();
+
+  locO := Create_Object();
+    locO.setDate(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setDate(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[DateType]), []);
+      CheckEquals(val_static, locO.getDate(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getDate(s_open_prop), s_open_prop);
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOOpenedDataObject_Test.addProperty_bytes();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_BYTES_1;
+  prop_type = BytesType;
+  
+var
+  locVal : TSDOBytes;
+  val_open : TSDOBytes;
+  
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    locVal := v;
+    v := nil;
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    val_open := v;
+  end;
+  
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  SetConstants();
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setBytes(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setBytes(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getBytes(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getBytes(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_bytes();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_BYTES_1;
+  item_data_type = BytesType;
+var
+  val_static : TSDOBytes;
+  val_open : array of TSDOBytes;
+  
+  procedure SetConstants();
+  var
+    v, e : TSDOBytes;
+    k, h : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    val_static := v;
+    v := nil;
+
+    SetLength(val_open,123);
+    for k := 0 to High(val_open) do begin
+      e := nil;
+      SetLength(e,RandomRange(0,1000));
+      if ( Length(e) > 0 ) then begin
+        for h := Low(e) to High(e) do
+          e[h] := RandomRange(Low(Byte),High(Byte));
+      end;
+      val_open[k] := e;
+    end;
+  end;
+  
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;  
+  staticPropCount : PtrInt;
+  i : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  SetConstants();
+
+  try
+    locO := Create_Object();
+      locO.setBytes(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.appendBytes(val_open[i]);
+        CheckEquals(val_static, locO.getBytes(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getBytes(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_bytes();
+const
+  s_static_prop = s_PROP_BYTES_1;
+  s_open_prop = 'open_prop';
+var  
+  val_open, val_static : TSDOBytes;
+  
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    val_open := v;
+    v := nil;
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    val_static := v;
+  end;
+  
+var
+  locO : ISDODataObject;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  SetConstants();
+
+  locO := Create_Object();
+    locO.setBytes(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setBytes(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[BytesType]), []);
+      CheckEquals(val_static, locO.getBytes(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getBytes(s_open_prop), s_open_prop);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOOpenedDataObject_Test.addProperty_char();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_CHAR_1;
+  prop_type = CharacterType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDOChar;
+  val_open : TSDOChar;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  val_open := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setCharacter(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setCharacter(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getCharacter(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getCharacter(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_char();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_CHAR_1;
+  item_data_type = CharacterType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDOChar;
+  val_open : array of TSDOChar;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+
+  try
+    locO := Create_Object();
+      locO.setCharacter(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.append(val_open[i]);
+        CheckEquals(val_static, locO.getCharacter(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getCharacter(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_char();
+const
+  s_static_prop = s_PROP_CHAR_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static : TSDOChar;
+  val_open : TSDOChar;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  val_open := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+
+  locO := Create_Object();
+    locO.setCharacter(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setCharacter(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[CharacterType]), []);
+      CheckEquals(val_static, locO.getCharacter(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getCharacter(s_open_prop), s_open_prop);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOOpenedDataObject_Test.addProperty_currency();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_CURRENCY_1;
+  prop_type = CurrencyType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDOCurrency;
+  val_open : TSDOCurrency;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setCurrency(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setCurrency(s_open_prop,val_open);
+      CheckEqualsCurrency(locVal, locO.getCurrency(s_static_prop), s_static_prop);
+      CheckEqualsCurrency(val_open, locO.getCurrency(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_currency();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_CURRENCY_1;
+  item_data_type = CurrencyType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDOCurrency;
+  val_open : array of TSDOCurrency;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  try
+    locO := Create_Object();
+      locO.setCurrency(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.appendCurrency(val_open[i]);
+        CheckEquals(val_static, locO.getCurrency(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getCurrency(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_currency();
+const
+  s_static_prop = s_PROP_CURRENCY_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static : TSDOCurrency;
+  val_open : TSDOCurrency;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+    locO.setCurrency(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setCurrency(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType]), []);
+      CheckEquals(val_static, locO.getCurrency(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getCurrency(s_open_prop), s_open_prop);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOOpenedDataObject_Test.addProperty_double();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_DOUBLE_1;
+  prop_type = DoubleType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDODouble;
+  val_open : TSDODouble;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setDouble(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setDouble(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getDouble(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getDouble(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_double();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_DOUBLE_1;
+  item_data_type = DoubleType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDODouble;
+  val_open : array of TSDODouble;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  try
+    locO := Create_Object();
+      locO.setDouble(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.append(val_open[i]);
+        CheckEquals(val_static, locO.getDouble(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getDouble(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_double();
+const
+  s_static_prop = s_PROP_DOUBLE_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static : TSDODouble;
+  val_open : TSDODouble;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+    locO.setDouble(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setDouble(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[DoubleType]), []);
+      CheckEquals(val_static, locO.getDouble(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getDouble(s_open_prop), s_open_prop);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOOpenedDataObject_Test.addProperty_float();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_FLOAT_1;
+  prop_type = FloatType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDOFloat;
+  val_open : TSDOFloat;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setFloat(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setFloat(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getFloat(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getFloat(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_float();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_FLOAT_1;
+  item_data_type = FloatType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDOFloat;
+  val_open : array of TSDOFloat;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  try
+    locO := Create_Object();
+      locO.setFloat(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.append(val_open[i]);
+        CheckEquals(val_static, locO.getFloat(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getFloat(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_float();
+const
+  s_static_prop = s_PROP_FLOAT_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static : TSDOFloat;
+  val_open : TSDOFloat;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+    locO.setFloat(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setFloat(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[FloatType]), []);
+      CheckEquals(val_static, locO.getFloat(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getFloat(s_open_prop), s_open_prop);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOOpenedDataObject_Test.addProperty_long();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_LONG_1;
+  prop_type = LongType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDOLong;
+  val_open : TSDOLong;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setLong(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setLong(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getLong(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getLong(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_long();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_LONG_1;
+  item_data_type = LongType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDOLong;
+  val_open : array of TSDOLong;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  try
+    locO := Create_Object();
+      locO.setLong(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.append(val_open[i]);
+        CheckEquals(val_static, locO.getLong(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getLong(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_long();
+const
+  s_static_prop = s_PROP_LONG_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static : TSDOLong;
+  val_open : TSDOLong;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_open := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+
+  locO := Create_Object();
+    locO.setLong(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setLong(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[LongType]), []);
+      CheckEquals(val_static, locO.getLong(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getLong(s_open_prop), s_open_prop);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOOpenedDataObject_Test.addProperty_short();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_SHORT_1;
+  prop_type = ShortType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  locVal : TSDOShort;
+  val_open : TSDOShort;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  locVal := RandomRange(Low(TSDOShort),High(TSDOShort));
+  val_open := RandomRange(Low(TSDOShort),High(TSDOShort));
+
+  locO := Create_Object();
+  locOX := locO as ISDODataObjectEx;
+    locO.setShort(s_static_prop,locVal);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]),[]);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[prop_type]), []);
+    locO.setShort(s_open_prop,val_open);
+      CheckEquals(locVal, locO.getShort(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getShort(s_open_prop), s_open_prop);
+end;
+
+procedure TSDOOpenedDataObject_Test.addProperty_multi_value_short();
+const
+  s_open_prop = 'open_prop';
+  s_static_prop = s_PROP_SHORT_1;
+  item_data_type = ShortType;
+var
+  locO : ISDODataObject;
+  locOX : ISDODataObjectEx;
+  val_static : TSDOShort;
+  val_open : array of TSDOShort;
+  staticPropCount : PtrInt;
+  i, c : PtrInt;
+  ls : ISDODataObjectList;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOShort),High(TSDOShort));
+  c := RandomRange(1,100);
+  SetLength(val_open,c);
+  for i := 0 to Pred(Length(val_open)) do
+    val_open[i] := RandomRange(Low(TSDOShort),High(TSDOShort));
+
+  try
+    locO := Create_Object();
+      locO.setShort(s_static_prop,val_static);
+    locOX := locO as ISDODataObjectEx;
+      staticPropCount := locO.getInstanceProperties().getCount();
+      locOX.addProperty(s_open_prop,FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]),[pfIsMany]);
+        CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+        check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[item_data_type]), [pfIsMany]);
+      ls := locO.getList(s_open_prop);
+        CheckNotEquals(PtrUInt(nil), PtrUInt(ls), 'getList(s_open_prop)');
+        for i := 0 to Pred(Length(val_open)) do
+          ls.append(val_open[i]);
+        CheckEquals(val_static, locO.getShort(s_static_prop), s_static_prop);
+        for i := 0 to Pred(Length(val_open)) do
+          CheckEquals(val_open[i], ls.getShort(i), s_open_prop);
+
+  finally
+    SetLength(val_open,0);
+  end;
+end;
+
+procedure TSDOOpenedDataObject_Test.implicit_add_property_short();
+const
+  s_static_prop = s_PROP_SHORT_1;
+  s_open_prop = 'open_prop';
+var
+  locO : ISDODataObject;
+  val_static : TSDOShort;
+  val_open : TSDOShort;
+  staticPropCount : PtrInt;
+begin
+  Randomize();
+  val_static := RandomRange(Low(TSDOShort),High(TSDOShort));
+  val_open := RandomRange(Low(TSDOShort),High(TSDOShort));
+
+  locO := Create_Object();
+    locO.setShort(s_static_prop,val_static);
+    staticPropCount := locO.getInstanceProperties().getCount();
+    locO.setShort(s_open_prop,val_open);
+      CheckEquals( ( staticPropCount + 1), locO.getInstanceProperties().getCount(), 'Property count');
+      check_property(locO.getInstanceProperties(), s_open_prop, FFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ShortType]), []);
+      CheckEquals(val_static, locO.getShort(s_static_prop), s_static_prop);
+      CheckEquals(val_open, locO.getShort(s_open_prop), s_open_prop);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+class function TSDOOpenedDataObject_Test.is_open_type() : Boolean;
+begin
+  Result := True;
+end;
+
+initialization
+  RegisterTest(TSDODataObject_Test.GetTestSuitePath(),TSDODataObject_Test.Suite);
+  RegisterTest(TSDOOpenedDataObject_Test.GetTestSuitePath(),TSDOOpenedDataObject_Test.Suite);
+  RegisterTest('object\observer', TObserver_Test.Suite);
+
+end.

+ 7898 - 0
packages/fcl-sdo/tests/test_suite/test_dataobjectlist.pas

@@ -0,0 +1,7898 @@
+{$INCLUDE sdo_global.inc}
+unit test_dataobjectlist;
+
+interface
+uses SysUtils
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , test_suite_utils, sdo, sdo_type, sdo_types, sdo_dataobjectlist, sdo_linked_list ;
+
+type
+
+  TSDODataObjectList_BaseTest = class(TWstBaseTest)
+  private
+    FFactory : ISDODataFactory;
+  protected
+    class function Create_Factory() : ISDODataFactory;
+    class function Create_List(AItemType : ISDOType) : ISDODataObjectList;virtual;abstract;
+    function Create_Object() : ISDODataObject;
+  protected
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+  published
+    procedure append_integer();
+    procedure insert_integer();
+    procedure get_integer_cursor();
+      procedure get_integer_index();
+    procedure set_integer_cursor();
+      procedure set_integer_index();
+    procedure delete_integer_with_cursor();
+      procedure delete_integer_with_index();
+
+    procedure append_boolean();
+    procedure insert_boolean();
+    procedure get_boolean_cursor();
+      procedure get_boolean_index();
+    procedure set_boolean_cursor();
+      procedure set_boolean_index();
+    procedure delete_boolean_with_cursor();
+      procedure delete_boolean_with_index();
+
+    procedure append_byte();
+    procedure insert_byte();
+    procedure get_byte_cursor();
+      procedure get_byte_index();
+    procedure set_byte_cursor();
+      procedure set_byte_index();
+    procedure delete_byte_with_cursor();
+      procedure delete_byte_with_index();
+
+    procedure append_date();
+    procedure insert_date();
+    procedure get_date_cursor();
+      procedure get_date_index();
+    procedure set_date_cursor();
+      procedure set_date_index();
+    procedure delete_date_with_cursor();
+      procedure delete_date_with_index();
+
+    procedure append_string();
+    procedure insert_string();
+    procedure get_string_cursor();
+      procedure get_string_index();
+    procedure set_string_cursor();
+      procedure set_string_index();
+    procedure delete_string_with_cursor();
+      procedure delete_string_with_index();
+
+    procedure append_dataObject();
+    procedure insert_dataObject();
+    procedure get_dataObject_cursor();
+      procedure get_dataObject_index();
+    procedure set_dataObject_cursor();
+      procedure set_dataObject_index();
+    procedure delete_dataObject_with_cursor();
+      procedure delete_dataObject_with_index();
+
+{$IFDEF HAS_SDO_BYTES}
+    procedure append_bytes();
+    procedure insert_bytes();
+    procedure get_bytes_cursor();
+      procedure get_bytes_index();
+    procedure set_bytes_cursor();
+      procedure set_bytes_index();
+    procedure delete_bytes_with_cursor();
+      procedure delete_bytes_with_index();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure append_char();
+    procedure insert_char();
+    procedure get_char_cursor();
+      procedure get_char_index();
+    procedure set_char_cursor();
+      procedure set_char_index();
+    procedure delete_char_with_cursor();
+      procedure delete_char_with_index();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure append_currency();
+    procedure insert_currency();
+    procedure get_currency_cursor();
+      procedure get_currency_index();
+    procedure set_currency_cursor();
+      procedure set_currency_index();
+    procedure delete_currency_with_cursor();
+      procedure delete_currency_with_index();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure append_double();
+    procedure insert_double();
+    procedure get_double_cursor();
+      procedure get_double_index();
+    procedure set_double_cursor();
+      procedure set_double_index();
+    procedure delete_double_with_cursor();
+      procedure delete_double_with_index();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure append_float();
+    procedure insert_float();
+    procedure get_float_cursor();
+      procedure get_float_index();
+    procedure set_float_cursor();
+      procedure set_float_index();
+    procedure delete_float_with_cursor();
+      procedure delete_float_with_index();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure append_long();
+    procedure insert_long();
+    procedure get_long_cursor();
+      procedure get_long_index();
+    procedure set_long_cursor();
+      procedure set_long_index();
+    procedure delete_long_with_cursor();
+      procedure delete_long_with_index();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure append_short();
+    procedure insert_short();
+    procedure get_short_cursor();
+      procedure get_short_index();
+    procedure set_short_cursor();
+      procedure set_short_index();
+    procedure delete_short_with_cursor();
+      procedure delete_short_with_index();
+{$ENDIF HAS_SDO_SHORT}
+  end;
+
+  TSDODataObjectList_Test = class(TSDODataObjectList_BaseTest)
+  protected
+    class function Create_List(AItemType : ISDOType) : ISDODataObjectList;override;
+  end;
+
+implementation
+
+uses
+  Math, sdo_datafactory, sdo_dataobject,
+  sdo_equalityhelper, DateUtils, sdo_date_utils;
+
+const s_URI_1  = 'uri:1';
+      s_TYPE_1 = 'type1';
+      s_PROP_BOOL_1 = 'propboolean1';
+      s_PROP_BYTE_1 = 'propbyte1';
+      s_PROP_INTEGER_1 = 'propinteger1';
+      s_PROP_STR_1 = 'propStr1';
+        s_PROP_STR_2 = 'propStr2';
+
+
+{ TSDODataObjectList_Test }
+
+procedure TSDODataObjectList_BaseTest.append_boolean();
+var
+  vals : array of TSDOBoolean;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := ( ( RandomRange(-10000,12345) mod 3 ) = 0 );
+    ls := Create_List(TSDOBooleanType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getBoolean());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getBoolean(k), Format('ls.getBoolean(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.append_byte();
+var
+  vals : array of TSDOByte;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomRange(Low(TSDOByte),High(TSDOByte));
+    ls := Create_List(TSDOByteType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getByte());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getByte(k), Format('ls.getByte(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.append_dataObject();
+var
+  vals : array of ISDODataObject;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := FFactory.createNew(s_URI_1,s_TYPE_1);
+    ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(PtrUInt(vals[i]),PtrUInt(ls.getDataObject()));
+      for k := 0 to i do begin
+        CheckEquals(PtrUInt(vals[k]),PtrUInt(ls.getDataObject(k)), Format('ls.getDataObject(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.append_date();
+var
+  vals : array of TSDODateTime;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomDate();
+    ls := Create_List(TSDODateTimeType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getDate());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getDate(k), Format('ls.getDate(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.append_integer();
+var
+  vals : array of TSDOInteger;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomRange(-10000,12345);
+    ls := Create_List(TSDOIntegerType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getInteger());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getInteger(k), Format('ls.getInteger(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.append_string();
+var
+  vals : array of TSDOString;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomString(RandomRange(0,123));
+    ls := Create_List(TSDOStringType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getString());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getString(k), Format('ls.getString(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDODataObjectList_BaseTest.append_bytes();
+var
+  vals : array of TSDOBytes;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomBytes(RandomRange(0,100));
+    ls := Create_List(TSDOBytesType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.appendBytes(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getBytes());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getBytes(k), Format('ls.getBytes(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_bytes();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOBytes);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insertBytes(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOBytes;
+begin
+  val_1 := RandomBytes(RandomRange(0,100));
+  val_2 := RandomBytes(RandomRange(0,100));
+  val_3 := RandomBytes(RandomRange(0,100));
+  ls := Create_List(TSDOBytesType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insertBytes(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getBytes(0));
+    ls.insertBytes(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getBytes(0));
+      CheckEquals(val_2, ls.getBytes(1));
+      ls.insertBytes(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getBytes(0));
+        CheckEquals(val_2, ls.getBytes(1));
+        CheckEquals(val_3, ls.getBytes(2));
+
+  ls := Create_List(TSDOBytesType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insertBytes(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getBytes(0));
+    ls.insertBytes(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getBytes(0));
+      CheckEquals(val_2, ls.getBytes(1));
+      ls.insertBytes(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getBytes(0));
+        CheckEquals(val_2, ls.getBytes(1));
+        CheckEquals(val_3, ls.getBytes(2));
+
+  ls := Create_List(TSDOBytesType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insertBytes(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getBytes(0));
+    ls.insertBytes(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getBytes(0));
+      CheckEquals(val_3, ls.getBytes(1));
+      ls.insertBytes(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getBytes(0));
+        CheckEquals(val_2, ls.getBytes(1));
+        CheckEquals(val_3, ls.getBytes(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.get_bytes_cursor();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : TSDOBytes;
+begin
+  VAL_1 := RandomBytes(RandomRange(0,100));
+  VAL_2 := RandomBytes(RandomRange(0,100));
+  VAL_3 := nil;
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getBytes();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendBytes(TSDOBytes(nil));
+  Check(c.MoveLast());
+  PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getBytes());
+    CheckEquals(False,c.MoveNext());
+    PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    CheckEquals(VAL_2,ls.getBytes());
+    PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+
+  ls.appendBytes(TSDOBytes(nil));
+  Check(c.MoveLast());
+  PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getBytes());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getBytes());
+    CheckEquals(False,c.MoveNext());
+
+  ls.appendBytes(TSDOBytes(nil));
+  Check(c.MoveLast());
+  PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getBytes());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getBytes());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getBytes());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendBytes(TSDOBytes(nil));
+  ls.appendBytes(TSDOBytes(nil));
+  ls.appendBytes(TSDOBytes(nil));
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),ls.getBytes());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),ls.getBytes());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),ls.getBytes());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_bytes_index();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : TSDOBytes;
+begin
+  VAL_1 := RandomBytes(RandomRange(0,100));
+  VAL_2 := RandomBytes(RandomRange(0,100));
+  VAL_3 := nil;
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getBytes(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendBytes(TSDOBytes(nil));
+  Check(c.MoveLast());
+  PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getBytes(0));
+    PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    CheckEquals(VAL_2,ls.getBytes(0));
+    PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+
+  ls.appendBytes(TSDOBytes(nil));
+  Check(c.MoveLast());
+  PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getBytes(0));
+    CheckEquals(VAL_2,ls.getBytes(1));
+
+  ls.appendBytes(TSDOBytes(nil));
+  Check(c.MoveLast());
+  PPSDOBytes(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getBytes(0));
+      CheckEquals(VAL_2,ls.getBytes(1));
+      CheckEquals(VAL_3,ls.getBytes(2));
+
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendBytes(TSDOBytes(nil));
+  ls.appendBytes(TSDOBytes(nil));
+  ls.appendBytes(TSDOBytes(nil));
+    CheckEquals(3,ls.size());
+    CheckEquals(TSDOBytes(nil),ls.getBytes(0));
+    CheckEquals(TSDOBytes(nil),ls.getBytes(1));
+    CheckEquals(TSDOBytes(nil),ls.getBytes(2));
+
+  ok := False;
+  try
+    ls.getBytes(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.set_bytes_cursor();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : TSDOBytes;
+begin
+  VAL_1 := RandomBytes(RandomRange(0,100));
+  VAL_2 := RandomBytes(RandomRange(0,100));
+  VAL_3 := nil;
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setBytes(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendBytes(TSDOBytes(nil));
+  c.MoveFirst();
+  ls.setBytes(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+    ls.setBytes(VAL_2);
+    CheckEquals(VAL_2,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    ls.setBytes(VAL_1);
+
+  ls.appendBytes(TSDOBytes(nil));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setBytes(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.appendBytes(TSDOBytes(nil));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setBytes(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+  ls.appendBytes(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setBytes(nil);
+  CheckEquals(True,c.MoveNext());
+    ls.setBytes(nil);
+  CheckEquals(True,c.MoveNext());
+    ls.setBytes(nil);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_bytes_index();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : TSDOBytes;
+begin
+  VAL_1 := RandomBytes(RandomRange(0,100));
+  VAL_2 := RandomBytes(RandomRange(0,100));
+  VAL_3 := nil;
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setBytes(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendBytes(TSDOBytes(nil));
+  ls.setBytes(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+    ls.setBytes(0,VAL_2);
+    CheckEquals(VAL_2,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    ls.setBytes(0,VAL_1);
+
+  ls.appendBytes(TSDOBytes(nil));
+  ls.setBytes(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.appendBytes(TSDOBytes(nil));
+  ls.setBytes(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOBytesType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+  ls.appendBytes(VAL_3);
+  ls.setBytes(0,nil);
+  ls.setBytes(1,nil);
+  ls.setBytes(2,nil);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOBytes(nil),PPSDOBytes( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_bytes_with_cursor();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : TSDOBytes;
+begin
+  VAL_1 := RandomBytes(RandomRange(0,100));
+  VAL_2 := RandomBytes(RandomRange(0,100));
+  VAL_3 := nil;
+  ls := Create_List(TSDOBytesType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendBytes(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getBytes());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getBytes());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+  ls.appendBytes(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getBytes());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getBytes());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+  ls.appendBytes(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getBytes());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getBytes());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_bytes_with_index();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : TSDOBytes;
+begin
+  VAL_1 := RandomBytes(RandomRange(0,100));
+  VAL_2 := RandomBytes(RandomRange(0,100));
+  VAL_3 := nil;
+  ls := Create_List(TSDOBytesType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendBytes(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getBytes(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getBytes(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+  ls.appendBytes(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getBytes(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getBytes(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.appendBytes(VAL_1);
+  ls.appendBytes(VAL_2);
+  ls.appendBytes(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getBytes(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getBytes(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDODataObjectList_BaseTest.append_char();
+var
+  vals : array of TSDOChar;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+    ls := Create_List(TSDOCharacterType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getCharacter());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getCharacter(k), Format('ls.getCharacter(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_char();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOChar);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOChar;
+begin
+  val_1 := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  val_2 := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  val_3 := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  ls := Create_List(TSDOCharacterType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getCharacter(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getCharacter(0));
+      CheckEquals(val_2, ls.getCharacter(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getCharacter(0));
+        CheckEquals(val_2, ls.getCharacter(1));
+        CheckEquals(val_3, ls.getCharacter(2));
+
+  ls := Create_List(TSDOCharacterType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getCharacter(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getCharacter(0));
+      CheckEquals(val_2, ls.getCharacter(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getCharacter(0));
+        CheckEquals(val_2, ls.getCharacter(1));
+        CheckEquals(val_3, ls.getCharacter(2));
+
+  ls := Create_List(TSDOCharacterType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getCharacter(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getCharacter(0));
+      CheckEquals(val_3, ls.getCharacter(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getCharacter(0));
+        CheckEquals(val_2, ls.getCharacter(1));
+        CheckEquals(val_3, ls.getCharacter(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.get_char_cursor();
+const VAL_1 : TSDOChar = 'y'; VAL_2 : TSDOChar = '8'; VAL_3 : TSDOChar = #0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getCharacter();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOChar(0));
+  Check(c.MoveLast());
+  PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getCharacter());
+    CheckEquals(False,c.MoveNext());
+    PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getCharacter());
+    PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOChar(0));
+  Check(c.MoveLast());
+  PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getCharacter());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getCharacter());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOChar(0));
+  Check(c.MoveLast());
+  PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getCharacter());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getCharacter());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getCharacter());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOChar(0));
+  ls.append(TSDOChar(0));
+  ls.append(TSDOChar(0));
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),ls.getCharacter());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),ls.getCharacter());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),ls.getCharacter());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_char_index();
+const VAL_1 : TSDOChar = 'y'; VAL_2 : TSDOChar = '8'; VAL_3 : TSDOChar = #0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getCharacter(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOChar(0));
+  Check(c.MoveLast());
+  PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getCharacter(0));
+    PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getCharacter(0));
+    PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOChar(0));
+  Check(c.MoveLast());
+  PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getCharacter(0));
+    CheckEquals(VAL_2,ls.getCharacter(1));
+
+  ls.append(TSDOChar(0));
+  Check(c.MoveLast());
+  PSDOChar(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getCharacter(0));
+      CheckEquals(VAL_2,ls.getCharacter(1));
+      CheckEquals(VAL_3,ls.getCharacter(2));
+
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOChar(0));
+  ls.append(TSDOChar(0));
+  ls.append(TSDOChar(0));
+    CheckEquals(3,ls.size());
+    CheckEquals(TSDOChar(0),ls.getCharacter(0));
+    CheckEquals(TSDOChar(0),ls.getCharacter(1));
+    CheckEquals(TSDOChar(0),ls.getCharacter(2));
+
+  ok := False;
+  try
+    ls.getCharacter(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.set_char_cursor();
+const VAL_1 : TSDOChar = 'y'; VAL_2 : TSDOChar = '8'; VAL_3 : TSDOChar = #0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setCharacter(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOChar(0));
+  c.MoveFirst();
+  ls.setCharacter(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setCharacter(VAL_2);
+    CheckEquals(VAL_2,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setCharacter(VAL_1);
+
+  ls.append(TSDOChar(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setCharacter(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOChar(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setCharacter(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setCharacter(TSDOChar(0));
+  CheckEquals(True,c.MoveNext());
+    ls.setCharacter(TSDOChar(0));
+  CheckEquals(True,c.MoveNext());
+    ls.setCharacter(TSDOChar(0));
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_char_index();
+const VAL_1 : TSDOChar = 'y'; VAL_2 : TSDOChar = '8'; VAL_3 : TSDOChar = #0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setCharacter(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOChar(0));
+  ls.setCharacter(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setCharacter(0,VAL_2);
+    CheckEquals(VAL_2,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setCharacter(0,VAL_1);
+
+  ls.append(TSDOChar(0));
+  ls.setCharacter(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOChar(0));
+  ls.setCharacter(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOCharacterType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setCharacter(0,TSDOChar(0));
+  ls.setCharacter(1,TSDOChar(0));
+  ls.setCharacter(2,TSDOChar(0));
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(TSDOChar(0),PSDOChar( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_char_with_cursor();
+const VAL_1 : TSDOChar = 'y'; VAL_2 : TSDOChar = '8'; VAL_3 : TSDOChar = #0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCharacterType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getCharacter());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getCharacter());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getCharacter());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getCharacter());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getCharacter());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getCharacter());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_char_with_index();
+const VAL_1 : TSDOChar = 'y'; VAL_2 : TSDOChar = '8'; VAL_3 : TSDOChar = #0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCharacterType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getCharacter(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getCharacter(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getCharacter(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getCharacter(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getCharacter(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getCharacter(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDODataObjectList_BaseTest.append_currency();
+var
+  vals : array of TSDOCurrency;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+    ls := Create_List(TSDOCurrencyType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.appendCurrency(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getCurrency());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getCurrency(k), Format('ls.getCurrency(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_currency();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOCurrency);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insertCurrency(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insertCurrency" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOCurrency;
+begin
+  val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_3 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  ls := Create_List(TSDOCurrencyType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insertCurrency(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getCurrency(0));
+    ls.insertCurrency(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getCurrency(0));
+      CheckEquals(val_2, ls.getCurrency(1));
+      ls.insertCurrency(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getCurrency(0));
+        CheckEquals(val_2, ls.getCurrency(1));
+        CheckEquals(val_3, ls.getCurrency(2));
+
+  ls := Create_List(TSDOCurrencyType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insertCurrency(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getCurrency(0));
+    ls.insertCurrency(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getCurrency(0));
+      CheckEquals(val_2, ls.getCurrency(1));
+      ls.insertCurrency(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getCurrency(0));
+        CheckEquals(val_2, ls.getCurrency(1));
+        CheckEquals(val_3, ls.getCurrency(2));
+
+  ls := Create_List(TSDOCurrencyType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insertCurrency(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getCurrency(0));
+    ls.insertCurrency(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getCurrency(0));
+      CheckEquals(val_3, ls.getCurrency(1));
+      ls.insertCurrency(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getCurrency(0));
+        CheckEquals(val_2, ls.getCurrency(1));
+        CheckEquals(val_3, ls.getCurrency(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.get_currency_cursor();
+const VAL_1 : TSDOCurrency = 8877552292000; VAL_2 : TSDOCurrency = -13654792522; VAL_3 : TSDOCurrency = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getCurrency();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendCurrency(0);
+  Check(c.MoveLast());
+  PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getCurrency());
+    CheckEquals(False,c.MoveNext());
+    PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getCurrency());
+    PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.appendCurrency(0);
+  Check(c.MoveLast());
+  PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getCurrency());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getCurrency());
+    CheckEquals(False,c.MoveNext());
+
+  ls.appendCurrency(0);
+  Check(c.MoveLast());
+  PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getCurrency());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getCurrency());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getCurrency());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendCurrency(0);
+  ls.appendCurrency(0);
+  ls.appendCurrency(0);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getCurrency());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getCurrency());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getCurrency());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_currency_index();
+const VAL_1 : TSDOCurrency = 8877552292000; VAL_2 : TSDOCurrency = -13654792522; VAL_3 : TSDOCurrency = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getCurrency(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendCurrency(0);
+  Check(c.MoveLast());
+  PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getCurrency(0));
+    PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getCurrency(0));
+    PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.appendCurrency(0);
+  Check(c.MoveLast());
+  PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getCurrency(0));
+    CheckEquals(VAL_2,ls.getCurrency(1));
+
+  ls.appendCurrency(0);
+  Check(c.MoveLast());
+  PSDOCurrency(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getCurrency(0));
+      CheckEquals(VAL_2,ls.getCurrency(1));
+      CheckEquals(VAL_3,ls.getCurrency(2));
+
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendCurrency(0);
+  ls.appendCurrency(0);
+  ls.appendCurrency(0);
+    CheckEquals(3,ls.size());
+    CheckEquals(0,ls.getCurrency(0));
+    CheckEquals(0,ls.getCurrency(1));
+    CheckEquals(0,ls.getCurrency(2));
+
+  ok := False;
+  try
+    ls.getCurrency(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.set_currency_cursor();
+const VAL_1 : TSDOCurrency = 8877552292000; VAL_2 : TSDOCurrency = -13654792522; VAL_3 : TSDOCurrency = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setCurrency(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendCurrency(0);
+  c.MoveFirst();
+  ls.setCurrency(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setCurrency(VAL_2);
+    CheckEquals(VAL_2,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setCurrency(VAL_1);
+
+  ls.appendCurrency(0);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setCurrency(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.appendCurrency(0);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setCurrency(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+  ls.appendCurrency(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setCurrency(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setCurrency(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setCurrency(0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_currency_index();
+const VAL_1 : TSDOCurrency = 8877552292000; VAL_2 : TSDOCurrency = -13654792522; VAL_3 : TSDOCurrency = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setCurrency(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendCurrency(0);
+  ls.setCurrency(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setCurrency(0,VAL_2);
+    CheckEquals(VAL_2,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setCurrency(0,VAL_1);
+
+  ls.appendCurrency(0);
+  ls.setCurrency(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.appendCurrency(0);
+  ls.setCurrency(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOCurrencyType.Create(FFactory));
+  c := ls.getCursor();
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+  ls.appendCurrency(VAL_3);
+  ls.setCurrency(0,0);
+  ls.setCurrency(1,0);
+  ls.setCurrency(2,0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOCurrency( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_currency_with_cursor();
+const VAL_1 : TSDOCurrency = 8877552292000; VAL_2 : TSDOCurrency = -13654792522; VAL_3 : TSDOCurrency = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCurrencyType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendCurrency(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getCurrency());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getCurrency());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+  ls.appendCurrency(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getCurrency());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getCurrency());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+  ls.appendCurrency(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getCurrency());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getCurrency());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_currency_with_index();
+const VAL_1 : TSDOCurrency = 8877552292000; VAL_2 : TSDOCurrency = -13654792522; VAL_3 : TSDOCurrency = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOCurrencyType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.appendCurrency(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getCurrency(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getCurrency(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+  ls.appendCurrency(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getCurrency(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getCurrency(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.appendCurrency(VAL_1);
+  ls.appendCurrency(VAL_2);
+  ls.appendCurrency(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getCurrency(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getCurrency(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+const ZERO_DOUBLE : TSDODouble = 0;
+procedure TSDODataObjectList_BaseTest.append_double();
+var
+  vals : array of TSDODouble;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+    ls := Create_List(TSDODoubleType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getDouble());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getDouble(k), Format('ls.getDouble(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_double();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDODouble);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDODouble;
+begin
+  val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_3 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  ls := Create_List(TSDODoubleType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getDouble(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getDouble(0));
+      CheckEquals(val_2, ls.getDouble(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getDouble(0));
+        CheckEquals(val_2, ls.getDouble(1));
+        CheckEquals(val_3, ls.getDouble(2));
+
+  ls := Create_List(TSDODoubleType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getDouble(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getDouble(0));
+      CheckEquals(val_2, ls.getDouble(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getDouble(0));
+        CheckEquals(val_2, ls.getDouble(1));
+        CheckEquals(val_3, ls.getDouble(2));
+
+  ls := Create_List(TSDODoubleType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getDouble(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getDouble(0));
+      CheckEquals(val_3, ls.getDouble(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getDouble(0));
+        CheckEquals(val_2, ls.getDouble(1));
+        CheckEquals(val_3, ls.getDouble(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.get_double_cursor();
+const VAL_1 : TSDODouble = 8877552292000; VAL_2 : TSDODouble = -13654792522; VAL_3 : TSDODouble = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getDouble();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DOUBLE);
+  Check(c.MoveLast());
+  PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getDouble());
+    CheckEquals(False,c.MoveNext());
+    PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getDouble());
+    PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(ZERO_DOUBLE);
+  Check(c.MoveLast());
+  PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getDouble());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getDouble());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_DOUBLE);
+  Check(c.MoveLast());
+  PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getDouble());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getDouble());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getDouble());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(ZERO_DOUBLE);
+  ls.append(ZERO_DOUBLE);
+  ls.append(ZERO_DOUBLE);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getDouble());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getDouble());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getDouble());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_double_index();
+const VAL_1 : TSDODouble = 8877552292000; VAL_2 : TSDODouble = -13654792522; VAL_3 : TSDODouble = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getDouble(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DOUBLE);
+  Check(c.MoveLast());
+  PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getDouble(0));
+    PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getDouble(0));
+    PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(ZERO_DOUBLE);
+  Check(c.MoveLast());
+  PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getDouble(0));
+    CheckEquals(VAL_2,ls.getDouble(1));
+
+  ls.append(ZERO_DOUBLE);
+  Check(c.MoveLast());
+  PSDODouble(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getDouble(0));
+      CheckEquals(VAL_2,ls.getDouble(1));
+      CheckEquals(VAL_3,ls.getDouble(2));
+
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(ZERO_DOUBLE);
+  ls.append(ZERO_DOUBLE);
+  ls.append(ZERO_DOUBLE);
+    CheckEquals(3,ls.size());
+    CheckEquals(0,ls.getDouble(0));
+    CheckEquals(0,ls.getDouble(1));
+    CheckEquals(0,ls.getDouble(2));
+
+  ok := False;
+  try
+    ls.getDouble(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.set_double_cursor();
+const VAL_1 : TSDODouble = 8877552292000; VAL_2 : TSDODouble = -13654792522; VAL_3 : TSDODouble = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setDouble(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DOUBLE);
+  c.MoveFirst();
+  ls.setDouble(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setDouble(VAL_2);
+    CheckEquals(VAL_2,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setDouble(VAL_1);
+
+  ls.append(ZERO_DOUBLE);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setDouble(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_DOUBLE);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setDouble(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setDouble(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setDouble(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setDouble(0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_double_index();
+const VAL_1 : TSDODouble = 8877552292000; VAL_2 : TSDODouble = -13654792522; VAL_3 : TSDODouble = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setDouble(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DOUBLE);
+  ls.setDouble(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setDouble(0,VAL_2);
+    CheckEquals(VAL_2,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setDouble(0,VAL_1);
+
+  ls.append(ZERO_DOUBLE);
+  ls.setDouble(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_DOUBLE);
+  ls.setDouble(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDODoubleType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setDouble(0,0);
+  ls.setDouble(1,0);
+  ls.setDouble(2,0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDODouble( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_double_with_cursor();
+const VAL_1 : TSDODouble = 8877552292000; VAL_2 : TSDODouble = -13654792522; VAL_3 : TSDODouble = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDODoubleType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getDouble());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getDouble());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getDouble());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getDouble());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getDouble());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getDouble());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_double_with_index();
+const VAL_1 : TSDODouble = 8877552292000; VAL_2 : TSDODouble = -13654792522; VAL_3 : TSDODouble = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDODoubleType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getDouble(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getDouble(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getDouble(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getDouble(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getDouble(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getDouble(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+const ZERO_FLOAT : TSDOFloat = 0;
+procedure TSDODataObjectList_BaseTest.append_float();
+var
+  vals : array of TSDOFloat;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+    ls := Create_List(TSDOFloatType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getFloat());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getFloat(k), Format('ls.getFloat(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_float();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOFloat);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOFloat;
+begin
+  val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_3 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  ls := Create_List(TSDOFloatType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getFloat(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getFloat(0));
+      CheckEquals(val_2, ls.getFloat(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getFloat(0));
+        CheckEquals(val_2, ls.getFloat(1));
+        CheckEquals(val_3, ls.getFloat(2));
+
+  ls := Create_List(TSDOFloatType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getFloat(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getFloat(0));
+      CheckEquals(val_2, ls.getFloat(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getFloat(0));
+        CheckEquals(val_2, ls.getFloat(1));
+        CheckEquals(val_3, ls.getFloat(2));
+
+  ls := Create_List(TSDOFloatType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getFloat(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getFloat(0));
+      CheckEquals(val_3, ls.getFloat(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getFloat(0));
+        CheckEquals(val_2, ls.getFloat(1));
+        CheckEquals(val_3, ls.getFloat(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.get_float_cursor();
+const VAL_1 : TSDOFloat = 8877552292000; VAL_2 : TSDOFloat = -13654792522; VAL_3 : TSDOFloat = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getFloat();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_FLOAT);
+  Check(c.MoveLast());
+  PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getFloat());
+    CheckEquals(False,c.MoveNext());
+    PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getFloat());
+    PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(ZERO_FLOAT);
+  Check(c.MoveLast());
+  PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getFloat());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getFloat());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_FLOAT);
+  Check(c.MoveLast());
+  PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getFloat());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getFloat());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getFloat());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(ZERO_FLOAT);
+  ls.append(ZERO_FLOAT);
+  ls.append(ZERO_FLOAT);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getFloat());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getFloat());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getFloat());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_float_index();
+const VAL_1 : TSDOFloat = 8877552292000; VAL_2 : TSDOFloat = -13654792522; VAL_3 : TSDOFloat = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getFloat(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_FLOAT);
+  Check(c.MoveLast());
+  PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getFloat(0));
+    PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getFloat(0));
+    PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(ZERO_FLOAT);
+  Check(c.MoveLast());
+  PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getFloat(0));
+    CheckEquals(VAL_2,ls.getFloat(1));
+
+  ls.append(ZERO_FLOAT);
+  Check(c.MoveLast());
+  PSDOFloat(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getFloat(0));
+      CheckEquals(VAL_2,ls.getFloat(1));
+      CheckEquals(VAL_3,ls.getFloat(2));
+
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(ZERO_FLOAT);
+  ls.append(ZERO_FLOAT);
+  ls.append(ZERO_FLOAT);
+    CheckEquals(3,ls.size());
+    CheckEquals(0,ls.getFloat(0));
+    CheckEquals(0,ls.getFloat(1));
+    CheckEquals(0,ls.getFloat(2));
+
+  ok := False;
+  try
+    ls.getFloat(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.set_float_cursor();
+const VAL_1 : TSDOFloat = 8877552292000; VAL_2 : TSDOFloat = -13654792522; VAL_3 : TSDOFloat = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setFloat(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_FLOAT);
+  c.MoveFirst();
+  ls.setFloat(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setFloat(VAL_2);
+    CheckEquals(VAL_2,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setFloat(VAL_1);
+
+  ls.append(ZERO_FLOAT);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setFloat(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_FLOAT);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setFloat(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setFloat(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setFloat(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setFloat(0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_float_index();
+const VAL_1 : TSDOFloat = 8877552292000; VAL_2 : TSDOFloat = -13654792522; VAL_3 : TSDOFloat = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setFloat(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_FLOAT);
+  ls.setFloat(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setFloat(0,VAL_2);
+    CheckEquals(VAL_2,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setFloat(0,VAL_1);
+
+  ls.append(ZERO_FLOAT);
+  ls.setFloat(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_FLOAT);
+  ls.setFloat(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOFloatType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setFloat(0,0);
+  ls.setFloat(1,0);
+  ls.setFloat(2,0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOFloat( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_float_with_cursor();
+const VAL_1 : TSDOFloat = 8877552292000; VAL_2 : TSDOFloat = -13654792522; VAL_3 : TSDOFloat = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOFloatType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getFloat());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getFloat());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getFloat());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getFloat());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getFloat());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getFloat());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_float_with_index();
+const VAL_1 : TSDOFloat = 8877552292000; VAL_2 : TSDOFloat = -13654792522; VAL_3 : TSDOFloat = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOFloatType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getFloat(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getFloat(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getFloat(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getFloat(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getFloat(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getFloat(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDODataObjectList_BaseTest.append_long();
+var
+  vals : array of TSDOLong;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+    ls := Create_List(TSDOLongType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getLong());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getLong(k), Format('ls.getLong(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_long();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOLong);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOLong;
+begin
+  val_1 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_2 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  val_3 := RandomRange(Low(TSDOInteger),High(TSDOInteger));
+  ls := Create_List(TSDOLongType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getLong(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getLong(0));
+      CheckEquals(val_2, ls.getLong(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getLong(0));
+        CheckEquals(val_2, ls.getLong(1));
+        CheckEquals(val_3, ls.getLong(2));
+
+  ls := Create_List(TSDOLongType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getLong(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getLong(0));
+      CheckEquals(val_2, ls.getLong(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getLong(0));
+        CheckEquals(val_2, ls.getLong(1));
+        CheckEquals(val_3, ls.getLong(2));
+
+  ls := Create_List(TSDOLongType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getLong(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getLong(0));
+      CheckEquals(val_3, ls.getLong(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getLong(0));
+        CheckEquals(val_2, ls.getLong(1));
+        CheckEquals(val_3, ls.getLong(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.get_long_cursor();
+const VAL_1 : TSDOLong = 8877552292000; VAL_2 : TSDOLong = -13654792522; VAL_3 : TSDOLong = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getLong();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOLong(0));
+  Check(c.MoveLast());
+  PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getLong());
+    CheckEquals(False,c.MoveNext());
+    PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getLong());
+    PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOLong(0));
+  Check(c.MoveLast());
+  PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getLong());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getLong());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOLong(0));
+  Check(c.MoveLast());
+  PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getLong());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getLong());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getLong());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOLong(0));
+  ls.append(TSDOLong(0));
+  ls.append(TSDOLong(0));
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getLong());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getLong());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getLong());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_long_index();
+const VAL_1 : TSDOLong = 8877552292000; VAL_2 : TSDOLong = -13654792522; VAL_3 : TSDOLong = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getLong(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOLong(0));
+  Check(c.MoveLast());
+  PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getLong(0));
+    PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getLong(0));
+    PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOLong(0));
+  Check(c.MoveLast());
+  PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getLong(0));
+    CheckEquals(VAL_2,ls.getLong(1));
+
+  ls.append(TSDOLong(0));
+  Check(c.MoveLast());
+  PSDOLong(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getLong(0));
+      CheckEquals(VAL_2,ls.getLong(1));
+      CheckEquals(VAL_3,ls.getLong(2));
+
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOLong(0));
+  ls.append(TSDOLong(0));
+  ls.append(TSDOLong(0));
+    CheckEquals(3,ls.size());
+    CheckEquals(0,ls.getLong(0));
+    CheckEquals(0,ls.getLong(1));
+    CheckEquals(0,ls.getLong(2));
+
+  ok := False;
+  try
+    ls.getLong(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.set_long_cursor();
+const VAL_1 : TSDOLong = 8877552292000; VAL_2 : TSDOLong = -13654792522; VAL_3 : TSDOLong = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setLong(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOLong(0));
+  c.MoveFirst();
+  ls.setLong(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setLong(VAL_2);
+    CheckEquals(VAL_2,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setLong(VAL_1);
+
+  ls.append(TSDOLong(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setLong(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOLong(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setLong(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setLong(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setLong(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setLong(0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_long_index();
+const VAL_1 : TSDOLong = 8877552292000; VAL_2 : TSDOLong = -13654792522; VAL_3 : TSDOLong = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setLong(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOLong(0));
+  ls.setLong(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setLong(0,VAL_2);
+    CheckEquals(VAL_2,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setLong(0,VAL_1);
+
+  ls.append(TSDOLong(0));
+  ls.setLong(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOLong(0));
+  ls.setLong(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOLongType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setLong(0,0);
+  ls.setLong(1,0);
+  ls.setLong(2,0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOLong( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_long_with_cursor();
+const VAL_1 : TSDOLong = 8877552292000; VAL_2 : TSDOLong = -13654792522; VAL_3 : TSDOLong = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOLongType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getLong());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getLong());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getLong());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getLong());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getLong());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getLong());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_long_with_index();
+const VAL_1 : TSDOLong = 8877552292000; VAL_2 : TSDOLong = -13654792522; VAL_3 : TSDOLong = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOLongType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getLong(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getLong(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getLong(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getLong(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getLong(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getLong(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDODataObjectList_BaseTest.append_short();
+var
+  vals : array of TSDOShort;
+  c, i, k : PtrInt;
+  ls : ISDODataObjectList;
+  crs : ILinkedListCursor;
+begin
+  c := RandomRange(10,100);
+  SetLength(vals,c);
+  try
+    for i := 0 to Pred(c) do
+      vals[i] := RandomRange(Low(TSDOShort),High(TSDOShort));
+    ls := Create_List(TSDOShortType.Create(FFactory) as ISDOType);
+    crs := ls.getCursor();
+
+    for i := 0 to Pred(c) do begin
+      CheckEquals(i, ls.size(), 'size() before');
+      ls.append(vals[i]);
+      CheckEquals(( i + 1 ),ls.size, 'size() after');
+      CheckEquals(True, crs.Eof());
+      CheckEquals(vals[i],ls.getShort());
+      for k := 0 to i do begin
+        CheckEquals(vals[k],ls.getShort(k), Format('ls.getShort(%d)',[k]));
+      end;
+    end;
+  finally
+    SetLength(vals,0);
+  end;
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_short();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOShort);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOShort;
+begin
+  val_1 := RandomRange(Low(TSDOShort),High(TSDOShort));
+  val_2 := RandomRange(Low(TSDOShort),High(TSDOShort));
+  val_3 := RandomRange(Low(TSDOShort),High(TSDOShort));
+  ls := Create_List(TSDOShortType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getShort(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getShort(0));
+      CheckEquals(val_2, ls.getShort(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getShort(0));
+        CheckEquals(val_2, ls.getShort(1));
+        CheckEquals(val_3, ls.getShort(2));
+
+  ls := Create_List(TSDOShortType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getShort(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getShort(0));
+      CheckEquals(val_2, ls.getShort(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getShort(0));
+        CheckEquals(val_2, ls.getShort(1));
+        CheckEquals(val_3, ls.getShort(2));
+
+  ls := Create_List(TSDOShortType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getShort(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getShort(0));
+      CheckEquals(val_3, ls.getShort(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getShort(0));
+        CheckEquals(val_2, ls.getShort(1));
+        CheckEquals(val_3, ls.getShort(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.get_short_cursor();
+const VAL_1 : TSDOShort = 4567; VAL_2 : TSDOShort = -9876; VAL_3 : TSDOShort = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getShort();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOShort(0));
+  Check(c.MoveLast());
+  PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getShort());
+    CheckEquals(False,c.MoveNext());
+    PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getShort());
+    PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOShort(0));
+  Check(c.MoveLast());
+  PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getShort());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getShort());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOShort(0));
+  Check(c.MoveLast());
+  PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getShort());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getShort());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getShort());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOShort(0));
+  ls.append(TSDOShort(0));
+  ls.append(TSDOShort(0));
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getShort());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getShort());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getShort());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_short_index();
+const VAL_1 : TSDOShort = 4567; VAL_2 : TSDOShort = -9876; VAL_3 : TSDOShort = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getShort(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOShort(0));
+  Check(c.MoveLast());
+  PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getShort(0));
+    PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getShort(0));
+    PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOShort(0));
+  Check(c.MoveLast());
+  PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getShort(0));
+    CheckEquals(VAL_2,ls.getShort(1));
+
+  ls.append(TSDOShort(0));
+  Check(c.MoveLast());
+  PSDOShort(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getShort(0));
+      CheckEquals(VAL_2,ls.getShort(1));
+      CheckEquals(VAL_3,ls.getShort(2));
+
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOShort(0));
+  ls.append(TSDOShort(0));
+  ls.append(TSDOShort(0));
+    CheckEquals(3,ls.size());
+    CheckEquals(0,ls.getShort(0));
+    CheckEquals(0,ls.getShort(1));
+    CheckEquals(0,ls.getShort(2));
+
+  ok := False;
+  try
+    ls.getShort(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.set_short_cursor();
+const VAL_1 : TSDOShort = 4567; VAL_2 : TSDOShort = -9876; VAL_3 : TSDOShort = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setShort(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOShort(0));
+  c.MoveFirst();
+  ls.setShort(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setShort(VAL_2);
+    CheckEquals(VAL_2,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setShort(VAL_1);
+
+  ls.append(TSDOShort(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setShort(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOShort(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setShort(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setShort(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setShort(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setShort(0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_short_index();
+const VAL_1 : TSDOShort = 4567; VAL_2 : TSDOShort = -9876; VAL_3 : TSDOShort = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setShort(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOShort(0));
+  ls.setShort(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setShort(0,VAL_2);
+    CheckEquals(VAL_2,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setShort(0,VAL_1);
+
+  ls.append(TSDOShort(0));
+  ls.setShort(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOShort(0));
+  ls.setShort(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOShortType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setShort(0,0);
+  ls.setShort(1,0);
+  ls.setShort(2,0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOShort( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_short_with_cursor();
+const VAL_1 : TSDOShort = 4567; VAL_2 : TSDOShort = -9876; VAL_3 : TSDOShort = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOShortType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getShort());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getShort());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getShort());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getShort());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getShort());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getShort());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_short_with_index();
+const VAL_1 : TSDOShort = 4567; VAL_2 : TSDOShort = -9876; VAL_3 : TSDOShort = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOShortType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getShort(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getShort(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getShort(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getShort(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getShort(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getShort(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDODataObjectList_BaseTest.CheckEquals(expected,
+  actual: TSDODate; msg: string; const AStrict: Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+class function TSDODataObjectList_BaseTest.Create_Factory: ISDODataFactory;
+var
+  typ : ISDOType;
+begin
+  Result := TSDODataFactory.Create();
+  Result.AddType(s_URI_1,s_TYPE_1,[]);
+  typ := Result.getType(s_URI_1,s_TYPE_1);
+    Result.addProperty(typ,s_PROP_BOOL_1,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ,s_PROP_BYTE_1,sdo_namespace,'Byte',[]);
+    Result.addProperty(typ,s_PROP_INTEGER_1,sdo_namespace,'Integer',[]);
+    Result.addProperty(typ,s_PROP_STR_1,sdo_namespace,'String',[]);
+end;
+
+function TSDODataObjectList_BaseTest.Create_Object() : ISDODataObject;
+begin
+  Result := FFactory.createNew(s_URI_1,s_TYPE_1);
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_boolean_with_cursor();
+const VAL_1 = False; VAL_2 = True; VAL_3 = False;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOBooleanType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getBoolean());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getBoolean());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getBoolean());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getBoolean());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getBoolean());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getBoolean());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_boolean_with_index();
+const VAL_1 = True; VAL_2 = False; VAL_3 = True;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOBooleanType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getBoolean(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getBoolean(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getBoolean(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getBoolean(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getBoolean(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getBoolean(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_byte_with_cursor();
+const VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 34; VAL_3 : TSDOByte = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOByteType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getByte());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getByte());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getByte());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getByte());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getByte());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getByte());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_byte_with_index();
+const VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 34; VAL_3 : TSDOByte = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOByteType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getByte(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getByte(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getByte(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getByte(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getByte(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getByte(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_dataObject_with_cursor();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : ISDODataObject;
+begin
+  VAL_1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_2 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_3 := FFactory.createNew(s_URI_1,s_TYPE_1);
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(PTrUInt(VAL_2),PTrUInt(ls.getDataObject()));
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(PTrUInt(VAL_1),PTrUInt(ls.getDataObject()));
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(PTrUInt(VAL_2),PTrUInt(ls.getDataObject()));
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(PTrUInt(VAL_2),PTrUInt(ls.getDataObject()));
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(PTrUInt(VAL_2),PTrUInt(ls.getDataObject()));
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(PTrUInt(VAL_1),PTrUInt(ls.getDataObject()));
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_dataObject_with_index();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : ISDODataObject;
+begin
+  VAL_1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_2 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_3 := FFactory.createNew(s_URI_1,s_TYPE_1);
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(PtrUInt(VAL_2),PtrUInt(ls.getDataObject(0)));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(PtrUInt(VAL_1),PtrUInt(ls.getDataObject(0)));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(PtrUInt(VAL_2),PtrUInt(ls.getDataObject(0)));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(PtrUInt(VAL_2),PtrUInt(ls.getDataObject(0)));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(PtrUInt(VAL_2),PtrUInt(ls.getDataObject(1)));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(PtrUInt(VAL_1),PtrUInt(ls.getDataObject(0)));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_date_with_cursor();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_2)^ := d;
+  end;
+
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  SetConstants();
+  ls := Create_List(TSDODateTimeType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getDate());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getDate());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getDate());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getDate());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getDate());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getDate());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_date_with_index();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_2)^ := d;
+  end;
+
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  SetConstants();
+  ls := Create_List(TSDODateTimeType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getDate(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getDate(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getDate(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getDate(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getDate(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getDate(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_integer_with_cursor();
+const VAL_1 : TSDOInteger = 1210; VAL_2 : TSDOInteger = -97456; VAL_3 : TSDOInteger = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOIntegerType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getInteger());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getInteger());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getInteger());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getInteger());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getInteger());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getInteger());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_integer_with_index();
+const VAL_1 : TSDOInteger = 1210; VAL_2 : TSDOInteger = -97456; VAL_3 : TSDOInteger = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOIntegerType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getInteger(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getInteger(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getInteger(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getInteger(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getInteger(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getInteger(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_string_with_cursor();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : string;
+begin
+  Randomize();
+  VAL_1 := RandomString(RandomRange(0,1000));
+  VAL_2 := RandomString(RandomRange(0,1000));
+  VAL_3 := RandomString(RandomRange(0,1000));
+  ls := Create_List(TSDOStringType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getString());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,ls.getString());
+      CheckEquals(1,ls.size());
+      ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveNext());
+    ls.delete();
+      CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_2,ls.getString());
+      CheckEquals(2,ls.size());
+      CheckEquals(True,c.MoveNext());
+      ls.delete();
+        CheckEquals(True,c.MoveFirst());
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getString());
+        ls.delete();
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    CheckEquals(True,c.MoveLast());
+    ls.delete();
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(VAL_2,ls.getString());
+      CheckEquals(2,ls.size());
+      ls.delete();
+        CheckEquals(1,ls.size());
+        CheckEquals(True,c.MoveLast());
+        CheckEquals(VAL_1,ls.getString());
+        ls.delete();
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.delete_string_with_index();
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+  VAL_1, VAL_2, VAL_3 : string;
+begin
+  Randomize();
+  VAL_1 := RandomString(RandomRange(0,1000));
+  VAL_2 := RandomString(RandomRange(0,1000));
+  VAL_3 := RandomString(RandomRange(0,1000));
+  ls := Create_List(TSDOStringType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  ok := False;
+  try
+    ls.delete(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ok := False;
+  try
+    ls.delete(123);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(VAL_1);
+    ls.delete(0);
+    CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getString(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+    ls.delete(1);
+      CheckEquals(VAL_1,ls.getString(0));
+      CheckEquals(1,ls.size());
+      ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    ls.delete(0);
+      CheckEquals(VAL_2,ls.getString(0));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_2,ls.getString(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+    c.Reset();
+    ls.delete(2);
+      CheckEquals(VAL_2,ls.getString(1));
+      CheckEquals(2,ls.size());
+      ls.delete(1);
+        CheckEquals(1,ls.size());
+        CheckEquals(VAL_1,ls.getString(0));
+        ls.delete(0);
+        CheckEquals(0,ls.size());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_boolean_cursor();
+const VAL_1 : TSDOBoolean = True; VAL_2 : TSDOBoolean = False; VAL_3 : TSDOBoolean = True;
+      INT_VAL_1 = 1; INT_VAL_2 = 0; INT_VAL_3 = 1;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getBoolean();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(False);
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getBoolean());
+    CheckEquals(False,c.MoveNext());
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_2;
+    CheckEquals(VAL_2,ls.getBoolean());
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_1;
+
+  ls.append(False);
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getBoolean());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getBoolean());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(False);
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getBoolean());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getBoolean());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getBoolean());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(False);
+  ls.append(False);
+  ls.append(False);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False,ls.getBoolean());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False,ls.getBoolean());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False,ls.getBoolean());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_boolean_index();
+const VAL_1 = True; VAL_2 = False; VAL_3 = True;
+      INT_VAL_1 = 1; INT_VAL_2 = 0; INT_VAL_3 = 1;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getBoolean(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(False);
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getBoolean(0));
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_2;
+    CheckEquals(VAL_2,ls.getBoolean(0));
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_1;
+
+  ls.append(False);
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getBoolean(0));
+    CheckEquals(VAL_2,ls.getBoolean(1));
+
+  ls.append(False);
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := INT_VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getBoolean(0));
+      CheckEquals(VAL_2,ls.getBoolean(1));
+      CheckEquals(VAL_3,ls.getBoolean(2));
+
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(False);
+  ls.append(False);
+  ls.append(False);
+    CheckEquals(3,ls.size());
+    CheckEquals(False,ls.getBoolean(0));
+    CheckEquals(False,ls.getBoolean(1));
+    CheckEquals(False,ls.getBoolean(2));
+
+  ok := False;
+  try
+    ls.getBoolean(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.get_byte_cursor();
+const VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 34; VAL_3 : TSDOByte = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getByte();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOByte(0));
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getByte());
+    CheckEquals(False,c.MoveNext());
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getByte());
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOByte(0));
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getByte());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getByte());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOByte(0));
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getByte());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getByte());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getByte());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOByte(0));
+  ls.append(TSDOByte(0));
+  ls.append(TSDOByte(0));
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getByte());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getByte());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getByte());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_byte_index();
+const VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 34; VAL_3 : TSDOByte = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getByte(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOByte(0));
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getByte(0));
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getByte(0));
+    PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(TSDOByte(0));
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getByte(0));
+    CheckEquals(VAL_2,ls.getByte(1));
+
+  ls.append(TSDOByte(0));
+  Check(c.MoveLast());
+  PByte(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getByte(0));
+      CheckEquals(VAL_2,ls.getByte(1));
+      CheckEquals(VAL_3,ls.getByte(2));
+
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(TSDOByte(0));
+  ls.append(TSDOByte(0));
+  ls.append(TSDOByte(0));
+    CheckEquals(3,ls.size());
+    CheckEquals(0,ls.getByte(0));
+    CheckEquals(0,ls.getByte(1));
+    CheckEquals(0,ls.getByte(2));
+
+  ok := False;
+  try
+    ls.getByte(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.get_dataObject_cursor();
+var
+  VAL_1, VAL_2, VAL_3 : ISDODataObject;
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  VAL_1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_2 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_3 := FFactory.createNew(s_URI_1,s_TYPE_1);
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getDataObject();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(NIL_OBJECT);
+  Check(c.MoveLast());
+  PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    Check(VAL_1 = ls.getDataObject());
+    CheckEquals(False,c.MoveNext());
+    PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    Check(VAL_2 = ls.getDataObject());
+    PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+
+  ls.append(nil);
+  Check(c.MoveLast());
+  PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    Check(VAL_1 = ls.getDataObject());
+    CheckEquals(True,c.MoveNext());
+    Check(VAL_2 = ls.getDataObject());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(nil);
+  Check(c.MoveLast());
+  PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_1 = ls.getDataObject());
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_2 = ls.getDataObject());
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_3 = ls.getDataObject());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+  ls.append(nil);
+  ls.append(nil);
+  ls.append(nil);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      Check(nil = ls.getDataObject());
+    CheckEquals(True,c.MoveNext());
+      Check(nil = ls.getDataObject());
+    CheckEquals(True,c.MoveNext());
+      Check(nil = ls.getDataObject());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_dataObject_index();
+var
+  VAL_1, VAL_2, VAL_3 : ISDODataObject;
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  VAL_1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_2 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_3 := FFactory.createNew(s_URI_1,s_TYPE_1);
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getDataObject(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(nil);
+  Check(c.MoveLast());
+  PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    Check(VAL_1 = ls.getDataObject(0));
+    PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    Check(VAL_2 = ls.getDataObject(0));
+    PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+
+  ls.append(nil);
+  Check(c.MoveLast());
+  PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    CheckEquals(2,ls.size());
+    Check(VAL_1 = ls.getDataObject(0));
+    Check(VAL_2 = ls.getDataObject(1));
+
+  ls.append(nil);
+  Check(c.MoveLast());
+  PPSDODataObject(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_3;
+      CheckEquals(3,ls.size());
+      Check(VAL_1 = ls.getDataObject(0));
+      Check(VAL_2 = ls.getDataObject(1));
+      Check(VAL_3 = ls.getDataObject(2));
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+  ls.append(nil);
+  ls.append(nil);
+  ls.append(nil);
+    CheckEquals(3,ls.size());
+    Check(nil = ls.getDataObject(0));
+    Check(nil = ls.getDataObject(1));
+    Check(nil = ls.getDataObject(2));
+
+  ok := False;
+  try
+    ls.getDataObject(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.get_date_cursor();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_2)^ := d;
+  end;
+
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  SetConstants();
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getDate();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DATE);
+  Check(c.MoveLast());
+  PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getDate());
+    CheckEquals(False,c.MoveNext());
+    PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getDate());
+    PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(ZERO_DATE);
+  Check(c.MoveLast());
+  PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getDate());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getDate());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_DATE);
+  Check(c.MoveLast());
+  PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getDate());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getDate());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getDate());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(ZERO_DATE);
+  ls.append(ZERO_DATE);
+  ls.append(ZERO_DATE);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,ls.getDate());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,ls.getDate());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,ls.getDate());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_date_index();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_2)^ := d;
+  end;
+
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  SetConstants();
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getDate(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DATE);
+  Check(c.MoveLast());
+  PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getDate(0));
+    PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getDate(0));
+    PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(ZERO_DATE);
+  Check(c.MoveLast());
+  PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getDate(0));
+    CheckEquals(VAL_2,ls.getDate(1));
+
+  ls.append(ZERO_DATE);
+  Check(c.MoveLast());
+  PSDODateTime(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getDate(0));
+      CheckEquals(VAL_2,ls.getDate(1));
+      CheckEquals(VAL_3,ls.getDate(2));
+
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(ZERO_DATE);
+  ls.append(ZERO_DATE);
+  ls.append(ZERO_DATE);
+    CheckEquals(3,ls.size());
+    CheckEquals(ZERO_DATE,ls.getDate(0));
+    CheckEquals(ZERO_DATE,ls.getDate(1));
+    CheckEquals(ZERO_DATE,ls.getDate(2));
+
+  ok := False;
+  try
+    ls.getDate(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.get_integer_cursor();
+const VAL_1 : TSDOInteger = 1210; VAL_2 : TSDOInteger = -97456; VAL_3 : TSDOInteger = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getInteger();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(0);
+  Check(c.MoveLast());
+  PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getInteger());
+    CheckEquals(False,c.MoveNext());
+    PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getInteger());
+    PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(0);
+  Check(c.MoveLast());
+  PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getInteger());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getInteger());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(0);
+  Check(c.MoveLast());
+  PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getInteger());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getInteger());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getInteger());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(0);
+  ls.append(0);
+  ls.append(0);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getInteger());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getInteger());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,ls.getInteger());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_integer_index();
+const VAL_1 : TSDOInteger = 1210; VAL_2 : TSDOInteger = -97456; VAL_3 : TSDOInteger = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getInteger(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(0);
+  Check(c.MoveLast());
+  PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getInteger(0));
+    PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(VAL_2,ls.getInteger(0));
+    PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_1;
+
+  ls.append(0);
+  Check(c.MoveLast());
+  PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getInteger(0));
+    CheckEquals(VAL_2,ls.getInteger(1));
+
+  ls.append(0);
+  Check(c.MoveLast());
+  PSDOInteger(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getInteger(0));
+      CheckEquals(VAL_2,ls.getInteger(1));
+      CheckEquals(VAL_3,ls.getInteger(2));
+
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(0);
+  ls.append(0);
+  ls.append(0);
+    CheckEquals(3,ls.size());
+    CheckEquals(0,ls.getInteger(0));
+    CheckEquals(0,ls.getInteger(1));
+    CheckEquals(0,ls.getInteger(2));
+
+  ok := False;
+  try
+    ls.getInteger(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.get_string_cursor();
+const VAL_1 : TSDOString = 'xxsqklmhgf[df]121ffsd0'; VAL_2 : TSDOString = ''; VAL_3 : TSDOString = 'aeiuoou';
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getString();
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append('');
+  Check(c.MoveLast());
+  PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+  CheckEquals(1,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getString());
+    CheckEquals(False,c.MoveNext());
+    PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    CheckEquals(VAL_2,ls.getString());
+    PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+
+  ls.append('');
+  Check(c.MoveLast());
+  PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,ls.getString());
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,ls.getString());
+    CheckEquals(False,c.MoveNext());
+
+  ls.append('');
+  Check(c.MoveLast());
+  PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_3;
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,ls.getString());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,ls.getString());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,ls.getString());
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append('');
+  ls.append('');
+  ls.append('');
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',ls.getString());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',ls.getString());
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',ls.getString());
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.get_string_index();
+const VAL_1 = 'sdlksxhgf[df]1ffsd0'; VAL_2 = ''; VAL_3 = 'sssddaeiuoou';
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.getString(0);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append('');
+  Check(c.MoveLast());
+  PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+  CheckEquals(1,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,ls.getString(0));
+    PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    CheckEquals(VAL_2,ls.getString(0));
+    PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_1;
+
+  ls.append('');
+  Check(c.MoveLast());
+  PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_2;
+    CheckEquals(2,ls.size());
+    CheckEquals(VAL_1,ls.getString(0));
+    CheckEquals(VAL_2,ls.getString(1));
+
+  ls.append('');
+  Check(c.MoveLast());
+  PPSDOString(PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^ := VAL_3;
+      CheckEquals(3,ls.size());
+      CheckEquals(VAL_1,ls.getString(0));
+      CheckEquals(VAL_2,ls.getString(1));
+      CheckEquals(VAL_3,ls.getString(2));
+
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append('');
+  ls.append('');
+  ls.append('');
+    CheckEquals(3,ls.size());
+    CheckEquals('',ls.getString(0));
+    CheckEquals('',ls.getString(1));
+    CheckEquals('',ls.getString(2));
+
+  ok := False;
+  try
+    ls.getString(3);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_boolean();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOBoolean);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOBoolean;
+begin
+  val_1 := True;
+  val_2 := True;
+  val_3 := False;
+  ls := Create_List(TSDOBooleanType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getBoolean(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getBoolean(0));
+      CheckEquals(val_2, ls.getBoolean(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getBoolean(0));
+        CheckEquals(val_2, ls.getBoolean(1));
+        CheckEquals(val_3, ls.getBoolean(2));
+
+  ls := Create_List(TSDOBooleanType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getBoolean(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getBoolean(0));
+      CheckEquals(val_2, ls.getBoolean(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getBoolean(0));
+        CheckEquals(val_2, ls.getBoolean(1));
+        CheckEquals(val_3, ls.getBoolean(2));
+
+  ls := Create_List(TSDOBooleanType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getBoolean(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getBoolean(0));
+      CheckEquals(val_3, ls.getBoolean(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getBoolean(0));
+        CheckEquals(val_2, ls.getBoolean(1));
+        CheckEquals(val_3, ls.getBoolean(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_byte();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOByte);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOByte;
+begin
+  val_1 := RandomRange(Low(TSDOByte),High(TSDOByte));
+  val_2 := RandomRange(Low(TSDOByte),High(TSDOByte));
+  val_3 := RandomRange(Low(TSDOByte),High(TSDOByte));
+  ls := Create_List(TSDOByteType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getByte(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getByte(0));
+      CheckEquals(val_2, ls.getByte(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getByte(0));
+        CheckEquals(val_2, ls.getByte(1));
+        CheckEquals(val_3, ls.getByte(2));
+
+  ls := Create_List(TSDOByteType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getByte(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getByte(0));
+      CheckEquals(val_2, ls.getByte(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getByte(0));
+        CheckEquals(val_2, ls.getByte(1));
+        CheckEquals(val_3, ls.getByte(2));
+
+  ls := Create_List(TSDOByteType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getByte(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getByte(0));
+      CheckEquals(val_3, ls.getByte(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getByte(0));
+        CheckEquals(val_2, ls.getByte(1));
+        CheckEquals(val_3, ls.getByte(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_dataObject();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : ISDODataObject);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : ISDODataObject;
+begin
+  val_1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  val_2 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  val_3 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(PtrUInt(val_1), PtrUInt(ls.getDataObject(0)));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(PtrUInt(val_1), PtrUInt(ls.getDataObject(0)));
+      CheckEquals(PtrUInt(val_2), PtrUInt(ls.getDataObject(1)));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(PtrUInt(val_1), PtrUInt(ls.getDataObject(0)));
+        CheckEquals(PtrUInt(val_2), PtrUInt(ls.getDataObject(1)));
+        CheckEquals(PtrUInt(val_3), PtrUInt(ls.getDataObject(2)));
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(PtrUInt(val_2), PtrUInt(ls.getDataObject(0)));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(PtrUInt(val_1), PtrUInt(ls.getDataObject(0)));
+      CheckEquals(PtrUInt(val_2), PtrUInt(ls.getDataObject(1)));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(PtrUInt(val_1), PtrUInt(ls.getDataObject(0)));
+        CheckEquals(PtrUInt(val_2), PtrUInt(ls.getDataObject(1)));
+        CheckEquals(PtrUInt(val_3), PtrUInt(ls.getDataObject(2)));
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(PtrUInt(val_3), PtrUInt(ls.getDataObject(0)));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(PtrUInt(val_1), PtrUInt(ls.getDataObject(0)));
+      CheckEquals(PtrUInt(val_3), PtrUInt(ls.getDataObject(1)));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(PtrUInt(val_1), PtrUInt(ls.getDataObject(0)));
+        CheckEquals(PtrUInt(val_2), PtrUInt(ls.getDataObject(1)));
+        CheckEquals(PtrUInt(val_3), PtrUInt(ls.getDataObject(2)));
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_date();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDODateTime);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDODateTime;
+begin
+  val_1 := RandomDate();
+  val_2 := RandomDate();
+  val_3 := RandomDate();
+  ls := Create_List(TSDODateTimeType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getDate(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getDate(0));
+      CheckEquals(val_2, ls.getDate(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getDate(0));
+        CheckEquals(val_2, ls.getDate(1));
+        CheckEquals(val_3, ls.getDate(2));
+
+  ls := Create_List(TSDODateTimeType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getDate(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getDate(0));
+      CheckEquals(val_2, ls.getDate(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getDate(0));
+        CheckEquals(val_2, ls.getDate(1));
+        CheckEquals(val_3, ls.getDate(2));
+
+  ls := Create_List(TSDODateTimeType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getDate(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getDate(0));
+      CheckEquals(val_3, ls.getDate(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getDate(0));
+        CheckEquals(val_2, ls.getDate(1));
+        CheckEquals(val_3, ls.getDate(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_integer();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOInteger);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOInteger;
+begin
+  val_1 := RandomRange(-12345,12345);
+  val_2 := RandomRange(-12345,12345);
+  val_3 := RandomRange(-12345,12345);
+  ls := Create_List(TSDOIntegerType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+                            
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);  
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getInteger(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getInteger(0));
+      CheckEquals(val_2, ls.getInteger(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getInteger(0));
+        CheckEquals(val_2, ls.getInteger(1));
+        CheckEquals(val_3, ls.getInteger(2));
+
+  ls := Create_List(TSDOIntegerType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getInteger(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getInteger(0));
+      CheckEquals(val_2, ls.getInteger(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getInteger(0));
+        CheckEquals(val_2, ls.getInteger(1));
+        CheckEquals(val_3, ls.getInteger(2));
+
+  ls := Create_List(TSDOIntegerType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getInteger(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getInteger(0));
+      CheckEquals(val_3, ls.getInteger(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getInteger(0));
+        CheckEquals(val_2, ls.getInteger(1));
+        CheckEquals(val_3, ls.getInteger(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.insert_string();
+var
+  ls : ISDODataObjectList;
+
+  procedure CheckInvalidIndex(const AIndex : PtrInt; const AValue : TSDOString);
+  var
+    pass : Boolean;
+    oldSize : PtrInt;
+  begin
+    oldSize := ls.size();
+    pass := False;
+    try
+      ls.insert(-10,AValue);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        pass := True;
+      end;
+    end;
+    CheckEquals(True,pass, Format('Index = %d',[AIndex]));
+    CheckEquals(oldSize, ls.size(), 'A failed "insert" must not modify the list''s size.');
+  end;
+
+var
+  c : ILinkedListCursor;
+  val_1, val_2, val_3 : TSDOString;
+begin
+  val_1 := RandomString(RandomRange(0,123));
+  val_2 := RandomString(RandomRange(0,123));
+  val_3 := RandomString(RandomRange(0,123));
+  ls := Create_List(TSDOStringType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+
+  CheckInvalidIndex(-12, val_1);
+  CheckInvalidIndex(-1, val_1);
+  CheckInvalidIndex(1, val_1);
+  CheckInvalidIndex(12, val_1);
+
+  ls.insert(0,val_1);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_1, ls.getString(0));
+    ls.insert(1,val_2);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getString(0));
+      CheckEquals(val_2, ls.getString(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getString(0));
+        CheckEquals(val_2, ls.getString(1));
+        CheckEquals(val_3, ls.getString(2));
+
+  ls := Create_List(TSDOStringType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_2);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_2, ls.getString(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getString(0));
+      CheckEquals(val_2, ls.getString(1));
+      ls.insert(2,val_3);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(2,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getString(0));
+        CheckEquals(val_2, ls.getString(1));
+        CheckEquals(val_3, ls.getString(2));
+
+  ls := Create_List(TSDOStringType.Create(FFactory) as ISDOType);
+  c := ls.getCursor();
+  ls.insert(0,val_3);
+    CheckEquals(1, ls.size(), 'size()');
+    CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+    CheckEquals(val_3, ls.getString(0));
+    ls.insert(0,val_1);
+      CheckEquals(2, ls.size(), 'size()');
+      CheckEquals(0,c.GetPosition(),'getCursor().GetPosition()');
+      CheckEquals(val_1, ls.getString(0));
+      CheckEquals(val_3, ls.getString(1));
+      ls.insert(1,val_2);
+        CheckEquals(3, ls.size(), 'size()');
+        CheckEquals(1,c.GetPosition(),'getCursor().GetPosition()');
+        CheckEquals(val_1, ls.getString(0));
+        CheckEquals(val_2, ls.getString(1));
+        CheckEquals(val_3, ls.getString(2));
+end;
+
+procedure TSDODataObjectList_BaseTest.SetUp();
+begin
+  inherited;
+  FFactory := Create_Factory();
+end;
+
+procedure TSDODataObjectList_BaseTest.set_boolean_cursor();
+const VAL_1 = True; VAL_2 = False; VAL_3 = True;
+      INT_VAL_1 = 1; INT_VAL_2 = 0; INT_VAL_3 = 1;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setBoolean(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(False);
+  c.MoveFirst();
+  ls.setBoolean(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setBoolean(VAL_2);
+    CheckEquals(VAL_2, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setBoolean(VAL_1);
+
+  ls.append(False);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setBoolean(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(False);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setBoolean(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setBoolean(False);
+  CheckEquals(True,c.MoveNext());
+    ls.setBoolean(False);
+  CheckEquals(True,c.MoveNext());
+    ls.setBoolean(False);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_boolean_index();
+const VAL_1 = True; VAL_2 = False; VAL_3 = True;
+      INT_VAL_1 = 1; INT_VAL_2 = 0; INT_VAL_3 = 1;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setBoolean(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(False);
+  ls.setBoolean(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setBoolean(0,VAL_2);
+    CheckEquals(VAL_2, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setBoolean(0,VAL_1);
+
+  ls.append(False);
+  ls.setBoolean(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(False);
+  ls.setBoolean(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOBooleanType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setBoolean(0,False);
+  ls.setBoolean(1,False);
+  ls.setBoolean(2,False);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(False, 0 <> PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_byte_cursor();
+const VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 34; VAL_3 : TSDOByte = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setByte(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOByte(0));
+  c.MoveFirst();
+  ls.setByte(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setByte(VAL_2);
+    CheckEquals(VAL_2,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setByte(VAL_1);
+
+  ls.append(TSDOByte(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setByte(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOByte(0));
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setByte(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setByte(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setByte(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setByte(0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_byte_index();
+const VAL_1 : TSDOByte = 12; VAL_2 : TSDOByte = 34; VAL_3 : TSDOByte = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setByte(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(TSDOByte(0));
+  ls.setByte(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setByte(0,VAL_2);
+    CheckEquals(VAL_2,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setByte(0,VAL_1);
+
+  ls.append(TSDOByte(0));
+  ls.setByte(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(TSDOByte(0));
+  ls.setByte(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOByteType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setByte(0,0);
+  ls.setByte(1,0);
+  ls.setByte(2,0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PByte( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_dataObject_cursor();
+var
+  VAL_1, VAL_2, VAL_3 : ISDODataObject;
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  VAL_1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_2 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_3 := FFactory.createNew(s_URI_1,s_TYPE_1);
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setDataObject(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(nil);
+  c.MoveFirst();
+  ls.setDataObject(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    Check(VAL_1 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+    ls.setDataObject(VAL_2);
+    Check(VAL_2 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    ls.setDataObject(VAL_1);
+
+  ls.append(nil);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setDataObject(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    Check(VAL_1 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+    Check(VAL_2 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(nil);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setDataObject(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_1 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_2 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_3 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setDataObject(nil);
+  CheckEquals(True,c.MoveNext());
+    ls.setDataObject(nil);
+  CheckEquals(True,c.MoveNext());
+    ls.setDataObject(nil);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      Check(nil = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(nil = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(nil = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_dataObject_index();
+var
+  VAL_1, VAL_2, VAL_3 : ISDODataObject;
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  VAL_1 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_2 := FFactory.createNew(s_URI_1,s_TYPE_1);
+  VAL_3 := FFactory.createNew(s_URI_1,s_TYPE_1);
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setDataObject(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(nil);
+  ls.setDataObject(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    Check(VAL_1 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+    ls.setDataObject(0,VAL_2);
+    Check(VAL_2 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    ls.setDataObject(0,VAL_1);
+
+  ls.append(nil);
+  ls.setDataObject(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    Check(VAL_1 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+    Check(VAL_2 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(nil);
+  ls.setDataObject(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      Check(VAL_1 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_2 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(VAL_3 = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(FFactory.getType(s_URI_1,s_TYPE_1));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setDataObject(0,nil);
+  ls.setDataObject(1,nil);
+  ls.setDataObject(2,nil);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      Check(nil = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(nil = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      Check(nil = PPSDODataObject( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_date_cursor();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_2)^ := d;
+  end;
+
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  SetConstants();
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setDate(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DATE);
+  c.MoveFirst();
+  ls.setDate(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setDate(VAL_2);
+    CheckEquals(VAL_2,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setDate(VAL_1);
+
+  ls.append(ZERO_DATE);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setDate(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_DATE);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setDate(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setDate(ZERO_DATE);
+  CheckEquals(True,c.MoveNext());
+    ls.setDate(ZERO_DATE);
+  CheckEquals(True,c.MoveNext());
+    ls.setDate(ZERO_DATE);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_date_index();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_2)^ := d;
+  end;
+
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  SetConstants();
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setDate(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(ZERO_DATE);
+  ls.setDate(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setDate(0,VAL_2);
+    CheckEquals(VAL_2,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setDate(0,VAL_1);
+
+  ls.append(ZERO_DATE);
+  ls.setDate(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(ZERO_DATE);
+  ls.setDate(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDODateTimeType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setDate(0,ZERO_DATE);
+  ls.setDate(1,ZERO_DATE);
+  ls.setDate(2,ZERO_DATE);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(ZERO_DATE,PSDODateTime( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_integer_cursor();
+const VAL_1 : TSDOInteger = 1210; VAL_2 : TSDOInteger = -97456; VAL_3 : TSDOInteger = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setInteger(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(0);
+  c.MoveFirst();
+  ls.setInteger(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setInteger(VAL_2);
+    CheckEquals(VAL_2,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setInteger(VAL_1);
+
+  ls.append(0);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setInteger(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(0);
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setInteger(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setInteger(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setInteger(0);
+  CheckEquals(True,c.MoveNext());
+    ls.setInteger(0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_integer_index();
+const VAL_1 : TSDOInteger = 1210; VAL_2 : TSDOInteger = -97456; VAL_3 : TSDOInteger = 0;
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setInteger(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append(0);
+  ls.setInteger(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+    ls.setInteger(0,VAL_2);
+    CheckEquals(VAL_2,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    ls.setInteger(0,VAL_1);
+
+  ls.append(0);
+  ls.setInteger(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append(0);
+  ls.setInteger(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOIntegerType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setInteger(0,0);
+  ls.setInteger(1,0);
+  ls.setInteger(2,0);
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(0,PSDOInteger( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_string_cursor();
+const VAL_1 = 'aqs##[df]}}'; VAL_2 = ''; VAL_3 = '?^* mlqdbcnd,';
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setString(VAL_1);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append('');
+  c.MoveFirst();
+  ls.setString(VAL_1);
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+    ls.setString(VAL_2);
+    CheckEquals(VAL_2,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    ls.setString(VAL_1);
+
+  ls.append('');
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  ls.setString(VAL_2);
+  CheckEquals(2,ls.size());
+  c.Reset();
+  CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_1,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append('');
+  CheckEquals(True,c.MoveFirst());
+  CheckEquals(True,c.MoveNext());
+  CheckEquals(True,c.MoveNext());
+  ls.setString(VAL_3);
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_1,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  CheckEquals(True,c.MoveFirst());
+    ls.setString('');
+  CheckEquals(True,c.MoveNext());
+    ls.setString('');
+  CheckEquals(True,c.MoveNext());
+    ls.setString('');
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.set_string_index();
+const VAL_1 = '""##aqs##[df]}}'; VAL_2 = ''; VAL_3 = '##?^* mldhbcnd,';
+var
+  ls : ISDODataObjectList;
+  c : ILinkedListCursor;
+  ok : Boolean;
+begin
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+
+  CheckEquals(0,ls.size());
+  Check(nil <> c);
+  ok := False;
+  try
+    ls.setString(1,VAL_1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok);
+
+  ls.append('');
+  ls.setString(0,VAL_1);
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+    ls.setString(0,VAL_2);
+    CheckEquals(VAL_2,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    ls.setString(0,VAL_1);
+
+  ls.append('');
+  ls.setString(1,VAL_2);
+  CheckEquals(2,ls.size());
+  CheckEquals(True,c.MoveFirst());
+    CheckEquals(VAL_1,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+    CheckEquals(VAL_2,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls.append('');
+  ls.setString(2,VAL_3);
+  CheckEquals(3,ls.size());
+    CheckEquals(True,c.MoveFirst());
+      CheckEquals(VAL_1,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_2,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals(VAL_3,PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+
+  ls := Create_List(TSDOStringType.Create(FFactory));
+  c := ls.getCursor();
+  ls.append(VAL_1);
+  ls.append(VAL_2);
+  ls.append(VAL_3);
+  ls.setString(0,'');
+  ls.setString(1,'');
+  ls.setString(2,'');
+
+  CheckEquals(3,ls.size());
+  c.Reset();
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(True,c.MoveNext());
+      CheckEquals('',PPSDOString( PtrUInt(GetData(c.GetCurrent())) + VALUE_STATUS_LENGTH )^^);
+    CheckEquals(False,c.MoveNext());
+end;
+
+procedure TSDODataObjectList_BaseTest.TearDown();
+begin
+  FFactory := nil;
+  inherited;
+end;
+
+{ TSDODataObjectList_Test }
+
+class function TSDODataObjectList_Test.Create_List(AItemType: ISDOType): ISDODataObjectList;
+begin
+  Result := TSDODataObjectList.Create(AItemType);
+end;
+
+initialization
+  RegisterTest('object',TSDODataObjectList_Test.Suite);
+
+end.

+ 1031 - 0
packages/fcl-sdo/tests/test_suite/test_equalityhelper.pas

@@ -0,0 +1,1031 @@
+{$INCLUDE sdo_global.inc}
+unit test_equalityhelper;
+
+interface
+uses
+  SysUtils, Classes//, Dialogs
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , sdo, sdo_types, sdo_equalityhelper, test_suite_utils;
+
+type
+
+  TSDOEqualityHelper_Test = class(TWstBaseTest)
+  private
+    function CreateFactory() : ISDODataFactory;
+    function CreateEqualityHelper() : TSDOEqualityHelperClass;
+    function createObjA(const AUri : string; const AFact : ISDODataFactory) : ISDODataObject;
+    function createObjB(const AUri : string; const AFact : ISDODataFactory) : ISDODataObject;
+    function createObjC(const AUri : string; const AFact : ISDODataFactory) : ISDODataObject;
+  published
+    procedure equalShallow_empty_object();
+    procedure equalShallow_object();
+    procedure equalShallow_object_not_equal_type();
+    procedure equalShallow_object_not_equal_value();
+    procedure equalShallow_cursorPos();
+
+    procedure equal_empty_object();
+    procedure equal_object();
+    procedure equal_object_not_equal_type();
+    procedure equal_object_not_equal_value();
+    procedure equal_cursorPos();
+  end;
+
+implementation
+
+uses sdo_datafactory, sdo_linked_list;
+
+const
+  s_uri              = 'urn-test'; s_uri_2              = 'urn-test2';
+  s_type_object_A    = 'objectA';
+  s_type_object_B    = 'objectB';
+  s_type_object_C    = 'objectC';
+  s_bool_prop        = 'bool_prop';            s_bool_propList      = 'bool_prop_list';
+  s_byte_prop        = 'byte_prop';            s_byte_propList      = 'byte_prop_list';
+  s_bytes_prop       = 'bytes_prop';           s_bytes_propList     = 'bytes_prop_list';
+  s_char_prop        = 'char_prop';            s_char_propList      = 'char_prop_list';
+  s_currency_prop    = 'currency_prop';        s_currency_propList  = 'currency_prop_list';
+  s_date_prop        = 'date_prop';            s_date_propList      = 'date_prop_list';
+  s_double_prop      = 'double_prop';          s_double_propList    = 'double_prop_list';
+  s_float_prop       = 'float_prop';           s_float_propList     = 'float_prop_list';
+  s_integer_prop     = 'integer_prop';         s_integer_propList   = 'integer_prop_list';
+  s_long_prop        = 'long_prop';            s_long_propList      = 'long_prop_list';
+  s_short_prop       = 'short_prop';           s_short_propList     = 'short_prop_list';
+  s_string_prop      = 'string_prop';          s_string_propList    = 'string_prop_list';
+  s_object_prop      = 'object_prop';          s_object_propList    = 'object_prop_list';
+
+{ TSDOEqualityHelper_Test }
+
+function TSDOEqualityHelper_Test.CreateEqualityHelper() : TSDOEqualityHelperClass;
+begin
+  Result := TSDOEqualityHelper;
+end;
+
+function TSDOEqualityHelper_Test.CreateFactory() : ISDODataFactory;
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_ObjectA(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}        
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+
+  procedure Add_ObjectB();
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(s_uri,s_type_object_B,[]);
+    locObj := locFactory.getType(s_uri,s_type_object_B);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+
+      locFactory.addProperty(locObj,s_object_prop,s_uri,s_type_object_A,[pfIsContainment]);
+        locFactory.addProperty(locObj,s_object_propList,s_uri,s_type_object_A,[pfIsMany,pfIsContainment]);
+  end;
+
+  procedure Add_ObjectC();
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(s_uri_2,s_type_object_C,[]);
+    locObj := locFactory.getType(s_uri_2,s_type_object_C);
+      locFactory.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+        locFactory.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locFactory.addProperty(locObj,s_byte_prop,sdo_namespace,SDOTypeDefaultTypeNames[ByteType], []);
+        locFactory.addProperty(locObj,s_byte_propList,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsMany]);
+{$IFDEF HAS_SDO_BYTES}
+      locFactory.addProperty(locObj,s_bytes_prop,sdo_namespace,SDOTypeDefaultTypeNames[BytesType], []);
+        locFactory.addProperty(locObj,s_bytes_propList,sdo_namespace,SDOTypeDefaultTypeNames[BytesType],[pfIsMany]);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      locFactory.addProperty(locObj,s_char_prop,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType], []);
+        locFactory.addProperty(locObj,s_char_propList,sdo_namespace,SDOTypeDefaultTypeNames[CharacterType],[pfIsMany]);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_currency_prop,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType], []);
+        locFactory.addProperty(locObj,s_currency_propList,sdo_namespace,SDOTypeDefaultTypeNames[CurrencyType],[pfIsMany]);
+{$ENDIF HAS_SDO_CURRENCY}
+      locFactory.addProperty(locObj,s_date_prop,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType], []);
+        locFactory.addProperty(locObj,s_date_propList,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+{$IFDEF HAS_SDO_DOUBLE}
+      locFactory.addProperty(locObj,s_double_prop,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType], []);
+        locFactory.addProperty(locObj,s_double_propList,sdo_namespace,SDOTypeDefaultTypeNames[DoubleType],[pfIsMany]);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      locFactory.addProperty(locObj,s_float_prop,sdo_namespace,SDOTypeDefaultTypeNames[FloatType], []);
+        locFactory.addProperty(locObj,s_float_propList,sdo_namespace,SDOTypeDefaultTypeNames[FloatType],[pfIsMany]);
+{$ENDIF HAS_SDO_FLOAT}        
+      locFactory.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+        locFactory.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+{$IFDEF HAS_SDO_LONG}
+      locFactory.addProperty(locObj,s_long_prop,sdo_namespace,SDOTypeDefaultTypeNames[LongType], []);
+        locFactory.addProperty(locObj,s_long_propList,sdo_namespace,SDOTypeDefaultTypeNames[LongType],[pfIsMany]);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      locFactory.addProperty(locObj,s_short_prop,sdo_namespace,SDOTypeDefaultTypeNames[ShortType], []);
+        locFactory.addProperty(locObj,s_short_propList,sdo_namespace,SDOTypeDefaultTypeNames[ShortType],[pfIsMany]);
+{$ENDIF HAS_SDO_SHORT}        
+      locFactory.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFactory.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+  end;
+
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_ObjectA(s_uri);
+  Add_ObjectA(s_uri_2);
+  Add_ObjectB();
+  Add_ObjectC();
+  Result := locFactory;
+end;
+
+function TSDOEqualityHelper_Test.createObjA(const AUri: string; const AFact: ISDODataFactory): ISDODataObject;
+const
+  VAL_1 : TSDODate = ( Date : 35000; HourOffset : 3; MinuteOffset : 4; );
+  VAL_2 : TSDODate = ( Date : 40000; HourOffset : 0; MinuteOffset : 0; );
+  VAL_3 : TSDODate = ( Date : 38000; HourOffset : 5; MinuteOffset : 45; );
+  VAL_4 : TSDODate = ( Date : 39000; HourOffset : 6; MinuteOffset : 55; );
+{$IFDEF HAS_SDO_DOUBLE}
+  DOUBLE_VALUES_REPEATED_DIGITED : array[0..3] of TSDODouble = (
+    123456789.3258942121, 0, -147258369.987654321, -58369.98321
+  );
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  FLOAT_VALUES_REPEATED_DIGITED : array[0..3] of TSDOFloat = (
+    -123789.325121, -96321.558, 0, 83629.5851
+  );
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_CURRENCY}
+  CURRENCY_VALUES_REPEATED_DIGITED : array[0..3] of TSDOCurrency = (
+    6789.3258, 0, -258369.9876, -542424242369.9421
+  );  
+{$ENDIF HAS_SDO_CURRENCY}
+var
+  VAL_1_BYTES, VAL_2_BYTES, VAL_3_BYTES, VAL_4_BYTES : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1_BYTES := v;
+    v := nil;    
+
+    VAL_2_BYTES := nil;
+
+    SetLength(v,20);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3_BYTES := v;
+    v := nil;  
+
+    SetLength(v,30);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_4_BYTES := v;
+    v := nil;
+  end;
+
+var
+  ls : ISDODataObjectList;
+begin
+  SetConstants();
+  Result := AFact.createNew(AUri,s_type_object_A);
+  Result.setBoolean(s_bool_prop,True);
+  Result.setByte(s_byte_prop,123);
+{$IFDEF HAS_SDO_BYTES}
+  Result.setBytes(s_bytes_prop,VAL_1_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+  Result.setCharacter(s_char_prop,'x');
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  Result.setCurrency(s_currency_prop,123.4567);
+{$ENDIF HAS_SDO_CURRENCY}
+  Result.setDate(s_date_prop,VAL_1);
+{$IFDEF HAS_SDO_DOUBLE}
+  Result.setDouble(s_double_prop,78.3654);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  Result.setFloat(s_float_prop,-159.753);
+{$ENDIF HAS_SDO_FLOAT}
+  Result.setInteger(s_integer_prop,1210);
+{$IFDEF HAS_SDO_LONG}
+  Result.setLong(s_long_prop,123456789987654321);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  Result.setShort(s_short_prop,6541);
+{$ENDIF HAS_SDO_SHORT}
+  Result.setString(s_string_prop,'inoussa wst fpc');
+
+  ls := Result.getList(s_bool_propList);
+    ls.append(True);
+    ls.append(True);
+    ls.append(False);
+    ls.append(True);
+    ls.append(False);
+
+  ls := Result.getList(s_byte_propList);
+    ls.append(TSDOByte(1));
+    ls.append(TSDOByte(12));
+    ls.append(TSDOByte(23));
+
+{$IFDEF HAS_SDO_BYTES}
+  ls := Result.getList(s_bytes_propList);
+    ls.appendBytes(VAL_1_BYTES);
+    ls.appendBytes(VAL_2_BYTES);
+    ls.appendBytes(VAL_3_BYTES);
+    ls.appendBytes(VAL_4_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  ls := Result.getList(s_char_propList);
+    ls.append(TSDOChar('a'));
+    ls.append(TSDOChar('b'));
+    ls.append(TSDOChar('p'));
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  ls := Result.getList(s_currency_propList);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[0]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[1]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[2]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[3]);
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+  ls := Result.getList(s_double_propList);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[0]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[1]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[2]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[3]);
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  ls := Result.getList(s_float_propList);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[0]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[1]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[2]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[3]);
+{$ENDIF HAS_SDO_FLOAT}
+
+  ls := Result.getList(s_date_propList);
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+    ls.append(VAL_3);
+    ls.append(VAL_4);
+
+  ls := Result.getList(s_integer_propList);
+    ls.append(12);
+    ls.append(10);
+    ls.append(76);
+    ls.append(-123);
+    ls.append(0);
+
+{$IFDEF HAS_SDO_LONG}
+  ls := Result.getList(s_long_propList);
+    ls.append(TSDOLong(748159623849516236));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3692581479137842655));
+    ls.append(TSDOLong(112233445566778899));
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  ls := Result.getList(s_short_propList);
+    ls.append(TSDOLong(7481));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3655));
+    ls.append(TSDOLong(8899));
+{$ENDIF HAS_SDO_ShORT}
+    
+  ls := Result.getList(s_string_propList);
+    ls.append('object');
+    ls.append('');
+    ls.append('pascal');
+    ls.append('Lazarus');
+    ls.append('Delphi');
+end;
+
+function TSDOEqualityHelper_Test.createObjB(const AUri: string; const AFact: ISDODataFactory): ISDODataObject;
+const
+  VAL_1 : TSDODate = ( Date : 45678; HourOffset : 3; MinuteOffset : 4; );
+  VAL_2 : TSDODate = ( Date : 41234; HourOffset : 0; MinuteOffset : 0; );
+  VAL_3 : TSDODate = ( Date : 38976; HourOffset : 5; MinuteOffset : 45; );
+  VAL_4 : TSDODate = ( Date : 39254; HourOffset : 6; MinuteOffset : 55; );
+{$IFDEF HAS_SDO_DOUBLE}
+  DOUBLE_VALUES_REPEATED_DIGITED : array[0..3] of TSDODouble = (
+    123456789.3258942121, 0, -147258369.987654321, -58369.98321
+  );
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  FLOAT_VALUES_REPEATED_DIGITED : array[0..3] of TSDOFloat = (
+    -123789.325121, -96321.558, 0, 83629.5851
+  );
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_CURRENCY}
+  CURRENCY_VALUES_REPEATED_DIGITED : array[0..3] of TSDOCurrency = (
+    6789.3258, 0, -258369.9876, -542424242369.9421
+  );  
+{$ENDIF HAS_SDO_CURRENCY}
+var
+  VAL_1_BYTES, VAL_2_BYTES, VAL_3_BYTES, VAL_4_BYTES : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,5);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1_BYTES := v;
+    v := nil;    
+
+    VAL_2_BYTES := nil;
+
+    SetLength(v,23);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3_BYTES := v;
+    v := nil;  
+
+    SetLength(v,35);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_4_BYTES := v;
+    v := nil;
+  end;
+
+var
+  ls : ISDODataObjectList;
+begin
+  SetConstants();
+  Result := AFact.createNew(AUri,s_type_object_B);
+    Result.setBoolean(s_bool_prop,True);
+  Result.setByte(s_byte_prop,123);
+{$IFDEF HAS_SDO_BYTES}
+  Result.setBytes(s_bytes_prop,VAL_1_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+  Result.setCharacter(s_char_prop,'l');
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  Result.setCurrency(s_currency_prop,23.45);
+{$ENDIF HAS_SDO_CURRENCY}
+  Result.setDate(s_date_prop,VAL_2);
+{$IFDEF HAS_SDO_DOUBLE}
+  Result.setDouble(s_double_prop,8521.0255);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  Result.setFloat(s_float_prop,-5852.655753);
+{$ENDIF HAS_SDO_FLOAT}
+  Result.setInteger(s_integer_prop,1210);
+{$IFDEF HAS_SDO_LONG}
+  Result.setLong(s_long_prop,123456789987654321);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  Result.setShort(s_short_prop,6541);
+{$ENDIF HAS_SDO_SHORT}
+  Result.setString(s_string_prop,'inoussa wst fpc');
+
+  ls := Result.getList(s_bool_propList);
+    ls.append(True);
+    ls.append(True);
+    ls.append(False);
+    ls.append(True);
+    ls.append(False);
+
+  ls := Result.getList(s_byte_propList);
+    ls.append(TSDOByte(1));
+    ls.append(TSDOByte(12));
+    ls.append(TSDOByte(23));
+
+{$IFDEF HAS_SDO_BYTES}
+  ls := Result.getList(s_bytes_propList);
+    ls.appendBytes(VAL_1_BYTES);
+    ls.appendBytes(VAL_2_BYTES);
+    ls.appendBytes(VAL_3_BYTES);
+    ls.appendBytes(VAL_4_BYTES);
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  ls := Result.getList(s_char_propList);
+    ls.append(TSDOChar('a'));
+    ls.append(TSDOChar('b'));
+    ls.append(TSDOChar('p'));
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  ls := Result.getList(s_currency_propList);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[0]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[1]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[2]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[3]);
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+  ls := Result.getList(s_double_propList);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[0]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[1]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[2]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[3]);
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  ls := Result.getList(s_float_propList);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[0]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[1]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[2]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[3]);
+{$ENDIF HAS_SDO_FLOAT}
+
+  ls := Result.getList(s_date_propList);
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+    ls.append(VAL_3);
+    ls.append(VAL_4);    
+
+  ls := Result.getList(s_integer_propList);
+    ls.append(12);
+    ls.append(10);
+    ls.append(76);
+    ls.append(-123);
+    ls.append(0);
+
+{$IFDEF HAS_SDO_LONG}
+  ls := Result.getList(s_long_propList);
+    ls.append(TSDOLong(7481596238495162375));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3692581479137842655));
+    ls.append(TSDOLong(112233445566778899));
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  ls := Result.getList(s_short_propList);
+    ls.append(TSDOLong(7481));
+    ls.append(TSDOLong(0));
+    ls.append(TSDOLong(-3655));
+    ls.append(TSDOLong(8899));
+{$ENDIF HAS_SDO_ShORT}    
+
+  ls := Result.getList(s_string_propList);
+    ls.append('object');
+    ls.append('');
+    ls.append('pascal');
+    ls.append('Lazarus');
+    ls.append('Delphi');
+
+  Result.setDataObject(s_object_prop,AFact.createNew(s_uri,s_type_object_A));
+  Result.getDataObject(s_object_prop).setString(s_string_prop,'B->A->' + s_string_prop);
+  ls := Result.getList(s_object_propList);
+    ls.append(AFact.createNew(AUri,s_type_object_A));
+    ls.append(AFact.createNew(AUri,s_type_object_A));
+    ls.getCursor().MoveFirst();
+      ls.getDataObject().setString(s_string_prop,'B->A[0]->' + s_string_prop);
+    ls.getCursor().MoveNext();
+      ls.getDataObject().setString(s_string_prop,'B->A[1]->' + s_string_prop);
+end;
+
+function TSDOEqualityHelper_Test.createObjC(const AUri: string; const AFact: ISDODataFactory): ISDODataObject;
+const
+  VAL_1 : TSDODate = ( Date : 38678; HourOffset : 3; MinuteOffset : 4; );
+  VAL_2 : TSDODate = ( Date : 39234; HourOffset : 0; MinuteOffset : 0; );
+  VAL_3 : TSDODate = ( Date : 40976; HourOffset : 5; MinuteOffset : 45; );
+  VAL_4 : TSDODate = ( Date : 41254; HourOffset : 6; MinuteOffset : 55; );
+var
+  ls : ISDODataObjectList;
+begin
+  Result := AFact.createNew(AUri,s_type_object_A);
+  Result.setByte(s_byte_prop,123);
+  Result.setDate(s_date_prop,VAL_3);
+  Result.setBoolean(s_bool_prop,True);
+  Result.setInteger(s_integer_prop,1210);
+  Result.setString(s_string_prop,'inoussa wst fpc');
+
+  ls := Result.getList(s_bool_propList);
+    ls.append(True);
+    ls.append(True);
+    ls.append(False);
+    ls.append(True);
+    ls.append(False);
+
+  ls := Result.getList(s_byte_propList);
+    ls.append(TSDOByte(1));
+    ls.append(TSDOByte(12));
+    ls.append(TSDOByte(23));
+
+  ls := Result.getList(s_date_propList);
+    ls.append(VAL_1);
+    ls.append(VAL_2);
+    ls.append(VAL_3);
+    ls.append(VAL_4);  
+    
+  ls := Result.getList(s_integer_propList);
+    ls.append(12);
+    ls.append(10);
+    ls.append(76);
+    ls.append(-123);
+    ls.append(0);
+
+  ls := Result.getList(s_string_propList);
+    ls.append('object');
+    ls.append('');
+    ls.append('pascal');
+    ls.append('Lazarus');
+    ls.append('Delphi');
+end;
+
+procedure TSDOEqualityHelper_Test.equal_empty_object();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := fA.createNew(s_uri,s_type_object_A);
+  y := fA.createNew(s_uri,s_type_object_A);
+  CheckEquals(True,eh.equal(x,y));
+  CheckEquals(True,eh.equal(y,x));
+
+  x := fA.createNew(s_uri,s_type_object_A);
+  y := fB.createNew(s_uri,s_type_object_A);
+  CheckEquals(True,eh.equal(x,y));
+  CheckEquals(True,eh.equal(y,x));
+
+  x := fA.createNew(s_uri,s_type_object_B);
+  y := fA.createNew(s_uri,s_type_object_B);
+  CheckEquals(True,eh.equal(x,y));
+  CheckEquals(True,eh.equal(y,x));
+
+  x := fA.createNew(s_uri,s_type_object_B);
+  y := fB.createNew(s_uri,s_type_object_B);
+  CheckEquals(True,eh.equal(x,y));
+  CheckEquals(True,eh.equal(y,x));
+
+  x := fA.createNew(s_uri_2,s_type_object_C);
+  y := fB.createNew(s_uri_2,s_type_object_C);
+  CheckEquals(True,eh.equal(x,y));
+  CheckEquals(True,eh.equal(y,x));
+end;
+
+procedure TSDOEqualityHelper_Test.equalShallow_empty_object();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := fA.createNew(s_uri,s_type_object_A);
+  y := fA.createNew(s_uri,s_type_object_A);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x := fA.createNew(s_uri,s_type_object_A);
+  y := fB.createNew(s_uri,s_type_object_A);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x := fA.createNew(s_uri,s_type_object_B);
+  y := fA.createNew(s_uri,s_type_object_B);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x := fA.createNew(s_uri,s_type_object_B);
+  y := fB.createNew(s_uri,s_type_object_B);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x := fA.createNew(s_uri_2,s_type_object_C);
+  y := fB.createNew(s_uri_2,s_type_object_C);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+end;
+
+procedure TSDOEqualityHelper_Test.equalShallow_object();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri, fA);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri, fB);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+end;
+
+procedure TSDOEqualityHelper_Test.equalShallow_object_not_equal_type();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri_2, fA);
+  CheckEquals(False,eh.equalShallow(x,y));
+  CheckEquals(False,eh.equalShallow(y,x));
+
+  x := createObjA(s_uri, fA);
+  y := createObjC(s_uri_2, fA);
+  CheckEquals(False,eh.equalShallow(x,y));
+  CheckEquals(False,eh.equalShallow(y,x));
+
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri_2, fB);
+  CheckEquals(False,eh.equalShallow(x,y));
+  CheckEquals(False,eh.equalShallow(y,x));
+
+  x := createObjA(s_uri, fA);
+  y := createObjC(s_uri_2, fB);
+  CheckEquals(False,eh.equalShallow(x,y));
+  CheckEquals(False,eh.equalShallow(y,x));
+end;
+
+procedure TSDOEqualityHelper_Test.equalShallow_object_not_equal_value();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+  ls : ISDODataObjectList;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+// ObjectA
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri, fA);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+
+  x.setByte(s_byte_prop, 98);
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setByte(s_byte_prop, y.getByte(s_byte_prop));
+
+  x.setInteger(s_integer_prop, 98766);
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setInteger(s_integer_prop, y.getInteger(s_integer_prop));
+
+  x.setString(s_string_prop, 'mlkqsdf');
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setString(s_string_prop, y.getString(s_string_prop));
+
+// ObjectB
+  x := createObjB(s_uri, fA);
+  y := createObjB(s_uri, fA);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+
+  x.setByte(s_byte_prop, 98);
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setByte(s_byte_prop, y.getByte(s_byte_prop));
+
+  x.setInteger(s_integer_prop, 98766);
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setInteger(s_integer_prop, y.getInteger(s_integer_prop));
+
+  x.setString(s_string_prop, 'mlkqsdf');
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  x.setString(s_string_prop, y.getString(s_string_prop));
+
+  x.getDataObject(s_object_prop).setByte(s_byte_prop,51);
+    CheckEquals(True,eh.equalShallow(x,y),'<equalShallow> should not compare object properties.');
+    CheckEquals(True,eh.equalShallow(y,x),'<equalShallow> should not compare object properties.');
+  x.getDataObject(s_object_prop).setByte(s_byte_prop,y.getDataObject(s_object_prop).getInteger(s_byte_prop));
+
+  x.getDataObject(s_object_prop).setInteger(s_integer_prop,66666);
+    CheckEquals(True,eh.equalShallow(x,y),'<equalShallow> should not compare object properties.');
+    CheckEquals(True,eh.equalShallow(y,x),'<equalShallow> should not compare object properties.');
+  x.getDataObject(s_object_prop).setInteger(s_integer_prop,y.getDataObject(s_object_prop).getInteger(s_integer_prop));
+
+  ls := x.getList(s_integer_propList);
+  ls.getCursor().MoveLast();
+  ls.setInteger(-777);
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+end;
+
+procedure TSDOEqualityHelper_Test.equal_object();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri, fA);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri, fB);
+  CheckEquals(True,eh.equalShallow(x,y));
+  CheckEquals(True,eh.equalShallow(y,x));
+end;
+
+procedure TSDOEqualityHelper_Test.equal_object_not_equal_type();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri_2, fA);
+  CheckEquals(False,eh.equal(x,y));
+  CheckEquals(False,eh.equal(y,x));
+
+  x := createObjA(s_uri, fA);
+  y := createObjC(s_uri_2, fA);
+  CheckEquals(False,eh.equal(x,y));
+  CheckEquals(False,eh.equal(y,x));
+
+
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri_2, fB);
+  CheckEquals(False,eh.equal(x,y));
+  CheckEquals(False,eh.equal(y,x));
+
+  x := createObjA(s_uri, fA);
+  y := createObjC(s_uri_2, fB);
+  CheckEquals(False,eh.equal(x,y));
+  CheckEquals(False,eh.equal(y,x));
+end;
+
+procedure TSDOEqualityHelper_Test.equal_object_not_equal_value();
+var
+  fA, fB : ISDODataFactory;
+  x, y : ISDODataObject;
+  eh : TSDOEqualityHelperClass;
+  ls : ISDODataObjectList;
+  tmpInt : TSDOInteger;
+begin
+  fA := CreateFactory();
+  fB := CreateFactory();
+  eh := CreateEqualityHelper();
+
+// ObjectA
+  x := createObjA(s_uri, fA);
+  y := createObjA(s_uri, fA);
+  CheckEquals(True,eh.equal(x,y));
+  CheckEquals(True,eh.equal(y,x));
+
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+
+  x.setByte(s_byte_prop, 64);
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setByte(s_byte_prop, y.getByte(s_byte_prop));
+
+  x.setInteger(s_integer_prop, 98766);
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setInteger(s_integer_prop, y.getInteger(s_integer_prop));
+
+  x.setString(s_string_prop, 'mlkqsdf');
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setString(s_string_prop, y.getString(s_string_prop));
+
+// ObjectB
+  x := createObjB(s_uri, fA);
+  y := createObjB(s_uri, fA);
+  CheckEquals(True,eh.equal(x,y));
+  CheckEquals(True,eh.equal(y,x));
+
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setBoolean(s_bool_prop, not x.getBoolean(s_bool_prop));
+
+  x.setByte(s_byte_prop, 64);
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setByte(s_byte_prop, y.getByte(s_byte_prop));
+    
+  CheckEquals(True,eh.equal(x,y));
+  x.setInteger(s_integer_prop, 98766);
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setInteger(s_integer_prop, y.getInteger(s_integer_prop));
+
+  CheckEquals(True,eh.equal(x,y));
+  x.setString(s_string_prop, 'mlkqsdf');
+    CheckEquals(False,eh.equal(x,y));
+    CheckEquals(False,eh.equal(y,x));
+  x.setString(s_string_prop, y.getString(s_string_prop));
+
+  CheckEquals(True,eh.equal(x,y));
+  x.getDataObject(s_object_prop).setInteger(s_integer_prop,66666);
+    CheckEquals(False,eh.equal(x,y),'<equalShallow> should compare object properties.');
+    CheckEquals(False,eh.equal(y,x),'<equalShallow> should compare object properties.');
+  if y.getDataObject(s_object_prop).isSet(s_integer_prop) then
+    x.getDataObject(s_object_prop).setInteger(s_integer_prop,y.getDataObject(s_object_prop).getInteger(s_integer_prop))
+  else
+    x.getDataObject(s_object_prop).unset(s_integer_prop);
+
+  CheckEquals(True,eh.equal(x,y));
+  ls := x.getList(s_integer_propList);
+  ls.getCursor().MoveLast();
+  tmpInt := ls.getInteger();
+  ls.setInteger(-777);
+    CheckEquals(False,eh.equalShallow(x,y));
+    CheckEquals(False,eh.equalShallow(y,x));
+  ls.setInteger(tmpInt);
+end;
+
+procedure TSDOEqualityHelper_Test.equalShallow_cursorPos();
+var
+  fA : ISDODataFactory;
+  x, y : ISDODataObject;
+  lsB, lsI : ISDODataObjectList;
+  eh : TSDOEqualityHelperClass;
+  bmB, bmI : TLinkedListBookmark;
+begin
+  fA := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := createObjA(s_uri, fA);
+    lsB := x.getList(s_bool_propList);
+      lsB.getCursor().MoveFirst();
+      lsB.getCursor().MoveNext();
+      lsB.getCursor().MoveNext();
+    lsI := x.getList(s_integer_propList);
+      lsI.getCursor().MoveLast();
+      lsI.getCursor().MovePrevious();
+  y := createObjA(s_uri, fA);
+  bmB := lsB.getCursor().GetBookmark();
+  bmI := lsI.getCursor().GetBookmark();
+
+  eh.equalShallow(x,y);
+    CheckEquals(bmB,lsB.getCursor().GetBookmark());
+    CheckEquals(bmI,lsI.getCursor().GetBookmark());
+
+  eh.equalShallow(y,x);
+    CheckEquals(bmB,lsB.getCursor().GetBookmark());
+    CheckEquals(bmI,lsI.getCursor().GetBookmark());
+end;
+
+procedure TSDOEqualityHelper_Test.equal_cursorPos();
+var
+  fA : ISDODataFactory;
+  x, y : ISDODataObject;
+  lsB, lsI : ISDODataObjectList;
+  eh : TSDOEqualityHelperClass;
+  bmB, bmI : TLinkedListBookmark;
+begin
+  fA := CreateFactory();
+  eh := CreateEqualityHelper();
+
+  x := createObjA(s_uri, fA);
+    lsB := x.getList(s_bool_propList);
+      lsB.getCursor().MoveFirst();
+      lsB.getCursor().MoveNext();
+      lsB.getCursor().MoveNext();
+    lsI := x.getList(s_integer_propList);
+      lsI.getCursor().MoveLast();
+      lsI.getCursor().MovePrevious();
+  y := createObjA(s_uri, fA);
+  bmB := lsB.getCursor().GetBookmark();
+  bmI := lsI.getCursor().GetBookmark();
+
+  eh.equal(x,y);
+    CheckEquals(bmB,lsB.getCursor().GetBookmark());
+    CheckEquals(bmI,lsI.getCursor().GetBookmark());
+
+  eh.equal(y,x);
+    CheckEquals(bmB,lsB.getCursor().GetBookmark());
+    CheckEquals(bmI,lsI.getCursor().GetBookmark());
+end;
+
+initialization
+  RegisterTest('Helpers',TSDOEqualityHelper_Test.Suite);
+
+end.

+ 10272 - 0
packages/fcl-sdo/tests/test_suite/test_field_imp.pas

@@ -0,0 +1,10272 @@
+{$INCLUDE sdo_global.inc}
+unit test_field_imp;
+
+interface
+uses SysUtils, Classes
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  ,test_suite_utils, sdo_types, sdo, sdo_field_imp ;
+
+type
+
+  TSDOField_Test = class(TWstBaseTest)
+  protected
+    function Create_Field() : ISDOField;virtual;abstract;
+    class function GetTestSuitePath() : string;
+  published
+    procedure isSet();
+    procedure unset();virtual;
+    procedure isNull();
+    procedure setNull();virtual;
+  end;
+
+  TSDOBooleanField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getBoolean();
+    procedure setBoolean();
+    procedure getString();
+    procedure setString();
+    procedure getInteger();
+    procedure setInteger();
+    procedure getByte();
+    procedure setByte();
+    procedure getLong();
+    procedure setLong();
+    procedure getShort();
+    procedure setShort();
+    procedure getCharacter();
+    procedure setCharacter();
+  end;
+
+  TSDOIntegerField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getBoolean();
+    procedure setBoolean();
+    procedure getString();
+    procedure setString();
+    procedure getInteger();
+    procedure setInteger();
+    procedure getByte();
+    procedure setByte();
+    procedure getLong();
+    procedure setLong();
+    procedure getShort();
+    procedure setShort();
+    procedure getCharacter();
+    procedure setCharacter();
+  end;
+
+  TSDOStringField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+    class procedure CleanUpBuffer(var ABuffer : PPSDOString);
+  published
+    procedure getBoolean();
+    procedure setBoolean();
+    procedure getString();
+    procedure setString();
+    procedure getInteger();
+    procedure setInteger();
+    procedure getByte();
+    procedure setByte();
+    procedure getLong();
+    procedure setLong();
+    procedure getShort();
+    procedure setShort();
+    procedure getCharacter();
+    procedure setCharacter();
+
+    procedure unset();override;
+    procedure setNull();override;
+
+    procedure setString_unset_setStrin();
+  end;
+
+  TSDOBaseDataObject_Test = class(TSDOField_Test)
+  private
+    FFactory : ISDODataFactory;
+  protected
+    class function Create_Factory() : ISDODataFactory;
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getDataObject();
+    procedure setDataObject();
+    procedure unset();override;
+    procedure setNull();override;
+  end;
+
+  TSDOChangeSummaryField_Test = class(TSDOField_Test)
+  private
+    FFactory : ISDODataFactory;
+  protected
+    class function Create_Factory() : ISDODataFactory;
+    procedure SetUp(); override;
+    procedure TearDown(); override;
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getChangeSummary();
+    procedure setChangeSummary();
+    procedure unset();override;
+    procedure setNull();override;
+  end;
+
+  TSDOByteField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getBoolean();
+    procedure setBoolean();
+    procedure getString();
+    procedure setString();
+    procedure getInteger();
+    procedure setInteger();
+    procedure getByte();
+    procedure setByte();
+    procedure getCharacter();
+    procedure setCharacter();
+    procedure getLong();
+    procedure setLong();
+    procedure getShort();
+    procedure setShort();
+  end;
+
+  TSDODateField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  public
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+  published
+    procedure getDate();
+    procedure setDate();
+    procedure getString();
+    procedure setString();
+  end;
+
+{$IFDEF HAS_SDO_BYTES}
+  TSDOBytesField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+    class procedure CleanUpBuffer(var ABuffer : PPSDOBytes);
+  published
+    procedure getBytes();
+    procedure setBytes();
+    procedure getString();
+    procedure setString();
+  end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  TSDOCharField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getBoolean();
+    procedure setBoolean();
+    procedure getString();
+    procedure setString();
+    procedure getInteger();
+    procedure setInteger();
+    procedure getByte();
+    procedure setByte();
+    procedure getCharacter();
+    procedure setCharacter();
+    procedure getLong();
+    procedure setLong();
+    procedure getShort();
+    procedure setShort();
+  end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  TSDOCurrencyField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getCurrency();
+    procedure setCurrency();
+    procedure getDouble();
+    procedure setDouble();
+    procedure getFloat();
+    procedure setFloat();
+    procedure getString();
+    procedure setString();
+  end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+  TSDODoubleField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getCurrency();
+    procedure setCurrency();
+    procedure getDouble();
+    procedure setDouble();
+    procedure getFloat();
+    procedure setFloat();
+    procedure getString();
+    procedure setString();
+  end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  TSDOFloatField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getCurrency();
+    procedure setCurrency();
+    procedure getDouble();
+    procedure setDouble();
+    procedure getFloat();
+    procedure setFloat();
+    procedure getString();
+    procedure setString();
+  end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+  TSDOLongField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getBoolean();
+    procedure setBoolean();
+    procedure getString();
+    procedure setString();
+    procedure getInteger();
+    procedure setInteger();
+    procedure getByte();
+    procedure setByte();
+    procedure getCharacter();
+    procedure setCharacter();
+    procedure getLong();
+    procedure setLong();
+    procedure getShort();
+    procedure setShort();
+  end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  TSDOShortField_Test = class(TSDOField_Test)
+  protected
+    function Create_Field() : ISDOField;override;
+  published
+    procedure getBoolean();
+    procedure setBoolean();
+    procedure getString();
+    procedure setString();
+    procedure getInteger();
+    procedure setInteger();
+    procedure getByte();
+    procedure setByte();
+    procedure getCharacter();
+    procedure setCharacter();
+    procedure getLong();
+    procedure setLong();
+    procedure getShort();
+    procedure setShort();
+  end;
+{$ENDIF HAS_SDO_SHORT}
+
+implementation
+
+uses
+  sdo_imp_utils, sdo_datafactory, sdo_changesummary, sdo_date_utils, DateUtils,
+  sdo_convert_helper;
+
+const s_URI_1  = 'uri:1'; s_URI_3 = 'uri:3';
+      s_TYPE_1 = 'type1'; s_TYPE_2 = 'type2'; s_TYPE_3 = 'type3';
+      s_PROP_BOOL_1 = 'propboolean1';  s_PROP_INTEGER_1 = 'propinteger1';
+      s_PROP_BOOL_2 = 'propboolean2';  s_PROP_INTEGER_2 = 'propinteger2';
+      s_PROP_STR_1 = 'propStr1';  s_PROP_STR_2 = 'propStr2';
+      s_PROP_OBJ_CONT = 'propobj_cont'; s_PROP_OBJ_REF = 'propobj_ref';
+      s_PROP_BOOL_A = 'propbooleanA';  s_PROP_INTEGER_A = 'propintegerA';
+      s_PROP_STR_A = 'propStrA';
+      s_PROP_CHANGE_SUMMARY = 'propChangeSummary';
+
+{ TSDOBooleanField_Test }
+
+function TSDOBooleanField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOBooleanField.Create();
+end;
+
+procedure TSDOBooleanField_Test.getBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := 0;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    valBuffer^ := 1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+          CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+          CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+          CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+          CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := 0;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+          CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+          CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+          CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+          CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOBooleanField_Test.getByte();
+const F_OFFSET = 0;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getByte(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getByte(buffer,F_OFFSET));
+
+  valBuffer^ := 0;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET));
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getByte(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getByte(buffer,F_OFFSET));
+end;
+
+procedure TSDOBooleanField_Test.getCharacter();
+const F_OFFSET = 0;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getCharacter(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getCharacter(buffer,F_OFFSET));
+
+  valBuffer^ := 0;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('0',obj.getCharacter(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('0',obj.getCharacter(buffer,F_OFFSET));
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getCharacter(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getCharacter(buffer,F_OFFSET));
+end;
+
+procedure TSDOBooleanField_Test.getInteger();
+const F_OFFSET = 0;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getInteger(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getInteger(buffer,F_OFFSET));
+
+  valBuffer^ := 0;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET));
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getInteger(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getInteger(buffer,F_OFFSET));
+end;
+
+procedure TSDOBooleanField_Test.getLong();
+const F_OFFSET = 0;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getLong(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getLong(buffer,F_OFFSET));
+
+  valBuffer^ := 0;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET));
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getLong(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getLong(buffer,F_OFFSET));
+end;
+
+procedure TSDOBooleanField_Test.getShort();
+const F_OFFSET = 0;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getShort(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getShort(buffer,F_OFFSET));
+
+  valBuffer^ := 0;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET));
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getShort(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(1,obj.getShort(buffer,F_OFFSET));
+end;
+
+procedure TSDOBooleanField_Test.getString();
+const F_OFFSET = 0;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getString(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getString(buffer,F_OFFSET));
+
+  valBuffer^ := 0;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('0',obj.getString(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('0',obj.getString(buffer,F_OFFSET));
+
+  valBuffer^ := 1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getString(buffer,F_OFFSET));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals('1',obj.getString(buffer,F_OFFSET));
+end;
+
+procedure TSDOBooleanField_Test.setBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer: PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  obj.setBoolean(buffer,F_OFFSET_0,True);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setBoolean(buffer,F_OFFSET_0,False);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    obj.setBoolean(buffer,F_OFFSET_1,True);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setBoolean(buffer,F_OFFSET_1,False);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOBooleanField_Test.setByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  obj.setByte(buffer,F_OFFSET_0,1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,0);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    obj.setByte(buffer,F_OFFSET_1,123);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,0);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOBooleanField_Test.setCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  obj.setCharacter(buffer,F_OFFSET_0,'T');
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setCharacter(buffer,F_OFFSET_0,#0);
+  CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    obj.setCharacter(buffer,F_OFFSET_1,'T');
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+    obj.setCharacter(buffer,F_OFFSET_1,#0);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOBooleanField_Test.setInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  obj.setInteger(buffer,F_OFFSET_0,1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,0);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    obj.setInteger(buffer,F_OFFSET_1,300);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,0);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOBooleanField_Test.setLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  obj.setLong(buffer,F_OFFSET_0,1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,0);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    obj.setLong(buffer,F_OFFSET_1,123);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,0);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOBooleanField_Test.setShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  obj.setShort(buffer,F_OFFSET_0,1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,0);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    obj.setShort(buffer,F_OFFSET_1,123);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,0);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOBooleanField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer, attributeBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  attributeBuffer := buffer;
+  valBuffer := buffer;
+  Inc(valBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,'True');
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,'False');
+  CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(valBuffer);
+  Inc(attributeBuffer);
+    obj.setString(buffer,F_OFFSET_1,'True');
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,'False');
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+end;
+
+
+{ TSDOField_Test }
+
+class function TSDOField_Test.GetTestSuitePath: string;
+begin
+  Result := 'Field';
+end;
+
+procedure TSDOField_Test.isNull();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  obj := Create_Field();
+
+  valBuffer^ := 0;
+  SetBit(valBuffer^,BIT_ORDER_SET,True);
+  SetBit(valBuffer^,BIT_ORDER_NULL,True);
+  CheckEquals(True,obj.isSet(buffer,F_OFFSET_0));
+  CheckEquals(True,obj.isNull(buffer,F_OFFSET_0));
+
+  valBuffer^ := 0;
+  CheckEquals(False,obj.isSet(buffer,F_OFFSET_0));
+  CheckEquals(False,obj.isNull(buffer,F_OFFSET_0));
+
+  valBuffer^ := 0;
+  SetBit(valBuffer^,BIT_ORDER_SET,False);
+  SetBit(valBuffer^,BIT_ORDER_NULL,True);
+  CheckEquals(False,obj.isSet(buffer,F_OFFSET_0));
+  CheckEquals(True,obj.isNull(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(valBuffer);
+    valBuffer^ := 0;
+    SetBit(valBuffer^,BIT_ORDER_SET,True);
+    SetBit(valBuffer^,BIT_ORDER_NULL,True);
+    CheckEquals(True,obj.isSet(buffer,F_OFFSET_1));
+    CheckEquals(True,obj.isNull(buffer,F_OFFSET_1));
+
+    valBuffer^ := 0;
+    CheckEquals(False,obj.isSet(buffer,F_OFFSET_1));
+    CheckEquals(False,obj.isNull(buffer,F_OFFSET_1));
+
+    valBuffer^ := 0;
+    SetBit(valBuffer^,BIT_ORDER_SET,False);
+    SetBit(valBuffer^,BIT_ORDER_NULL,True);
+    CheckEquals(False,obj.isSet(buffer,F_OFFSET_1));
+    CheckEquals(True,obj.isNull(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOField_Test.isSet();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  obj := Create_Field();
+
+  SetBit(valBuffer^,BIT_ORDER_SET,True);// valBuffer^ := 2;
+  CheckEquals(True,obj.isSet(buffer,F_OFFSET_0));
+
+  valBuffer^ := 0;
+  CheckEquals(False,obj.isSet(buffer,F_OFFSET_0));
+
+
+  intVal := 0;
+  Inc(valBuffer);
+    SetBit(valBuffer^,BIT_ORDER_SET,True);
+    SetBit(valBuffer^,BIT_ORDER_SET + 1,True); //valBuffer^ := 6;
+    CheckEquals(True,obj.isSet(buffer,F_OFFSET_1));
+
+    valBuffer^ := 0;
+    CheckEquals(False,obj.isSet(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOField_Test.setNull();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  obj := Create_Field();
+
+  obj.setNull(buffer,F_OFFSET_0);
+  CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_SET));
+  CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_NULL));
+
+  SetBit(valBuffer^,BIT_ORDER_SET,True);
+  SetBit(valBuffer^,BIT_ORDER_SET,False);
+  obj.setNull(buffer,F_OFFSET_0);
+  CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_SET));
+  CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_NULL));
+
+  intVal := 0;
+  Inc(valBuffer);
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_NULL));
+
+    SetBit(valBuffer^,BIT_ORDER_SET,True);
+    SetBit(valBuffer^,BIT_ORDER_SET,False);
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_NULL));
+end;
+
+procedure TSDOField_Test.unset();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : DWord;
+  buffer, valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  valBuffer := buffer;
+  obj := Create_Field();
+
+  obj.unset(buffer,F_OFFSET_0);
+  CheckEquals(False,IsBitON(valBuffer^,BIT_ORDER_SET));
+
+  SetBit(valBuffer^,BIT_ORDER_SET,True);//valBuffer^ := 2;
+  obj.unset(buffer,F_OFFSET_0);
+  CheckEquals(False,IsBitON(valBuffer^,BIT_ORDER_SET));
+
+  SetBit(valBuffer^,BIT_ORDER_SET,True);//valBuffer^ := 6;
+  SetBit(valBuffer^,BIT_ORDER_SET + 1,True);
+  obj.unset(buffer,F_OFFSET_0);
+  CheckEquals(False,IsBitON(valBuffer^,BIT_ORDER_SET));
+  CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_SET + 1));
+
+  intVal := 0;
+  Inc(valBuffer);  
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(valBuffer^,BIT_ORDER_SET));
+
+    SetBit(valBuffer^,BIT_ORDER_SET,True);//valBuffer^ := 2;
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(valBuffer^,BIT_ORDER_SET));
+
+    SetBit(valBuffer^,BIT_ORDER_SET,True);//valBuffer^ := 6;
+    SetBit(valBuffer^,BIT_ORDER_SET + 1,True);//
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(valBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(valBuffer^,BIT_ORDER_SET + 1));
+end;
+
+{ TSDOIntegerField_Test }
+
+function TSDOIntegerField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOIntegerField.Create();
+end;
+
+procedure TSDOIntegerField_Test.getBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOIntegerField_Test.getByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOIntegerField_Test.getCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar('I')); VAL_2 = Ord(TSDOChar('W')); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOIntegerField_Test.getInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOIntegerField_Test.getLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -98765; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOIntegerField_Test.getShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -987; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOIntegerField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOIntegerField_Test.setBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setBoolean(buffer,F_OFFSET_0,True);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setBoolean(buffer,F_OFFSET_0,False);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+
+    obj.setBoolean(buffer,F_OFFSET_1,True);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setBoolean(buffer,F_OFFSET_1,False);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOIntegerField_Test.setByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOIntegerField_Test.setCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar('I')); VAL_2 = Ord(TSDOChar('W')); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+
+procedure TSDOIntegerField_Test.setInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOIntegerField_Test.setLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOIntegerField_Test.setShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOIntegerField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOInteger;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOInteger(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+
+{ TSDOStringField_Test }
+
+class procedure TSDOStringField_Test.CleanUpBuffer(var ABuffer : PPSDOString);
+begin
+  if ( ABuffer <> nil ) then begin
+    ABuffer^^ := '';
+    FreeMem(ABuffer^,SizeOf(PSDOString));
+    ABuffer^ := nil;
+  end;
+end;
+
+function TSDOStringField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOBaseStringField.Create();
+end;
+
+procedure TSDOStringField_Test.getBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = 'true'; VAL_3 = 'false'; VAL_4 = '1'; VAL_5 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+  ok : Boolean;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  ok := False;
+  try
+    obj.getBoolean(buffer,F_OFFSET_0);
+  except
+    on e : ESDOInvalidConversionException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Invalid conversion of empty string');
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+
+  GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+  try
+    valBuffer^^ := VAL_1;
+    ok := False;
+    try
+      obj.getBoolean(buffer,F_OFFSET_0);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid conversion : ' + VAL_1);
+
+
+    valBuffer^^ := VAL_2;
+    CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_3;
+    CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_4;
+    CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_5;
+    CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+    valBuffer^^ := '';
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOString));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    ok := False;
+    try
+      obj.getInteger(buffer,F_OFFSET_1);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid Conversion');
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    try
+      valBuffer^^ := VAL_1;
+      valBuffer^^ := VAL_1;
+      ok := False;
+      try
+        obj.getBoolean(buffer,F_OFFSET_1);
+      except
+        on e : ESDOInvalidConversionException do begin
+          ok := True;
+        end;
+      end;
+      CheckEquals(True,ok,'Invalid conversion : ' + VAL_1);
+
+
+      valBuffer^^ := VAL_2;
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_3;
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_4;
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_5;
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+
+      
+    finally
+      valBuffer^^ := '';
+      FreeMem(valBuffer^,SizeOf(PSDOString));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOStringField_Test.getByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = '12'; VAL_3 = '34'; VAL_4 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+  ok : Boolean;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  ok := False;
+  try
+    obj.getByte(buffer,F_OFFSET_0);
+  except
+    on e : ESDOInvalidConversionException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Invalid conversion');
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+
+  GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+  try
+    valBuffer^^ := VAL_1;
+    ok := False;
+    try
+      obj.getByte(buffer,F_OFFSET_0);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid conversion');
+
+
+    valBuffer^^ := VAL_2;
+    CheckEquals(StrToInt(VAL_2),obj.getByte(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_3;
+    CheckEquals(StrToInt(VAL_3),obj.getByte(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_4;
+    CheckEquals(StrToInt(VAL_4),obj.getByte(buffer,F_OFFSET_0));
+
+    valBuffer^^ := '';
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOString));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    ok := False;
+    try
+      obj.getByte(buffer,F_OFFSET_1);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid Conversion');
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    try
+      valBuffer^^ := VAL_1;
+      ok := False;
+      try
+        obj.getByte(buffer,F_OFFSET_1);
+      except
+        on e : ESDOInvalidConversionException do begin
+          ok := True;
+        end;
+      end;
+      CheckEquals(True,ok,'Invalid conversion');
+
+
+      valBuffer^^ := VAL_2;
+      CheckEquals(StrToInt(VAL_2),obj.getByte(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_3;
+      CheckEquals(StrToInt(VAL_3),obj.getByte(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_4;
+      CheckEquals(StrToInt(VAL_4),obj.getByte(buffer,F_OFFSET_1));
+
+      valBuffer^^ := '';
+    finally
+      FreeMem(valBuffer^,SizeOf(PSDOString));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOStringField_Test.getCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'K'; VAL_2 = 'w'; VAL_3 = #0;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+  ok : Boolean;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  ok := False;
+  try
+    obj.getCharacter(buffer,F_OFFSET_0);
+  except
+    on e : ESDOInvalidConversionException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Invalid conversion');
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+
+  GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+  try
+    valBuffer^^ := VAL_1;
+    CheckEquals(VAL_1,obj.getCharacter(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_2;
+    CheckEquals(VAL_2,obj.getCharacter(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_3;
+    CheckEquals(VAL_3,obj.getCharacter(buffer,F_OFFSET_0));
+
+    valBuffer^^ := '';
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOString));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    ok := False;
+    try
+      obj.getCharacter(buffer,F_OFFSET_1);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid Conversion');
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    try
+      valBuffer^^ := VAL_1;
+      CheckEquals(VAL_1,obj.getCharacter(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_2;
+      CheckEquals(VAL_2,obj.getCharacter(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_3;
+      CheckEquals(VAL_3,obj.getCharacter(buffer,F_OFFSET_1));
+
+      valBuffer^^ := '';
+    finally
+      FreeMem(valBuffer^,SizeOf(PSDOString));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOStringField_Test.getInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = '-9876'; VAL_3 = '567'; VAL_4 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+  ok : Boolean;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  ok := False;
+  try
+    obj.getInteger(buffer,F_OFFSET_0);
+  except
+    on e : ESDOInvalidConversionException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Invalid conversion');
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+
+  GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+  try
+    valBuffer^^ := VAL_1;
+    ok := False;
+    try
+      obj.getInteger(buffer,F_OFFSET_0);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid conversion');
+
+
+    valBuffer^^ := VAL_2;
+    CheckEquals(StrToInt(VAL_2),obj.getInteger(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_3;
+    CheckEquals(StrToInt(VAL_3),obj.getInteger(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_4;
+    CheckEquals(StrToInt(VAL_4),obj.getInteger(buffer,F_OFFSET_0));
+
+    valBuffer^^ := '';
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOString));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    ok := False;
+    try
+      obj.getInteger(buffer,F_OFFSET_1);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid Conversion');
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    try
+      valBuffer^^ := VAL_1;
+      ok := False;
+      try
+        obj.getInteger(buffer,F_OFFSET_1);
+      except
+        on e : ESDOInvalidConversionException do begin
+          ok := True;
+        end;
+      end;
+      CheckEquals(True,ok,'Invalid conversion');
+
+
+      valBuffer^^ := VAL_2;
+      CheckEquals(StrToInt(VAL_2),obj.getInteger(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_3;
+      CheckEquals(StrToInt(VAL_3),obj.getInteger(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_4;
+      CheckEquals(StrToInt(VAL_4),obj.getInteger(buffer,F_OFFSET_1));
+
+      valBuffer^^ := '';
+    finally
+      FreeMem(valBuffer^,SizeOf(PSDOString));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOStringField_Test.getLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = '123456852'; VAL_3 = '-3489962255'; VAL_4 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+  ok : Boolean;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  ok := False;
+  try
+    obj.getLong(buffer,F_OFFSET_0);
+  except
+    on e : ESDOInvalidConversionException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Invalid conversion');
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+
+  GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+  try
+    valBuffer^^ := VAL_1;
+    ok := False;
+    try
+      obj.getLong(buffer,F_OFFSET_0);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid conversion');
+
+
+    valBuffer^^ := VAL_2;
+    CheckEquals(StrToInt64(VAL_2),obj.getLong(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_3;
+    CheckEquals(StrToInt64(VAL_3),obj.getLong(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_4;
+    CheckEquals(StrToInt64(VAL_4),obj.getLong(buffer,F_OFFSET_0));
+
+    valBuffer^^ := '';
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOString));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    ok := False;
+    try
+      obj.getLong(buffer,F_OFFSET_1);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid Conversion');
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    try
+      valBuffer^^ := VAL_1;
+      ok := False;
+      try
+        obj.getLong(buffer,F_OFFSET_1);
+      except
+        on e : ESDOInvalidConversionException do begin
+          ok := True;
+        end;
+      end;
+      CheckEquals(True,ok,'Invalid conversion');
+
+
+      valBuffer^^ := VAL_2;
+      CheckEquals(StrToInt64(VAL_2),obj.getLong(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_3;
+      CheckEquals(StrToInt64(VAL_3),obj.getLong(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_4;
+      CheckEquals(StrToInt64(VAL_4),obj.getLong(buffer,F_OFFSET_1));
+
+      valBuffer^^ := '';
+    finally
+      FreeMem(valBuffer^,SizeOf(PSDOString));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOStringField_Test.getShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = '5678'; VAL_3 = '-3489'; VAL_4 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+  ok : Boolean;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  ok := False;
+  try
+    obj.getShort(buffer,F_OFFSET_0);
+  except
+    on e : ESDOInvalidConversionException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Invalid conversion');
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+
+  GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+  try
+    valBuffer^^ := VAL_1;
+    ok := False;
+    try
+      obj.getShort(buffer,F_OFFSET_0);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid conversion');
+
+
+    valBuffer^^ := VAL_2;
+    CheckEquals(StrToInt(VAL_2),obj.getShort(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_3;
+    CheckEquals(StrToInt(VAL_3),obj.getShort(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_4;
+    CheckEquals(StrToInt(VAL_4),obj.getShort(buffer,F_OFFSET_0));
+
+    valBuffer^^ := '';
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOString));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    ok := False;
+    try
+      obj.getShort(buffer,F_OFFSET_1);
+    except
+      on e : ESDOInvalidConversionException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Invalid Conversion');
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    try
+      valBuffer^^ := VAL_1;
+      ok := False;
+      try
+        obj.getShort(buffer,F_OFFSET_1);
+      except
+        on e : ESDOInvalidConversionException do begin
+          ok := True;
+        end;
+      end;
+      CheckEquals(True,ok,'Invalid conversion');
+
+
+      valBuffer^^ := VAL_2;
+      CheckEquals(StrToInt(VAL_2),obj.getShort(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_3;
+      CheckEquals(StrToInt(VAL_3),obj.getShort(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_4;
+      CheckEquals(StrToInt(VAL_4),obj.getShort(buffer,F_OFFSET_1));
+
+      valBuffer^^ := '';
+    finally
+      FreeMem(valBuffer^,SizeOf(PSDOString));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOStringField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = 'xyz-9876'; VAL_3 = '';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+
+  GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+  try
+    valBuffer^^ := VAL_1;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_2;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+
+    valBuffer^^ := VAL_3;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+
+    valBuffer^^ := '';
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOString));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+    CheckEquals('',obj.getString(buffer,F_OFFSET_0));
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    try
+      valBuffer^^ := VAL_1;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_2;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+
+      valBuffer^^ := VAL_3;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals('',obj.getString(buffer,F_OFFSET_1));
+
+      valBuffer^^ := '';
+    finally
+      FreeMem(valBuffer^,SizeOf(PSDOString));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOStringField_Test.setBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setBoolean(buffer,F_OFFSET_0,True);
+  CheckEquals('1',valBuffer^^);
+
+  obj.setBoolean(buffer,F_OFFSET_0,False);
+  CheckEquals('0',valBuffer^^);
+  // Clean up to avoid false MEM-LEAK
+    CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    obj.setBoolean(buffer,F_OFFSET_1,True);
+    CheckEquals('1',valBuffer^^);
+
+    obj.setBoolean(buffer,F_OFFSET_1,False);
+    CheckEquals('0',valBuffer^^);
+
+    // Clean up to avoid false MEM-LEAK
+    CleanUpBuffer(valBuffer);
+end;
+
+procedure TSDOStringField_Test.setByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = '123'; VAL_2 = '45'; VAL_3 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setByte(buffer,F_OFFSET_0,StrToInt(VAL_1));
+  CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setByte(buffer,F_OFFSET_0,StrToInt(VAL_2));
+  CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setByte(buffer,F_OFFSET_0,StrToInt(VAL_3));
+  CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    obj.setByte(buffer,F_OFFSET_1,StrToInt(VAL_1));
+    CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setByte(buffer,F_OFFSET_1,StrToInt(VAL_2));
+    CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setByte(buffer,F_OFFSET_1,StrToInt(VAL_3));
+    CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+end;
+
+procedure TSDOStringField_Test.setCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'K'; VAL_2 = 'W'; VAL_3 = #0;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setCharacter(buffer,F_OFFSET_0,VAL_1);
+  CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setCharacter(buffer,F_OFFSET_0,VAL_2);
+  CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setCharacter(buffer,F_OFFSET_0,VAL_3);
+  CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    obj.setCharacter(buffer,F_OFFSET_1,VAL_1);
+    CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setCharacter(buffer,F_OFFSET_1,VAL_2);
+    CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setCharacter(buffer,F_OFFSET_1,VAL_3);
+    CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+end;
+
+procedure TSDOStringField_Test.setInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = '12345'; VAL_2 = '-3476'; VAL_3 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setInteger(buffer,F_OFFSET_0,StrToInt(VAL_1));
+  CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setInteger(buffer,F_OFFSET_0,StrToInt(VAL_2));
+  CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setInteger(buffer,F_OFFSET_0,StrToInt(VAL_3));
+  CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    obj.setInteger(buffer,F_OFFSET_1,StrToInt(VAL_1));
+    CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setInteger(buffer,F_OFFSET_1,StrToInt(VAL_2));
+    CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setInteger(buffer,F_OFFSET_1,StrToInt(VAL_3));
+    CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+end;
+
+procedure TSDOStringField_Test.setLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = '123456852'; VAL_2 = '3489962255'; VAL_3 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setLong(buffer,F_OFFSET_0,StrToInt64(VAL_1));
+  CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setLong(buffer,F_OFFSET_0,StrToInt64(VAL_2));
+  CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setLong(buffer,F_OFFSET_0,StrToInt64(VAL_3));
+  CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    obj.setLong(buffer,F_OFFSET_1,StrToInt64(VAL_1));
+    CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setLong(buffer,F_OFFSET_1,StrToInt64(VAL_2));
+    CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setLong(buffer,F_OFFSET_1,StrToInt64(VAL_3));
+    CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+end;
+
+procedure TSDOStringField_Test.setNull();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = 'xyz-9876'; VAL_3 = '';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  SetBit(startBuffer^,BIT_ORDER_SET,False);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_1;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_2;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL)); 
+    Check(valBuffer^ = nil);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_SET,False);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_1;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_2;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+end;
+
+procedure TSDOStringField_Test.setShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = '6852'; VAL_2 = '-255'; VAL_3 = '0';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setShort(buffer,F_OFFSET_0,StrToInt(VAL_1));
+  CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setShort(buffer,F_OFFSET_0,StrToInt(VAL_2));
+  CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+
+  obj.setShort(buffer,F_OFFSET_0,StrToInt(VAL_3));
+  CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    obj.setShort(buffer,F_OFFSET_1,StrToInt(VAL_1));
+    CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setShort(buffer,F_OFFSET_1,StrToInt(VAL_2));
+    CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+
+    obj.setShort(buffer,F_OFFSET_1,StrToInt(VAL_3));
+    CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+end;
+
+procedure TSDOStringField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = 'xyz-9876'; VAL_3 = '';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,'');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  obj.setString(buffer,F_OFFSET_0,VAL_1);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'string buffer' );
+  CheckEquals(VAL_1,valBuffer^^);
+
+  obj.setString(buffer,F_OFFSET_0,VAL_2);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'string buffer' );
+  CheckEquals(VAL_2,valBuffer^^);
+
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  obj.setString(buffer,F_OFFSET_0,VAL_3);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'string buffer' );
+  CheckEquals(VAL_3,valBuffer^^);
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    obj.setString(buffer,F_OFFSET_1,'');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+
+    obj.setString(buffer,F_OFFSET_1,VAL_1);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'string buffer' );
+    CheckEquals(VAL_1,valBuffer^^);
+
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    obj.setString(buffer,F_OFFSET_1,VAL_2);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'string buffer' );
+    CheckEquals(VAL_2,valBuffer^^);
+
+    obj.setString(buffer,F_OFFSET_1,VAL_3);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'string buffer' );
+    CheckEquals(VAL_3,valBuffer^^);
+    // Clean up to avoid false MEM-LEAK
+    CleanUpBuffer(valBuffer);
+
+end;
+
+procedure TSDOStringField_Test.setString_unset_setStrin;
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = 'xyz-9876'; VAL_3 = '';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,'');
+    obj.unset(buffer,F_OFFSET_0);
+      obj.setString(buffer,F_OFFSET_0,'');
+        CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+        CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+        CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+  valBuffer^^ := ''; FreeMem(valBuffer^,SizeOf(PSDOString));
+end;
+
+procedure TSDOStringField_Test.unset();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 'azerty12345'; VAL_2 = 'xyz-9876'; VAL_3 = '';
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOString;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+  obj := Create_Field();
+
+
+  SetBit(startBuffer^,BIT_ORDER_SET,False);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_1;
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(
+        True(*this is necessary for default value management*),
+        IsBitON(startBuffer^,BIT_ORDER_BUFFER),
+        'BIT_ORDER_SET, this is necessary for default value management'
+      );
+      CheckNotEquals(PtrUInt(nil), PtrUInt(valBuffer^), 'The buffer must remains, this is necessary for default value management');
+      CheckEquals(VAL_1, valBuffer^^);
+      valBuffer^^ := ''; FreeMem(valBuffer^,SizeOf(PSDOString));
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);//startBuffer^ := 2;
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_2;
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_BUFFER),'BIT_ORDER_SET, this is necessary for default value management');
+      CheckNotEquals(PtrUInt(nil), PtrUInt(valBuffer^), 'The buffer must remains, this is necessary for default value management');
+      CheckEquals(VAL_2, valBuffer^^);
+      valBuffer^^ := ''; FreeMem(valBuffer^,SizeOf(PSDOString));
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);//startBuffer^ := 2;
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_3;
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_BUFFER),'BIT_ORDER_SET, this is necessary for default value management');
+      CheckNotEquals(PtrUInt(nil), PtrUInt(valBuffer^), 'The buffer must remains, this is necessary for default value management');
+      CheckEquals(VAL_3, valBuffer^^);
+      valBuffer^^ := ''; FreeMem(valBuffer^,SizeOf(PSDOString));
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOString(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_SET,False);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_1;
+    obj.unset(buffer,F_OFFSET_1);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_BUFFER),'BIT_ORDER_SET, this is necessary for default value management');
+      CheckNotEquals(PtrUInt(nil), PtrUInt(valBuffer^), 'The buffer must remains, this is necessary for default value management');
+      CheckEquals(VAL_1, valBuffer^^);
+      valBuffer^^ := ''; FreeMem(valBuffer^,SizeOf(PSDOString));
+
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);//startBuffer^ := 2;
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_2;
+    obj.unset(buffer,F_OFFSET_1);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_BUFFER),'BIT_ORDER_SET, this is necessary for default value management');
+      CheckNotEquals(PtrUInt(nil), PtrUInt(valBuffer^), 'The buffer must remains, this is necessary for default value management');
+      CheckEquals(VAL_2, valBuffer^^);
+      valBuffer^^ := ''; FreeMem(valBuffer^,SizeOf(PSDOString));
+
+    GetMem(valBuffer^,SizeOf(PSDOString)); FillChar(valBuffer^^,SizeOf(TSDOString),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := VAL_3;
+    obj.unset(buffer,F_OFFSET_1);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_BUFFER),'BIT_ORDER_SET, this is necessary for default value management');
+      CheckNotEquals(PtrUInt(nil), PtrUInt(valBuffer^), 'The buffer must remains, this is necessary for default value management');
+      CheckEquals(VAL_3, valBuffer^^);
+      valBuffer^^ := ''; FreeMem(valBuffer^,SizeOf(PSDOString));
+
+end;
+
+{ TSDOBaseDataObject_Test }
+
+class function TSDOBaseDataObject_Test.Create_Factory() : ISDODataFactory;
+var
+  typ, typ2 : ISDOType;
+begin
+  Result := TSDODataFactory.Create();
+  Result.AddType(s_URI_1,s_TYPE_1,[]);
+  Result.AddType(s_URI_1,s_TYPE_2,[]);
+  Result.AddType(s_URI_3,s_TYPE_3,[]);
+  typ := Result.getType(s_URI_1,s_TYPE_1);
+    Result.addProperty(typ,s_PROP_BOOL_1,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ,s_PROP_INTEGER_1,sdo_namespace,'Integer',[]);
+    Result.addProperty(typ,s_PROP_STR_1,sdo_namespace,'String',[]);
+
+    Result.addProperty(typ,s_PROP_BOOL_2,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ,s_PROP_INTEGER_2,sdo_namespace,'Integer',[]);
+    Result.addProperty(typ,s_PROP_STR_2,sdo_namespace,'String',[]);
+    Result.addProperty(typ,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[]);
+    Result.addProperty(typ,s_PROP_OBJ_REF,s_URI_1,s_TYPE_2,[]);
+
+  typ2 := Result.getType(s_URI_1,s_TYPE_2);
+    Result.addProperty(typ2,s_PROP_BOOL_A,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ2,s_PROP_INTEGER_A,sdo_namespace,'Integer',[]);
+    Result.addProperty(typ2,s_PROP_STR_A,sdo_namespace,'String',[]);
+    Result.addProperty(typ2,s_PROP_OBJ_CONT,s_URI_3,s_TYPE_3,[]);
+end;
+
+function TSDOBaseDataObject_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOObjectField.Create() as ISDOField;
+end;
+
+procedure TSDOBaseDataObject_Test.getDataObject();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDODataObject;
+  val_1, val_2, val_3 : ISDODataObject;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+  obj := Create_Field();
+  val_1 := FFactory.createNew(s_URI_1,s_TYPE_1) as ISDODataObject;
+  val_2 := FFactory.createNew(s_URI_1,s_TYPE_2) as ISDODataObject;
+  val_3 := nil;
+
+  Check(nil = obj.getDataObject(buffer,F_OFFSET_0));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+
+  GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+  try
+    valBuffer^^ := val_1;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(VAL_1),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(VAL_1),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+
+    valBuffer^^ := val_2;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_2),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_2),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+
+    valBuffer^^ := val_3;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_3),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_3),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_0)));
+
+    valBuffer^^ := nil;
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDODataObject));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+    Check(nil = obj.getDataObject(buffer,F_OFFSET_0));
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    try
+      SetBit(startBuffer^,BIT_ORDER_SET,True);
+      valBuffer^^ := val_1;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_1),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_1),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+
+      valBuffer^^ := val_2;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_2),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_2),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+
+      valBuffer^^ := val_3;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_3),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_3),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getDataObject(buffer,F_OFFSET_1)));
+    finally
+      FreeMem(valBuffer^,SizeOf(PSDODataObject));
+      valBuffer^ := nil;
+    end;
+end;
+
+procedure TSDOBaseDataObject_Test.setDataObject();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDODataObject;
+  val_1, val_2, val_3 : ISDODataObject;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+  obj := Create_Field();
+  val_1 := FFactory.createNew(s_URI_1,s_TYPE_1) as ISDODataObject;
+  val_2 := FFactory.createNew(s_URI_1,s_TYPE_2) as ISDODataObject;
+  val_3 := nil;
+
+  obj.setDataObject(buffer,F_OFFSET_0,nil);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+
+  obj.setDataObject(buffer,F_OFFSET_0,val_1);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+  Check(val_1  = valBuffer^^);
+
+  obj.setDataObject(buffer,F_OFFSET_0,val_2);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+  Check(val_2 = valBuffer^^);
+
+  obj.setDataObject(buffer,F_OFFSET_0,val_3);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+  Check(val_3 = valBuffer^^);
+
+  valBuffer^^ := nil;
+  FreeMem(valBuffer^,SizeOf(PSDODataObject));
+  valBuffer^ := nil;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+
+    obj.setDataObject(buffer,F_OFFSET_1,nil);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+
+    obj.setDataObject(buffer,F_OFFSET_1,val_1);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+    Check(val_1 = valBuffer^^);
+
+    obj.setDataObject(buffer,F_OFFSET_1,val_2);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+    Check(val_2 = valBuffer^^);
+
+    obj.setDataObject(buffer,F_OFFSET_1,val_3);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+    Check(val_3 = valBuffer^^);
+
+  valBuffer^^ := nil;
+  FreeMem(valBuffer^,SizeOf(PSDODataObject));
+  valBuffer^ := nil;    
+end;
+
+procedure TSDOBaseDataObject_Test.setNull();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDODataObject;
+  val_1, val_2, val_3 : ISDODataObject;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+  obj := Create_Field();
+  val_1 := FFactory.createNew(s_URI_1,s_TYPE_1) as ISDODataObject;
+  val_2 := FFactory.createNew(s_URI_1,s_TYPE_2) as ISDODataObject;
+  val_3 := nil;
+
+
+  SetBit(startBuffer^,BIT_ORDER_SET,False);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_SET,False);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+end;
+
+procedure TSDOBaseDataObject_Test.SetUp();
+begin
+  inherited;
+  FFactory := Create_Factory();
+end;
+
+procedure TSDOBaseDataObject_Test.TearDown;
+begin
+  FFactory := nil;
+  inherited;
+end;
+
+procedure TSDOBaseDataObject_Test.unset();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDODataObject;
+  val_1, val_2, val_3 : ISDODataObject;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+  obj := Create_Field();
+  val_1 := FFactory.createNew(s_URI_1,s_TYPE_1) as ISDODataObject;
+  val_2 := FFactory.createNew(s_URI_1,s_TYPE_2) as ISDODataObject;
+  val_3 := nil;
+
+  SetBit(startBuffer^,BIT_ORDER_SET,False);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.unset(buffer,F_OFFSET_0);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.unset(buffer,F_OFFSET_0);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.unset(buffer,F_OFFSET_0);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDODataObject(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_SET,False);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+  
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDODataObject)); FillChar(valBuffer^^,SizeOf(ISDODataObject),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+end;
+
+{ TSDOChangeSummaryField_Test }
+
+class function TSDOChangeSummaryField_Test.Create_Factory: ISDODataFactory;
+var
+  typ, typ2 : ISDOType;
+begin
+  Result := TSDODataFactory.Create();
+  Result.AddType(s_URI_1,s_TYPE_1,[]);
+  Result.AddType(s_URI_1,s_TYPE_2,[]);
+  Result.AddType(s_URI_3,s_TYPE_3,[]);
+  typ := Result.getType(s_URI_1,s_TYPE_1);
+    Result.addProperty(typ,s_PROP_BOOL_1,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ,s_PROP_INTEGER_1,sdo_namespace,'Integer',[]);
+    Result.addProperty(typ,s_PROP_STR_1,sdo_namespace,'String',[]);
+    Result.addProperty(typ,s_PROP_CHANGE_SUMMARY,sdo_namespace,'ChangeSummary',[pfIsReadOnly]);
+
+    Result.addProperty(typ,s_PROP_BOOL_2,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ,s_PROP_INTEGER_2,sdo_namespace,'Integer',[]);
+    Result.addProperty(typ,s_PROP_STR_2,sdo_namespace,'String',[]);
+    Result.addProperty(typ,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_2,[]);
+    Result.addProperty(typ,s_PROP_OBJ_REF,s_URI_1,s_TYPE_2,[]);
+
+  typ2 := Result.getType(s_URI_1,s_TYPE_2);
+    Result.addProperty(typ2,s_PROP_BOOL_A,sdo_namespace,'Boolean',[]);
+    Result.addProperty(typ2,s_PROP_INTEGER_A,sdo_namespace,'Integer',[]);
+    Result.addProperty(typ2,s_PROP_STR_A,sdo_namespace,'String',[]);
+    Result.addProperty(typ2,s_PROP_OBJ_CONT,s_URI_1,s_TYPE_1,[]);
+end;
+
+function TSDOChangeSummaryField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOChangeSummaryField.Create();
+end;
+
+procedure TSDOChangeSummaryField_Test.getChangeSummary();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOChangeSummary;
+  val_1, val_2, val_3 : ISDOChangeSummary;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+  obj := Create_Field();
+  val_1 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create());;
+  val_2 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create());;
+  val_3 := nil;
+
+  Check(nil = obj.getChangeSummary(buffer,F_OFFSET_0));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+
+  GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+  try
+    valBuffer^^ := val_1;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(VAL_1),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(VAL_1),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+
+    valBuffer^^ := val_2;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_2),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_2),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+
+    valBuffer^^ := val_3;
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_3),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(val_3),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+      SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+        SetBit(startBuffer^,BIT_ORDER_SET,True);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+        SetBit(startBuffer^,BIT_ORDER_SET,False);
+          SetBit(startBuffer^,BIT_ORDER_NULL,True);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+          SetBit(startBuffer^,BIT_ORDER_NULL,False);
+            CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_0)));
+
+    valBuffer^^ := nil;
+
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOChangeSummary));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+    Check(nil = obj.getChangeSummary(buffer,F_OFFSET_0));
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    try
+      SetBit(startBuffer^,BIT_ORDER_SET,True);
+      valBuffer^^ := val_1;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_1),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_1),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+
+      valBuffer^^ := val_2;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_2),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_2),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+
+      valBuffer^^ := val_3;
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_3),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(val_3),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+        SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+          SetBit(startBuffer^,BIT_ORDER_SET,True);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+          SetBit(startBuffer^,BIT_ORDER_SET,False);
+            SetBit(startBuffer^,BIT_ORDER_NULL,True);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+            SetBit(startBuffer^,BIT_ORDER_NULL,False);
+              CheckEquals(PtrInt(nil),PtrInt(obj.getChangeSummary(buffer,F_OFFSET_1)));
+    finally
+      valBuffer^^ := nil;
+      FreeMem(valBuffer^,SizeOf(PSDOChangeSummary));
+      valBuffer^ := nil;
+    end;  
+end;
+
+procedure TSDOChangeSummaryField_Test.setChangeSummary();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOChangeSummary;
+  val_1, val_2, val_3 : ISDOChangeSummary;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+  obj := Create_Field();
+  val_1 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create()) as ISDOChangeSummary;
+  val_2 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create()) as ISDOChangeSummary;
+  val_3 := nil;
+
+  obj.setChangeSummary(buffer,F_OFFSET_0,nil);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+
+  obj.setChangeSummary(buffer,F_OFFSET_0,val_1);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+  Check(val_1  = valBuffer^^);
+
+  obj.setChangeSummary(buffer,F_OFFSET_0,val_2);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+  Check(val_2 = valBuffer^^);
+
+  obj.setChangeSummary(buffer,F_OFFSET_0,val_3);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+  Check(val_3 = valBuffer^^);
+
+  valBuffer^^ := nil;
+  FreeMem(valBuffer^,SizeOf(PSDOChangeSummary));
+  valBuffer^ := nil;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+
+    obj.setChangeSummary(buffer,F_OFFSET_1,nil);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+
+    obj.setChangeSummary(buffer,F_OFFSET_1,val_1);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+    Check(val_1 = valBuffer^^);
+
+    obj.setChangeSummary(buffer,F_OFFSET_1,val_2);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+    Check(val_2 = valBuffer^^);
+
+    obj.setChangeSummary(buffer,F_OFFSET_1,val_3);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'object buffer' );
+    Check(val_3 = valBuffer^^);
+
+  valBuffer^^ := nil;
+  FreeMem(valBuffer^,SizeOf(PSDOChangeSummary));
+  valBuffer^ := nil;    
+
+end;
+
+procedure TSDOChangeSummaryField_Test.setNull();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOChangeSummary;
+  val_1, val_2, val_3 : ISDOChangeSummary;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+  obj := Create_Field();
+  val_1 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create()) as ISDOChangeSummary;
+  val_2 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create()) as ISDOChangeSummary;
+  val_3 := nil;
+
+
+  SetBit(startBuffer^,BIT_ORDER_SET,False);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.setNull(buffer,F_OFFSET_0);
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.setNull(buffer,F_OFFSET_0);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_SET,False);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.setNull(buffer,F_OFFSET_1);
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.setNull(buffer,F_OFFSET_1);
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(True,IsBitON(startBuffer^,BIT_ORDER_NULL));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+end;
+
+procedure TSDOChangeSummaryField_Test.SetUp;
+begin
+  inherited;
+  FFactory := Create_Factory();
+end;
+
+procedure TSDOChangeSummaryField_Test.TearDown;
+begin
+  FFactory := nil;
+  inherited;
+end;
+
+procedure TSDOChangeSummaryField_Test.unset();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  trueBuffer : array[0..200] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOChangeSummary;
+  val_1, val_2, val_3 : ISDOChangeSummary;
+begin
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+  obj := Create_Field();
+  val_1 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create()) as ISDOChangeSummary;
+  val_2 := TSDOChangeSummary.Create(TSDOChangedDataObjectList.Create()) as ISDOChangeSummary;
+  val_3 := nil;
+
+  SetBit(startBuffer^,BIT_ORDER_SET,False);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,False);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+  SetBit(startBuffer^,BIT_ORDER_SET,True);
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+    obj.unset(buffer,F_OFFSET_0);
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.unset(buffer,F_OFFSET_0);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.unset(buffer,F_OFFSET_0);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.unset(buffer,F_OFFSET_0);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOChangeSummary(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_SET,False);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,False);
+      obj.unset(buffer,F_OFFSET_1);
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+        CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_1;
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_2;
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+    GetMem(valBuffer^,SizeOf(PSDOChangeSummary)); FillChar(valBuffer^^,SizeOf(ISDOChangeSummary),#0);
+    SetBit(startBuffer^,BIT_ORDER_SET,True);
+    SetBit(startBuffer^,BIT_ORDER_NULL,False);
+    SetBit(startBuffer^,BIT_ORDER_BUFFER,True);
+    valBuffer^^ := val_3;
+    obj.unset(buffer,F_OFFSET_1);
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(startBuffer^,BIT_ORDER_BUFFER));
+    Check(valBuffer^ = nil);
+
+end;
+
+{ TSDOByteField_Test }
+
+function TSDOByteField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOByteField.Create();
+end;
+
+procedure TSDOByteField_Test.getBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOByteField_Test.getByte;
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOByteField_Test.getCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar(125)); VAL_2 = Ord(TSDOChar(45)); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOByteField_Test.getInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOByteField_Test.getLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOByteField_Test.getShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 55; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOByteField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOByteField_Test.setBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setBoolean(buffer,F_OFFSET_0,True);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setBoolean(buffer,F_OFFSET_0,False);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+
+    obj.setBoolean(buffer,F_OFFSET_1,True);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setBoolean(buffer,F_OFFSET_1,False);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOByteField_Test.setByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOByteField_Test.setCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar(125)); VAL_2 = Ord(TSDOChar(45)); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+
+procedure TSDOByteField_Test.setInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOByteField_Test.setLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 35; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOByteField_Test.setShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 35; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOByteField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = 45; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PByte;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PByte(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PByte(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+
+{ TSDODateField_Test }
+
+procedure TSDODateField_Test.CheckEquals(expected, actual: TSDODate; msg: string; const AStrict : Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+function TSDODateField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDODateField.Create() as ISDOField;
+end;
+
+procedure TSDODateField_Test.getDate();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_3)^ := d;
+  end;
+
+var
+  obj : ISDOField;
+  trueBuffer : array[0..( 3 * SizeOf(TSDODate))] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODate;
+begin
+  SetConstants();
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getDate(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getDate(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getDate(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getDate(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getDate(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getDate(buffer,F_OFFSET_0));
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getDate(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getDate(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getDate(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getDate(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getDate(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_DATE,obj.getDate(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getDate(buffer,F_OFFSET_1));
+end;
+
+procedure TSDODateField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_3)^ := d;
+  end;
+
+var
+  obj : ISDOField;
+  trueBuffer : array[0..( 3 * SizeOf(TSDODate))] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODate;
+begin
+  SetConstants();
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(xsd_DateTimeToStr(VAL_1,xdkDateTime),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(xsd_DateTimeToStr(VAL_1,xdkDateTime),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(xsd_DateTimeToStr(VAL_2,xdkDateTime),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(xsd_DateTimeToStr(VAL_2,xdkDateTime),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(xsd_DateTimeToStr(VAL_3,xdkDateTime),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(xsd_DateTimeToStr(VAL_3,xdkDateTime),obj.getString(buffer,F_OFFSET_0));
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(xsd_DateTimeToStr(VAL_1,xdkDateTime),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(xsd_DateTimeToStr(VAL_1,xdkDateTime),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(xsd_DateTimeToStr(VAL_2,xdkDateTime),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(xsd_DateTimeToStr(VAL_2,xdkDateTime),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(xsd_DateTimeToStr(VAL_3,xdkDateTime),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(xsd_DateTimeToStr(VAL_3,xdkDateTime),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDODateField_Test.setDate();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_3)^ := d;
+  end;
+
+var
+  obj : ISDOField;
+  trueBuffer : array[0..( 3 * SizeOf(TSDODate))] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODate;
+begin
+  SetConstants();
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setDate(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setDate(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setDate(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+
+    obj.setDate(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setDate(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setDate(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDODateField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_3)^ := d;
+  end;
+
+var
+  obj : ISDOField;
+  trueBuffer : array[0..( 3 * SizeOf(TSDODate))] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODate;
+begin
+  SetConstants();
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,xsd_DateTimeToStr(VAL_1,xdkDateTime));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^,'',False);
+
+  obj.setString(buffer,F_OFFSET_0,xsd_DateTimeToStr(VAL_2,xdkDateTime));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODate(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,xsd_DateTimeToStr(VAL_1,xdkDateTime));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^,'',False);
+
+    obj.setString(buffer,F_OFFSET_1,xsd_DateTimeToStr(VAL_2,xdkDateTime));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+{ TSDOCharField_Test }
+
+function TSDOCharField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOCharField.Create() as ISDOField;
+end;
+
+procedure TSDOCharField_Test.getBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar('X'); VAL_2 = TSDOChar('Y'); VAL_3 = TSDOChar(#0);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCharField_Test.getByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#123); VAL_2 = TSDOChar(#45); VAL_3 = TSDOChar(#0);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_1),obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_1),obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getByte(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getByte(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getByte(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getByte(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCharField_Test.getCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar('a'); VAL_2 = TSDOChar('i'); VAL_3 = TSDOChar('1');
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getCharacter(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getCharacter(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getCharacter(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getCharacter(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getCharacter(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getCharacter(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getCharacter(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getCharacter(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getCharacter(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(#0,obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getCharacter(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCharField_Test.getInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#97); VAL_2 = TSDOChar(#48); VAL_3 = TSDOChar(#100);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_1),obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(Ord(VAL_1)),obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getInteger(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getInteger(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getInteger(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getInteger(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCharField_Test.getLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#97); VAL_2 = TSDOChar(#48); VAL_3 = TSDOChar(#100);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_1),obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(Ord(VAL_1)),obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getLong(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getLong(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getLong(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getLong(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCharField_Test.getShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#97); VAL_2 = TSDOChar(#48); VAL_3 = TSDOChar(#100);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_1),obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(Ord(VAL_1)),obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_2),obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(Ord(VAL_3),obj.getShort(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_1),obj.getShort(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_2),obj.getShort(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(Ord(VAL_3),obj.getShort(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCharField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar('a'); VAL_2 = TSDOChar('b'); VAL_3 = TSDOChar('c');
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_0));
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCharField_Test.setBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setBoolean(buffer,F_OFFSET_0,True);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals('1',valBuffer^);
+
+  obj.setBoolean(buffer,F_OFFSET_0,False);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals('0',valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+
+    obj.setBoolean(buffer,F_OFFSET_1,True);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals('1',valBuffer^);
+
+    obj.setBoolean(buffer,F_OFFSET_1,False);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals('0',valBuffer^);
+end;
+
+procedure TSDOCharField_Test.setByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#98); VAL_2 = TSDOChar(#56); VAL_3 = TSDOChar(#110);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setByte(buffer,F_OFFSET_0,Ord(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,Ord(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,Ord(VAL_3));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+
+    obj.setByte(buffer,F_OFFSET_1,Ord(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,Ord(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,Ord(VAL_3));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCharField_Test.setCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar('A'); VAL_2 = TSDOChar('b'); VAL_3 = TSDOChar('1');
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setCharacter(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setCharacter(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setCharacter(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+
+    obj.setCharacter(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setCharacter(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setCharacter(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCharField_Test.setInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#98); VAL_2 = TSDOChar(#56); VAL_3 = TSDOChar(#110);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setInteger(buffer,F_OFFSET_0,Ord(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,Ord(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,Ord(VAL_3));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+
+    obj.setInteger(buffer,F_OFFSET_1,Ord(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,Ord(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,Ord(VAL_3));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCharField_Test.setLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#98); VAL_2 = TSDOChar(#56); VAL_3 = TSDOChar(#110);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setLong(buffer,F_OFFSET_0,Ord(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,Ord(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,Ord(VAL_3));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+
+    obj.setLong(buffer,F_OFFSET_1,Ord(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,Ord(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,Ord(VAL_3));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCharField_Test.setShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar(#98); VAL_2 = TSDOChar(#56); VAL_3 = TSDOChar(#110);
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setShort(buffer,F_OFFSET_0,Ord(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,Ord(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,Ord(VAL_3));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+
+    obj.setShort(buffer,F_OFFSET_1,Ord(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,Ord(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,Ord(VAL_3));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCharField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = TSDOChar('a'); VAL_2 = TSDOChar('b'); VAL_3 = TSDOChar('c');
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOChar;
+begin
+  intVal := 0;
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  intVal := 0;
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOChar(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_LONG}
+{ TSDOLongField_Test }
+
+function TSDOLongField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOLongField.Create() as ISDOField;
+end;
+
+procedure TSDOLongField_Test.getBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345678912345; VAL_2 = -12345678912345; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOLongField_Test.getByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12; VAL_2 = 123; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOLongField_Test.getCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar('I')); VAL_2 = Ord(TSDOChar('W')); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOLongField_Test.getInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345678; VAL_2 = -78945612; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOLongField_Test.getLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234586791234567; VAL_2 = -98765532166547; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOLongField_Test.getShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -987; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOLongField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123456789123456; VAL_2 = -9876543211234; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOLongField_Test.setBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setBoolean(buffer,F_OFFSET_0,True);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setBoolean(buffer,F_OFFSET_0,False);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+
+    obj.setBoolean(buffer,F_OFFSET_1,True);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setBoolean(buffer,F_OFFSET_1,False);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOLongField_Test.setByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12; VAL_2 = 123; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOLongField_Test.setCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar('I')); VAL_2 = Ord(TSDOChar('W')); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+
+procedure TSDOLongField_Test.setInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345678; VAL_2 = -98765432; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOLongField_Test.setLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234586791234567; VAL_2 = -98765532166547; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOLongField_Test.setShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 123; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOLongField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345678912345; VAL_2 = -987654321654321; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+{ TSDOShortField_Test }
+
+function TSDOShortField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOShortField.Create() as ISDOField;
+end;
+
+procedure TSDOShortField_Test.getBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(True,obj.getBoolean(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(False,obj.getBoolean(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOShortField_Test.getByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12; VAL_2 = 123; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getByte(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getByte(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getByte(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getByte(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getByte(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOShortField_Test.getCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar('I')); VAL_2 = Ord(TSDOChar('W')); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_1),obj.getCharacter(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_2),obj.getCharacter(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOChar(VAL_3),obj.getCharacter(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOShortField_Test.getInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -7894; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getInteger(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getInteger(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getInteger(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getInteger(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getInteger(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOShortField_Test.getLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -987; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOLong;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getLong(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOLong(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getLong(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getLong(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getLong(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getLong(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOShortField_Test.getShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getShort(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getShort(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getShort(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getShort(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getShort(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOShortField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_1),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_2),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(IntToStr(VAL_3),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOShortField_Test.setBoolean();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setBoolean(buffer,F_OFFSET_0,True);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(1,valBuffer^);
+
+  obj.setBoolean(buffer,F_OFFSET_0,False);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(0,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+
+    obj.setBoolean(buffer,F_OFFSET_1,True);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(1,valBuffer^);
+
+    obj.setBoolean(buffer,F_OFFSET_1,False);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(0,valBuffer^);
+end;
+
+procedure TSDOShortField_Test.setByte();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12; VAL_2 = 123; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setByte(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setByte(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOShortField_Test.setCharacter();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = Ord(TSDOChar('I')); VAL_2 = Ord(TSDOChar('W')); VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setCharacter(buffer,F_OFFSET_0,TSDOChar(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setCharacter(buffer,F_OFFSET_1,TSDOChar(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+
+procedure TSDOShortField_Test.setInteger();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setInteger(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setInteger(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOShortField_Test.setLong();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setLong(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setLong(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOShortField_Test.setShort();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : QWord;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setShort(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setShort(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOShortField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 1234; VAL_2 = -9876; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOShort;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,IntToStr(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOShort(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,IntToStr(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+{$IFDEF HAS_SDO_BYTES}
+{ TSDOBytesField_Test }
+
+class procedure TSDOBytesField_Test.CleanUpBuffer(var ABuffer: PPSDOBytes);
+begin
+  if ( ABuffer <> nil ) then begin
+    ABuffer^^ := nil;
+    FreeMem(ABuffer^,SizeOf(PSDOBytes));
+    ABuffer^ := nil;
+  end;
+end;
+
+function TSDOBytesField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOBytesField.Create() as ISDOField;
+end;
+
+procedure TSDOBytesField_Test.getBytes();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1; ZERO_BYTES : TSDOBytes = nil;
+var
+      VAL_1, VAL_2, VAL_3 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;
+
+    VAL_2 := nil;    
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3 := v;     
+  end;
+
+var
+  obj : ISDOField;
+  trueBuffer : array[0..( 3 * SizeOf(TSDOBytes))] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PPSDOBytes;
+begin
+  SetConstants();
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := @VAL_1; SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getBytes(buffer,F_OFFSET_0));
+
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getBytes(buffer,F_OFFSET_0));
+  valBuffer^ := nil;
+  
+  valBuffer^ := @VAL_2; SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getBytes(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getBytes(buffer,F_OFFSET_0));
+  valBuffer^ := nil;
+  
+  valBuffer^ := @VAL_3; SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getBytes(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getBytes(buffer,F_OFFSET_0));
+  valBuffer^ := nil;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+    valBuffer^ := @VAL_1; SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getBytes(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getBytes(buffer,F_OFFSET_1));
+    valBuffer^ := nil;
+
+    valBuffer^ := @VAL_2; SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getBytes(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getBytes(buffer,F_OFFSET_1));
+    valBuffer^ := nil;
+
+    valBuffer^ := @VAL_3; SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getBytes(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(ZERO_BYTES,obj.getBytes(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getBytes(buffer,F_OFFSET_1));
+    valBuffer^ := nil;
+end;
+
+procedure TSDOBytesField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1; ZERO_BYTES : TSDOBytes = nil;
+var
+      VAL_1, VAL_2, VAL_3 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;
+
+    VAL_2 := nil;
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3 := v;     
+  end;
+
+var
+  obj : ISDOField;
+  trueBuffer : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PPSDOBytes;
+begin
+  SetConstants();
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+  obj := Create_Field();
+
+  GetMem(valBuffer^,SizeOf(PSDOBytes)); FillChar(valBuffer^^,SizeOf(TSDOBytes),#0);
+  SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+  try
+    valBuffer^^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    valBuffer^^ := nil;
+
+    valBuffer^^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    valBuffer^^ := nil;
+  
+    valBuffer^^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    valBuffer^^ := nil;
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOBytes));
+    valBuffer^ := nil;
+  end;
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+  GetMem(valBuffer^,SizeOf(PSDOBytes)); FillChar(valBuffer^^,SizeOf(TSDOBytes),#0);
+  SetBit(attributeBuffer^,BIT_ORDER_BUFFER,True);
+  try
+    valBuffer^^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+    valBuffer^^ := nil;
+
+    valBuffer^^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+    valBuffer^^ := nil;
+    
+    valBuffer^^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(BytesToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+    valBuffer^^ := nil;
+  finally
+    FreeMem(valBuffer^,SizeOf(PSDOBytes));
+  end;
+end;
+
+procedure TSDOBytesField_Test.setBytes();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1; ZERO_BYTES : TSDOBytes = nil;
+var
+      VAL_1, VAL_2, VAL_3 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;
+
+    VAL_2 := nil;
+    
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3 := v;     
+  end;
+  
+var
+  obj : ISDOField;
+  trueBuffer : array[0..100] of Byte;
+  buffer, tmpBuffer, startBuffer : PByte;
+  valBuffer : PPSDOBytes;
+begin
+  SetConstants();
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setBytes(buffer,F_OFFSET_0,nil);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  obj.setBytes(buffer,F_OFFSET_0,VAL_1);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'bytes buffer' );
+  CheckEquals(VAL_1,valBuffer^^);
+
+  obj.setBytes(buffer,F_OFFSET_0,VAL_2);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'bytes buffer' );
+  CheckEquals(VAL_2,valBuffer^^);
+
+  SetBit(startBuffer^,BIT_ORDER_NULL,True);
+  obj.setBytes(buffer,F_OFFSET_0,VAL_3);
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+  CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+  CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+  CheckEquals(True, ( valBuffer^ <> nil ), 'bytes buffer' );
+  CheckEquals(VAL_3,valBuffer^^);
+
+  // Clean up to avoid false MEM-LEAK
+  CleanUpBuffer(valBuffer);
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  startBuffer := tmpBuffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    obj.setBytes(buffer,F_OFFSET_1,nil);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+
+    obj.setBytes(buffer,F_OFFSET_1,VAL_1);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'bytes buffer' );
+    CheckEquals(VAL_1,valBuffer^^);
+
+    SetBit(startBuffer^,BIT_ORDER_NULL,True);
+    obj.setBytes(buffer,F_OFFSET_1,VAL_2);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'bytes buffer' );
+    CheckEquals(VAL_2,valBuffer^^);
+
+    obj.setBytes(buffer,F_OFFSET_1,VAL_3);
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_SET), 'set bit');
+    CheckEquals(False, IsBitON(startBuffer^,BIT_ORDER_NULL), 'set bit');
+    CheckEquals(True, IsBitON(startBuffer^,BIT_ORDER_BUFFER), 'set bit');
+    CheckEquals(True, ( valBuffer^ <> nil ), 'bytes buffer' );
+    CheckEquals(VAL_3,valBuffer^^);
+    // Clean up to avoid false MEM-LEAK
+    CleanUpBuffer(valBuffer);
+
+end;
+
+procedure TSDOBytesField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1; ZERO_BYTES : TSDOBytes = nil;
+var
+      VAL_1, VAL_2, VAL_3 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,100);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;    
+
+    VAL_2 := nil;
+
+    SetLength(v,200);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3 := v;     
+  end;
+
+var
+  obj : ISDOField;
+  trueBuffer : array[0..( 3 * SizeOf(TSDOBytes))] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PPSDOBytes;
+begin
+  SetConstants();
+
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  buffer := @(trueBuffer[0]);
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,BytesToString(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^^);
+
+  obj.setString(buffer,F_OFFSET_0,BytesToString(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^^);
+
+  CleanUpBuffer(valBuffer);
+  FillChar(trueBuffer,SizeOf(trueBuffer),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PPSDOBytes(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,BytesToString(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^^);
+
+    obj.setString(buffer,F_OFFSET_1,BytesToString(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^^);
+      
+  CleanUpBuffer(valBuffer);
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CURRENCY}
+function TSDOCurrencyField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOCurrencyField.Create() as ISDOField;
+end;
+
+procedure TSDOCurrencyField_Test.getCurrency();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOCurrency = 123458679123.1234; VAL_2 : TSDOCurrency = -98765532166547.9876; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getCurrency(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getCurrency(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getCurrency(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getCurrency(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getCurrency(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getCurrency(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getCurrency(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getCurrency(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getCurrency(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getCurrency(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getCurrency(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getCurrency(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getCurrency(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCurrencyField_Test.setCurrency();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOCurrency = 12345; VAL_2 : TSDOCurrency = -98765; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCurrencyField_Test.getDouble();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOCurrency = 12345; VAL_2 : TSDOCurrency = -98765; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCurrencyField_Test.setDouble();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOCurrency = 12345; VAL_2 : TSDOCurrency = -98765; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte; 
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCurrencyField_Test.getFloat();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOCurrency = 12345; VAL_2 : TSDOCurrency = -98765; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getFloat(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getFloat(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getFloat(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getFloat(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getFloat(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getFloat(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getFloat(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getFloat(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getFloat(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getFloat(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getFloat(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getFloat(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getFloat(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getFloat(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getFloat(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getFloat(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getFloat(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getFloat(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getFloat(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getFloat(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getFloat(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getFloat(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getFloat(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getFloat(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCurrencyField_Test.setFloat();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOCurrency = 12345; VAL_2 : TSDOCurrency = -98765; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte; 
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setFloat(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setFloat(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setFloat(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+
+    obj.setFloat(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setFloat(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setFloat(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDOCurrencyField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 = 12345.6789; VAL_2 = -987654.3211; VAL_3 = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.CurrencyToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOCurrencyField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOCurrency = 12345; VAL_2 : TSDOCurrency = -98765; VAL_3 : TSDOCurrency = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOCurrency;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,TSDOConvertHelper.CurrencyToString(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,TSDOConvertHelper.CurrencyToString(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOCurrency(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,TSDOConvertHelper.CurrencyToString(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,TSDOConvertHelper.CurrencyToString(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+function TSDODoubleField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDODoubleField.Create() as ISDOField;
+end;
+
+procedure TSDODoubleField_Test.getCurrency();
+begin
+
+end;
+
+procedure TSDODoubleField_Test.setCurrency();
+begin
+
+end;
+
+procedure TSDODoubleField_Test.getDouble();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODouble = 123458679123.1234; VAL_2 : TSDODouble = -98765532166547.9876; VAL_3 : TSDODouble = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODouble;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+  SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_0));
+  SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+      CheckEquals(0,obj.getDouble(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+    valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_1,obj.getDouble(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_2,obj.getDouble(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_1));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,True);
+        CheckEquals(0,obj.getDouble(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(VAL_3,obj.getDouble(buffer,F_OFFSET_1));
+end;
+
+procedure TSDODoubleField_Test.setDouble();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODouble = 12345; VAL_2 : TSDODouble = -98765; VAL_3 : TSDODouble = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODouble;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_1);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_2);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  obj.setDouble(buffer,F_OFFSET_0,VAL_3);
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_3,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_1);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_2);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+
+    obj.setDouble(buffer,F_OFFSET_1,VAL_3);
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_3,valBuffer^);
+end;
+
+procedure TSDODoubleField_Test.getFloat();
+begin
+
+end;
+
+procedure TSDODoubleField_Test.setFloat();
+begin
+
+end;
+
+procedure TSDODoubleField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODouble = 12345; VAL_2 : TSDODouble = -987654; VAL_3 : TSDODouble = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODouble;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDODoubleField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDODouble = 12345; VAL_2 : TSDODouble = -98765; VAL_3 : TSDODouble = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDODouble;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,TSDOConvertHelper.FloatToString(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,TSDOConvertHelper.FloatToString(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDODouble(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,TSDOConvertHelper.FloatToString(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,TSDOConvertHelper.FloatToString(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+function TSDOFloatField_Test.Create_Field() : ISDOField;
+begin
+  Result := TSDOFloatField.Create() as ISDOField;
+end;
+
+procedure TSDOFloatField_Test.getCurrency();
+begin
+
+end;
+
+procedure TSDOFloatField_Test.setCurrency();
+begin
+
+end;
+
+procedure TSDOFloatField_Test.getDouble();
+begin
+
+end;
+
+procedure TSDOFloatField_Test.setDouble();
+begin
+
+end;
+
+procedure TSDOFloatField_Test.getFloat();
+begin
+
+end;
+
+procedure TSDOFloatField_Test.setFloat();
+begin
+
+end;
+
+procedure TSDOFloatField_Test.getString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOFloat = 12345; VAL_2 : TSDOFloat = -987654; VAL_3 : TSDOFloat = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOFloat;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOFloat(tmpBuffer);
+  obj := Create_Field();
+
+  valBuffer^ := VAL_1;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_2;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_0));
+
+  valBuffer^ := VAL_3;
+    SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+    SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+      SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+      CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_0));
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOFloat(tmpBuffer);
+    valBuffer^ := VAL_1;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_1),obj.getString(buffer,F_OFFSET_1));
+
+
+    valBuffer^ := VAL_2;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_2),obj.getString(buffer,F_OFFSET_1));
+
+    valBuffer^ := VAL_3;
+      SetBit(attributeBuffer^,BIT_ORDER_SET,True);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+      SetBit(attributeBuffer^,BIT_ORDER_SET,False);
+        SetBit(attributeBuffer^,BIT_ORDER_NULL,False);
+        CheckEquals(TSDOConvertHelper.FloatToString(VAL_3),obj.getString(buffer,F_OFFSET_1));
+end;
+
+procedure TSDOFloatField_Test.setString();
+const F_OFFSET_0 = 0; F_OFFSET_1 = 1;
+      VAL_1 : TSDOFloat = 12345; VAL_2 : TSDOFloat = -98765; VAL_3 : TSDOFloat = 0;
+var
+  obj : ISDOField;
+  intVal : array[0..100] of Byte;
+  buffer, tmpBuffer, attributeBuffer : PByte;
+  valBuffer : PSDOFloat;
+begin
+  FillChar(intVal,SizeOf(intVal),#0);
+  buffer := @intVal;
+  tmpBuffer := buffer;
+  attributeBuffer := buffer;
+  Inc(tmpBuffer);
+  valBuffer := PSDOFloat(tmpBuffer);
+  obj := Create_Field();
+
+  obj.setString(buffer,F_OFFSET_0,TSDOConvertHelper.FloatToString(VAL_1));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_1,valBuffer^);
+
+  obj.setString(buffer,F_OFFSET_0,TSDOConvertHelper.FloatToString(VAL_2));
+    CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+    CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+    CheckEquals(VAL_2,valBuffer^);
+
+  FillChar(intVal,SizeOf(intVal),#0);
+  Inc(tmpBuffer);
+  Inc(attributeBuffer);
+  valBuffer := PSDOFloat(tmpBuffer);
+
+    obj.setString(buffer,F_OFFSET_1,TSDOConvertHelper.FloatToString(VAL_1));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_1,valBuffer^);
+
+    obj.setString(buffer,F_OFFSET_1,TSDOConvertHelper.FloatToString(VAL_2));
+      CheckEquals(True,IsBitON(attributeBuffer^,BIT_ORDER_SET));
+      CheckEquals(False,IsBitON(attributeBuffer^,BIT_ORDER_NULL));
+      CheckEquals(VAL_2,valBuffer^);
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+initialization
+  RegisterTest(TSDOBooleanField_Test.GetTestSuitePath(),TSDOBooleanField_Test.Suite);
+  RegisterTest(TSDOIntegerField_Test.GetTestSuitePath(),TSDOIntegerField_Test.Suite);
+{$IFDEF HAS_SDO_LONG}
+  RegisterTest(TSDOLongField_Test.GetTestSuitePath(),TSDOLongField_Test.Suite);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  RegisterTest(TSDOShortField_Test.GetTestSuitePath(),TSDOShortField_Test.Suite);
+{$ENDIF HAS_SDO_SHORT}
+  RegisterTest(TSDOStringField_Test.GetTestSuitePath(),TSDOStringField_Test.Suite);
+  RegisterTest(TSDOBaseDataObject_Test.GetTestSuitePath(),TSDOBaseDataObject_Test.Suite);
+  RegisterTest(TSDOChangeSummaryField_Test.GetTestSuitePath(),TSDOChangeSummaryField_Test.Suite);
+  RegisterTest(TSDOByteField_Test.GetTestSuitePath(),TSDOByteField_Test.Suite);
+  RegisterTest(TSDODateField_Test.GetTestSuitePath(),TSDODateField_Test.Suite);
+{$IFDEF HAS_SDO_BYTES}
+  RegisterTest(TSDOBytesField_Test.GetTestSuitePath(),TSDOBytesField_Test.Suite);
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+  RegisterTest(TSDOCharField_Test.GetTestSuitePath(),TSDOCharField_Test.Suite);
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  RegisterTest(TSDOCurrencyField_Test.GetTestSuitePath(),TSDOCurrencyField_Test.Suite);
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+  RegisterTest(TSDODoubleField_Test.GetTestSuitePath(),TSDODoubleField_Test.Suite);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  RegisterTest(TSDOFloatField_Test.GetTestSuitePath(),TSDOFloatField_Test.Suite);
+{$ENDIF HAS_SDO_FLOAT}
+end.

+ 1035 - 0
packages/fcl-sdo/tests/test_suite/test_property.pas

@@ -0,0 +1,1035 @@
+{$INCLUDE sdo_global.inc}
+unit test_property;
+
+interface
+uses SysUtils
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  ,test_suite_utils, sdo, sdo_type, sdo_types, sdo_property ;
+
+type
+
+  TSDOPropertyAsbtract_Test = class(TWstBaseTest)
+  protected
+    class function create_obj(
+      const AName  : string;
+      const AType  : ISDOType;
+      const AMany  : Boolean;
+      const AContained : Boolean;
+      const AContainingType : ISDOType;
+      const AReadOnly : Boolean;
+      const AIsAttribute : Boolean
+    ) : ISDOProperty;virtual;abstract;
+  public
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+  published
+    procedure test_create();
+
+    procedure setDefault_boolean();
+    procedure setDefault_byte();
+    procedure setDefault_integer();
+    procedure setDefault_string();
+    procedure setDefault_object();
+    procedure setDefault_date();
+
+{$IFDEF HAS_SDO_BYTES}
+    procedure setDefault_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure setDefault_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure setDefault_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure setDefault_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure setDefault_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure setDefault_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure setDefault_short();
+{$ENDIF HAS_SDO_SHORT}
+  end;
+
+  TSDOProperty_Test = class(TSDOPropertyAsbtract_Test)
+  protected
+    class function create_obj(
+      const AName  : string;
+      const AType  : ISDOType;
+      const AMany  : Boolean;
+      const AContained : Boolean;
+      const AContainingType : ISDOType;
+      const AReadOnly : Boolean;
+      const AIsAttribute : Boolean
+    ) : ISDOProperty;override;
+  end;
+
+implementation
+
+uses sdo_datafactory, Math, DateUtils, sdo_date_utils;
+
+const
+  s_uri = 'test-uri';
+  s_type_object_A = 'Object_A'; s_type_object_B = 'Object_B';
+
+{ TSDOPropertyAsbtract_Test }
+
+procedure TSDOPropertyAsbtract_Test.CheckEquals(expected, actual: TSDODate;
+  msg: string; const AStrict: Boolean
+);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+procedure TSDOPropertyAsbtract_Test.setDefault_boolean();
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOBoolean;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_bool',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[BooleanType]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getIntegerDefault());
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := False;
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getBooleanDefault());
+  tmpVal := True;
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getBooleanDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(False);
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+
+procedure TSDOPropertyAsbtract_Test.setDefault_byte();
+const
+  PROP_TYPE = ByteType;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOByte;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+  CheckEquals(0, locObj.getIntegerDefault());
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := RandomRange(Low(TSDOByte),High(TSDOByte));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getByteDefault());
+  tmpVal := RandomRange(Low(TSDOByte),High(TSDOByte));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getByteDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(TSDOByte(123));
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+
+procedure TSDOPropertyAsbtract_Test.setDefault_date();
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDODate;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_dt',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+  CheckEquals(0, locObj.getIntegerDefault());
+  CheckEquals('', locObj.getStringDefault());
+  CheckEquals(ZERO_DATE,locObj.getDateDefault());
+
+  tmpVal := xsd_StrToDate('1976-10-12T23:34:56.7',xdkDateTime);
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getDateDefault());
+  tmpVal := xsd_StrToDate('1987-11-12',xdkDateTime);
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getDateDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(xsd_StrToDate('1987-11-12',xdkDateTime));
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+
+procedure TSDOPropertyAsbtract_Test.setDefault_integer();
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOInteger;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_int',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getIntegerDefault());
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := RandomRange(-12345,12345);
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getIntegerDefault());
+  tmpVal := RandomRange(-12345,12345);
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getIntegerDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(123);
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOPropertyAsbtract_Test.setDefault_bytes();
+const
+  PROP_TYPE = BytesType;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOBytes;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(TSDOBytes(nil), locObj.getBytesDefault());
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := RandomBytes(100);
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getBytesDefault());
+    CheckEquals(BytesToString(tmpVal), locObj.getStringDefault());
+  tmpVal := RandomBytes(100);
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getBytesDefault());
+    CheckEquals(BytesToString(tmpVal), locObj.getStringDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(RandomBytes(100));
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOPropertyAsbtract_Test.setDefault_char();
+const
+  PROP_TYPE = CharacterType;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOChar;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+{$IFDEF HAS_SDO_CHAR}
+  CheckEquals(#0, locObj.getCharacterDefault());
+{$ENDIF HAS_SDO_CHAR}
+  CheckEquals(0, locObj.getIntegerDefault());
+{$IFDEF HAS_SDO_LONG}
+  CheckEquals(0, locObj.getLongDefault());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  CheckEquals(0, locObj.getShortDefault());
+{$ENDIF HAS_SDO_SHORT}
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getCharacterDefault());
+  tmpVal := TSDOChar(RandomRange(Ord(Low(TSDOChar)),Ord(High(TSDOChar))));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getCharacterDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(TSDOChar('s'));
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TSDOPropertyAsbtract_Test.setDefault_currency();
+const
+  PROP_TYPE = CurrencyType;
+  VAL_1 : TSDOCurrency = 1238653223453;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOCurrency;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+{$IFDEF HAS_SDO_CHAR}
+  CheckEquals(#0, locObj.getCharacterDefault());
+{$ENDIF HAS_SDO_CHAR}  
+ 
+{$IFDEF HAS_SDO_DOUBLE}
+  CheckEquals(0, locObj.getDoubleDefault());
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  CheckEquals(0, locObj.getFloatDefault());
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}  
+  CheckEquals(0, locObj.getLongDefault());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  CheckEquals(0, locObj.getShortDefault());
+{$ENDIF HAS_SDO_SHORT}
+  CheckEquals(0, locObj.getIntegerDefault()); 
+  CheckEquals('', locObj.getStringDefault());
+  
+  CheckEquals(0, locObj.getCurrencyDefault());
+
+  tmpVal := test_suite_utils.RandomRange(Low(Word),High(Word));
+  locObj.setDefaultCurrency(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getCurrencyDefault());
+  tmpVal := test_suite_utils.RandomRange(Low(Word),High(Word));
+  locObj.setDefaultCurrency(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getCurrencyDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefaultCurrency(VAL_1);
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TSDOPropertyAsbtract_Test.setDefault_double();
+const
+  PROP_TYPE = DoubleType;
+  VAL_1 : TSDODouble = 1238653223453;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDODouble;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+{$IFDEF HAS_SDO_CHAR}
+  CheckEquals(#0, locObj.getCharacterDefault());
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+  CheckEquals(0, locObj.getCurrencyDefault());
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_FLOAT}
+  CheckEquals(0, locObj.getFloatDefault());
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}  
+  CheckEquals(0, locObj.getLongDefault());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  CheckEquals(0, locObj.getShortDefault());
+{$ENDIF HAS_SDO_SHORT}
+  CheckEquals(0, locObj.getIntegerDefault()); 
+  CheckEquals('', locObj.getStringDefault());
+  
+  CheckEquals(0, locObj.getDoubleDefault());
+
+  tmpVal := test_suite_utils.RandomRange(Low(Word),High(Word));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getDoubleDefault());
+  tmpVal := test_suite_utils.RandomRange(Low(Word),High(Word));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getDoubleDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(VAL_1);
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TSDOPropertyAsbtract_Test.setDefault_float();
+const
+  PROP_TYPE = FloatType;
+  VAL_1 : TSDOFloat = 1238653223453;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOFloat;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+{$IFDEF HAS_SDO_CHAR}
+  CheckEquals(#0, locObj.getCharacterDefault());
+{$ENDIF HAS_SDO_CHAR}  
+{$IFDEF HAS_SDO_CURRENCY}  
+  CheckEquals(0, locObj.getCurrencyDefault());
+{$ENDIF HAS_SDO_CURRENCY}  
+{$IFDEF HAS_SDO_DOUBLE}
+  CheckEquals(0, locObj.getDoubleDefault());
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_LONG}  
+  CheckEquals(0, locObj.getLongDefault());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  CheckEquals(0, locObj.getShortDefault());
+{$ENDIF HAS_SDO_SHORT}
+  CheckEquals(0, locObj.getIntegerDefault()); 
+  CheckEquals('', locObj.getStringDefault());
+  
+  CheckEquals(0, locObj.getFloatDefault());
+
+  tmpVal := test_suite_utils.RandomRange(Low(Word),High(Word));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getFloatDefault());
+  tmpVal := test_suite_utils.RandomRange(Low(Word),High(Word));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getFloatDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(VAL_1);
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOPropertyAsbtract_Test.setDefault_long();
+const
+  PROP_TYPE = LongType;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOLong;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+{$IFDEF HAS_SDO_CHAR}
+  CheckEquals(#0, locObj.getCharacterDefault());
+{$ENDIF HAS_SDO_CHAR}    
+  CheckEquals(0, locObj.getIntegerDefault());
+{$IFDEF HAS_SDO_LONG}  
+  CheckEquals(0, locObj.getLongDefault());
+{$ENDIF HAS_SDO_LONG}  
+{$IFDEF HAS_SDO_SHORT}  
+  CheckEquals(0, locObj.getShortDefault());
+{$ENDIF HAS_SDO_SHORT}  
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getLongDefault());
+  tmpVal := test_suite_utils.RandomRange(Low(TSDOLong),High(TSDOLong));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getLongDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(TSDOLong(123865322345363636));
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOPropertyAsbtract_Test.setDefault_short();
+const
+  PROP_TYPE = ShortType;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOShort;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_sample',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getByteDefault());
+{$IFDEF HAS_SDO_CHAR}
+  CheckEquals(#0, locObj.getCharacterDefault());
+{$ENDIF HAS_SDO_CHAR}    
+  CheckEquals(0, locObj.getIntegerDefault());
+{$IFDEF HAS_SDO_LONG}
+  CheckEquals(0, locObj.getLongDefault());
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}  
+  CheckEquals(0, locObj.getShortDefault());
+{$ENDIF HAS_SDO_SHORT}  
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := RandomRange(Low(TSDOShort),High(TSDOShort));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getShortDefault());
+  tmpVal := RandomRange(Low(TSDOShort),High(TSDOShort));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getShortDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault(TSDOShort(12386));
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOPropertyAsbtract_Test.setDefault_object;
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  ok : boolean;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_string',
+              (*Type*)            locFac.getType(s_uri,s_type_object_B),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       False
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  ok := False;
+  try
+    locObj.setDefault('asa');
+  except
+    on e : ESDOUnsupportedOperationException do
+      ok := True;
+  end;
+  Check(ok, 'setDefault(string)');
+
+  ok := False;
+  try
+    locObj.setDefault(True);
+  except
+    on e : ESDOUnsupportedOperationException do
+      ok := True;
+  end;
+  Check(ok, 'setDefault(Boolean)');
+
+  ok := False;
+  try
+    locObj.setDefault(1210);
+  except
+    on e : ESDOUnsupportedOperationException do
+      ok := True;
+  end;
+  Check(ok, 'setDefault(Integer)');
+end;
+
+procedure TSDOPropertyAsbtract_Test.setDefault_string();
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+  tmpVal : TSDOString;
+  ok : Boolean;
+begin
+  Randomize();
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+
+  locObj := create_obj(
+              (*Name*)            'p_string',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+  CheckEquals(False, locObj.isDefaulted());
+  CheckEquals(False, locObj.getBooleanDefault());
+  CheckEquals(0, locObj.getIntegerDefault());
+  CheckEquals('', locObj.getStringDefault());
+
+  tmpVal := RandomString(RandomRange(1,1000));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getStringDefault());
+  tmpVal := RandomString(RandomRange(1,1000));
+  locObj.setDefault(tmpVal);
+    CheckEquals(True, locObj.isDefaulted());
+    CheckEquals(tmpVal, locObj.getStringDefault());
+
+  locFac.createNew(s_uri,s_type_object_A);
+    ok := False;
+    try
+      locObj.setDefault('azerty');
+    except
+      on e : ESDOUnsupportedOperationException do
+        ok := True;
+    end;
+    Check(ok, 'Once an instance has been created, the metadata becomes read-only.');
+end;
+
+procedure TSDOPropertyAsbtract_Test.test_create();
+  procedure check_invalid_args(
+    const AName  : string;
+    const AType  : ISDOType;
+    const AMany  : Boolean;
+    const AContained : Boolean;
+    const AContainingType : ISDOType;
+    const AReadOnly : Boolean;
+    const AIsAttribute : Boolean;
+
+    const AMsg : string
+  );
+  var
+    ok : Boolean;
+  begin
+    ok := False;
+    try
+      create_obj(AName,AType,AMany,AContained,AContainingType,AReadOnly,AIsAttribute);
+    except
+      on e : ESDOIllegalArgumentException do
+        ok := True;
+    end;
+    Check(ok, AMsg);
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locObj : ISDOProperty;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+    locFac.AddType(s_uri,s_type_object_A,[]);
+    locFac.AddType(s_uri,s_type_object_B,[]);
+  check_invalid_args(
+    (*Name*)            '',
+    (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+    (* Many *)          False,
+    (*Contained*)       False,
+    (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+    (*ReadOnly*)        False,
+    (*Attribute*)       True,
+    'Invalid Name.'
+  );
+
+  check_invalid_args(
+    (*Name*)            '1az',
+    (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+    (* Many *)          False,
+    (*Contained*)       False,
+    (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+    (*ReadOnly*)        False,
+    (*Attribute*)       True,
+    'Invalid Name.'
+  );
+
+  check_invalid_args(
+    (*Name*)            'ab[1]',
+    (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+    (* Many *)          False,
+    (*Contained*)       False,
+    (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+    (*ReadOnly*)        False,
+    (*Attribute*)       True,
+    'Invalid Name.'
+  );
+
+  check_invalid_args(
+    (*Name*)            'azerty',
+    (*Type*)            nil,
+    (* Many *)          False,
+    (*Contained*)       False,
+    (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+    (*ReadOnly*)        False,
+    (*Attribute*)       True,
+    'Invalid type.'
+  );
+
+  check_invalid_args(
+    (*Name*)            'azerty',
+    (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+    (* Many *)          False,
+    (*Contained*)       True,
+    (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+    (*ReadOnly*)        False,
+    (*Attribute*)       True,
+    'Invalid Contained.'
+  );
+
+  check_invalid_args(
+    (*Name*)            'azerty',
+    (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+    (* Many *)          False,
+    (*Contained*)       True,
+    (*ContainingType*)  locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]),
+    (*ReadOnly*)        False,
+    (*Attribute*)       True,
+    'Invalid containingType : The containing type must be a DataObject.'
+  );
+
+  locObj := create_obj(
+              (*Name*)            'p_string',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       True
+            );
+    CheckEquals('p_string', locObj.getName(), 'Name');
+    Check(locObj.getType().equals(locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType])), 'Type');
+    CheckEquals(False, locObj.isMany(), 'isMany');
+    CheckEquals(False, locObj.isReadOnly(), 'isReadOnly');
+    CheckEquals(False, locObj.isContainment(), 'isContainment');
+    CheckEquals(Ord(locObj.getType().getTypeEnum), Ord(locObj.getTypeEnum()), 'getTypeEnum');
+    CheckEquals(False, locObj.isReference(), 'isReference');
+    CheckEquals(True, locObj.isAttribute(), 'isAttribute');
+    CheckEquals(False, locObj.isDefaulted(), 'isDefaulted');   
+
+  locObj := create_obj(
+              (*Name*)            'p_string',
+              (*Type*)            locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType]),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       False
+            );
+    CheckEquals('p_string', locObj.getName(), 'Name');
+    Check(locObj.getType().equals(locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[StringType])), 'Type');
+    CheckEquals(False, locObj.isMany(), 'isMany');
+    CheckEquals(False, locObj.isReadOnly(), 'isReadOnly');
+    CheckEquals(False, locObj.isContainment(), 'isContainment');
+    CheckEquals(Ord(locObj.getType().getTypeEnum), Ord(locObj.getTypeEnum()), 'getTypeEnum');
+    CheckEquals(False, locObj.isReference(), 'isReference');
+    CheckEquals(False, locObj.isAttribute(), 'isAttribute');
+    CheckEquals(False, locObj.isDefaulted(), 'isDefaulted');
+
+  locObj := create_obj(
+              (*Name*)            'p_ab',
+              (*Type*)            locFac.getType(s_uri,s_type_object_B),
+              (* Many *)          False,
+              (*Contained*)       False,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       False
+            );
+    CheckEquals('p_ab', locObj.getName(), 'Name');
+    Check(locObj.getType().equals(locFac.getType(s_uri,s_type_object_B)), 'Type');
+    CheckEquals(False, locObj.isMany(), 'isMany');
+    CheckEquals(False, locObj.isReadOnly(), 'isReadOnly');
+    CheckEquals(False, locObj.isContainment(), 'isContainment');
+    CheckEquals(Ord(locObj.getType().getTypeEnum), Ord(locObj.getTypeEnum()), 'getTypeEnum');
+    CheckEquals(True, locObj.isReference(), 'isReference');
+    CheckEquals(False, locObj.isDefaulted(), 'isDefaulted');
+
+  locObj := create_obj(
+              (*Name*)            'p_ab2',
+              (*Type*)            locFac.getType(s_uri,s_type_object_B),
+              (* Many *)          False,
+              (*Contained*)       True,
+              (*ContainingType*)  locFac.getType(s_uri,s_type_object_A),
+              (*ReadOnly*)        False,
+              (*Attribute*)       False
+            );
+    CheckEquals('p_ab2', locObj.getName(), 'Name');
+    Check(locObj.getType().equals(locFac.getType(s_uri,s_type_object_B)), 'Type');
+    CheckEquals(False, locObj.isMany(), 'isMany');
+    CheckEquals(False, locObj.isReadOnly(), 'isReadOnly');
+    CheckEquals(True, locObj.isContainment(), 'isContainment');
+    CheckEquals(Ord(locObj.getType().getTypeEnum), Ord(locObj.getTypeEnum()), 'getTypeEnum');
+    CheckEquals(False, locObj.isReference(), 'isReference');
+    CheckEquals(False, locObj.isDefaulted(), 'isDefaulted');
+end;
+
+{ TSDOProperty_Test }
+
+class function TSDOProperty_Test.create_obj(
+  const AName: string;
+  const AType: ISDOType;
+  const AMany, AContained: Boolean;
+  const AContainingType: ISDOType;
+  const AReadOnly: Boolean;
+      const AIsAttribute : Boolean
+): ISDOProperty;
+var
+  f : TPropertyFlags;
+begin
+  f := [];
+  if AMany then
+    Include(f, pfIsMany);
+  if AContained then
+    Include(f, pfIsContainment);
+  if AReadOnly then
+    Include(f, pfIsReadOnly);    
+  if AIsAttribute then
+    Include(f, pfIsAttribute);
+
+  Result := TSDOProperty.Create(AName,AType,f,AContainingType) as ISDOProperty;
+end;
+
+initialization
+  RegisterTest('Metadata',TSDOProperty_Test.Suite);
+
+end.

+ 5118 - 0
packages/fcl-sdo/tests/test_suite/test_serializer.pas

@@ -0,0 +1,5118 @@
+{$INCLUDE sdo_global.inc}
+unit test_serializer;
+
+interface
+uses
+  SysUtils, Classes//, Dialogs
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , test_suite_utils, sdo, sdo_types,
+  sdo_serialization, sdo_serialization_utils, sdo_changesummary ;
+
+type
+
+  TListCompareOption = ( lcoCompareOrder );
+  TListCompareOptions = set of TListCompareOption;
+
+  TSDOBaseSerializer_Test = class(TWstBaseTest)
+  protected
+    class function CreateSerializerStream() : ISDOSerializerStream; virtual; abstract;
+  end;
+
+  { TSDOSerializer_Test }
+
+  TSDOSerializer_Test = class(TSDOBaseSerializer_Test)
+  private
+    function CreateSdoTypes() : ISDODataFactory;
+    function CreateCompanyObject(const AFactory : ISDODataFactory) : ISDODataObject;
+    procedure Compare(const A, B : ISDOChangedDataObjectListEx; const AOptions : TListCompareOptions = []);overload;
+    procedure Compare(const A, B : TDataObjectChangeInfo);overload;
+    procedure Compare(const A, B : TValueBuffer; const ADataType : TSDOTypeKind);overload;
+    procedure Compare(const A, B : TValueSetting);overload;
+    procedure Compare(const A, B : TManyValuePropChangesList);overload;
+  protected
+    procedure CheckEquals(expected, actual: TSDODate; msg: string = ''; const AStrict : Boolean = True); overload;
+
+    //function GetFileName() : string;
+    procedure CompareTypesInclude(
+      // A included in B ?
+      const A,B : ISDOTypeList
+    );
+  published
+    procedure save_to_stream();
+    procedure save_to_stream_without_name();
+    procedure save_to_file();
+    procedure save_to_file_without_name();
+    procedure save_to_file_null_bool_prop();
+    procedure save_to_file_null_byte_prop();
+    procedure save_to_file_null_bytes_prop(); 
+    procedure save_to_file_null_char_prop();
+    procedure save_to_file_null_currency_prop();
+    procedure save_to_file_null_datetime_prop(); 
+    procedure save_to_file_null_double_prop();  
+    procedure save_to_file_null_float_prop();  
+    procedure save_to_file_null_int_prop();    
+    procedure save_to_file_null_long_prop();    
+    procedure save_to_file_null_object_prop();    
+    procedure save_to_file_null_short_prop();  
+    procedure save_to_file_null_string_prop();
+
+    procedure load_from_stream_start_with_empty();
+    procedure load_from_stream_one_object();
+    procedure load_from_stream_two_object();
+    procedure load_from_file_start_with_empty();
+    procedure load_from_file_one_object();
+    procedure load_from_file_two_object();
+
+    // -- tests with ChangeSummary --
+    procedure save_to_file_changesummary_simple();
+    procedure save_to_file_changesummary_object_modify_nested();
+
+    procedure save_to_file_changesummary_prop_list_bool();
+    procedure save_to_file_changesummary_prop_list_byte();
+{$IFDEF HAS_SDO_BYTES}
+    procedure save_to_file_changesummary_prop_list_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure save_to_file_changesummary_prop_list_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure save_to_file_changesummary_prop_list_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure save_to_file_changesummary_prop_list_date();
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure save_to_file_changesummary_prop_list_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure save_to_file_changesummary_prop_list_float();
+{$ENDIF HAS_SDO_FLOAT}
+    procedure save_to_file_changesummary_prop_list_integer();
+{$IFDEF HAS_SDO_LONG}
+    procedure save_to_file_changesummary_prop_list_long();
+{$ENDIF HAS_SDO_LONG}
+    procedure save_to_file_changesummary_prop_list_object();
+    procedure save_to_file_changesummary_prop_list_object_nested();
+{$IFDEF HAS_SDO_SHORT}
+    procedure save_to_file_changesummary_prop_list_short();
+{$ENDIF HAS_SDO_SHORT}
+    procedure save_to_file_changesummary_prop_list_string();
+
+
+    procedure save_to_file_changesummary_object_create();
+    procedure save_to_file_changesummary_object_create_cont_ref();
+    procedure save_to_file_changesummary_object_delete();
+    procedure save_to_file_changesummary_object_delete_nested();
+    procedure save_to_file_changesummary_object_delete_2_objects_same_type();
+    procedure save_to_file_changesummary_object_2_objects_same_type_del_upd();
+
+
+    procedure load_from_file_changesummary_simple();
+    procedure load_from_file_changesummary_bool();
+    procedure load_from_file_changesummary_byte();
+{$IFDEF HAS_SDO_BYTES}
+    procedure load_from_file_changesummary_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure load_from_file_changesummary_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure load_from_file_changesummary_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure load_from_file_changesummary_date();
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure load_from_file_changesummary_double();
+{$ENDIF HAS_SDO_DOUBLE}
+    procedure load_from_file_changesummary_integer();
+{$IFDEF HAS_SDO_LONG}
+    procedure load_from_file_changesummary_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure load_from_file_changesummary_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_SHORT}
+    procedure load_from_file_changesummary_short();
+{$ENDIF HAS_SDO_SHORT}
+    procedure load_from_file_changesummary_string();
+
+
+    procedure load_from_file_changesummary_object_create_cont_ref();
+    procedure load_from_file_changesummary_object_delete();
+    procedure load_from_file_changesummary_object_delete_nested();
+    procedure load_from_file_changesummary_object_delete_2_objects_same_type();
+    procedure load_from_file_changesummary_object_2_objects_same_type_del_upd();
+    
+
+    procedure load_from_file_changesummary_prop_list_bool();
+    procedure load_from_file_changesummary_prop_list_byte();
+{$IFDEF HAS_SDO_BYTES}
+    procedure load_from_file_changesummary_prop_list_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure load_from_file_changesummary_prop_list_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure load_from_file_changesummary_prop_list_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+    procedure load_from_file_changesummary_prop_list_date();
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure load_from_file_changesummary_prop_list_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure load_from_file_changesummary_prop_list_float();
+{$ENDIF HAS_SDO_FLOAT}
+    procedure load_from_file_changesummary_prop_list_integer();
+{$IFDEF HAS_SDO_LONG}
+    procedure load_from_file_changesummary_prop_list_long();
+{$ENDIF HAS_SDO_LONG}
+    procedure load_from_file_changesummary_prop_list_object();
+    procedure load_from_file_changesummary_prop_list_object_nested();
+{$IFDEF HAS_SDO_SHORT}
+    procedure load_from_file_changesummary_prop_list_short();
+{$ENDIF HAS_SDO_SHORT}
+    procedure load_from_file_changesummary_prop_list_string();
+
+    procedure save_to_and_load_file_ref_prop_crash_1();
+    procedure save_to_and_load_file_ref_prop_crash_2();
+
+    procedure load_from_file_reference_property();
+    procedure save_object_open_type();
+    procedure load_object_open_type();
+  end;
+
+  TSDOSerializerXML_Test = class(TSDOSerializer_Test)
+  protected
+    class function CreateSerializerStream() : ISDOSerializerStream; override;
+  end;
+
+implementation
+
+uses
+  sdo_datafactory,
+  sdo_serialization_xml, sdo_dataobjectlist, sdo_equalityhelper
+{$IFNDEF FPC}
+  , xmldom, sdo_win_xml
+{$ELSE}
+  , DOM, sdo_fpc_xml, XMLRead, XMLWrite
+{$ENDIF}
+  , sdo_consts, sdo_utils, Math, DateUtils, sdo_date_utils;
+
+const
+  s_uri = 'company.xsd';
+  s_Employee = 'Employee';
+  s_EmployeeType = 'EmployeeType';
+  s_DepartmentType = 'DepartmentType';
+  s_CompanyType = 'CompanyType';
+  s_company = 'company';
+  s_list_bool = 'list_bool';
+  s_list_byte = 'list_byte';
+  s_list_bytes = 'list_bytes';
+  s_list_char = 'list_char';
+  s_list_currency = 'list_currency';
+  s_list_date = 'list_date';
+  s_list_double = 'list_double';
+  s_list_float = 'list_float';
+  s_list_int = 'list_int';
+  s_list_long = 'list_long';
+  s_list_object = 'list_object';
+  s_list_short = 'list_short';
+  s_list_string = 'list_string';
+  s_location = 'location';
+  s_manager = 'manager';
+  s_name = 'name';
+  s_number = 'number';
+  s_sn = 'SN';
+  s_age = 'age';
+  s_birthDate = 'birthDate';
+  
+  s_bool_prop               = 'bool_prop';
+  s_byte_prop               = 'byte_prop';
+  s_bytes_prop              = 'bytes_prop';
+  s_char_prop               = 'char_prop';
+  s_currency_prop           = 'currency_prop';
+  s_datetime_prop           = 'datetime_prop';
+  s_double_prop             = 'double_prop'; 
+  s_float_prop              = 'float_prop';      
+  s_int_prop                = 'int_prop';       
+  s_long_prop               = 'long_prop';   
+  s_object_prop             = 'object_prop';
+  s_object_type             = 'object_type';
+  s_object_type2            = 'object_type2';      
+  s_short_prop              = 'short_prop';   
+  s_string_prop             = 'string_prop';
+  
+
+function CompareNodes(const A,B : TDOMNode) : Boolean;overload;
+var
+  ca, cb : TDOMNode;
+  i : PtrInt;
+begin
+  if ( A = nil ) and ( B = nil ) then begin
+    Result := True;
+  end else if ( A <> nil ) and ( B <> nil ) then begin
+    Result := False;
+    if ( A.NodeName = B.NodeName ) and
+       ( A.NodeValue = B.NodeValue )
+    then begin
+      if ( ( A.FirstChild = nil ) and ( B.FirstChild = nil ) ) or
+         ( ( A.FirstChild <> nil ) and ( B.FirstChild <> nil ) )
+      then begin
+        ca := a.FirstChild;
+        cb := b.FirstChild;
+        while ( ca <> nil ) do begin
+          if not CompareNodes(ca,cb) then
+            Exit;
+          ca := ca.NextSibling;
+          cb := cb.NextSibling;
+        end;
+        if ( ( A.Attributes = nil ) and ( B.Attributes = nil ) ) or
+           ( ( A.Attributes <> nil ) and ( B.Attributes <> nil ) )
+        then begin
+          if ( A.Attributes <> nil ) then begin
+            if ( A.Attributes.Length <> B.Attributes.Length ) then
+              Exit;
+            if ( A.Attributes.Length > 0 ) then begin
+              for i := 0 to Pred(A.Attributes.Length) do begin
+                if not CompareNodes(A.Attributes.Item[i],B.Attributes.GetNamedItem(A.Attributes.Item[i].NodeName)) then
+                  Exit;
+              end;
+            end;
+          end;
+          Result := True;
+        end;
+      end;
+    end;
+  end else begin
+    Result := False;
+  end;
+end; 
+
+{ TSDOSerializer_Test }
+
+procedure TSDOSerializer_Test.CompareTypesInclude(const A, B: ISDOTypeList);
+var
+  i, c : PtrInt;
+  typA, typB : ISDOType;
+begin
+  if Assigned(A) then begin
+    Check(Assigned(B),'B = nil');
+    c := A.getCount();
+    if ( c > 0 ) then begin
+      for i := 0 to Pred(c) do begin
+        typA := A.getItem(i);
+        typB := B.find(typA.getURI(),typA.getName());
+        Check(typB.equals(typA),'A.getItem(i) <> B.find(typA.getURI(),typA.getName())');
+      end;
+    end;
+  end;
+end;
+
+function TSDOSerializer_Test.CreateCompanyObject(const AFactory : ISDODataFactory): ISDODataObject;
+var
+  locFactory : ISDODataFactory;
+  compObj, depObj, empObj : ISDODataObject;
+  depLs, empLs : ISDODataObjectList;
+begin
+  locFactory := AFactory;
+  compObj := locFactory.createNew(s_uri,s_company);
+
+  compObj.setString('name','A Sample company');
+  compObj.setString('employeeOfTheMonth','Inoussa');
+
+  depLs := compObj.getList('departments');
+  depObj := compObj.createDataObject('departments');
+  depLs.append(depObj);
+  depObj.setString('name','RAD Departement');
+  depObj.setString('location','Moon');
+  depObj.setInteger('number',2);
+    empLs := depObj.getList('employees');
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','inoussa OUEDRAOGO');
+      empObj.setString('SN','1122334455667');
+      empObj.setBoolean('manager',True);
+      empObj.setByte('age',32);
+    empLs.append(empObj);
+
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','SDO man');
+      empObj.setString('SN','867787667');
+      empObj.setBoolean('manager',False);
+      empObj.setByte('age',1);
+    empLs.append(empObj);
+
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','FPC');
+      empObj.setString('SN','_e-(''');
+      empObj.setBoolean('manager',False);
+      empObj.setByte('age',13);
+    empLs.append(empObj);
+
+
+  depObj := compObj.createDataObject('departments');
+  depLs.append(depObj);
+  depObj.setString('name','Sales Departement');
+  depObj.setString('location','Mars');
+  depObj.setInteger('number',2);
+    empLs := depObj.getList('employees');
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','wst man');
+      empObj.setString('SN','e"''fsdfdf');
+      empObj.setBoolean('manager',True);
+      empObj.setByte('age',2);
+    empLs.append(empObj);
+
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','azerty');
+      empObj.setString('SN','jkjk_e5679');
+      empObj.setBoolean('manager',False);
+    empLs.append(empObj);
+
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','qwerty');
+      empObj.setString('SN','_s-(''');
+      empObj.setBoolean('manager',False);
+    empLs.append(empObj);
+
+  Result := compObj;
+end;
+
+function TSDOSerializer_Test.CreateSdoTypes() : ISDODataFactory;
+var
+  locObj : ISDOType;
+begin
+  Result := TSDODataFactory.Create() as ISDODataFactory;
+  Result.AddType(s_uri,s_EmployeeType,[]);
+  locObj := Result.getType(s_uri,s_EmployeeType);
+    Result.addProperty(locObj,'name',sdo_namespace,'string',[pfIsAttribute]);
+    Result.addProperty(locObj,'SN',sdo_namespace,'string',[pfIsAttribute]);
+    Result.addProperty(locObj,'manager',sdo_namespace,'boolean',[pfIsAttribute]);
+    Result.addProperty(locObj,'age',sdo_namespace,'byte',[pfIsAttribute]);
+
+  Result.AddType(s_uri,s_DepartmentType,[]);
+  locObj := Result.getType(s_uri,s_DepartmentType);
+    Result.addProperty(locObj,'employees',s_uri,s_EmployeeType,[pfIsMany, pfIsContainment]);
+    Result.addProperty(locObj,'name',sdo_namespace,'string',[pfIsAttribute]);
+    Result.addProperty(locObj,'location',sdo_namespace,'string',[pfIsAttribute]);
+    Result.addProperty(locObj,'number',sdo_namespace,'integer',[pfIsAttribute]);
+
+  Result.AddType(s_uri,s_CompanyType,[]);
+  locObj := Result.getType(s_uri,s_CompanyType);
+    Result.setAlias(locObj.getURI(),locObj.getName(),s_company);
+    Result.addProperty(locObj,'departments',s_uri,s_DepartmentType,[pfIsMany, pfIsContainment]);
+    Result.addProperty(locObj,'name',sdo_namespace,'string',[pfIsAttribute]);
+    Result.addProperty(locObj,'employeeOfTheMonth',sdo_namespace,'string',[pfIsAttribute]);
+    Result.setAlias(s_uri,locObj.getName(),s_company);
+end;
+
+procedure TSDOSerializer_Test.load_from_stream_one_object();
+var
+  locFactory, tmpFactory : ISDODataFactory;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  strm : TMemoryStream;
+  ol : ISDODataObjectList;
+  locComp : ISDODataObject;
+begin
+  strm := TMemoryStream.Create();
+  try
+    strm.LoadFromFile(sdoExpandLocalFileName(TestFilesPath + 'company.one.xml'));
+    strm.Position := 0;
+    f := TSDOSerializerStreamXML.Create();
+    tmpFactory := TSDODataFactory.Create();
+    s := TSDOSerializer.Create(tmpFactory,f);
+    ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+    s.load(strm,ol);
+
+    locFactory := CreateSdoTypes();
+    CompareTypesInclude(tmpFactory.getTypes(), locFactory.getTypes());
+    CompareTypesInclude(locFactory.getTypes(), tmpFactory.getTypes());
+    CheckEquals(1,ol.size(),'loaded objects count');
+    locComp := CreateCompanyObject(locFactory);
+    ol.getCursor().MoveFirst();
+    CheckEquals(True,TSDOEqualityHelper.equalShallow(locComp, ol.getDataObject()),'equalShallow');
+    CheckEquals(True,TSDOEqualityHelper.equal(locComp, ol.getDataObject()),'equal');
+  finally
+    strm.Free();
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_stream_start_with_empty();
+var
+  locFactory, tmpFactory : ISDODataFactory;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  strm : TMemoryStream;
+  ol : ISDODataObjectList;
+begin
+  strm := TMemoryStream.Create();
+  try
+    strm.LoadFromFile(sdoExpandLocalFileName(TestFilesPath + 'company.xml'));
+    strm.Position := 0;
+    f := TSDOSerializerStreamXML.Create();
+    tmpFactory := TSDODataFactory.Create();
+    s := TSDOSerializer.Create(tmpFactory,f);
+    ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+    s.load(strm,ol);
+    locFactory := CreateSdoTypes();
+    CompareTypesInclude(tmpFactory.getTypes(), locFactory.getTypes());
+    CompareTypesInclude(locFactory.getTypes(), tmpFactory.getTypes());
+  finally
+    strm.Free();
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_stream_two_object();
+var
+  locFactory, tmpFactory : ISDODataFactory;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  strm : TMemoryStream;
+  ol : ISDODataObjectList;
+  locComp : ISDODataObject;
+begin
+  strm := TMemoryStream.Create();
+  try
+    strm.LoadFromFile(sdoExpandLocalFileName(TestFilesPath + 'company.two.xml'));
+    strm.Position := 0;
+    f := TSDOSerializerStreamXML.Create();
+    tmpFactory := TSDODataFactory.Create();
+    s := TSDOSerializer.Create(tmpFactory,f);
+    ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+    s.load(strm,ol);
+
+    locFactory := CreateSdoTypes();
+    CompareTypesInclude(tmpFactory.getTypes(), locFactory.getTypes());
+    CompareTypesInclude(locFactory.getTypes(), tmpFactory.getTypes());
+    CheckEquals(2,ol.size(),'loaded objects count');
+    locComp := CreateCompanyObject(locFactory);
+    locComp.setString('name','A Second Sample company');
+    ol.getCursor().MoveFirst();
+    CheckEquals(True,TSDOEqualityHelper.equalShallow(locComp, ol.getDataObject()),'equalShallow');
+    CheckEquals(True,TSDOEqualityHelper.equal(locComp, ol.getDataObject()),'equal');
+  finally
+    strm.Free();
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_stream();
+var
+  locFactory : ISDODataFactory;
+  compObj : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  strm : TMemoryStream;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  locFactory := CreateSdoTypes();
+  compObj := CreateCompanyObject(locFactory);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFactory,f);
+  strm := TMemoryStream.Create();
+  try
+    s.save(s_CompanyType,compObj,strm);
+{$IFDEF TEST_GENERATE_FILE}
+    strm.SaveToFile(sdoExpandLocalFileName('company.soap.xml'));
+{$ENDIF TEST_GENERATE_FILE}    
+
+    strm.Position := 0;
+    existDoc := nil;
+    serialDoc := nil;
+    ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'company.one.xml'));
+    try
+      ReadXMLFile(serialDoc,strm);
+      CheckEquals(True, CompareNodes(existDoc,serialDoc));
+    finally
+      ReleaseDomNode(existDoc);
+      ReleaseDomNode(serialDoc);
+    end;
+  finally
+    strm.Free();
+  end;
+end;
+
+{procedure TSDOSerializer_Test.save2();
+var
+  locFactory : ISDODataFactory;
+  compObj, depObj, empObj : ISDODataObject;
+  depLs, empLs : ISDODataObjectList;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  strm : TMemoryStream;
+  i : Integer;
+  dd, ff : TDateTime;
+begin
+  dd := Now();
+  locFactory := CreateSdoTypes();
+  compObj := locFactory.createNew(s_uri,s_company);
+
+  compObj.setString('name','A Sample company');
+  compObj.setString('employeeOfTheMonth','Inoussa');
+
+  depLs := compObj.getList('departments');
+  depObj := compObj.createDataObject('departments');
+  depLs.append(depObj);
+  depObj.setString('name','RAD Departement');
+  depObj.setString('location','Moon');
+  depObj.setInteger('number',2);
+    empLs := depObj.getList('employees');
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','inoussa OUEDRAOGO');
+      empObj.setString('SN','1122334455667');
+      empObj.setBoolean('manager',True);
+    empLs.append(empObj);
+
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','SDO man');
+      empObj.setString('SN','867787667');
+      empObj.setBoolean('manager',False);
+    empLs.append(empObj);
+
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','FPC');
+      empObj.setString('SN','_e-(''');
+      empObj.setBoolean('manager',False);
+    empLs.append(empObj);
+
+
+  depObj := compObj.createDataObject('departments');
+  depLs.append(depObj);
+  depObj.setString('name','Sales Departement');
+  depObj.setString('location','Mars');
+  depObj.setInteger('number',2);
+    empLs := depObj.getList('employees');
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','wst man');
+      empObj.setString('SN','e"''fsdfdf');
+      empObj.setBoolean('manager',True);
+    empLs.append(empObj);
+
+    empObj := depObj.createDataObject('employees');
+      empObj.setString('name','azerty');
+      empObj.setString('SN','jkjk_e5679');
+      empObj.setBoolean('manager',False);
+    empLs.append(empObj);
+
+    for i := 0 to 10000 do begin
+      empObj := depObj.createDataObject('employees');
+        empObj.setString('name','Personne N°' + IntToStr(i));
+        empObj.setString('SN','#'+ IntToStr(i));
+        empObj.setBoolean('manager',( i mod 3 ) = 0 );
+      empLs.append(empObj);
+    end;
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFactory,f);
+  strm := TMemoryStream.Create();
+  s.save('compagnie',compObj,strm);
+
+  strm.Position := 0;
+  f := TSDOSerializerStreamXML.Create();
+  f.LoadFromStream(strm);
+  ff := Now();
+  //ShowMessageFmt('%s'#13'%s'#13'Size=%d',[DateTimeToStr(dd),DateTimeToStr(ff),strm.Size]);
+  strm.SaveToFile('.' + PathDelim + 'company2.soap.xml');
+end; }
+
+procedure TSDOSerializer_Test.save_to_stream_without_name();
+var
+  locFactory : ISDODataFactory;
+  compObj : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  strm : TMemoryStream;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  locFactory := CreateSdoTypes();
+  compObj := CreateCompanyObject(locFactory);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFactory,f);
+  strm := TMemoryStream.Create();
+  try
+    s.save(compObj,strm);
+
+    strm.Position := 0;
+    existDoc := nil;
+    serialDoc := nil;
+    ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'company.one.xml'));
+    try
+      ReadXMLFile(serialDoc,strm);
+      CheckEquals(True, CompareNodes(existDoc,serialDoc));
+    finally
+      ReleaseDomNode(existDoc);
+      ReleaseDomNode(serialDoc);       
+    end;
+  finally
+    FreeAndNil(strm);
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file();
+var
+  locFactory : ISDODataFactory;
+  compObj : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  existDoc, serialDoc : TSDOXMLDocument;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName('save_to_file.xml');
+  locFactory := CreateSdoTypes();
+  compObj := CreateCompanyObject(locFactory);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFactory,f);
+  s.save(s_CompanyType,compObj,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'company.one.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file_without_name();
+var
+  locFactory : ISDODataFactory;
+  compObj : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  existDoc, serialDoc : TSDOXMLDocument;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName('save_to_file.xml');
+  locFactory := CreateSdoTypes();
+  compObj := CreateCompanyObject(locFactory);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFactory,f);
+  s.save(compObj,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'company.one.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_bool_prop();
+const
+  TARGET_PROP_NAME = s_bool_prop; TARGET_PROP_TYPE_NAME = 'Boolean';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;              
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_byte_prop(); 
+const
+  TARGET_PROP_NAME = s_byte_prop; TARGET_PROP_TYPE_NAME = 'Byte';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;       
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_bytes_prop(); 
+const
+  TARGET_PROP_NAME = s_bytes_prop; TARGET_PROP_TYPE_NAME = 'Bytes';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;   
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_char_prop(); 
+const
+  TARGET_PROP_NAME = s_char_prop; TARGET_PROP_TYPE_NAME = 'Character';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;          
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_currency_prop();  
+const
+  TARGET_PROP_NAME = s_currency_prop; TARGET_PROP_TYPE_NAME = 'Currency';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end; 
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_datetime_prop();   
+const
+  TARGET_PROP_NAME = s_datetime_prop; TARGET_PROP_TYPE_NAME = 'DateTime';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;         
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_double_prop();
+const
+  TARGET_PROP_NAME = s_double_prop; TARGET_PROP_TYPE_NAME = 'Double';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;      
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_float_prop();
+const
+  TARGET_PROP_NAME = s_float_prop; TARGET_PROP_TYPE_NAME = 'Float';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;      
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_int_prop();  
+const
+  TARGET_PROP_NAME = s_int_prop; TARGET_PROP_TYPE_NAME = 'Integer';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_string_prop,sdo_namespace,'String',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setString(s_string_prop,'azerty');
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getString(s_string_prop), locInstanceLoaded.getString(s_string_prop),s_string_prop);
+  finally
+    ms.Free();
+  end;   
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_long_prop(); 
+const
+  TARGET_PROP_NAME = s_long_prop; TARGET_PROP_TYPE_NAME = 'Long';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;  
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_object_prop(); 
+const
+  TARGET_PROP_NAME = s_object_prop; TARGET_PROP_TYPE_NAME = s_object_type2;
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    Result.AddType(s_uri,s_object_type2,[]);           
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,s_uri,TARGET_PROP_TYPE_NAME,[pfIsContainment]);
+    locObj := Result.getType(s_uri,s_object_type2);
+      Result.addProperty(locObj,s_string_prop,sdo_namespace,'String',[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;  
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_short_prop();
+const
+  TARGET_PROP_NAME = s_short_prop; TARGET_PROP_TYPE_NAME = 'Short';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end;  
+end;
+
+procedure TSDOSerializer_Test.save_to_file_null_string_prop(); 
+const
+  TARGET_PROP_NAME = s_string_prop; TARGET_PROP_TYPE_NAME = 'String';
+  
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+  begin
+    Result := TSDODataFactory.Create() as ISDODataFactory;
+    Result.AddType(s_uri,s_object_type,[]);
+    locObj := Result.getType(s_uri,s_object_type);
+      Result.addProperty(locObj,s_int_prop,sdo_namespace,'Integer',[]);
+      Result.addProperty(locObj,TARGET_PROP_NAME,sdo_namespace,TARGET_PROP_TYPE_NAME,[]);
+  end;
+  
+var
+  locFactory : ISDODataFactory;
+  locInstance, locInstanceLoaded : ISDODataObject;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ms : TMemoryStream;
+begin
+  locFactory := CreateFactory();
+  locInstance := locFactory.createNew(s_uri,s_object_type);
+  locInstance.setNull(TARGET_PROP_NAME);
+  locInstance.setInteger(s_int_prop,123);
+
+  ms := TMemoryStream.Create();
+  try
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    s.save(locInstance,ms);  
+    
+    f := TSDOSerializerStreamXML.Create();
+    s := TSDOSerializer.Create(locFactory,f);
+    ms.Position := 0;
+    locInstanceLoaded := s.load(ms);
+    CheckEquals(locInstance.isNull(TARGET_PROP_NAME), locInstanceLoaded.isNull(TARGET_PROP_NAME),Format('isNull(%s)',[TARGET_PROP_NAME]));
+    CheckEquals(locInstance.getInteger(s_int_prop), locInstanceLoaded.getInteger(s_int_prop),s_int_prop);
+  finally
+    ms.Free();
+  end; 
+end;
+
+procedure TSDOSerializer_Test.load_from_file_start_with_empty();
+var
+  locFactory, tmpFactory : ISDODataFactory;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ol : ISDODataObjectList;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'company.xml');
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+  locFactory := CreateSdoTypes();
+  CompareTypesInclude(tmpFactory.getTypes(), locFactory.getTypes());
+  CompareTypesInclude(locFactory.getTypes(), tmpFactory.getTypes());
+end;
+
+procedure TSDOSerializer_Test.load_from_file_one_object();
+var
+  locFactory, tmpFactory : ISDODataFactory;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ol : ISDODataObjectList;
+  locComp : ISDODataObject;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'company.one.xml');
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+
+  locFactory := CreateSdoTypes();
+  CompareTypesInclude(tmpFactory.getTypes(), locFactory.getTypes());
+  CompareTypesInclude(locFactory.getTypes(), tmpFactory.getTypes());
+  CheckEquals(1,ol.size(),'loaded objects count');
+  locComp := CreateCompanyObject(locFactory);
+  ol.getCursor().MoveFirst();
+  CheckEquals(True,TSDOEqualityHelper.equalShallow(locComp, ol.getDataObject()),'equalShallow');
+  CheckEquals(True,TSDOEqualityHelper.equal(locComp, ol.getDataObject()),'equal');
+end;
+
+procedure TSDOSerializer_Test.load_from_file_two_object();
+var
+  locFactory, tmpFactory : ISDODataFactory;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  ol : ISDODataObjectList;
+  locComp : ISDODataObject;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'company.two.xml');
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+
+  locFactory := CreateSdoTypes();
+  CompareTypesInclude(tmpFactory.getTypes(), locFactory.getTypes());
+  CompareTypesInclude(locFactory.getTypes(), tmpFactory.getTypes());
+  CheckEquals(2,ol.size(),'loaded objects count');
+  locComp := CreateCompanyObject(locFactory);
+  locComp.setString('name','A Second Sample company');
+  ol.getCursor().MoveFirst();
+  CheckEquals(True,TSDOEqualityHelper.equalShallow(locComp, ol.getDataObject()),'equalShallow');
+  CheckEquals(True,TSDOEqualityHelper.equal(locComp, ol.getDataObject()),'equal');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_simple();
+var
+  locFac : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('change_summary_simple.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_age,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setString(s_name,'Inoussa O.');
+    locEmployee.setString(s_sn,'002');
+    locEmployee.setBoolean(s_manager,True);
+    locEmployee.setByte(s_age,30);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();
+    locEmployee.setString(s_name,'Inoussa OUEDRAOGO');
+    locEmployee.setString(s_sn,'001');
+    locEmployee.setByte(s_age,32);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_Employee,locEmployee,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'change_summary_simple.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.Compare(const A, B: ISDOChangedDataObjectListEx; const AOptions : TListCompareOptions);
+var
+  i, c, j, k : PtrInt;
+  tmpObj : ISDODataObject;
+begin
+  Check(
+    ( ( A = nil ) and ( B = nil ) ) or
+    ( ( A <> nil ) and ( B <> nil ) ) ,
+    'nil'
+  );
+  if ( A <> nil ) then begin
+    CheckEquals(A.size(),B.size(), 'size()');
+    c := A.size();
+    if ( c > 0 ) then begin
+      if ( lcoCompareOrder in AOptions ) then begin
+        for i := 0 to Pred(c) do begin
+          CheckEquals(Ord(A.getType(i)), Ord(B.getType(i)), Format('getType(%d)',[i]));
+          Check(TSDOEqualityHelper.equal(A.getDataObject(i),B.getDataObject(i)),Format('A.getDataObject(%d)',[i]));
+          Compare(A.getInfo(i),B.getInfo(i));
+        end;
+      end else begin
+        for i := 0 to Pred(c) do begin
+          tmpObj := A.getDataObject(i);
+          k := -1;
+          for j := 0 to Pred(B.size()) do begin
+            if TSDOEqualityHelper.equal(tmpObj,B.getDataObject(j)) then begin
+              k := j;
+              Break;
+            end;
+          end;
+          Check( ( k > -1 ), Format('Object not found  : A.getDataObject(%d)',[i]));
+          CheckEquals(Ord(A.getType(i)), Ord(B.getType(k)), Format('getType(%d)',[i]));
+          Check(TSDOEqualityHelper.equal(A.getDataObject(i),B.getDataObject(k)),Format('A.getDataObject(%d), B.getDataObject(%d)',[i,k]));
+          Compare(A.getInfo(i),B.getInfo(k));
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_simple();
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'change_summary_simple.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+    locFac.addProperty(s_uri,s_Employee,s_age,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setString(s_name,'Inoussa O.');
+    locEmployee.setString(s_sn,'002');
+    locEmployee.setBoolean(s_manager,True);
+    locEmployee.setByte(s_age,30);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();
+    locEmployee.setString(s_name,'Inoussa OUEDRAOGO');
+    locEmployee.setString(s_sn,'001');
+    locEmployee.setByte(s_age,32);
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.Compare(const A, B: TDataObjectChangeInfo);
+var
+  i, c, j : PtrInt;
+  ok : Boolean;
+  x, y : TValueSetting;
+begin
+  Check( ( A = nil ) or ( B <> nil ), 'nil');
+  if ( A <> nil ) then begin
+    A.ExtractPendingOldValues();
+    B.ExtractPendingOldValues();
+    Check(TSDOEqualityHelper.equal(A.DataObject,B.DataObject));
+    CheckEquals(Ord(A.ChangeType), Ord(B.ChangeType), 'ChangeType');
+    Check(TSDOEqualityHelper.equal(A.OldContainer,B.OldContainer));
+    CheckEquals(A.ChangeList.size(),B.ChangeList.size(),'ChangeList.size()');
+    c := A.ChangeList.size();
+    if ( c > 0 ) then begin
+      y := nil;
+      for i := 0 to Pred(c) do begin
+        x := A.ChangeList.getItem(i);
+        ok := False;
+        for j := 0 to ( c - 1 ) do begin
+          y := B.ChangeList.getItem(j);
+          if ( x.getProperty().getName() = y.getProperty().getName() ) and
+             x.getProperty().getType().equals(y.getProperty().getType()) and
+             ( x.getIndex() = y.getIndex() )
+          then begin
+            ok := True;
+            Break;
+          end;
+        end;
+        Check(ok, Format('A.ChangeList.getItem(%d) %s, not found.',[i, x.getProperty().getName()]));
+        Compare(x,y);
+      end;
+    end;
+    Check(
+      ( ( A.ManyValuePropChangesList = nil ) and ( B.ManyValuePropChangesList = nil ) ) or
+      ( ( A.ManyValuePropChangesList <> nil ) and ( B.ManyValuePropChangesList <> nil ) ),
+      'ManyValuePropChangesList'
+    );
+    if ( A.ManyValuePropChangesList <> nil ) then begin
+      Compare(A.ManyValuePropChangesList, B.ManyValuePropChangesList);
+    end;
+  end;
+end;
+
+procedure TSDOSerializer_Test.Compare(const A, B: TValueSetting);
+begin
+  Check( ( A = nil ) or ( B <> nil ), 'nil');
+  if ( A <> nil ) then begin
+    CheckEquals(A.getProperty().getName(), B.getProperty().getName(), 'getProperty().getName()');
+    Check(A.getProperty().getType().equals(B.getProperty().getType()), 'getProperty().getType()');
+    CheckEquals(A.isSet, B.isSet, Format('%s.isSet',[A.getProperty().getName()]));
+    CheckEquals(A.isNull, B.isNull, 'isNull');
+    case A.getProperty.getTypeEnum() of
+      BooleanType   : CheckEquals(A.getBooleanValue(),B.getBooleanValue(),'getBooleanValue()');
+      ByteType      : CheckEquals(A.getByteValue(),B.getByteValue(),'getByteValue()');
+{$IFDEF HAS_SDO_BYTES}
+      BytesType     : CheckEquals(A.getBytesValue(),B.getBytesValue(),'getBytesValue()');
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+      CharacterType : CheckEquals(A.getCharacterValue(),B.getCharacterValue(),'getCharacterValue()');
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+      CurrencyType  : CheckEquals(A.getCurrencyValue(),B.getCurrencyValue(),'getCurrencyValue()');
+{$ENDIF HAS_SDO_CURRENCY}
+      DateType      : CheckEquals(A.getDateValue(),B.getDateValue(),'getDateValue()',False);
+{$IFDEF HAS_SDO_DOUBLE}
+      DoubleType    : CheckEquals(A.getDoubleValue(),B.getDoubleValue(),'getDoubleValue()');
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+      FloatType     : CheckEquals(A.getFloatValue(),B.getFloatValue(),'getFloatValue()');
+{$ENDIF HAS_SDO_FLOAT}
+      IntegerType   : CheckEquals(A.getIntegerValue(),B.getIntegerValue(),'getIntegerValue()');
+{$IFDEF HAS_SDO_LONG}
+      LongType      : CheckEquals(A.getLongValue(),B.getLongValue(),'getLongValue()');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+      ShortType     : CheckEquals(A.getShortValue(),B.getShortValue(),'getShortValue()');
+{$ENDIF HAS_SDO_SHORT}
+      ObjectType    : Check(TSDOEqualityHelper.equal(A.getDataObjectValue(),B.getDataObjectValue()),'getDataObjectValue()');
+      StringType    : CheckEquals(A.getStringValue(),B.getStringValue(),'getStringValue()');
+      else
+        Assert(False);
+    end;
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_object_modify_nested();
+var
+  locFac : ISDODataFactory;
+  locDep, locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('change_summary_object_modify_nested.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_Employee,s_uri,s_Employee,[pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_age,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    locEmployee := locDep.createDataObject(s_Employee);
+      locEmployee.setString(s_name,'Inoussa O.');
+      locEmployee.setString(s_sn,'002');
+      locEmployee.setBoolean(s_manager,True);
+      locEmployee.setByte(s_age,12);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+      locEmployee.setString(s_name,'Inoussa OUEDRAOGO');
+      locEmployee.setString(s_sn,'001');
+      locEmployee.setByte(s_age,32);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_modify_nested.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_integer();
+const
+  FILE_NAME = 'changesummary_prop_list_integer.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_int,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_int);
+      ls.append(1);
+      ls.append(2);
+      ls.append(3);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setInteger(0,10);
+    ls.append(123);
+    ls.append(456);
+    ls.setInteger(1,20);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, 1076);
+    ls.append(789);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}
+
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_object_create();
+var
+  locFac : ISDODataFactory;
+  locDep, locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('change_summary_object_create.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_Employee,s_uri,s_Employee,[pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+  locCS := locDep.getChangeSummary();
+    locDep.setString(s_location,'Ouaga, BF');
+  locCS.beginLogging();
+    locDep.setInteger(s_number,1210);
+    locEmployee := locDep.createDataObject(s_Employee);
+      locEmployee.setString(s_name,'Inoussa O.');
+      locEmployee.setString(s_sn,'002');
+      locEmployee.setBoolean(s_manager,True);
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+      locEmployee.setString(s_name,'Inoussa OUEDRAOGO');
+      locEmployee.setString(s_sn,'001');
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_create.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_object_create_cont_ref();
+var
+  locFac : ISDODataFactory;
+  locDep, locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('change_summary_object_create_cont_ref.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_Employee,s_uri,s_Employee,[pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,'employee_ref',s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+  locCS := locDep.getChangeSummary();
+    locDep.setString(s_location,'Ouaga, BF');
+  locCS.beginLogging();
+    locDep.setInteger(s_number,1210);
+    locEmployee := locDep.createDataObject(s_Employee);
+      locEmployee.setString(s_name,'Inoussa O.');
+      locEmployee.setString(s_sn,'002');
+      locEmployee.setBoolean(s_manager,True);
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    locDep.setDataObject('employee_ref',locEmployee);
+      locEmployee.setString(s_name,'Inoussa OUEDRAOGO');
+      locEmployee.setString(s_sn,'001');
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_create_cont_ref.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_object_create_cont_ref();
+var
+  locFac : ISDODataFactory;
+  locDep, locEmployee, locLoadedDep : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName('change_summary_object_create_cont_ref.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_Employee,s_uri,s_Employee,[pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,'employee_ref',s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsAttribute]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+  locCS := locDep.getChangeSummary();
+    locDep.setString(s_location,'Ouaga, BF');
+  locCS.beginLogging();
+    locDep.setInteger(s_number,1210);
+    locEmployee := locDep.createDataObject(s_Employee);
+      locEmployee.setString(s_name,'Inoussa O.');
+      locEmployee.setString(s_sn,'002');
+      locEmployee.setBoolean(s_manager,True);
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    locDep.setDataObject('employee_ref',locEmployee);
+      locEmployee.setString(s_name,'Inoussa OUEDRAOGO');
+      locEmployee.setString(s_sn,'001');
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  locLoadedDep := s.load(sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_create_cont_ref.xml'));
+    Check(TSDOEqualityHelper.equal(locLoadedDep,locDep),'Object');
+    Compare(
+      locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locDep.getChangeSummary().undoChanges();
+    locLoadedDep.getChangeSummary().undoChanges();
+      CheckEquals( 0, locDep.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals( 0, locLoadedDep.getChangeSummary().getChangedDataObjects().size());
+      Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_object_delete();
+var
+  locFac : ISDODataFactory;
+  locDep, locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('change_summary_object_delete.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_Employee,s_uri,s_Employee,[pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], [pfIsAttribute]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locEmployee := locDep.createDataObject(s_Employee);
+      locEmployee.setString(s_name,'Inoussa O.');
+      locEmployee.setString(s_sn,'002');
+      locEmployee.setBoolean(s_manager,True);
+  locCS := locDep.getChangeSummary();
+    locDep.setString(s_location,'Ouaga, BF');
+  locCS.beginLogging();
+    locDep.setInteger(s_number,1210);
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    locDep.setDataObject(s_Employee,nil);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_delete.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_object_delete();
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locEmployee, locLoadedDep : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_delete.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+    locFac.addProperty(s_uri,s_DepartmentType,s_Employee,s_uri,s_Employee,[pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+    locFac.addProperty(s_uri,s_Employee,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+    locFac.addProperty(s_uri,s_Employee,s_sn,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+    locFac.addProperty(s_uri,s_Employee,s_manager,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locEmployee := locDep.createDataObject(s_Employee);
+      locEmployee.setString(s_name,'Inoussa O.');
+      locEmployee.setString(s_sn,'002');
+      locEmployee.setBoolean(s_manager,True);
+  locCS := locDep.getChangeSummary();
+    locDep.setString(s_location,'Ouaga, BF');
+  locCS.beginLogging();
+    locDep.setInteger(s_number,1210);
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    locDep.setDataObject(s_Employee,nil);     (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,'change_summary_object_delete.xml');
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep,locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+
+  locDep.getChangeSummary().undoChanges();
+  locLoadedDep.getChangeSummary().undoChanges();
+    CheckEquals( 0, locDep.getChangeSummary().getChangedDataObjects().size());
+    CheckEquals( 0, locLoadedDep.getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_object_delete_nested();
+var
+  locFac : ISDODataFactory;
+  locA, locB, locC, locD : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('change_summary_object_delete_nested.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+  locFac.AddType(s_uri,'c',[]);
+  locFac.AddType(s_uri,'d',[]);
+    locFac.addProperty(s_uri,'a','p_a_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ac',s_uri,'c',[]);
+    locFac.addProperty(s_uri,'a','p_ad',s_uri,'d',[]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+      locFac.addProperty(s_uri,'b','p_bc',s_uri,'c',[pfIsContainment]);
+      locFac.addProperty(s_uri,'b','p_b_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+        locFac.addProperty(s_uri,'c','p_cd',s_uri,'d',[pfIsContainment]);
+        locFac.addProperty(s_uri,'c','p_c_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+          locFac.addProperty(s_uri,'d','p_d_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.setString('p_a_str','sample A'' property.');
+    locB := locA.createDataObject('p_ab');
+      locB.setString('p_b_str','Inoussa O.');
+      locC := locB.createDataObject('p_bc');
+      locC.setString('p_c_str','azerty');
+      locD := locC.createDataObject('p_cd');
+        locD.setString('p_d_str','D value');
+    locA.setDataObject('p_ac',locC);
+    locA.setDataObject('p_ad',locD);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locC.setDataObject('p_cd',nil);
+    locA.setDataObject('p_ab',nil);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save('a',locA,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_delete_nested.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_integer();
+const
+  FILE_NAME = 'changesummary_prop_list_integer.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_int,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_int);
+      ls.append(1);
+      ls.append(2);
+      ls.append(3);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setInteger(0,10);
+    ls.append(123);
+    ls.append(456);
+    ls.setInteger(1,20);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, 1076);
+    ls.append(789);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_long();
+const
+  PROP_NAME = s_list_long;
+  PROP_TYPE = LongType;
+  FILE_NAME = 'changesummary_prop_list_long.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(PROP_NAME);
+      ls.append(TSDOLong(11111111111111111));
+      ls.append(TSDOLong(-2222222222222222));
+      ls.append(TSDOLong(333333333333333333));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setLong(0,4444444444444444444);
+    ls.append(TSDOLong(5555555555555555555));
+    ls.append(TSDOLong(-6666666666666666666));
+    ls.setLong(1,7777777777777777777);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOLong(8));
+    ls.append(TSDOLong(-9));
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+    
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_short();
+const
+  PROP_NAME = s_list_short;
+  PROP_TYPE = ShortType;
+  FILE_NAME = 'changesummary_prop_list_short.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(PROP_NAME);
+      ls.append(TSDOShort(1));
+      ls.append(TSDOShort(2));
+      ls.append(TSDOShort(3));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setShort(0,10);
+    ls.append(TSDOShort(12345));
+    ls.append(TSDOShort(-5245));
+    ls.setShort(1,20);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOShort(107));
+    ls.append(TSDOShort(89));
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+    
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOSerializer_Test.Compare(const A, B : TManyValuePropChangesList);
+var
+  i, c, q, k : PtrInt;
+  x, y : TManyValuePropChanges;
+  xd, yd : TManyValuePropRecordData;
+begin
+  Check(
+    ( ( A = nil ) and ( B = nil ) ) or
+    ( ( A <> nil ) and ( B <> nil ) ) ,
+    'nil'
+  );
+  if ( A <> nil ) then begin
+    CheckEquals(A.Count(),B.Count(), 'Count()');
+    c := A.Count();
+    if ( c > 0 ) then begin
+      for i := 0 to Pred(c) do begin
+        x := A.Item[i];
+        y := B.Item[i];
+        CheckEquals(x.Prop.getName(), y.Prop.getName(), Format('item[%d] : Property ( name )',[i]));
+        Check(x.Prop.getType().equals(y.Prop.getType()), Format('item[%d] : Property ( type )',[i]));
+        CheckEquals(x.Count, y.Count, Format('item[%d] : Count',[i]));
+        q := x.Count;
+        if ( q > 0 ) then begin
+          for k := 0 to Pred(q) do begin
+            xd := x.GetItem(i);
+            yd := y.GetItem(i);
+            CheckEquals(Ord(xd.Action), Ord(yd.Action), Format('item[%d][%d].Action : Count',[i,k]));
+            CheckEquals(xd.Index, yd.Index, Format('item[%d][%d].Index : Count',[i,k]));
+            Compare(xd.Value, yd.Value, x.Prop.getTypeEnum());
+          end;
+        end;
+      end;
+    end;
+  end;
+end;
+
+procedure TSDOSerializer_Test.Compare(const A, B: TValueBuffer; const ADataType : TSDOTypeKind);
+begin
+  case ADataType of
+    BooleanType   : CheckEquals(A.BooleanValue,B.BooleanValue,'BooleanValue');
+    ByteType      : CheckEquals(A.ByteValue,B.ByteValue,'ByteValue');
+{$IFDEF HAS_SDO_BYTES}
+    BytesType     : CheckEquals(A.BytesValue^,B.BytesValue^,'BytesValue');
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    CharacterType : CheckEquals(A.CharValue,B.CharValue,'CharValue');
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    CurrencyType  : CheckEquals(A.CurrencyValue,B.CurrencyValue,'CurrencyValue');
+{$ENDIF HAS_SDO_CURRENCY}
+    DateTimeType  : CheckEquals(A.DateValue,B.DateValue,'DateValue',False);
+{$IFDEF HAS_SDO_DOUBLE}
+    DoubleType    : CheckEquals(A.DoubleValue,B.DoubleValue,'DoubleValue');
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    FloatType     : CheckEquals(A.FloatValue,B.FloatValue,'FloatValue');
+{$ENDIF HAS_SDO_FLOAT}
+    IntegerType   : CheckEquals(A.IntegerValue,B.IntegerValue,'IntegerValue');
+{$IFDEF HAS_SDO_LONG}
+    LongType      : CheckEquals(A.LongValue,B.LongValue,'LongValue');
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    ShortType     : CheckEquals(A.ShortValue,B.ShortValue,'ShortValue');
+{$ENDIF HAS_SDO_SHORT}
+    ObjectType    : Check(TSDOEqualityHelper.equal(A.ObjectValue^,B.ObjectValue^),'ObjectValue');
+    StringType    : CheckEquals(A.StringValue^,B.StringValue^,'StringValue');
+    else
+      Assert(False);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_object_delete_nested();
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locA, locB, locC, locD, locLoadedA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'change_summary_object_delete_nested.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+  locFac.AddType(s_uri,'c',[]);
+  locFac.AddType(s_uri,'d',[]);
+    locFac.addProperty(s_uri,'a','p_a_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+    locFac.addProperty(s_uri,'a','p_ab',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ac',s_uri,'c',[]);
+    locFac.addProperty(s_uri,'a','p_ad',s_uri,'d',[]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+      locFac.addProperty(s_uri,'b','p_bc',s_uri,'c',[pfIsContainment]);
+      locFac.addProperty(s_uri,'b','p_b_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+        locFac.addProperty(s_uri,'c','p_cd',s_uri,'d',[pfIsContainment]);
+        locFac.addProperty(s_uri,'c','p_c_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+          locFac.addProperty(s_uri,'d','p_d_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.setString('p_a_str','sample A'' property.');
+    locB := locA.createDataObject('p_ab');
+      locB.setString('p_b_str','Inoussa O.');
+      locC := locB.createDataObject('p_bc');
+      locC.setString('p_c_str','azerty');
+      locD := locC.createDataObject('p_cd');
+        locD.setString('p_d_str','D value');
+    locA.setDataObject('p_ac',locC);
+    locA.setDataObject('p_ad',locD);
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locC.setDataObject('p_cd',nil);
+    locA.setDataObject('p_ab',nil);
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedA := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locA,locLoadedA),'Object');
+  Compare(
+    locA.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedA.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+
+  locA.getChangeSummary().undoChanges();
+  locLoadedA.getChangeSummary().undoChanges();
+    CheckEquals( 0, locA.getChangeSummary().getChangedDataObjects().size());
+    CheckEquals( 0, locLoadedA.getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locA, locLoadedA),'Object');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_object_delete_2_objects_same_type();
+var
+  locFac : ISDODataFactory;
+  locA, locB : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('changesummary_object_delete_2_objects_same_type.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+    locFac.addProperty(s_uri,'a','p_a_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,'a','p_ab1',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ab2',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+      locFac.addProperty(s_uri,'b','p_b_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.setString('p_a_str','sample A'' property.');
+    locB := locA.createDataObject('p_ab1');
+      locB.setString('p_b_str','p_ab1\p_b_str value');
+    locB := locA.createDataObject('p_ab2');
+      locB.setString('p_b_str','p_ab2\p_b_str value');
+
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.setDataObject('p_ab1',nil);
+    locA.setDataObject('p_ab2',nil);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save('a',locA,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'changesummary_object_delete_2_objects_same_type.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_object_delete_2_objects_same_type();
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locA, locB, locLoadedA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'changesummary_object_delete_2_objects_same_type.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+    locFac.addProperty(s_uri,'a','p_a_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+    locFac.addProperty(s_uri,'a','p_ab1',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ab2',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+      locFac.addProperty(s_uri,'b','p_b_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.setString('p_a_str','sample A'' property.');
+    locB := locA.createDataObject('p_ab1');
+      locB.setString('p_b_str','p_ab1\p_b_str value');
+    locB := locA.createDataObject('p_ab2');
+      locB.setString('p_b_str','p_ab2\p_b_str value');
+
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.setDataObject('p_ab1',nil);
+    locA.setDataObject('p_ab2',nil);
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedA := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locA,locLoadedA),'Object');
+  Compare(
+    locA.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedA.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+
+  locA.getChangeSummary().undoChanges();
+  locLoadedA.getChangeSummary().undoChanges();
+    CheckEquals( 0, locA.getChangeSummary().getChangedDataObjects().size());
+    CheckEquals( 0, locLoadedA.getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locA, locLoadedA),'Object');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_object_2_objects_same_type_del_upd();
+var
+  locFac : ISDODataFactory;
+  locA, locB : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('changesummary_object_2_objects_same_type_del_upd.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+    locFac.addProperty(s_uri,'a','p_a_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+    locFac.addProperty(s_uri,'a','p_ab1',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ab2',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ab3',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+      locFac.addProperty(s_uri,'b','p_b_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], [pfIsAttribute]);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.setString('p_a_str','sample A'' property.');
+    locB := locA.createDataObject('p_ab1');
+      locB.setString('p_b_str','p_ab1\p_b_str value');
+    locB := locA.createDataObject('p_ab2');
+      locB.setString('p_b_str','p_ab2\p_b_str value before');
+    locB := locA.createDataObject('p_ab3');
+      locB.setString('p_b_str','p_ab3\p_b_str value');
+
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.setDataObject('p_ab1',nil);
+    locA.setString('p_ab2/p_b_str','p_ab3\p_b_str value after');
+    locA.setDataObject('p_ab3',nil);
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save('a',locA,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'changesummary_object_2_objects_same_type_del_upd.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_object_2_objects_same_type_del_upd();
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locA, locB, locLoadedA : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'changesummary_object_2_objects_same_type_del_upd.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'a',[]);
+  locFac.AddType(s_uri,'b',[]);
+    locFac.addProperty(s_uri,'a','p_a_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+    locFac.addProperty(s_uri,'a','p_ab1',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ab2',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a','p_ab3',s_uri,'b',[pfIsContainment]);
+    locFac.addProperty(s_uri,'a',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+      locFac.addProperty(s_uri,'b','p_b_str',sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+
+  locA := locFac.createNew(s_uri,'a');
+    locA.setString('p_a_str','sample A'' property.');
+    locB := locA.createDataObject('p_ab1');
+      locB.setString('p_b_str','p_ab1\p_b_str value');
+    locB := locA.createDataObject('p_ab2');
+      locB.setString('p_b_str','p_ab2\p_b_str value before');
+    locB := locA.createDataObject('p_ab3');
+      locB.setString('p_b_str','p_ab3\p_b_str value');
+
+  locCS := locA.getChangeSummary();
+  locCS.beginLogging();
+    locA.setDataObject('p_ab1',nil);
+    locA.setString('p_ab2/p_b_str','p_ab3\p_b_str value after');
+    locA.setDataObject('p_ab3',nil);
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedA := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locA,locLoadedA),'Object');
+  Compare(
+    locA.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedA.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+
+  locA.getChangeSummary().undoChanges();
+  locLoadedA.getChangeSummary().undoChanges();
+    CheckEquals( 0, locA.getChangeSummary().getChangedDataObjects().size());
+    CheckEquals( 0, locLoadedA.getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locA, locLoadedA),'Object');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_object();
+
+  function create_employee(
+    const AFac : ISDODataFactory;
+    const AName, ASN : TSDOString;
+    const AManager : Boolean
+  ) : ISDODataObject;
+  begin
+    Result := AFac.createNew(s_uri, s_EmployeeType);
+    Result.setString(s_name, AName);
+    Result.setString(s_sn, ASN);
+    Result.setBoolean(s_manager, AManager);
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locDep, e1, e2 : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('changesummary_prop_list_object.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_EmployeeType,[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'name',sdo_namespace,'string',[pfIsAttribute]);
+    locFac.addProperty(s_uri, s_EmployeeType,'SN',sdo_namespace,'string',[pfIsAttribute]);
+    locFac.addProperty(s_uri, s_EmployeeType,'manager',sdo_namespace,'boolean',[pfIsAttribute]);
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_object,s_uri,s_EmployeeType,[pfIsMany,pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_object);
+      ls.append(create_employee(locFac,'Inoussa O.', '0001', True));
+      ls.append(create_employee(locFac,'Kis O.', '0002', False));
+      ls.append(create_employee(locFac,'WST', '0003', False));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    e1 := create_employee(locFac,'FPC', '0010', False);
+    e2 := create_employee(locFac,'Lazarus', '0011', False);
+    ls.setDataObject(0,e1);
+    ls.append(create_employee(locFac,'FPC 2 ', '0020', True));
+    ls.insert(3,create_employee(locFac,'FPC 5', '0050', False));
+    ls.append(create_employee(locFac,'FPC 3', '0030', False));
+    ls.setDataObject(1,e2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.append(create_employee(locFac,'FPC 4', '0040', True));
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_object.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_object();
+
+  function create_employee(
+    const AFac : ISDODataFactory;
+    const AName, ASN : TSDOString;
+    const AManager : Boolean
+  ) : ISDODataObject;
+  begin
+    Result := AFac.createNew(s_uri, s_EmployeeType);
+    Result.setString(s_name, AName);
+    Result.setString(s_sn, ASN);
+    Result.setBoolean(s_manager, AManager);
+  end;
+
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep, e1, e2 : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_EmployeeType,[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'name',sdo_namespace,'string',[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'SN',sdo_namespace,'string',[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'manager',sdo_namespace,'boolean',[]);
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_object,s_uri,s_EmployeeType,[pfIsMany,pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_object);
+      ls.append(create_employee(locFac,'Inoussa O.', '0001', True));
+      ls.append(create_employee(locFac,'Kis O.', '0002', False));
+      ls.append(create_employee(locFac,'WST', '0003', False));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    e1 := create_employee(locFac,'FPC', '0010', False);
+    e2 := create_employee(locFac,'Lazarus', '0011', False);
+    ls.setDataObject(0,e1);
+    ls.append(create_employee(locFac,'FPC 2 ', '0020', True));
+    ls.insert(3,create_employee(locFac,'FPC 5', '0050', False));
+    ls.append(create_employee(locFac,'FPC 3', '0030', False));
+    ls.setDataObject(1,e2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.append(create_employee(locFac,'FPC 4', '0040', True));
+
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_object.xml');
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+  locDep.getChangeSummary().getOldValues(locDep);
+  locLoadedDep.getChangeSummary().getOldValues(locLoadedDep);
+
+  Check(TSDOEqualityHelper.equal(locDep,locLoadedDep),'Object');
+  {Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );}
+
+  locDep.getChangeSummary().undoChanges();
+  locLoadedDep.getChangeSummary().undoChanges();
+    CheckEquals( 0, locDep.getChangeSummary().getChangedDataObjects().size());
+    CheckEquals( 0, locLoadedDep.getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_bool();
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('changesummary_prop_list_bool.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_bool,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_bool);
+      ls.append(False);
+      ls.append(True);
+      ls.append(False);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setBoolean(0,True);
+    ls.append(True);
+    ls.append(True);
+    ls.setBoolean(1,False);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, False);
+    ls.append(False);
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_bool.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_bool();
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_bool,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_bool);
+      ls.append(False);
+      ls.append(True);
+      ls.append(False);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setBoolean(0,True);
+    ls.append(True);
+    ls.append(True);
+    ls.setBoolean(1,False);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, False);
+    ls.append(False);
+
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_bool.xml');
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_string();
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('changesummary_prop_list_string.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_string,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_string);
+      ls.append('wst');
+      ls.append('sdo');
+      ls.append('fpc-lazarus');
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setString(0,'azerty');
+    ls.append('Ouagadougou');
+    ls.append('BF');
+    ls.setString(1,'kis');
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, '107612');
+    ls.append('this is a multi words text. Lets test it!');
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_string.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_string();
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_string,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_string);
+      ls.append('wst');
+      ls.append('sdo');
+      ls.append('fpc-lazarus');
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setString(0,'azerty');
+    ls.append('Ouagadougou');
+    ls.append('BF');
+    ls.setString(1,'kis');
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, '107612');
+    ls.append('this is a multi words text. Lets test it!');
+
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_string.xml');
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_object_nested();
+
+  function create_employee(
+    const AFac : ISDODataFactory;
+    const AName, ASN : TSDOString;
+    const AManager : Boolean;
+    const AJobCount : Integer
+  ) : ISDODataObject;
+  var
+    jb : ISDODataObject;
+    k : Integer;
+  begin
+    Result := AFac.createNew(s_uri, s_EmployeeType);
+    Result.setString(s_name, AName);
+    Result.setString(s_sn, ASN);
+    Result.setBoolean(s_manager, AManager);
+    for k := 0 to Pred(AJobCount) do begin
+      jb := Result.createDataObject('jobs');
+        jb.setString('title', Format('%s''s job #%d',[AName,k]));
+        jb.setByte('MaxEmployeeCount',( k * AJobCount ) mod High(TSDOByte));
+      Result.getList('jobs').append(jb);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locDep, e1, e2 : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName('changesummary_prop_list_object_nested.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'job',[]);
+    locFac.addProperty(s_uri, 'job','title',sdo_namespace,'string',[pfIsAttribute]);
+    locFac.addProperty(s_uri, 'job','MaxEmployeeCount',sdo_namespace,'byte',[pfIsAttribute]);
+  locFac.AddType(s_uri,s_EmployeeType,[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'name',sdo_namespace,'string',[pfIsAttribute]);
+    locFac.addProperty(s_uri, s_EmployeeType,'SN',sdo_namespace,'string',[pfIsAttribute]);
+    locFac.addProperty(s_uri, s_EmployeeType,'manager',sdo_namespace,'boolean',[pfIsAttribute]);
+    locFac.addProperty(s_uri, s_EmployeeType,'jobs',s_uri,'job',[pfIsMany,pfIsContainment]);
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_object,s_uri,s_EmployeeType,[pfIsMany,pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_object);
+      ls.append(create_employee(locFac,'Inoussa O.', '0001', True,3));
+      ls.append(create_employee(locFac,'Kis O.', '0002', False,2));
+      ls.append(create_employee(locFac,'WST', '0003', False,4));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    e1 := create_employee(locFac,'FPC', '0010', False,1);
+    e2 := create_employee(locFac,'Lazarus', '0011', False,3);
+    ls.setDataObject(0,e1);
+    ls.append(create_employee(locFac,'FPC 2 ', '0020', True,0));
+    ls.insert(3,create_employee(locFac,'FPC 5', '0050', False,1));
+    ls.append(create_employee(locFac,'FPC 3', '0030', False,0));
+    ls.setDataObject(1,e2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.append(create_employee(locFac,'FPC 4', '0040', True,1));
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_object_nested.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_object_nested();
+
+  function create_employee(
+    const AFac : ISDODataFactory;
+    const AName, ASN : TSDOString;
+    const AManager : Boolean;
+    const AJobCount : Integer
+  ) : ISDODataObject;
+  var
+    jb : ISDODataObject;
+    k : Integer;
+  begin
+    Result := AFac.createNew(s_uri, s_EmployeeType);
+    Result.setString(s_name, AName);
+    Result.setString(s_sn, ASN);
+    Result.setBoolean(s_manager, AManager);
+    for k := 0 to Pred(AJobCount) do begin
+      jb := Result.createDataObject('jobs');
+        jb.setString('title', Format('%s''s job #%d',[AName,k]));
+        jb.setByte('MaxEmployeeCount',( k * AJobCount ) mod High(TSDOByte));
+      Result.getList('jobs').append(jb);
+    end;
+  end;
+
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, e1, e2, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'job',[]);
+    locFac.addProperty(s_uri, 'job','title',sdo_namespace,'string',[]);
+    locFac.addProperty(s_uri, 'job','MaxEmployeeCount',sdo_namespace,'byte',[]);
+  locFac.AddType(s_uri,s_EmployeeType,[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'name',sdo_namespace,'string',[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'SN',sdo_namespace,'string',[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'manager',sdo_namespace,'boolean',[]);
+    locFac.addProperty(s_uri, s_EmployeeType,'jobs',s_uri,'job',[pfIsMany,pfIsContainment]);
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_object,s_uri,s_EmployeeType,[pfIsMany,pfIsContainment]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setInteger(s_number,1210);
+    ls := locDep.getList(s_list_object);
+      ls.append(create_employee(locFac,'Inoussa O.', '0001', True,3));
+      ls.append(create_employee(locFac,'Kis O.', '0002', False,2));
+      ls.append(create_employee(locFac,'WST', '0003', False,4));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    e1 := create_employee(locFac,'FPC', '0010', False,1);
+    e2 := create_employee(locFac,'Lazarus', '0011', False,3);
+    ls.setDataObject(0,e1);
+    ls.append(create_employee(locFac,'FPC 2 ', '0020', True,0));
+    ls.insert(3,create_employee(locFac,'FPC 5', '0050', False,1));
+    ls.append(create_employee(locFac,'FPC 3', '0030', False,0));
+    ls.setDataObject(1,e2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.append(create_employee(locFac,'FPC 4', '0040', True,1));
+
+    localFileName := sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_object_nested.xml');
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+  locDep.getChangeSummary().getOldValues(locDep);
+  locLoadedDep.getChangeSummary().getOldValues(locLoadedDep);
+
+  Check(TSDOEqualityHelper.equal(locDep,locLoadedDep),'Object');
+  {Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );}
+
+  locDep.getChangeSummary().undoChanges();
+  locLoadedDep.getChangeSummary().undoChanges();
+    CheckEquals( 0, locDep.getChangeSummary().getChangedDataObjects().size());
+    CheckEquals( 0, locLoadedDep.getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+end;
+
+procedure TSDOSerializer_Test.save_to_and_load_file_ref_prop_crash_1();
+var
+  locFac : ISDODataFactory;
+  locPL, locPL1, locPJ0, locPJ1, locP1, locP2, locP3 : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  serializer : ISDOSerializer;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'ProjectList',[]);
+  locFac.AddType(s_uri,'ProjectType',[]);
+  locFac.AddType(s_uri,'Person',[]);
+    locFac.addProperty(s_uri,'ProjectList','Project',s_uri,'ProjectType',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'ProjectList',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+      locFac.addProperty(s_uri,'ProjectType','Member',s_uri,'Person',[pfIsContainment,pfIsMany]);
+        locFac.addProperty(s_uri,'Person','Manager',s_uri,'Person',[]);
+          locFac.addProperty(s_uri,'Person','Name',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+
+  locPL := locFac.createNew(s_uri,'ProjectList');
+  locCS := locPL.getChangeSummary();
+  locCS.endLogging();
+    locPJ0 := locPL.createDataObject('Project');
+    locPL.getList('Project').append(locPJ0);
+    locPJ1 := locPL.createDataObject('Project');
+    locPL.getList('Project').append(locPJ1);
+      locP1 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP1);
+        locP1.setString('Name', 'P1 person');
+      locP2 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP2);
+        locP2.setString('Name', 'P2 person');
+        locP2.setDataObject('Manager', locPJ1.getDataObject('Member[Name="P1 person"]'));
+      locP3 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP3);
+        locP3.setString('Name', 'P3 person');
+        locP1.setDataObject('Manager', locPJ1.getDataObject('Member[Name="P3 person"]'));
+
+  locCS.beginLogging();
+    locPL.getList('Project').delete(1);
+
+  serializer := TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create());
+  serializer.save('ProjectList',locPL,'save_to_and_load_file_ref_prop_crash_1.xml');
+
+  serializer := TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create());
+  locPL1 := serializer.load('save_to_and_load_file_ref_prop_crash_1.xml');
+end;
+
+procedure TSDOSerializer_Test.save_to_and_load_file_ref_prop_crash_2();
+var
+  locFac : ISDODataFactory;
+  locPL, locPL1, locPJ0, locPJ1, locP1, locP2, locP3 : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  serializer : ISDOSerializer;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'ProjectList',[]);
+  locFac.AddType(s_uri,'ProjectType',[]);
+  locFac.AddType(s_uri,'Person',[]);
+    locFac.addProperty(s_uri,'ProjectList','Project',s_uri,'ProjectType',[pfIsContainment,pfIsMany]);
+    locFac.addProperty(s_uri,'ProjectList',s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+      locFac.addProperty(s_uri,'ProjectType','Member',s_uri,'Person',[pfIsContainment,pfIsMany]);
+        locFac.addProperty(s_uri,'Person','Manager',s_uri,'Person',[]);
+          locFac.addProperty(s_uri,'Person','Name',sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+
+  locPL := locFac.createNew(s_uri,'ProjectList');
+  locCS := locPL.getChangeSummary();
+  locCS.endLogging();
+    locPJ0 := locPL.createDataObject('Project');
+    locPL.getList('Project').append(locPJ0);
+    locPJ1 := locPL.createDataObject('Project');
+    locPL.getList('Project').append(locPJ1);
+      locP1 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP1);
+        locP1.setString('Name', 'P1 person');
+      locP2 := locPJ1.createDataObject('Member');
+      locPJ1.getList('Member').append(locP2);
+        locP2.setString('Name', 'P2 person');
+        locP2.setDataObject('Manager', locPJ1.getDataObject('Member[Name="P1 person"]'));
+
+  locCS.beginLogging();
+    locP3 := locPJ1.createDataObject('Member');
+    locPJ1.getList('Member').append(locP3);
+      locP3.setString('Name', 'P3 person');
+      locP1.setDataObject('Manager', locPJ1.getDataObject('Member[Name="P3 person"]'));
+    locPL.getList('Project').delete(1);
+
+  serializer := TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create());
+  serializer.save('ProjectList',locPL,'save_to_and_load_file_ref_prop_crash_2.xml');
+
+  serializer := TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create());
+  locPL1 := serializer.load('save_to_and_load_file_ref_prop_crash_2.xml');
+end;
+
+procedure TSDOSerializer_Test.load_from_file_reference_property();
+var
+  locFac : ISDODataFactory;
+  locLoadedObj : ISDODataObject;
+  s : ISDOSerializer;
+  localFileName : string;
+  locType : ISDOType;
+  p : ISDOProperty;
+  projObj, user1, user2, man : ISDODataObject;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'load_from_file_reference_property.xml');
+  s := TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create());
+  locLoadedObj := s.load(localFileName);
+
+  locType := locFac.getType('uri:sample','ProjectType');
+  Check(( locType <> nil ),'ProjectType');
+    p := locType.getProperty('ProjectLeader');
+    Check(p <> nil,'ProjectLeader');
+    Check(p.isReference(),'"ProjectLeader" should be a "Reference" property');
+    Check(p.getType() = locFac.getType('uri:sample','Person'),'"ProjectLeader" should be a "Person" type property');
+
+  Check(locLoadedObj <> nil,'ProjectList');
+  projObj := locLoadedObj.getDataObject('Project[ProjectName="WST"]');
+    Check(projObj <> nil,'Project');
+    user1 := projObj.getDataObject('Member[Name="wst user 1"]');
+      Check(user1 <> nil,'Member[Name="wst user 1"]');
+    user2 := projObj.getDataObject('Member[Name="wst user 2"]');
+      Check(user1 <> nil,'Member[Name="wst user 2"]');
+    man := projObj.getDataObject('Member[Name="Inoussa O."]');
+      Check(user1 <> nil,'Member[Name="Inoussa O."]');
+    Check( man = projObj.getDataObject('ProjectLeader'),  'ProjectLeader');
+    Check( man = user2.getDataObject('Manager'), 'user Manager');
+end;
+
+procedure TSDOSerializer_Test.save_object_open_type();
+var
+  fact : ISDODataFactory;
+  dst, row : ISDODataObject;
+  ser : ISDOSerializer;
+  stream : TMemoryStream;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  fact := TSDODataFactory.Create() as ISDODataFactory;
+  fact.AddType(s_uri,'Datarow',[tfIsOpen]);
+  fact.AddType(s_uri,'Dataset',[tfIsOpen]);
+  fact.addProperty(s_uri,'Dataset','rows',s_uri,'Datarow',[pfIsMany,pfIsContainment]);
+
+  dst := fact.createNew(s_uri,'Dataset');
+  row := dst.createDataObject('rows');
+    row.setString('Name','SDO-Pascal');
+    row.setString('Description','Object Pascal implementation of SDO');
+    row.setInteger('Order',1);
+  dst.getList('rows').append(row);
+  row := dst.createDataObject('rows');
+    row.setString('Name','WST');
+    row.setString('Description','Object Pascal Web Services Toolkit');
+    row.setInteger('Order',2);
+  dst.getList('rows').append(row);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ser := TSDOSerializer.Create(fact,TSDOSerializerStreamXML.Create());
+  stream := TMemoryStream.Create();
+  try
+    ser.save(dst,stream);
+{$IFDEF TEST_GENERATE_FILE}
+    stream.SaveToFile(sdoExpandLocalFileName('open_type.xml'));
+{$ENDIF TEST_GENERATE_FILE}
+    stream.Position := 0;
+    ReadXMLFile(serialDoc,stream);
+    ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'open_type.xml'));
+    CheckEquals(True, CompareNodes(existDoc,serialDoc),'generated document differs from the existent one.');
+  finally
+    stream.Free();
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_object_open_type();
+var
+  fact, factGen : ISDODataFactory;
+  ser : ISDOSerializer;
+  loadedObj, dstGen, row : ISDODataObject;
+begin
+  // Load the existing file
+  fact := TSDODataFactory.Create();
+  ser := TSDOSerializer.Create(fact,TSDOSerializerStreamXML.Create());
+  loadedObj := ser.load(sdoExpandLocalFileName(TestFilesPath + 'open_type.xml'));
+  Check(( loadedObj <> nil ), 'Root object is NULL.');
+  CheckEquals('Dataset',loadedObj.getType().getName());
+  CheckEquals(2,loadedObj.getList('rows').size());
+
+  // Generate the object copy
+  factGen := TSDODataFactory.Create() as ISDODataFactory;
+  factGen.AddType(s_uri,'Datarow',[tfIsOpen]);
+  factGen.AddType(s_uri,'Dataset',[tfIsOpen]);
+  factGen.addProperty(s_uri,'Dataset','rows',s_uri,'Datarow',[pfIsMany,pfIsContainment]);
+  dstGen := factGen.createNew(s_uri,'Dataset');
+  row := dstGen.createDataObject('rows');
+    row.setString('Name','SDO-Pascal');
+    row.setString('Description','Object Pascal implementation of SDO');
+    row.setInteger('Order',1);
+  dstGen.getList('rows').append(row);
+  row := dstGen.createDataObject('rows');
+    row.setString('Name','WST');
+    row.setString('Description','Object Pascal Web Services Toolkit');
+    row.setInteger('Order',2);
+  dstGen.getList('rows').append(row);
+
+  // ... compare them now
+  Check(TSDOEqualityHelper.equal(dstGen,loadedObj), 'Loaded object differs from generated object');
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_byte();
+const
+  LIST_PROP_NAME = s_list_byte;
+  LIST_PROP_TYPE = ByteType;
+  FILE_NAME = 'changesummary_prop_list_byte.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LIST_PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.append(TSDOByte(1));
+      ls.append(TSDOByte(2));
+      ls.append(TSDOByte(3));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setByte(0,10);
+    ls.append(TSDOByte(123));
+    ls.append(TSDOByte(45));
+    ls.setByte(1,20);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOByte(107));
+    ls.append(TSDOByte(89));
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_date();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_4 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_5 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_3)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2009,9,1,2,3,0,1);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_4)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1900,11,8,1,2,0,0);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_5)^ := d;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  SetConstants();
+  localFileName := sdoExpandLocalFileName('changesummary_prop_list_date.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_birthDate,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_date,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setDate(s_birthDate,VAL_1);
+    ls := locDep.getList(s_list_date);
+      ls.append(VAL_1);
+      ls.append(VAL_2);
+      ls.append(VAL_3);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setDate(0,VAL_4);
+    ls.append(VAL_5);
+    ls.append(VAL_1);
+    ls.setDate(1,VAL_2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, VAL_3);
+    ls.append(VAL_4);
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_date.xml'));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_bytes();
+const
+  FILE_NAME = 'changesummary_prop_list_bytes.xml';
+  LIST_PROP_NAME = s_list_bytes;
+  PROP_TYPE = BytesType;
+  
+var
+  VAL_1, VAL_2, VAL_3, VAL_4, VAL_5 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;    
+
+    VAL_2 := nil;
+
+    SetLength(v,20);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3 := v; 
+    v := nil;  
+
+    SetLength(v,30);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_4 := v; 
+    v := nil;   
+
+    SetLength(v,40);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_5 := v; 
+    v := nil;       
+  end;
+  
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  SetConstants();
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_birthDate,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    //locDep.setBytes(s_birthDate,VAL_1);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.appendBytes(VAL_1);
+      ls.appendBytes(VAL_2);
+      ls.appendBytes(VAL_3);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setBytes(0,VAL_4);
+    ls.appendBytes(VAL_5);
+    ls.appendBytes(VAL_1);
+    ls.setBytes(1,VAL_2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insertBytes(2, VAL_3);
+    ls.appendBytes(VAL_4);
+{$IFDEF TEST_GENERATE_FILE}
+    (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE} 
+    
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_bytes();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = BytesType;
+  FILE_NAME = 'change_summary_bytes.xml';
+var
+  VAL_1, VAL_2 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;    
+
+    SetLength(v,20);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_2 := v;
+  end;  
+
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  SetConstants();
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setBytes(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();
+    locEmployee.setBytes(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+    (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}     
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_bytes();
+const
+  FILE_NAME = 'changesummary_prop_list_bytes.xml';
+  LIST_PROP_NAME = s_list_bytes;
+  PROP_TYPE = BytesType;
+var
+  VAL_1, VAL_2, VAL_3, VAL_4, VAL_5 : TSDOBytes;
+
+  procedure SetConstants();
+  var
+    v : TSDOBytes;
+    k : Integer;
+  begin
+    SetLength(v,10);
+    for k := 0 to High(v) do
+      v[k] := k mod High(Byte);
+    VAL_1 := v;
+    v := nil;    
+
+    VAL_2 := nil;
+
+    SetLength(v,20);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_3 := v; 
+    v := nil;  
+
+    SetLength(v,30);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_4 := v; 
+    v := nil;   
+
+    SetLength(v,40);
+    for k := 0 to High(v) do
+      v[k] := ( ( 3 * k ) + 1 ) mod High(Byte);
+    VAL_5 := v; 
+    v := nil;       
+  end;
+
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  SetConstants();
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_birthDate,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    //locDep.setBytes(s_birthDate,VAL_1);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.appendBytes(VAL_1);
+      ls.appendBytes(VAL_2);
+      ls.appendBytes(VAL_3);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setBytes(0,VAL_4);
+    ls.appendBytes(VAL_5);
+    ls.appendBytes(VAL_1);
+    ls.setBytes(1,VAL_2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insertBytes(2, VAL_3);
+    ls.appendBytes(VAL_4);
+
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_char();
+const
+  LIST_PROP_NAME = s_list_char;
+  LIST_PROP_TYPE = CharacterType;
+  FILE_NAME = 'changesummary_prop_list_char.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LIST_PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.append(TSDOChar('k'));
+      ls.append(TSDOChar('y'));
+      ls.append(TSDOChar('g'));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setCharacter(0,TSDOChar('j'));
+    ls.append(TSDOChar('a'));
+    ls.append(TSDOChar('x'));
+    ls.setCharacter(1,TSDOChar('v'));
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOChar('A'));
+    ls.append(TSDOChar('Z'));
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}
+  
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_long();
+const
+  LIST_PROP_NAME = s_list_long;
+  LIST_PROP_TYPE = LongType;
+  FILE_NAME = 'changesummary_prop_list_long.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LIST_PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.append(TSDOLong(11111111111111111));
+      ls.append(TSDOLong(-2222222222222222));
+      ls.append(TSDOLong(333333333333333333));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setLong(0,4444444444444444444);
+    ls.append(TSDOLong(5555555555555555555));
+    ls.append(TSDOLong(-6666666666666666666));
+    ls.setLong(1,7777777777777777777);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOLong(8));
+    ls.append(TSDOLong(-9));
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_short();
+const
+  LIST_PROP_NAME = s_list_short;
+  LIST_PROP_TYPE = ShortType;
+  FILE_NAME = 'changesummary_prop_list_short.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LIST_PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.append(TSDOShort(1));
+      ls.append(TSDOShort(2));
+      ls.append(TSDOShort(3));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setShort(0,10);
+    ls.append(TSDOShort(12345));
+    ls.append(TSDOShort(-5245));
+    ls.setShort(1,20);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOShort(107));
+    ls.append(TSDOShort(89));
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}
+  
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+{$IFDEF HAS_SDO_CURRENCY}
+const
+  CURRENCY_VALUES_REPEATED_DIGITED : array[0..8] of TSDOCurrency = (
+    1111111111111.1111, -222222222222.2222, 33333333333333.3333, 444444444444444.4444, 555555555555555.5555, 
+    -666666666666666.6666, 777777777777777.7777, 8, -9
+  );
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_currency();
+const
+  LIST_PROP_NAME = s_list_currency;
+  LIST_PROP_TYPE = CurrencyType;
+  FILE_NAME = 'changesummary_prop_list_currency.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LIST_PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[0]);
+      ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[1]);
+      ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[2]);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setCurrency(0,CURRENCY_VALUES_REPEATED_DIGITED[3]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[4]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[5]);
+    ls.setCurrency(1,CURRENCY_VALUES_REPEATED_DIGITED[6]);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insertCurrency(2, CURRENCY_VALUES_REPEATED_DIGITED[7]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[8]);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_currency();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = CurrencyType;
+  FILE_NAME = 'change_summary_currency.xml';
+  VAL_1 : TSDOCurrency = 12398745632145.6987;
+  VAL_2 : TSDOCurrency = -45821568.7422;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setCurrency(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();     
+    locEmployee.setCurrency(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_currency();
+const
+  PROP_NAME = s_list_currency;
+  PROP_TYPE = CurrencyType;
+  FILE_NAME = 'changesummary_prop_list_currency.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(PROP_NAME);
+      ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[0]);
+      ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[1]);
+      ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[2]);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setCurrency(0,CURRENCY_VALUES_REPEATED_DIGITED[3]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[4]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[5]);
+    ls.setCurrency(1,CURRENCY_VALUES_REPEATED_DIGITED[6]);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insertCurrency(2, CURRENCY_VALUES_REPEATED_DIGITED[7]);
+    ls.appendCurrency(CURRENCY_VALUES_REPEATED_DIGITED[8]);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+    
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+const
+  DOUBLE_VALUES_REPEATED_DIGITED : array[0..8] of TSDODouble = (
+    111111111, -22222222, 3333333333, 44444444, 555555555,
+    -666666666, 777777777, 8, -9
+  );
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_double();
+const
+  LIST_PROP_NAME = s_list_double;
+  LIST_PROP_TYPE = DoubleType;
+  FILE_NAME = 'changesummary_prop_list_double.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LIST_PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.append(DOUBLE_VALUES_REPEATED_DIGITED[0]);
+      ls.append(DOUBLE_VALUES_REPEATED_DIGITED[1]);
+      ls.append(DOUBLE_VALUES_REPEATED_DIGITED[2]);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setDouble(0,DOUBLE_VALUES_REPEATED_DIGITED[3]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[4]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[5]);
+    ls.setDouble(1,DOUBLE_VALUES_REPEATED_DIGITED[6]);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, DOUBLE_VALUES_REPEATED_DIGITED[7]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[8]);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_double();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = DoubleType;
+  FILE_NAME = 'change_summary_double.xml';
+  VAL_1 : TSDODouble = 1239874567;
+  VAL_2 : TSDODouble = -4582152;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setDouble(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();     
+    locEmployee.setDouble(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_double();
+const
+  PROP_NAME = s_list_double;
+  PROP_TYPE = DoubleType;
+  FILE_NAME = 'changesummary_prop_list_double.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(PROP_NAME);
+      ls.append(DOUBLE_VALUES_REPEATED_DIGITED[0]);
+      ls.append(DOUBLE_VALUES_REPEATED_DIGITED[1]);
+      ls.append(DOUBLE_VALUES_REPEATED_DIGITED[2]);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setDouble(0,DOUBLE_VALUES_REPEATED_DIGITED[3]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[4]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[5]);
+    ls.setDouble(1,DOUBLE_VALUES_REPEATED_DIGITED[6]);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, DOUBLE_VALUES_REPEATED_DIGITED[7]);
+    ls.append(DOUBLE_VALUES_REPEATED_DIGITED[8]);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+    
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+const
+  FLOAT_VALUES_REPEATED_DIGITED : array[0..8] of TSDOFloat = (
+    111111111, -222222222, 333333333, 444444444, 5555555555,
+    -6666666666, 777777777, 8, -9
+  );
+procedure TSDOSerializer_Test.save_to_file_changesummary_prop_list_float();
+const
+  LIST_PROP_NAME = s_list_float;
+  LIST_PROP_TYPE = FloatType;
+  FILE_NAME = 'changesummary_prop_list_float.xml';
+var
+  locFac : ISDODataFactory;
+  locDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  existDoc, serialDoc : TSDOXMLDocument;
+begin
+  localFileName := sdoExpandLocalFileName(FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[pfIsAttribute]);
+    locFac.addProperty(s_uri,s_DepartmentType,LIST_PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[LIST_PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(LIST_PROP_NAME);
+      ls.append(FLOAT_VALUES_REPEATED_DIGITED[0]);
+      ls.append(FLOAT_VALUES_REPEATED_DIGITED[1]);
+      ls.append(FLOAT_VALUES_REPEATED_DIGITED[2]);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setFloat(0,FLOAT_VALUES_REPEATED_DIGITED[3]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[4]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[5]);
+    ls.setFloat(1,FLOAT_VALUES_REPEATED_DIGITED[6]);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, FLOAT_VALUES_REPEATED_DIGITED[7]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[8]);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create()) as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}
+
+  f := TSDOSerializerStreamXML.Create();
+  s := TSDOSerializer.Create(locFac,f);
+  s.save(s_DepartmentType,locDep,localFileName);
+
+  existDoc := nil;
+  serialDoc := nil;
+  ReadXMLFile(existDoc,sdoExpandLocalFileName(TestFilesPath + FILE_NAME));
+  try
+    ReadXMLFile(serialDoc,localFileName);
+    CheckEquals(True, CompareNodes(existDoc,serialDoc));
+  finally
+    ReleaseDomNode(existDoc);
+    ReleaseDomNode(serialDoc);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_float();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = FloatType;
+  FILE_NAME = 'change_summary_float.xml';
+  VAL_1 : TSDOFloat = 1239874567;
+  VAL_2 : TSDOFloat = -4582152;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setFloat(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();     
+    locEmployee.setFloat(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_float();
+const
+  PROP_NAME = s_list_float;
+  PROP_TYPE = FloatType;
+  FILE_NAME = 'changesummary_prop_list_float.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(PROP_NAME);
+      ls.append(FLOAT_VALUES_REPEATED_DIGITED[0]);
+      ls.append(FLOAT_VALUES_REPEATED_DIGITED[1]);
+      ls.append(FLOAT_VALUES_REPEATED_DIGITED[2]);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setFloat(0,FLOAT_VALUES_REPEATED_DIGITED[3]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[4]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[5]);
+    ls.setFloat(1,FLOAT_VALUES_REPEATED_DIGITED[6]);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, FLOAT_VALUES_REPEATED_DIGITED[7]);
+    ls.append(FLOAT_VALUES_REPEATED_DIGITED[8]);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+    
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_bool();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = BooleanType;
+  VAL_1 : TSDOBoolean = True;
+  VAL_2 : TSDOBoolean = False;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'change_summary_bool.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setBoolean(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();
+    locEmployee.setBoolean(PROP_NAME,VAL_2);
+  //(TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName('change_summary_bool.xml'));
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_byte();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = ByteType;
+  FILE_NAME = 'change_summary_byte.xml';
+  VAL_1 : TSDOByte = 200;
+  VAL_2 : TSDOByte = 123;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setByte(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();     
+    locEmployee.setByte(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOSerializer_Test.load_from_file_changesummary_char();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = CharacterType;
+  FILE_NAME = 'change_summary_char.xml';
+  VAL_1 : TSDOChar = 'a';
+  VAL_2 : TSDOChar = 'z';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setCharacter(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();     
+    locEmployee.setCharacter(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_date();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = DateTimeType;
+  VAL_1 : TSDODate = ( Date : 45123; HourOffset : 0; MinuteOffset : 5; );
+  VAL_2 : TSDODate = ( Date : 39000; HourOffset : -8; MinuteOffset : 0; );
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'change_summary_date.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setDate(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();
+    locEmployee.setDate(PROP_NAME,VAL_2);
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_integer();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = IntegerType;
+  VAL_1 : TSDOInteger = 12345;
+  VAL_2 : TSDOInteger = -789;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'change_summary_integer.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setInteger(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();
+    locEmployee.setInteger(PROP_NAME,VAL_2);
+  //(TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName('change_summary_integer.xml'));
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+{$IFDEF HAS_SDO_LONG}
+procedure TSDOSerializer_Test.load_from_file_changesummary_long();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = LongType;
+  FILE_NAME = 'change_summary_long.xml';
+  VAL_1 : TSDOLong = 123987456321456987;
+  VAL_2 : TSDOLong = -458215687422;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setLong(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();     
+    locEmployee.setLong(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TSDOSerializer_Test.load_from_file_changesummary_short();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = ShortType;
+  FILE_NAME = 'change_summary_short.xml';
+  VAL_1 : TSDOShort = 1592;
+  VAL_2 : TSDOShort = -9876;
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME);
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setShort(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();     
+    locEmployee.setShort(PROP_NAME,VAL_2);
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_string();
+const
+  PROP_NAME = 'sampleProperty';
+  PROP_TYPE = StringType;
+  VAL_1 : TSDOString = 'Inoussa.O';
+  VAL_2 : TSDOString = 'sdo.fpc.delphi';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locEmployee : ISDODataObject;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+  ol : ISDODataObjectList;
+begin
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'change_summary_string.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_Employee,[]);
+    locFac.addProperty(s_uri,s_Employee,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[]);
+    locFac.addProperty(s_uri,s_Employee,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locEmployee := locFac.createNew(s_uri,s_Employee);
+    locEmployee.setString(PROP_NAME,VAL_1);
+    locCS := locEmployee.getChangeSummary();
+
+  locCS.beginLogging();
+    locEmployee.setString(PROP_NAME,VAL_2);
+  //(TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locEmployee,sdoExpandLocalFileName('change_summary_string.xml'));
+
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDODataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  ol := TSDODataObjectList.Create(tmpFactory.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]));
+  s.load(localFileName,ol);
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+    Compare(
+      locEmployee.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+      ol.getDataObject(0).getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+    );
+    locEmployee.getChangeSummary().undoChanges();
+    ol.getDataObject(0).getChangeSummary().undoChanges();
+      CheckEquals(0, locEmployee.getChangeSummary().getChangedDataObjects().size());
+      CheckEquals(0, ol.getDataObject(0).getChangeSummary().getChangedDataObjects().size());
+    Check(TSDOEqualityHelper.equal(locEmployee,ol.getDataObject(0)));
+end;
+
+procedure TSDOSerializer_Test.CheckEquals(expected, actual: TSDODate;
+  msg: string; const AStrict: Boolean);
+var
+  e, a : TDateTime;
+  e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms : Word;
+  a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms : Word;
+begin
+  if AStrict then begin
+    Check(CompareMem(@expected, @actual, SizeOf(TSDODate)), msg);
+  end else begin
+    e := NormalizeToUTC(expected);
+    a := NormalizeToUTC(actual);
+    DecodeDateTime(e, e_y, e_m, e_d, e_h, e_mn, e_ss, e_ms);
+    DecodeDateTime(a, a_y, a_m, a_d, a_h, a_mn, a_ss, a_ms);
+    CheckEquals(e_y,a_y,msg);
+    CheckEquals(e_m,a_m,msg);
+    CheckEquals(e_d,a_d,msg);
+    CheckEquals(e_h,a_h,msg);
+    CheckEquals(e_mn,a_mn,msg);
+    CheckEquals(e_ss,a_ss,msg);
+    CheckEquals(e_ms,a_ms,msg);
+  end;
+end;
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_byte();
+const
+  PROP_NAME = s_list_byte;
+  PROP_TYPE = ByteType;
+  FILE_NAME = 'changesummary_prop_list_byte.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(PROP_NAME);
+      ls.append(TSDOByte(1));
+      ls.append(TSDOByte(2));
+      ls.append(TSDOByte(3));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setByte(0,10);
+    ls.append(TSDOByte(123));
+    ls.append(TSDOByte(45));
+    ls.setByte(1,20);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOByte(107));
+    ls.append(TSDOByte(89));
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+    
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_char();
+const
+  PROP_NAME = s_list_char;
+  PROP_TYPE = CharacterType;
+  FILE_NAME = 'changesummary_prop_list_char.xml';
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_number,sdo_namespace,SDOTypeDefaultTypeNames[ByteType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,PROP_NAME,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setByte(s_number,123);
+    ls := locDep.getList(PROP_NAME);
+      ls.append(TSDOChar('k'));
+      ls.append(TSDOChar('y'));
+      ls.append(TSDOChar('g'));
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setCharacter(0,TSDOChar('j'));
+    ls.append(TSDOChar('a'));
+    ls.append(TSDOChar('x'));
+    ls.setCharacter(1,TSDOChar('v'));
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, TSDOChar('A'));
+    ls.append(TSDOChar('Z'));
+{$IFDEF TEST_GENERATE_FILE}
+  (TSDOSerializer.Create(locFac,TSDOSerializerStreamXML.Create())as ISDOSerializer).save(locDep,sdoExpandLocalFileName(FILE_NAME));
+{$ENDIF TEST_GENERATE_FILE}  
+    
+  localFileName := sdoExpandLocalFileName(TestFilesPath + FILE_NAME); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+procedure TSDOSerializer_Test.load_from_file_changesummary_prop_list_date();
+const VAL_1 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_2 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_3 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_4 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+      VAL_5 : TSDODate = ( Date : 0; HourOffset : 0; MinuteOffset : 0; );
+
+  procedure SetConstants();
+  var
+    d : TSDODate;
+  begin
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1976,10,12,23,34,45,56);
+    d.HourOffset := 5;
+    d.MinuteOffset := 6;
+    PSDODate(@VAL_1)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2008,7,8,9,10,11,12);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_3)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(2009,9,1,2,3,0,1);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_4)^ := d;
+
+    FillChar(d,SizeOf(TSDODate),#0);
+    d.Date := EncodeDateTime(1900,11,8,1,2,0,0);
+    d.HourOffset := 0;
+    d.MinuteOffset := 13;
+    PSDODate(@VAL_5)^ := d;
+  end;
+
+var
+  locFac, tmpFactory : ISDODataFactory;
+  locDep, locLoadedDep : ISDODataObject;
+  ls : ISDODataObjectList;
+  locCS : ISDOChangeSummary;
+  f : ISDOSerializerStream;
+  s : ISDOSerializer;
+  localFileName : string;
+begin
+  SetConstants();
+  localFileName := sdoExpandLocalFileName('changesummary_prop_list_date.xml');
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,s_DepartmentType,[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_name,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_location,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_birthDate,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_list_date,sdo_namespace,SDOTypeDefaultTypeNames[DateTimeType],[pfIsMany]);
+    locFac.addProperty(s_uri,s_DepartmentType,s_changeSummary,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly,pfIsNotNullable]);
+
+  locDep := locFac.createNew(s_uri,s_DepartmentType);
+    locDep.setString(s_name,'R & D');
+    locDep.setString(s_location,'Ouaga, BF');
+    locDep.setDate(s_birthDate,VAL_1);
+    ls := locDep.getList(s_list_date);
+      ls.append(VAL_1);
+      ls.append(VAL_2);
+      ls.append(VAL_3);
+    locCS := locDep.getChangeSummary();
+
+  locCS.beginLogging();
+    locDep.setString(s_name,'R & D Department');
+    locDep.setString(s_location,'Ouaga 01, BF');
+    ls.setDate(0,VAL_4);
+    ls.append(VAL_5);
+    ls.append(VAL_1);
+    ls.setDate(1,VAL_2);
+    ls.delete(0);
+    ls.delete(1);
+    ls.insert(2, VAL_3);
+    ls.append(VAL_4);
+
+  localFileName := sdoExpandLocalFileName(TestFilesPath + 'changesummary_prop_list_date.xml'); 
+  f := TSDOSerializerStreamXML.Create();
+  tmpFactory := TSDOBaseDataFactory.Create();
+  s := TSDOSerializer.Create(tmpFactory,f);
+  locLoadedDep := s.load(localFileName);
+
+  Check(TSDOEqualityHelper.equal(locDep, locLoadedDep),'Object');
+  Compare(
+    locDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx,
+    locLoadedDep.getChangeSummary().getChangedDataObjects() as ISDOChangedDataObjectListEx
+  );
+end;
+
+{ TSDOSerializerXML_Test }
+
+class function TSDOSerializerXML_Test.CreateSerializerStream: ISDOSerializerStream;
+begin
+  Result := TSDOSerializerStreamXML.Create();
+end;
+
+initialization
+  RegisterTest('Helpers',TSDOSerializerXML_Test.Suite);
+
+end.

+ 206 - 0
packages/fcl-sdo/tests/test_suite/test_suite_utils.pas

@@ -0,0 +1,206 @@
+{$INCLUDE sdo_global.inc}
+unit test_suite_utils;
+
+interface
+uses
+  SysUtils, Classes,
+{$IFDEF FPC}
+  fpcunit,
+{$ENDIF}
+{$IFNDEF FPC}
+  TestFrameWork,
+{$ENDIF}
+  sdo, sdo_types;
+
+const
+  TestFilesPath = '..' + PathDelim + '..' + PathDelim + 'files' + PathDelim;
+  XsdTestFilesPath = '..' + PathDelim + '..' + PathDelim + 'files' + PathDelim + 'xsd' + PathDelim;
+
+type
+
+  { TWstBaseTest }
+
+  TWstBaseTest = class(TTestCase)
+  protected
+    procedure CheckEquals(expected, actual: TSDOBytes; msg: string = ''; const AStrict : Boolean = True); overload;
+    procedure CheckEqualsCurrency(expected, actual: Currency; const delta: Currency; const msg: string = ''); overload;
+    procedure CheckEqualsCurrency(expected, actual: Currency; const msg: string = ''); overload;
+{$IFDEF FPC}
+    procedure CheckEquals(expected, actual: Int64; msg: string = ''; const AStrict : Boolean = True); overload;
+    procedure CheckEquals(expected, actual: QWord; msg: string = ''; const AStrict : Boolean = True); overload;
+{$ENDIF FPC}
+  end;
+
+//{$IFDEF FPC}
+//  {$IF not Defined(RandomRange)}
+    //function RandomRange(const AFrom, ATo : Integer) : Integer ;overload;
+//  {$IFEND}
+//{$ENDIF}
+   function RandomRange(const AFrom, ATo : Int64) : Int64 ;overload;
+
+   function RandomString(const AMaxLen : PtrInt) : TSDOString;
+   function RandomDate() : TSDODateTime ;
+   function RandomBytes(const AMaxLen : Integer) : TSDOBytes;
+   function BytesToString(const AValue: TSDOBytes): TSDOString;overload;
+   function BytesToString(const AValue: array of Byte): TSDOString;overload;
+   function RandomDouble(const AFrom, ATo: Integer): TSDODouble;
+   function RandomFloat(const AFrom, ATo: Integer): TSDOFloat;
+
+
+   function sdoExpandLocalFileName(const AFileName : string) : string;
+
+implementation
+uses
+  Math;
+
+//{$IFDEF FPC}
+ // {$IF not Defined(RandomRange)}
+    {function RandomRange(const AFrom, ATo : Integer) : Integer ;
+    var
+      a : Integer;
+    begin
+      if ( AFrom <= ATo ) then
+        a := AFrom
+      else
+        a := ATo;
+      Result := a + Random(Abs(ATo - AFrom));
+    end; }
+//  {$IFEND}
+//{$ENDIF}
+
+function RandomRange(const AFrom, ATo : Int64) : Int64 ;
+var
+  a : Int64;
+begin
+  if ( AFrom <= ATo ) then
+    a := AFrom
+  else
+    a := ATo;
+  Result := a + Random(Abs(ATo - AFrom));
+end;
+
+function RandomString(const AMaxLen : PtrInt) : TSDOString;
+var
+  i, l, j : PtrInt;
+begin
+  l := RandomRange(0,AMaxLen);
+  j := RandomRange(1, 3);
+  SetLength(Result,l);
+  for i := 1 to l do begin
+    case j of
+      1 : Result[i] := Char(RandomRange(Ord('a'),Ord('z')));
+      2 : Result[i] := Char(RandomRange(Ord('0'),Ord('9')));
+      3 : Result[i] := Char(RandomRange(Ord('A'),Ord('Z')));
+    end;
+    j := ( j + 1 );
+    if ( j > 3 ) then
+      j := 1;
+  end;
+end;
+
+function BytesToString(const AValue: TSDOBytes): TSDOString;
+var
+  locRes : AnsiString;
+begin
+  if (  Length(AValue) > 0 ) then begin
+    SetLength(locRes, ( 2 * Length(AValue) ) );
+    BinToHex(PAnsiChar(@(AValue[0])),PAnsiChar(@(locRes[1])),Length(AValue));
+    Result := locRes;
+  end;
+end;
+
+function BytesToString(const AValue: array of Byte): TSDOString;
+var
+  locRes : AnsiString;
+begin
+  if (  Length(AValue) > 0 ) then begin
+    SetLength(locRes, ( 2 * Length(AValue) ) );
+    BinToHex(PAnsiChar(@(AValue[0])),PAnsiChar(@(locRes[1])),Length(AValue));
+    Result := locRes;
+  end;
+end;
+
+function RandomDate() : TSDODateTime ;
+begin
+  Result.Date := RandomRange(0,50000);
+  Result.HourOffset := RandomRange(-12,12);
+  Result.MinuteOffset := RandomRange(-59,59)
+end;
+
+function sdoExpandLocalFileName(const AFileName : string) : string;
+begin
+  Result := ExtractFilePath(ParamStr(0)) + AFileName;
+end;
+
+function RandomBytes(const AMaxLen : Integer) : TSDOBytes;
+var
+  i : Integer;
+begin
+  if ( AMaxLen > 0 ) then begin
+    SetLength(Result,AMaxLen);
+    for i:= 0 to Pred(AMaxLen) do
+      Result[i] := RandomRange(Low(Byte),High(Byte));
+  end else begin
+    Result := nil;
+  end;
+end;
+
+function RandomDouble(const AFrom, ATo: Integer): TSDODouble;
+begin
+  Result := RandomRange(AFrom,ATo)
+end;
+
+function RandomFloat(const AFrom, ATo: Integer): TSDOFloat;
+begin
+  Result := RandomRange(AFrom,ATo)
+end;
+
+{ TWstBaseTest }
+
+{$IFDEF FPC}
+procedure TWstBaseTest.CheckEquals(expected, actual: Int64; msg: string;
+  const AStrict: Boolean);
+begin
+  if (expected <> actual) then
+    FailNotEquals(IntToStr(expected), IntToStr(actual), msg{$IFDEF WST_DELPHI}, CallerAddr{$ENDIF WST_DELPHI});
+end;
+
+procedure TWstBaseTest.CheckEquals(expected, actual: QWord; msg: string;
+  const AStrict: Boolean);
+begin
+  if (expected <> actual) then
+    FailNotEquals(IntToStr(expected), IntToStr(actual), msg{$IFDEF WST_DELPHI}, CallerAddr{$ENDIF WST_DELPHI});
+end;
+{$ENDIF FPC}
+
+procedure TWstBaseTest.CheckEquals(expected, actual: TSDOBytes;
+  msg: string; const AStrict: Boolean
+);
+begin
+  if ( expected = nil ) then begin
+    Check(actual = nil, msg);
+  end else begin
+    CheckEquals(Length(expected),Length(actual),msg);
+    if ( Length(expected) > 0 ) then
+      Check(CompareMem(Pointer(expected), Pointer(actual),Length(expected)),msg);
+  end;
+end;
+
+procedure TWstBaseTest.CheckEqualsCurrency(expected, actual: Currency; const delta: Currency; const msg: string);
+begin
+  if ( delta = 0 ) then begin
+    if (expected <> actual) then
+      FailNotEquals(CurrToStr(expected), CurrToStr(actual), msg{$IFDEF WST_DELPHI}, CallerAddr{$ENDIF});
+  end else begin
+    if ( Abs(expected-actual) > delta ) then
+      FailNotEquals(CurrToStr(expected), CurrToStr(actual), msg{$IFDEF WST_DELPHI}, CallerAddr{$ENDIF});
+  end;
+end;
+
+procedure TWstBaseTest.CheckEqualsCurrency(expected, actual: Currency;
+  const msg: string);
+begin
+  CheckEqualsCurrency(expected,actual,0,msg);
+end;
+
+end.

+ 2120 - 0
packages/fcl-sdo/tests/test_suite/test_type.pas

@@ -0,0 +1,2120 @@
+{$INCLUDE sdo_global.inc}
+unit test_type;
+
+interface
+uses
+  SysUtils, Classes
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , sdo, sdo_type, sdo_types ;
+
+type
+
+  TTSDOSimpleType_Test = class(TTestCase)
+  private
+    FDataFactory : ISDODataFactory;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  protected
+    function get_datafactory() : ISDODataFactory;virtual;
+    function Create_Type() : ISDOType;virtual;abstract;
+    class function GetTestSuitePath() : string;
+    class function GetPredefinedAlias(AList : TStrings) : Integer;virtual;
+  published
+    procedure test_getName();
+	  procedure getBaseType();
+	  procedure getURI();
+	  procedure isDataObjectType();
+	  procedure isSequencedType();
+	  procedure isOpenType();
+	  procedure isAbstractType();
+    procedure isDataType();
+    procedure getTypeEnum();
+    procedure Alias_procs();
+    procedure Used();
+    procedure equals();
+    procedure getPropertyIndex();
+    procedure inherits();
+  end;
+
+  TSDOBooleanType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+  end;
+
+  TSDOByteType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+  end;
+
+{$IFDEF HAS_SDO_BYTES}  
+  TSDOBytesType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+    class function GetPredefinedAlias(AList : TStrings) : Integer;override;
+  end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+  TSDOCharacterType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+    class function GetPredefinedAlias(AList : TStrings) : Integer;override;
+  end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+  TSDOCurrencyType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+  end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+  TSDODateTimeType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+    class function GetPredefinedAlias(AList : TStrings) : Integer;override;
+  end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+  TSDODoubleType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+  end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+  TSDOFloatType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+  end;
+{$ENDIF HAS_SDO_FLOAT}
+
+  TSDOIntegerType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+    class function GetPredefinedAlias(AList : TStrings) : Integer;override;
+  end;
+
+{$IFDEF HAS_SDO_LONG}
+  TSDOLongType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+  end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+  TSDOShortType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+  end;
+{$ENDIF HAS_SDO_SHORT}
+
+  TSDOStringType_Test = class(TTSDOSimpleType_Test)
+  protected
+    function Create_Type() : ISDOType;override;
+    class function GetPredefinedAlias(AList : TStrings) : Integer;override;
+  end;
+
+  TTSDOBaseObjectType_Test = class(TTestCase)
+  private
+    FDataFactory : ISDODataFactory;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  protected
+    function get_datafactory() : ISDODataFactory;virtual;
+  protected
+    function Create_Type(
+      const AName       : string   = 'AObjType';
+      const AUri        : string   = sdo_namespace;
+      const ASequenced  : Boolean  = False ;
+      const AOpened     : Boolean  = False ;
+      const AAbstract   : Boolean  = False
+    ) : ISDOObjectType;virtual;abstract;
+    class function GetTestSuitePath() : string;
+  published
+    procedure test_getName();
+	  procedure getBaseType();
+	  procedure getURI();
+	  procedure getPropertyIndex();
+	  procedure isDataObjectType();
+	  procedure isSequencedType();
+	  procedure isOpenType();
+	  procedure isAbstractType();
+    procedure isDataType();
+    procedure getTypeEnum();
+    procedure equals();
+    procedure Alias_procs();
+    procedure Used();
+  end;
+
+  TSDOObjectType_Test = class(TTSDOBaseObjectType_Test)
+  protected
+    function Create_Type(
+      const AName       : string   = 'AObjType';
+      const AUri        : string   = sdo_namespace;
+      const ASequenced  : Boolean  = False ;
+      const AOpened     : Boolean  = False ;
+      const AAbstract   : Boolean  = False
+    ) : ISDOObjectType;override;
+  end;
+
+  TSDOUserDefinedSimpleType_Test = class(TTestCase)
+  private
+    FDataFactory : ISDODataFactory;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  protected
+    function get_datafactory() : ISDODataFactory;virtual;
+    function Create_Type(
+      const AName       : string   = 'AObjType';
+      const AUri        : string   = sdo_namespace;
+      const AAbstract   : Boolean  = False
+    ) : ISDOTypeEx;virtual;
+    class function GetTestSuitePath() : string;
+  published
+    procedure test_getName();
+	  procedure getBaseType();
+	  procedure getURI();
+	  procedure getPropertyIndex(const APropertyName : string);
+	  procedure isDataObjectType();
+	  procedure isSequencedType();
+	  procedure isOpenType();
+	  procedure isAbstractType();
+    procedure isDataType();
+    procedure getTypeEnum();
+    procedure equals(const AOther : ISDOType);
+    procedure Alias_procs();
+    procedure Used();
+  end;
+
+  TTSDOChangeSummaryType_Test = class(TTestCase)
+  private
+    FDataFactory : ISDODataFactory;
+  protected
+    procedure SetUp; override;
+    procedure TearDown; override;
+  protected
+    function get_datafactory() : ISDODataFactory;virtual;
+  protected
+    function Create_Type() : ISDOType;
+    class function GetTestSuitePath() : string;
+    class function GetPredefinedAlias(AList : TStrings) : Integer;
+  published
+    procedure test_getName();
+	  procedure getBaseType();
+	  procedure getURI();
+	  procedure isDataObjectType();
+	  procedure isSequencedType();
+	  procedure isOpenType();
+	  procedure isAbstractType();
+    procedure isDataType();
+    procedure getTypeEnum();
+    procedure Alias_procs();
+    procedure Used();
+    procedure equals();
+    procedure getPropertyIndex();
+  end;
+
+  TSDOBaseDataFactory_Test = class(TTestCase)
+  protected
+    function Create_Factory(
+    ) : ISDODataFactory;virtual;
+    class function GetTestSuitePath() : string;
+  published
+    procedure AddType();
+    procedure setBaseType();
+    procedure setAlias();
+    procedure addPropertyToType();
+    procedure addPropertyToType_Duplicate();
+    procedure addPropertyToType_DuplicateDerived();
+    procedure addPropertyToType_ChangeSummary();
+    procedure createNew();
+    procedure inherits();
+    procedure inherits_root();
+    procedure type_equals();
+
+    procedure check_circular_dependy();
+    procedure check_circular_dependy_1();
+    procedure check_circular_dependy_2();
+    procedure check_circular_dependy_3();
+    procedure check_circular_dependy_4();
+  end;
+
+implementation
+
+uses sdo_datafactory;
+
+{ TTSDOSimpleType_Test }
+
+procedure TTSDOSimpleType_Test.equals();
+begin
+  CheckEquals(True,Create_Type().equals(Create_Type()));
+end;
+
+procedure TTSDOSimpleType_Test.getBaseType();
+var
+  t, bt : ISDOType;
+begin
+  t := Create_Type();
+  bt := t.getBaseType();
+  CheckNull(bt);
+end;
+
+procedure TTSDOSimpleType_Test.test_getName();
+begin
+  CheckEquals(True,Create_Type().getName() <> '');
+end;
+
+procedure TTSDOSimpleType_Test.getPropertyIndex();
+var
+  ok : Boolean;
+  t : ISDOType;
+begin
+  ok := False;
+  try
+    t := Create_Type();
+    t.getPropertyIndex('a');
+  except
+    on e : ESDOUnsupportedOperationException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok);
+end;
+
+procedure TTSDOSimpleType_Test.getTypeEnum();
+begin
+  CheckEquals(
+    True,
+    Create_Type().getTypeEnum() in
+      [ BooleanType,ByteType{$IFDEF HAS_SDO_BYTES},BytesType{$ENDIF}
+        {$IFDEF HAS_SDO_CHAR},CharacterType{$ENDIF}
+        ,DateTimeType
+        {$IFDEF HAS_SDO_DOUBLE},DoubleType{$ENDIF}
+        {$IFDEF HAS_SDO_FLOAT},FloatType{$ENDIF}
+        ,IntegerType
+        {$IFDEF HAS_SDO_LONG},LongType{$ENDIF}
+        {$IFDEF HAS_SDO_SHORT},ShortType{$ENDIF}
+        ,StringType 
+      ]
+    );
+end;
+
+procedure TTSDOSimpleType_Test.getURI();
+begin
+  CheckEquals(True,Create_Type().getURI() <> '');
+end;
+
+procedure TTSDOSimpleType_Test.isAbstractType() ;
+begin
+  CheckEquals(False,Create_Type().isAbstractType());
+end;
+
+procedure TTSDOSimpleType_Test.isDataObjectType() ;
+begin
+  CheckEquals(False,Create_Type().isDataObjectType());
+end;
+
+procedure TTSDOSimpleType_Test.isDataType() ;
+begin
+  CheckEquals(True,Create_Type().isDataType());
+end;
+
+procedure TTSDOSimpleType_Test.isOpenType() ;
+begin
+  CheckEquals(False,Create_Type().isOpenType());
+end;
+
+procedure TTSDOSimpleType_Test.isSequencedType() ;
+begin
+  CheckEquals(False,Create_Type().isSequencedType());
+end;
+
+class function TTSDOSimpleType_Test.GetTestSuitePath: string;
+begin
+  Result := 'Metadata';
+end;
+
+procedure TTSDOSimpleType_Test.Alias_procs();
+var
+  obj : ISDOTypeEx;
+
+  function AliasExists(const AAlias : TSDOString) : Boolean;
+  var
+    k : Integer;
+  begin
+    Result := False;
+    for k := 0 to (obj.getAliasCount() - 1) do begin
+      if (AAlias = obj.getAlias(k)) then begin
+        Result := True;
+        Break;
+      end;
+    end;
+  end;
+
+var
+  ok : Boolean;
+  nativeAliasList : TStringList;
+  nativeAliasCount, i : Integer;
+  s : string;
+begin
+  nativeAliasList := TStringList.Create();
+  try
+    obj := Create_Type() as ISDOTypeEx;
+
+    nativeAliasCount := GetPredefinedAlias(nativeAliasList);
+    CheckEquals(nativeAliasCount,obj.getAliasCount(),'getAliasCount');
+    if ( nativeAliasCount > 0 ) then begin
+      for i := 0 to Pred(nativeAliasCount) do begin
+        s := nativeAliasList[i];
+        CheckEquals(True,AliasExists(s),Format('Unable to find predefined alias : "%s"',[s]));
+      end;
+    end;
+
+    ok := False;
+    try
+      obj.getAlias(nativeAliasCount);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('getAlias(%d) : ESDOIndexOutOfRangeException expected.',[nativeAliasCount]));
+
+    obj.SetAlias('aaaaaaaaaaaa');
+    CheckEquals(True,AliasExists('aaaaaaaaaaaa'),'Alias not found.');
+    CheckEquals(nativeAliasCount + 1,obj.getAliasCount(),'getAliasCount');
+    ok := False;
+    try
+      obj.getAlias(nativeAliasCount + 1);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('getAlias(%d) : ESDOIndexOutOfRangeException expected.',[nativeAliasCount + 1]));
+
+    obj.SetAlias('aaaaaaaaaaaa');
+    CheckEquals(True,AliasExists('aaaaaaaaaaaa'),'Alias not found.');
+    CheckEquals(nativeAliasCount + 1,obj.getAliasCount(),'getAliasCount');
+
+    obj.SetAlias('aaaaaaaaaaaab');
+    CheckEquals(nativeAliasCount + 2,obj.getAliasCount(),'getAliasCount');
+    CheckEquals(True,AliasExists('aaaaaaaaaaaab'),'Alias not found.');
+    CheckEquals(True,AliasExists('aaaaaaaaaaaa'),'Alias not found.');
+    ok := False;
+    try
+      obj.getAlias(nativeAliasCount + 2);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('getAlias(%d) : ESDOIndexOutOfRangeException expected.',[nativeAliasCount + 2]));
+  finally
+    FreeAndNil(nativeAliasList);
+  end;
+end;
+
+procedure TTSDOSimpleType_Test.Used();
+var
+  obj : ISDOTypeEx;
+  ok : Boolean;
+begin
+  obj := Create_Type() as ISDOTypeEx;
+  CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+    ok := False;
+    try
+      obj.setAlias('azerty_qwerty');
+    except
+      on e : ESDOUnsupportedOperationException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'Modify an used type.');
+end;
+
+class function TTSDOSimpleType_Test.GetPredefinedAlias(AList: TStrings): Integer;
+begin
+  AList.Clear();
+  Result := AList.Count;
+end;
+
+procedure TTSDOSimpleType_Test.inherits();
+var
+  tX : ISDOTypeEx;
+begin
+  tX := Create_Type() as ISDOTypeEx;
+  Check(not tx.inherits(nil));
+  Check(not tx.inherits(tx));
+end;
+
+function TTSDOSimpleType_Test.get_datafactory() : ISDODataFactory;
+begin
+  if ( FDataFactory = nil ) then
+    FDataFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Result := FDataFactory;
+end;
+
+procedure TTSDOSimpleType_Test.SetUp;
+begin
+  inherited;
+  FDataFactory := nil;
+end;
+
+procedure TTSDOSimpleType_Test.TearDown;
+begin
+  FDataFactory := nil;
+  inherited;
+end;
+
+{ TSDOBooleanType_Test }
+
+function TSDOBooleanType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOBooleanType.Create(get_datafactory()) as ISDOType;
+end;
+
+{ TSDOByteType_Test }
+
+function TSDOByteType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOByteType.Create(get_datafactory()) as ISDOType;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+{ TSDOBytesType_Test }
+
+function TSDOBytesType_Test.Create_Type: ISDOType;
+begin
+  Result := TSDOBytesType.Create(get_datafactory()) as ISDOType;
+end;
+
+class function TSDOBytesType_Test.GetPredefinedAlias(AList: TStrings): Integer;
+begin
+  AList.Clear();
+  AList.Add('hexBinary');
+  Result := AList.Count;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+{ TSDOCharacterType_Test }
+
+function TSDOCharacterType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOCharacterType.Create(get_datafactory()) as ISDOType;
+end;
+
+class function TSDOCharacterType_Test.GetPredefinedAlias(AList: TStrings): Integer;
+begin
+  AList.Clear();
+  AList.Add('Char');
+  AList.Add('WideChar');
+  AList.Add('AnsiChar');
+  Result := AList.Count;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+{ TSDOCurrencyType_Test }
+
+function TSDOCurrencyType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOCurrencyType.Create(get_datafactory()) as ISDOType;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{ TSDODateTimeType_Test }
+
+function TSDODateTimeType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDODateTimeType.Create(get_datafactory()) as ISDOType;
+end;
+
+class function TSDODateTimeType_Test.GetPredefinedAlias(AList: TStrings): Integer;
+begin
+  AList.Clear();
+  AList.Add('Date');
+  Result := AList.Count;
+end;
+
+{$IFDEF HAS_SDO_DOUBLE}
+{ TSDODoubleType_Test }
+
+function TSDODoubleType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDODoubleType.Create(get_datafactory()) as ISDOType;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+{ TSDOFloatType_Test }
+
+function TSDOFloatType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOFloatType.Create(get_datafactory()) as ISDOType;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{ TSDOIntegerType_Test }
+
+function TSDOIntegerType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOIntegerType.Create(get_datafactory()) as ISDOType;
+end;
+
+class function TSDOIntegerType_Test.GetPredefinedAlias(AList: TStrings): Integer;
+begin
+  AList.Clear();
+  AList.Add('Int');
+  Result := AList.Count;
+end;
+
+{$IFDEF HAS_SDO_LONG}
+{ TSDOLongType_Test }
+
+function TSDOLongType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOLongType.Create(get_datafactory()) as ISDOType;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{ TSDOStringType_Test }
+
+function TSDOStringType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOStringType.Create(get_datafactory()) as ISDOType;
+end;
+
+class function TSDOStringType_Test.GetPredefinedAlias(AList: TStrings): Integer;
+begin
+  AList.Clear();
+  AList.Add('Strings');
+  Result := AList.Count;
+end;
+
+{ TTSDOBaseObjectType_Test }
+
+procedure TTSDOBaseObjectType_Test.Alias_procs();
+var
+  obj : ISDOTypeEx;
+  ok : Boolean;
+begin
+  obj := Create_Type() as ISDOTypeEx;
+  CheckEquals(0,obj.getAliasCount(),'getAliasCount');
+
+  ok := False;
+  try
+    obj.getAlias(1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(1) : ESDOIndexOutOfRangeException expected.');
+
+  obj.SetAlias('a');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals(1,obj.getAliasCount(),'getAliasCount');
+  ok := False;
+  try
+    obj.getAlias(1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(1) : ESDOIndexOutOfRangeException expected.');
+
+  obj.SetAlias('a');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals(1,obj.getAliasCount(),'getAliasCount');
+
+  obj.SetAlias('b');
+  CheckEquals(2,obj.getAliasCount(),'getAliasCount');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals('b',obj.getAlias(1),'getAlias');
+  ok := False;
+  try
+    obj.getAlias(2);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(2) : ESDOIndexOutOfRangeException expected.');
+end;
+
+procedure TTSDOBaseObjectType_Test.equals();
+var
+  a, b : ISDOType;
+  ls : IInterfaceList;
+begin
+  ls := TInterfaceList.Create();
+
+  a := Create_Type('A', 'uri-a'); ls.Add(a);
+  b := Create_Type('A', 'uri-a'); ls.Add(b);
+  CheckEquals(True,a.equals(b));
+
+  a := Create_Type('A', 'uri-a'); ls.Add(a);
+  b := Create_Type('B', 'uri-a'); ls.Add(b);
+  CheckEquals(False,a.equals(b));
+
+  a := Create_Type('A', 'uri-a'); ls.Add(a);
+  b := Create_Type('A', 'uri-b'); ls.Add(b);
+  CheckEquals(False,a.equals(b));
+
+  a := Create_Type('A', 'uri-a'); ls.Add(a);
+  b := Create_Type('B', 'uri-b'); ls.Add(b);
+  CheckEquals(False,a.equals(b));
+end;
+
+procedure TTSDOBaseObjectType_Test.getBaseType();
+var
+  baseObj, obj : ISDOObjectType;
+begin
+  obj := Create_Type();
+  CheckNull(obj.getBaseType());
+  baseObj := Create_Type('BaseAQZ');
+  obj.SetBaseType(baseObj);
+  Check(baseObj = obj.getBaseType());
+  obj.SetBaseType(nil);
+  CheckNull(obj.getBaseType());
+end;
+
+procedure TTSDOBaseObjectType_Test.getPropertyIndex();
+var
+  baseObj, obj : ISDOObjectType;
+  ok : Boolean;
+  boolType : ISDOType;
+  i : Integer;
+begin
+  boolType := TSDOBooleanType.Create(get_datafactory());
+
+  obj := Create_Type('Z');
+  ok := False;
+  try
+    obj.getPropertyIndex('a') ;
+  except
+    on e : ESDOPropertyNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok);
+
+  obj.AddProperty('a',boolType,[]);
+  i := obj.getPropertyIndex('a') ;
+  CheckEquals(i,obj.getPropertyIndex('a'));
+  CheckEquals(i,obj.getProperties().getIndex('a'));
+
+  obj.AddProperty('b',boolType,[]);
+  i := obj.getPropertyIndex('b') ;
+  CheckEquals(i,obj.getPropertyIndex('b'));
+  CheckEquals(i,obj.getProperties().getIndex('b'));
+
+  i := obj.getPropertyIndex('a') ;
+  CheckEquals(i,obj.getPropertyIndex('a'));
+  CheckEquals(i,obj.getProperties().getIndex('a'));
+
+  CheckNotEquals(obj.getPropertyIndex('a') , obj.getPropertyIndex('b'));
+  CheckNotEquals(obj.getProperties().getIndex('a') , obj.getProperties().getIndex('b'));
+
+  CheckEquals(True,obj.getPropertyIndex('a') < obj.getPropertyIndex('b'), 'Index(a) < Index(b)');
+  CheckEquals(True,obj.getProperties().getIndex('a') < obj.getProperties().getIndex('b'), 'getProperties : Index(a) < Index(b)');
+
+  baseObj := Create_Type('ZZ');
+  baseObj.AddProperty('za',boolType,[]);
+  obj.SetBaseType(baseObj);
+
+  i := obj.getPropertyIndex('za') ;
+  CheckEquals(i,obj.getPropertyIndex('za'));
+  CheckEquals(i,obj.getProperties().getIndex('za'));
+
+  CheckNotEquals(obj.getPropertyIndex('za') , obj.getPropertyIndex('a'));
+  CheckNotEquals(obj.getProperties().getIndex('za') , obj.getProperties().getIndex('a'));
+
+  CheckNotEquals(obj.getPropertyIndex('a') , obj.getPropertyIndex('b'));
+  CheckNotEquals(obj.getProperties().getIndex('a') , obj.getProperties().getIndex('b'));
+
+  CheckEquals(True,obj.getPropertyIndex('za') < obj.getPropertyIndex('a'), 'Index(za) < Index(a)');
+  CheckEquals(True,obj.getProperties().getIndex('za') < obj.getProperties().getIndex('a'), 'getProperties : Index(za) < Index(a)');
+
+  CheckEquals(True,obj.getPropertyIndex('a') < obj.getPropertyIndex('b'), 'Index(a) < Index(b)');
+  CheckEquals(True,obj.getProperties().getIndex('a') < obj.getProperties().getIndex('b'), 'getProperties : Index(a) < Index(b)');
+ 
+end;
+
+class function TTSDOBaseObjectType_Test.GetTestSuitePath: string;
+begin
+  Result := 'Metadata';
+end;
+
+procedure TTSDOBaseObjectType_Test.getTypeEnum();
+begin
+  CheckEquals(True,Create_Type().getTypeEnum() = ObjectType);
+end;
+
+procedure TTSDOBaseObjectType_Test.getURI();
+const sTYPE_NAME = 'aqwsdfgg'; sTYPE_URI = 'ldhdsyhjhn';
+var
+  obj : ISDOObjectType;
+begin
+  obj := Create_Type(sTYPE_NAME,sTYPE_URI);
+  CheckEquals(sTYPE_NAME,obj.getName());
+  CheckEquals(sTYPE_URI,obj.getURI());
+end;
+
+function TTSDOBaseObjectType_Test.get_datafactory(): ISDODataFactory;
+begin
+  if ( FDataFactory = nil ) then
+    FDataFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Result := FDataFactory;
+end;
+
+procedure TTSDOBaseObjectType_Test.isAbstractType();
+const sTYPE_NAME = 'aqwsdfgg'; sTYPE_URI = 'ldhdsyhjhn';
+var
+  obj : ISDOObjectType;
+begin
+  obj := Create_Type(sTYPE_NAME,sTYPE_URI,False,False,False);
+  CheckEquals(False,obj.isAbstractType());
+
+  obj := Create_Type(sTYPE_NAME,sTYPE_URI,False,False,True);
+  CheckEquals(True,obj.isAbstractType());
+end;
+
+procedure TTSDOBaseObjectType_Test.isDataObjectType();
+begin
+  CheckEquals(True,Create_Type().isDataObjectType());
+end;
+
+procedure TTSDOBaseObjectType_Test.isDataType();
+begin
+  CheckEquals(False,Create_Type().isDataType());
+end;
+
+procedure TTSDOBaseObjectType_Test.isOpenType();
+const sTYPE_NAME = 'aqwsdfgg'; sTYPE_URI = 'ldhdsyhjhn';
+var
+  obj : ISDOObjectType;
+begin
+  obj := Create_Type(sTYPE_NAME,sTYPE_URI,False,False,False);
+  CheckEquals(False,obj.isOpenType());
+
+  obj := Create_Type(sTYPE_NAME,sTYPE_URI,False,True,False);
+  CheckEquals(True,obj.isOpenType());
+end;
+
+procedure TTSDOBaseObjectType_Test.isSequencedType();
+const sTYPE_NAME = 'aqwsdfgg'; sTYPE_URI = 'ldhdsyhjhn';
+var
+  obj : ISDOObjectType;
+begin
+  obj := Create_Type(sTYPE_NAME,sTYPE_URI,False,False,False);
+  CheckEquals(False,obj.isSequencedType());
+
+  obj := Create_Type(sTYPE_NAME,sTYPE_URI,True,False,False);
+  CheckEquals(True,obj.isSequencedType());
+end;
+
+procedure TTSDOBaseObjectType_Test.SetUp;
+begin
+  inherited;
+  FDataFactory := nil;
+end;
+
+procedure TTSDOBaseObjectType_Test.TearDown;
+begin
+  FDataFactory := nil;
+  inherited;
+end;
+
+procedure TTSDOBaseObjectType_Test.test_getName();
+const sNAME = 'AQZ';
+begin
+  CheckEquals(sNAME,Create_Type(sNAME).getName());
+end;
+
+procedure TTSDOBaseObjectType_Test.Used();
+var
+  obj, obj2, baseObj : ISDOObjectType;
+  ok : Boolean;
+  boolType, intType, strType : ISDOTypeEx;
+begin
+  obj := Create_Type() as ISDOObjectType;
+  obj2 := Create_Type() as ISDOObjectType;
+  CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+    ok := False;
+    try
+      obj.setAlias('azerty_qwerty');
+    except
+      on e : ESDOUnsupportedOperationException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'Modify an used type (setAlias).');
+
+    ok := False;
+    try
+      obj.setBaseType(obj2 as ISDOType);
+    except
+      on e : ESDOUnsupportedOperationException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'Modify an used type(setBaseType).');
+
+    ok := False;
+    try
+      obj.AddProperty('a',TSDOBooleanType.Create(get_datafactory()) as ISDOType,[]);
+    except
+      on e : ESDOUnsupportedOperationException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'Modify an used type (AddProperty).');
+
+  //--------------------------------------------------
+  boolType := TSDOBooleanType.Create(get_datafactory());
+  intType := TSDOIntegerType.Create(get_datafactory());
+  strType := TSDOStringType.Create(get_datafactory());
+
+  obj := Create_Type('Z');
+  obj.AddProperty('a',boolType,[]);
+  obj.AddProperty('b',intType,[]);
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+    CheckEquals(True,boolType.isUsed());
+    CheckEquals(True,intType.isUsed());
+
+  obj.setUsedFlag(False);
+
+  baseObj := Create_Type('ZZ');
+  baseObj.AddProperty('za',strType,[]);
+  obj.SetBaseType(baseObj);
+
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+    CheckEquals(True,boolType.isUsed());
+    CheckEquals(True,intType.isUsed());
+    CheckEquals(True,baseObj.isUsed());
+    CheckEquals(True,strType.isUsed());
+
+end;
+
+{ TSDOObjectType_Test }
+
+function TSDOObjectType_Test.Create_Type(const AName, AUri: string;
+  const ASequenced, AOpened, AAbstract: Boolean): ISDOObjectType;
+begin
+  Result := TSDOObjectType.Create(get_datafactory(),AName,AUri,ASequenced,AOpened,AAbstract);
+end;
+
+{ TSDOUserDefinedSimpleType_Test }
+
+procedure TSDOUserDefinedSimpleType_Test.Alias_procs;
+var
+  obj : ISDOTypeEx;
+  ok : Boolean;
+begin
+  obj := Create_Type() as ISDOTypeEx;
+  CheckEquals(0,obj.getAliasCount(),'getAliasCount');
+
+  ok := False;
+  try
+    obj.getAlias(1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(1) : ESDOIndexOutOfRangeException expected.');
+
+  obj.SetAlias('a');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals(1,obj.getAliasCount(),'getAliasCount');
+  ok := False;
+  try
+    obj.getAlias(1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(1) : ESDOIndexOutOfRangeException expected.');
+
+  obj.SetAlias('a');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals(1,obj.getAliasCount(),'getAliasCount');
+
+  obj.SetAlias('b');
+  CheckEquals(2,obj.getAliasCount(),'getAliasCount');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals('b',obj.getAlias(1),'getAlias');
+  ok := False;
+  try
+    obj.getAlias(2);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(2) : ESDOIndexOutOfRangeException expected.');
+end;
+
+function TSDOUserDefinedSimpleType_Test.Create_Type(const AName,
+  AUri: string; const AAbstract: Boolean): ISDOTypeEx;
+begin
+  Result := TSDOUserDefinedSimpleType.Create(get_datafactory(),AName,AUri,AAbstract);
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.equals(const AOther: ISDOType);
+begin
+  CheckEquals(True,Create_Type().equals(Create_Type()));
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.getBaseType();
+var
+  baseObj, obj : ISDOTypeEx;
+  ok : Boolean;
+begin
+  obj := TSDOUserDefinedSimpleType.Create(get_datafactory(), 'a',sdo_namespace,False);
+  CheckNull(obj.getBaseType());
+  baseObj := TSDOByteType.Create(get_datafactory());
+  obj.SetBaseType(baseObj);
+  Check(baseObj=obj.getBaseType());
+  obj.SetBaseType(nil);
+  CheckNull(obj.getBaseType());
+
+  baseObj := TSDOObjectType.Create(get_datafactory(),'x',sdo_namespace,False,False,False);
+  ok := False;
+  try
+    obj.setBaseType(baseObj);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Can not derive from ObjectType.');
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.getPropertyIndex(const APropertyName: string);
+var
+  ok : Boolean;
+  t : ISDOType;
+begin
+  ok := False;
+  try
+    t := Create_Type();
+    t.getPropertyIndex('a');
+  except
+    on e : ESDOUnsupportedOperationException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok);
+end;
+
+class function TSDOUserDefinedSimpleType_Test.GetTestSuitePath: string;
+begin
+  Result := 'Metadata';
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.getTypeEnum();
+var
+  baseObj, obj : ISDOTypeEx;
+  ok : Boolean;
+begin
+  obj := Create_Type();
+  ok := False;
+  try
+    obj.getTypeEnum();
+  except
+    on e : ESDOIncompleteTypeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Incomplete Type.');
+
+  baseObj := TSDOByteType.Create(get_datafactory());
+  obj.SetBaseType(baseObj);
+  CheckEquals(True,baseObj.getTypeEnum() = obj.getTypeEnum());
+
+  obj.setBaseType(nil);
+  try
+    obj.getTypeEnum();
+  except
+    on e : ESDOIncompleteTypeException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Incomplete Type.');
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.getURI();
+begin
+  CheckEquals(sdo_namespace,Create_Type().getURI());
+end;
+
+function TSDOUserDefinedSimpleType_Test.get_datafactory: ISDODataFactory;
+begin
+  if ( FDataFactory = nil ) then
+    FDataFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Result := FDataFactory;
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.isAbstractType();
+begin
+  CheckEquals(False,Create_Type('a',sdo_namespace,False).isAbstractType());
+  CheckEquals(True,Create_Type('a',sdo_namespace,True).isAbstractType());
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.isDataObjectType();
+begin
+  CheckEquals(False,Create_Type().isDataObjectType());
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.isDataType();
+begin
+  CheckEquals(True,Create_Type().isDataType());
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.isOpenType();
+begin
+  CheckEquals(False,Create_Type().isOpenType());
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.isSequencedType();
+begin
+  CheckEquals(False,Create_Type().isSequencedType());
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.SetUp;
+begin
+  inherited;
+  FDataFactory := nil;
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.TearDown;
+begin
+  FDataFactory := nil;
+  inherited;
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.test_getName();
+const sNAME = 'AQZ';
+begin
+  CheckEquals(sNAME,Create_Type(sNAME).getName());
+end;
+
+procedure TSDOUserDefinedSimpleType_Test.Used();
+var
+  obj : ISDOTypeEx;
+  ok : Boolean;
+begin
+  obj := Create_Type() as ISDOTypeEx;
+  CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+    ok := False;
+    try
+      obj.setAlias('azerty_qwerty');
+    except
+      on e : ESDOUnsupportedOperationException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'Modify an used type (setAlias).');
+
+    ok := False;
+    try
+      obj.setBaseType(TSDOBooleanType.Create(get_datafactory()) as ISDOType);
+    except
+      on e : ESDOUnsupportedOperationException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'Modify an used type(setBaseType).');
+end;
+
+{ TSDOBaseDataFactory_Test }
+
+procedure TSDOBaseDataFactory_Test.addPropertyToType();
+const s_URI_1  = 'uri:1'; s_TYPE_1 = 'type1';
+      s_PROP = 'aprop'; s_PROP_2 = 'aprop2'; s_PROP_3 = 'aprop3';
+      s_URI_2  = 'uri:2'; s_TYPE_2 = 'type2';
+var
+  obj : ISDODataFactory;
+  typ : ISDOType;
+  prpList : ISDOPropertyList;
+  ok : Boolean;
+begin
+  obj := Create_Factory();
+
+  ok := False;
+  try
+    obj.addProperty(nil,s_PROP,sdo_namespace,'String',[]);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'nil Type.');
+
+  ok := False;
+  try
+    obj.addProperty(s_URI_1,s_TYPE_1,s_PROP,sdo_namespace,'String',[]);
+  except
+    on e : ESDOTypeNotFoundException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'Type not created.');
+
+  obj.AddType(s_URI_1,s_TYPE_1,[]);
+  obj.AddType(s_URI_2,s_TYPE_2,[]);
+    ok := False;
+    try
+      obj.addProperty(s_URI_1,s_TYPE_1,s_PROP,nil,[]);
+    except
+      on e : ESDOIllegalArgumentException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'property Type = nil.');
+
+    ok := False;
+    try
+      obj.addProperty(s_URI_1,s_TYPE_1,s_PROP,sdo_namespace,'String',[pfIsContainment]);
+    except
+      on e : ESDOIllegalArgumentException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True,ok,'Adding a boolean as Object.');
+
+    obj.addProperty(s_URI_1,s_TYPE_1,s_PROP,sdo_namespace,'String',[]);
+    typ := obj.getType(s_URI_1,s_TYPE_1);
+    prpList := typ.getProperties();
+    Check(Assigned(prpList));
+    CheckEquals(True,prpList.getCount() > 0,'prpList.getCount() > 0');
+    Check(nil <> prpList.find(s_PROP));
+    Check(obj.getType(sdo_namespace,'String') = prpList.find(s_PROP).getType());
+
+    obj.addProperty(typ,s_PROP_2,obj.getType(sdo_namespace,'Integer'),[]);
+    typ := obj.getType(s_URI_1,s_TYPE_1);
+    prpList := typ.getProperties();
+    Check(nil <> prpList);
+    CheckEquals(True,prpList.getCount() > 1,'prpList.getCount() > 0');
+    Check(nil <> prpList.find(s_PROP_2));
+    Check(obj.getType(sdo_namespace,'Integer') = prpList.find(s_PROP_2).getType());
+
+end;
+
+procedure TSDOBaseDataFactory_Test.addPropertyToType_ChangeSummary();
+const s_uri  = 'uri:1'; s_type = 'type1';
+      s_integer_prop = 'int_prop'; s_bool_prop = 'bool_prop'; s_string_prop = 'string_prop';
+      s_changesummary_prop = 'change_summary_prop';
+var
+  obj : ISDODataFactory;
+  typ : ISDOType;
+  prpList : ISDOPropertyList;
+  prp : ISDOProperty;
+  ok : Boolean;
+begin
+  obj := Create_Factory();
+
+  obj.AddType(s_uri,s_type,[]);
+    typ := obj.getType(s_uri,s_type);
+    obj.addProperty(typ,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[]);
+    obj.addProperty(typ,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[]);
+    obj.addProperty(typ,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[]);
+
+    ok := False;
+    try
+      obj.addProperty(typ,s_changesummary_prop,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsMany]);
+    except
+      on e : ESDOIllegalArgumentException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True, ok, 'ChangeSummary property can not be a multi-value property.');
+
+    ok := False;
+    try
+      obj.addProperty(typ,s_changesummary_prop,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[]);
+    except
+      on e : ESDOIllegalArgumentException do begin
+        ok := True;
+      end;
+    end;
+    CheckEquals(True, ok, 'ChangeSummary property must be read-only.');
+
+    obj.addProperty(typ,s_changesummary_prop,sdo_namespace,SDOTypeDefaultTypeNames[ChangeSummaryType],[pfIsReadOnly]);
+
+    prpList := typ.getProperties();
+    Check(Assigned(prpList));
+    CheckEquals(4,prpList.getCount(),'prpList.getCount() > 0');
+    prp := typ.getProperty(s_changesummary_prop);
+    CheckNotEquals(PtrUInt(nil),PtrUInt(prp));
+    CheckEquals(Ord(ChangeSummaryType), Ord(prp.getTypeEnum()));
+end;
+
+procedure TSDOBaseDataFactory_Test.addPropertyToType_Duplicate();
+const s_uri = 'uri1'; s_type = 'type1'; s_prop = 'prop1';
+var
+  obj : ISDODataFactory;
+  ok : Boolean;
+begin
+  obj := Create_Factory();
+  obj.AddType(s_uri,s_type,[]);
+
+  obj.addProperty(s_uri,s_type,s_prop,sdo_namespace,'String',[]);
+  ok := False;
+  try
+    obj.addProperty(s_uri,s_type,s_prop,sdo_namespace,'String',[]);
+  except
+    on e : ESDODuplicatedItemException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok);
+end;
+
+procedure TSDOBaseDataFactory_Test.addPropertyToType_DuplicateDerived();
+const s_uri = 'uri1'; s_type = 'type1'; s_type2 = 'type2';  s_prop = 'prop1';
+var
+  obj : ISDODataFactory;
+  ok : Boolean;
+begin
+  obj := Create_Factory();
+  obj.AddType(s_uri,s_type,[]);
+  obj.AddType(s_uri,s_type2,[]);
+  obj.setBaseType(s_uri,s_type2,s_uri,s_type);
+
+  obj.addProperty(s_uri,s_type,s_prop,sdo_namespace,'String',[]);
+  ok := False;
+  try
+    obj.addProperty(s_uri,s_type2,s_prop,sdo_namespace,'String',[]);
+  except
+    on e : ESDODuplicatedItemException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok);
+end;
+
+procedure TSDOBaseDataFactory_Test.AddType();
+const s_URI_1  = 'uri:1'; s_URI_2  = 'uri:2';
+      s_TYPE_1 = 'type1'; s_TYPE_2 = 'type2';
+var
+  obj : ISDODataFactory;
+  typ, typ2 : ISDOType;
+  typLst : ISDOTypeList;
+  ok : Boolean;
+begin
+  obj := Create_Factory();
+
+  ok := False;
+  try
+    obj.AddType(s_URI_1,s_TYPE_1,[tfIsSequenced,tfIsDataType]);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'IllegalArgument :  Sequence = True; DataType = True');
+
+  ok := False;
+  try
+    obj.AddType(s_URI_1,s_TYPE_1,[tfIsOpen,tfIsDataType]);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'IllegalArgument :  Open = True; DataType = True');
+
+  ok := False;
+  try
+    obj.AddType(s_URI_1,s_TYPE_1,[tfIsSequenced,tfIsOpen,tfIsDataType]);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'IllegalArgument :  Sequence = True; Open = True; DataType = True');
+
+  ok := False;
+  try
+    obj.AddType(s_URI_1,'',[]);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'IllegalArgument :  Name = ""');
+
+  ok := False;
+  try
+    obj.AddType(s_URI_1,'1az',[]);
+  except
+    on e : ESDOIllegalArgumentException do begin
+      ok := True;
+    end;
+  end;
+  CheckEquals(True,ok,'IllegalArgument :  Name = "1az"');
+
+  typLst := obj.getTypes();
+  Check(nil <> typLst,'getTypes()');
+
+  obj.AddType(s_URI_1,s_TYPE_1, [tfIsDataType]);
+  typ := typLst.find(s_URI_1,s_TYPE_1);
+  Check(nil <> typ,'typLst.find(s_URI_1,s_TYPE_1)');
+  Check(nil <> obj.getTypes().find(s_URI_1,s_TYPE_1),'getTypes().find(s_URI_1,s_TYPE_1)');
+  Check(typLst=obj.getTypes(),'typLst = obj.getTypes()');
+  CheckEquals(s_URI_1,typ.getURI());
+  CheckEquals(s_TYPE_1,typ.getName());
+  CheckEquals(False,typ.isDataObjectType(), 'isDataObjectType');
+  CheckEquals(False,typ.isSequencedType(),'isSequencedType');
+  CheckEquals(True,typ.isDataType(),'isDataType');
+  CheckNull(typ.getBaseType(),'getBaseType()');
+
+  obj.AddType(s_URI_2,s_TYPE_2,[]);
+  typ2 := typLst.find(s_URI_2,s_TYPE_2);
+  Check(nil <> typ2,'typLst.find(s_URI_2,s_TYPE_2)');
+  Check(nil <> obj.getTypes().find(s_URI_2,s_TYPE_2),'getTypes().find(s_URI_2,s_TYPE_2)');
+  Check(typLst=obj.getTypes(),'typLst = obj.getTypes()');
+  CheckEquals(s_URI_2,typ2.getURI());
+  CheckEquals(s_TYPE_2,typ2.getName());
+  CheckEquals(True,typ2.isDataObjectType(), 'isDataObjectType');
+  CheckEquals(False,typ2.isSequencedType(),'isSequencedType');
+  CheckEquals(False,typ2.isDataType(),'isDataType');
+  CheckNull(typ2.getBaseType(),'getBaseType()');
+
+  typ := typLst.find(s_URI_1,s_TYPE_1);
+  Check(nil <> typ,'typLst.find(s_URI_1,s_TYPE_1)');
+end;
+
+procedure TSDOBaseDataFactory_Test.check_circular_dependy();
+const
+  s_uri = 'uri';
+var
+  locFac : ISDODataFactory;
+begin
+  // Auto reference should be allowed!
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'A',[]);
+    locFac.addProperty(s_uri,'A','p_circular',s_uri,'A',[]);
+
+  locFac.createNew(s_uri,'A');
+end;
+
+procedure TSDOBaseDataFactory_Test.check_circular_dependy_1();
+const
+  s_uri = 'uri';
+var
+  locFac : ISDODataFactory;
+  ok : Boolean;
+  locTypeX : ISDOObjectType;
+begin  
+  { Auto reference should be allowed!
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'A',[]);
+  locFac.AddType(s_uri,'B',[]);
+
+  locFac.addProperty(s_uri,'A','p_AB',s_uri,'B',[]);
+    locFac.addProperty(s_uri,'B','p_BB',s_uri,'B',[]);
+      ok := False;
+      try
+        locFac.createNew(s_uri,'A');
+      except
+        on e : ESDOCircularDependencyTypeException do begin
+          ok := True;
+        end;
+      end;
+      Check(ok, 'Succefully create a object who''s type tree contains circular dependency.');
+      locTypeX := locFac.getType(s_uri,'B') as ISDOObjectType;
+      locTypeX.DropProperty(locTypeX.getProperty('p_BB'));
+      locFac := nil;}
+
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'A',[]);
+  locFac.AddType(s_uri,'B',[]);
+
+  locFac.addProperty(s_uri,'A','p_AB',s_uri,'B',[]);
+    locFac.addProperty(s_uri,'B','p_BA',s_uri,'A',[]);
+      ok := False;
+      try
+        locFac.createNew(s_uri,'A');
+      except
+        on e : ESDOCircularDependencyTypeException do begin
+          ok := True;
+        end;
+      end;
+      Check(ok, 'Succefully create a object who''s type tree contains circular dependency.');
+      locTypeX := locFac.getType(s_uri,'B') as ISDOObjectType;
+      locTypeX.DropProperty(locTypeX.getProperty('p_BA'));
+      locFac := nil;
+end;
+
+procedure TSDOBaseDataFactory_Test.check_circular_dependy_2();
+const
+  s_uri = 'uri';
+var
+  locFac : ISDODataFactory;
+  ok : Boolean;
+  locTypeX : ISDOObjectType;
+begin
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'A',[]);
+  locFac.AddType(s_uri,'B',[]);
+  locFac.AddType(s_uri,'C',[]);
+    locFac.addProperty(s_uri,'A','p_AB',s_uri,'B',[]);
+      locFac.addProperty(s_uri,'B','p_BC',s_uri,'C',[]);
+        locFac.addProperty(s_uri,'C','p_CA',s_uri,'A',[]);
+        ok := False;
+        try
+          locFac.createNew(s_uri,'A');
+        except
+          on e : ESDOCircularDependencyTypeException do begin
+            ok := True;
+          end;
+        end;
+        Check(ok, 'Succefully create a object who''s type tree contains circular dependency.');
+        locTypeX := locFac.getType(s_uri,'C') as ISDOObjectType;
+        locTypeX.DropProperty(locTypeX.getProperty('p_CA'));
+        locFac := nil;
+
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'A',[]);
+  locFac.AddType(s_uri,'B',[]);
+  locFac.AddType(s_uri,'C',[]);
+    locFac.addProperty(s_uri,'A','p_AB',s_uri,'B',[]);
+      locFac.addProperty(s_uri,'B','p_BC',s_uri,'C',[]);
+        locFac.addProperty(s_uri,'C','p_CB',s_uri,'B',[]);
+        ok := False;
+        try
+          locFac.createNew(s_uri,'A');
+        except
+          on e : ESDOCircularDependencyTypeException do begin
+            ok := True;
+          end;
+        end;
+        Check(ok, 'Succefully create a object who''s type tree contains circular dependency.');
+        locTypeX := locFac.getType(s_uri,'C') as ISDOObjectType;
+        locTypeX.DropProperty(locTypeX.getProperty('p_CB'));
+        locFac := nil;
+end;
+
+procedure TSDOBaseDataFactory_Test.check_circular_dependy_3();
+const
+  s_uri = 'uri';
+var
+  locFac : ISDODataFactory;
+  ok : Boolean;
+begin
+  locFac := TSDODataFactory.Create() as ISDODataFactory;
+  locFac.AddType(s_uri,'X',[]);
+    locFac.AddType(s_uri,'A',[]);
+      locFac.setBaseType(s_uri,'A',s_uri,'X');
+    locFac.AddType(s_uri,'B',[]);
+    locFac.AddType(s_uri,'C',[]);
+      locFac.addProperty(s_uri,'A','p_ab',s_uri,'B',[pfIsContainment]);
+      locFac.addProperty(s_uri,'B','p_bc',s_uri,'C',[pfIsContainment]);
+      locFac.addProperty(s_uri,'C','p_ca_circular',s_uri,'X',[pfIsContainment]);
+
+      ok := False;
+      try
+        locFac.createNew(s_uri,'A');
+      except
+        on  e : ESDOCircularDependencyTypeException do
+          ok := True
+      end;
+      Check(ok, 'Succefully create a object who''s type tree contains circular dependency.');
+end;
+
+procedure TSDOBaseDataFactory_Test.check_circular_dependy_4();
+const
+  s_uri = 'uri';
+var
+  locFac : ISDODataFactory;
+  ok : Boolean;
+  locTypeX : ISDOObjectType;
+begin
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'X',[]);
+    locFac.AddType(s_uri,'A',[]);
+    locFac.setBaseType(s_uri,'A',s_uri,'X');
+      locFac.addProperty(s_uri,'A','p_circular',s_uri,'X',[]);
+
+  ok := False;
+  try
+    locFac.createNew(s_uri,'A');
+  except
+    on e : ESDOCircularDependencyTypeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok, 'Succefully create a object who''s type contains circular dependency.');
+  locTypeX := locFac.getType(s_uri,'A') as ISDOObjectType;
+  locTypeX.DropProperty(locTypeX.getProperty('p_circular'));
+end;
+
+procedure TSDOBaseDataFactory_Test.createNew();
+const s_URI_1  = 'uri:1'; s_TYPE_1 = 'type1'; s_TYPE_2 = 'type2';
+var
+  obj : ISDODataFactory;
+  typ : ISDOType;
+  dataObj : ISDODataObject;
+  ok : Boolean;
+begin
+  obj := Create_Factory();
+
+  obj.AddType(s_URI_1,s_TYPE_1,[]);
+  typ := obj.getType(s_URI_1,s_TYPE_1);
+  obj.addProperty(typ,'propboolean',sdo_namespace,'Boolean',[]);
+  obj.addProperty(typ,'propinteger',sdo_namespace,'Integer',[]);
+
+  dataObj := obj.createNew(typ);
+  Check(nil <> dataObj);
+  Check(typ=dataObj.getType(),'getType');
+  Check(nil <> dataObj.getProperty('propboolean'),'getProperty');
+  Check(nil <> dataObj.getProperty('propboolean').getType(),'getProperty().getType');
+  Check(dataObj.getProperty('propboolean').getType()=obj.getType(sdo_namespace,'Boolean'));
+  Check(nil <> dataObj.getProperty('propinteger'),'getProperty');
+  Check(nil <> dataObj.getProperty('propinteger').getType(),'getProperty().getType');
+  Check(dataObj.getProperty('propinteger').getType()=obj.getType(sdo_namespace,'Integer'));
+
+  dataObj := obj.createNew(s_URI_1,s_TYPE_1);
+  Check(nil <> dataObj);
+  Check(typ=dataObj.getType(),'getType');
+  Check(nil <> dataObj.getProperty('propboolean'),'getProperty');
+  Check(nil <> dataObj.getProperty('propboolean').getType(),'getProperty().getType');
+  Check(dataObj.getProperty('propboolean').getType()=obj.getType(sdo_namespace,'Boolean'));
+  Check(nil <> dataObj.getProperty('propinteger'),'getProperty');
+  Check(nil <> dataObj.getProperty('propinteger').getType(),'getProperty().getType');
+  Check(dataObj.getProperty('propinteger').getType()=obj.getType(sdo_namespace,'Integer'));
+
+  obj.AddType(s_URI_1,s_TYPE_2,[tfIsAbstract]);
+  typ := obj.getType(s_URI_1,s_TYPE_2);
+  obj.addProperty(typ,'propboolean',sdo_namespace,'Boolean',[]);
+  obj.addProperty(typ,'propinteger',sdo_namespace,'Integer',[]);
+  ok := False;
+  try
+    dataObj := obj.createNew(s_URI_1,s_TYPE_2);
+  except
+    on e : ESDOAbstractTypeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok, 'Create abtract type instance.');
+end;
+
+function TSDOBaseDataFactory_Test.Create_Factory() : ISDODataFactory;
+begin
+  Result := TSDOBaseDataFactory.Create();
+end;
+
+class function TSDOBaseDataFactory_Test.GetTestSuitePath() : string;
+begin
+  Result := 'Metadata';
+end;
+
+procedure TSDOBaseDataFactory_Test.inherits();
+const
+  s_uri = 'u';
+var
+  locFac : ISDODataFactory;
+  locTypeX : ISDOTypeEx;
+begin
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'a',[]);
+    locFac.AddType(s_uri,'a_b_1',[]);
+      locFac.setBaseType(s_uri,'a_b_1',s_uri,'a');
+    locFac.AddType(s_uri,'a_b_2',[]);
+      locFac.setBaseType(s_uri,'a_b_2',s_uri,'a');
+      locFac.AddType(s_uri,'a_b_2_c',[]);
+        locFac.setBaseType(s_uri,'a_b_2_c',s_uri,'a_b_2');
+
+  locFac.AddType(s_uri,'b',[]);
+    locFac.AddType(s_uri,'b_c',[]);
+      locFac.setBaseType(s_uri,'b_c',s_uri,'b');
+  locFac.AddType(s_uri,'c',[]);
+
+  locTypeX := locFac.getType(s_uri,'a') as ISDOTypeEx;
+  Check(locTypeX.inherits(locTypeX));
+
+  locTypeX := locFac.getType(s_uri,'a_b_1') as ISDOTypeEx;
+  Check(locTypeX.inherits(locTypeX));
+  Check(locTypeX.inherits(locFac.getType(s_uri,'a')));
+
+  locTypeX := locFac.getType(s_uri,'a_b_2') as ISDOTypeEx;
+  Check(locTypeX.inherits(locTypeX));
+  Check(locTypeX.inherits(locFac.getType(s_uri,'a')));
+    locTypeX := locFac.getType(s_uri,'a_b_2_c') as ISDOTypeEx;
+    Check(locTypeX.inherits(locFac.getType(s_uri,'a_b_2')));
+    Check(locTypeX.inherits(locFac.getType(s_uri,'a')));
+
+  locTypeX := locFac.getType(s_uri,'b_c') as ISDOTypeEx;
+  Check(locTypeX.inherits(locTypeX));
+  Check(locTypeX.inherits(locFac.getType(s_uri,'b')));
+
+  locTypeX := locFac.getType(s_uri,'a') as ISDOTypeEx;
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_1')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_2')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_2_c')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'b')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'b_c')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'c')));
+
+  locTypeX := locFac.getType(s_uri,'b') as ISDOTypeEx;
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_1')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_2')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_2_c')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'b_c')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'c')));
+
+  locTypeX := locFac.getType(s_uri,'c') as ISDOTypeEx;
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_1')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_2')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'a_b_2_c')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'b')));
+    Check(not locTypeX.inherits(locFac.getType(s_uri,'b_c')));
+end;
+
+procedure TSDOBaseDataFactory_Test.inherits_root();
+const
+  s_uri = 'u';
+var
+  locFac : ISDODataFactory;
+  locTypeX : ISDOTypeEx;
+begin
+  locFac := Create_Factory();
+  locFac.AddType(s_uri,'a',[]);
+  locTypeX := locFac.getType(s_uri,'a') as ISDOTypeEx;
+
+  Check(
+    locTypeX.inherits(locFac.getType(sdo_namespace,SDOTypeDefaultTypeNames[ObjectType])),
+    Format('Every data object inherits from the base DataObject( uri = "%s", name = "%s" )',[sdo_namespace,SDOTypeDefaultTypeNames[ObjectType]])
+  );
+end;
+
+procedure TSDOBaseDataFactory_Test.setAlias();
+const s_URI_1  = 'uri:1'; s_TYPE_1  = 'type1';
+var
+  df : ISDODataFactory;
+  obj, obj2 : ISDOType;
+  ok : Boolean;
+begin
+  df := Create_Factory();
+  df.AddType(s_URI_1,s_TYPE_1,[]);
+  obj := df.getType(s_URI_1,s_TYPE_1);
+  CheckEquals(0,obj.getAliasCount(),'getAliasCount');
+
+  ok := False;
+  try
+    obj.getAlias(1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(1) : ESDOIndexOutOfRangeException expected.');
+
+  df.setAlias(s_URI_1,s_TYPE_1,'a');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals(1,obj.getAliasCount(),'getAliasCount');
+  ok := False;
+  try
+    obj.getAlias(1);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(1) : ESDOIndexOutOfRangeException expected.');
+
+  obj2 := df.getType(s_URI_1,'a');
+  Check(obj = obj2);
+
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals(1,obj.getAliasCount(),'getAliasCount');
+
+  df.setAlias(obj.getURI(),obj.getName(),'b');
+  CheckEquals(2,obj.getAliasCount(),'getAliasCount');
+  CheckEquals('a',obj.getAlias(0),'getAlias');
+  CheckEquals('b',obj.getAlias(1),'getAlias');
+  ok := False;
+  try
+    obj.getAlias(2);
+  except
+    on e : ESDOIndexOutOfRangeException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'getAlias(2) : ESDOIndexOutOfRangeException expected.');
+end;
+
+procedure TSDOBaseDataFactory_Test.setBaseType();
+const s_URI_1  = 'uri:1'; s_URI_2  = 'uri:2'; s_TYPE_3 = 'type3';
+      s_TYPE_1 = 'type1'; s_TYPE_2 = 'type2';
+var
+  obj : ISDODataFactory;
+  typ, typ2, typ3 : ISDOType;
+  typLst : ISDOTypeList;
+begin
+  obj := Create_Factory();
+  typLst := obj.getTypes();
+
+  obj.AddType(s_URI_1,s_TYPE_1,[tfIsDataType]);
+  typ := obj.getType(s_URI_1,s_TYPE_1);
+  CheckNull(typ.getBaseType(),'getBaseType()');
+
+  Check(nil <> typLst.find(sdo_namespace,'Boolean'),'find(sdo_namespace,''Boolean'')');
+  obj.setBaseType(typ,obj.getType(sdo_namespace,'Boolean'));
+  Check(nil <> typ.getBaseType(),'getBaseType()');
+  Check(obj.getType(sdo_namespace,'Boolean')=typ.getBaseType());
+  CheckEquals(True,obj.getType(sdo_namespace,'Boolean').getTypeEnum() = typ.getBaseType().getTypeEnum(), 'getTypeEnum()');
+
+  obj.setBaseType(typ,nil);
+  CheckNull(typ.getBaseType(),'getBaseType()');
+
+  obj.AddType(s_URI_2,s_TYPE_2,[]);
+  typ2 := typLst.find(s_URI_2,s_TYPE_2);
+  CheckNull(typ2.getBaseType(),'getBaseType()');
+
+  obj.AddType(s_URI_2,s_TYPE_3,[]);
+  typ3 := typLst.find(s_URI_2,s_TYPE_3);
+  CheckNull(typ3.getBaseType(),'getBaseType()');
+
+  obj.setBaseType(typ2,typ3);
+  Check(nil <> typ2.getBaseType(),'getBaseType()');
+  Check(typ3=typ2.getBaseType());
+
+  obj.setBaseType(typ2,nil);
+  CheckNull(typ2.getBaseType(),'getBaseType()');
+
+  obj.setBaseType(s_URI_2,s_TYPE_2,s_URI_2,s_TYPE_3);
+  Check(nil <> typ2.getBaseType(),'getBaseType()');
+  Check(typ3=typ2.getBaseType());
+end;
+
+
+procedure TSDOBaseDataFactory_Test.type_equals();
+const
+  s_uri_1 = 'u1';
+  s_uri_2 = 'u2';
+var
+  locFac, locFac2 : ISDODataFactory;
+begin
+  locFac := Create_Factory();
+  locFac.AddType(s_uri_1,'a',[]);
+  locFac.AddType(s_uri_1,'b',[]);
+    Check(not locFac.getType(s_uri_1,'a').equals(locFac.getType(s_uri_1,'b')));
+
+  locFac := Create_Factory();
+  locFac.AddType(s_uri_1,'a',[]);
+  locFac.AddType(s_uri_2,'a',[]);
+    Check(not locFac.getType(s_uri_1,'a').equals(locFac.getType(s_uri_2,'a')));
+
+  locFac := Create_Factory();
+  locFac2 := Create_Factory();
+  locFac.AddType(s_uri_1,'a',[]);
+    locFac.setAlias(s_uri_1,'a','b');
+  locFac2.AddType(s_uri_1,'b',[]);
+    Check(locFac.getType(s_uri_1,'a').equals(locFac2.getType(s_uri_1,'b')));
+
+  locFac := Create_Factory();
+  locFac2 := Create_Factory();
+  locFac.AddType(s_uri_1,'a',[]);
+  locFac2.AddType(s_uri_1,'b',[]);
+    locFac2.setAlias(s_uri_1,'b','a');
+    Check(locFac.getType(s_uri_1,'a').equals(locFac2.getType(s_uri_1,'b')));
+end;
+
+{ TTSDOChangeSummaryType_Test }
+
+procedure TTSDOChangeSummaryType_Test.Alias_procs();
+var
+  obj : ISDOTypeEx;
+  ok : Boolean;
+  nativeAliasList : TStringList;
+  nativeAliasCount, i, j : Integer;
+  s : string;
+begin
+  nativeAliasList := TStringList.Create();
+  try
+    obj := Create_Type() as ISDOTypeEx;
+
+    nativeAliasCount := GetPredefinedAlias(nativeAliasList);
+    CheckEquals(nativeAliasCount,obj.getAliasCount(),'getAliasCount');
+    if ( nativeAliasCount > 0 ) then begin
+      for i := 0 to Pred(nativeAliasCount) do begin
+        s := nativeAliasList[i];
+        ok := False;
+        for j := 0 to Pred(obj.getAliasCount()) do begin
+          if  ( s = obj.getAlias(j) ) then begin
+            ok := True;
+            Break;
+          end;
+        end;
+        CheckEquals(True,ok,Format('Unable to find predefined alias : "%s"',[s]));
+      end;
+    end;
+
+    ok := False;
+    try
+      obj.getAlias(nativeAliasCount);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('getAlias(%d) : ESDOIndexOutOfRangeException expected.',[nativeAliasCount]));
+
+    obj.SetAlias('aaaaaaaaaaaa');
+    CheckEquals('aaaaaaaaaaaa',obj.getAlias(0),'getAlias'); // because it is sorted !!!!
+    CheckEquals(nativeAliasCount + 1,obj.getAliasCount(),'getAliasCount');
+    ok := False;
+    try
+      obj.getAlias(nativeAliasCount + 1);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('getAlias(%d) : ESDOIndexOutOfRangeException expected.',[nativeAliasCount + 1]));
+
+    obj.SetAlias('aaaaaaaaaaaa');
+    CheckEquals('aaaaaaaaaaaa',obj.getAlias(0),'getAlias');
+    CheckEquals(nativeAliasCount + 1,obj.getAliasCount(),'getAliasCount');
+
+    obj.SetAlias('aaaaaaaaaaaab');
+    CheckEquals(nativeAliasCount + 2,obj.getAliasCount(),'getAliasCount');
+    CheckEquals('aaaaaaaaaaaa',obj.getAlias(0),'getAlias');
+    CheckEquals('aaaaaaaaaaaab',obj.getAlias(1),'getAlias');
+    ok := False;
+    try
+      obj.getAlias(nativeAliasCount + 2);
+    except
+      on e : ESDOIndexOutOfRangeException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,Format('getAlias(%d) : ESDOIndexOutOfRangeException expected.',[nativeAliasCount + 2]));
+  finally
+    FreeAndNil(nativeAliasList);
+  end;
+end;
+
+function TTSDOChangeSummaryType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOChangeSummaryType.Create(get_datafactory()) as ISDOType;
+end;
+
+procedure TTSDOChangeSummaryType_Test.equals();
+begin
+  CheckEquals(True,Create_Type().equals(Create_Type()));
+end;
+
+procedure TTSDOChangeSummaryType_Test.getBaseType();
+var
+  t, bt : ISDOType;
+begin
+  t := Create_Type();
+  bt := t.getBaseType();
+  CheckNull(bt);
+end;
+
+class function TTSDOChangeSummaryType_Test.GetPredefinedAlias(AList: TStrings): Integer;
+begin
+  AList.Clear();
+  Result := AList.Count;
+end;
+
+procedure TTSDOChangeSummaryType_Test.getPropertyIndex();
+var
+  ok : Boolean;
+  t : ISDOType;
+begin
+  ok := False;
+  try
+    t := Create_Type();
+    t.getPropertyIndex('a');
+  except
+    on e : ESDOUnsupportedOperationException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok);
+end;
+
+class function TTSDOChangeSummaryType_Test.GetTestSuitePath() : string;
+begin
+  Result := 'Metadata';
+end;
+
+procedure TTSDOChangeSummaryType_Test.getTypeEnum();
+begin
+  CheckEquals(Ord(ChangeSummaryType),Ord(Create_Type().getTypeEnum()));
+end;
+
+procedure TTSDOChangeSummaryType_Test.getURI();
+begin
+  CheckEquals(sdo_namespace,Create_Type().getURI());
+end;
+
+function TTSDOChangeSummaryType_Test.get_datafactory: ISDODataFactory;
+begin
+  if ( FDataFactory = nil ) then
+    FDataFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Result := FDataFactory;
+end;
+
+procedure TTSDOChangeSummaryType_Test.isAbstractType();
+begin
+  CheckEquals(False,Create_Type().isAbstractType());
+end;
+
+procedure TTSDOChangeSummaryType_Test.isDataObjectType();
+begin
+  CheckEquals(False,Create_Type().isDataObjectType());
+end;
+
+procedure TTSDOChangeSummaryType_Test.isDataType();
+begin
+  CheckEquals(True,Create_Type().isDataType());
+end;
+
+procedure TTSDOChangeSummaryType_Test.isOpenType();
+begin
+  CheckEquals(False,Create_Type().isOpenType());
+end;
+
+procedure TTSDOChangeSummaryType_Test.isSequencedType();
+begin
+  CheckEquals(False,Create_Type().isSequencedType());
+end;
+
+procedure TTSDOChangeSummaryType_Test.SetUp;
+begin
+  inherited;
+  FDataFactory := nil;
+end;
+
+procedure TTSDOChangeSummaryType_Test.TearDown;
+begin
+  FDataFactory := nil;
+  inherited;
+end;
+
+procedure TTSDOChangeSummaryType_Test.test_getName();
+begin
+  CheckEquals(SDOTypeDefaultTypeNames[ChangeSummaryType],Create_Type().getName());
+end;
+
+procedure TTSDOChangeSummaryType_Test.Used();
+var
+  obj : ISDOTypeEx;
+  ok : Boolean;
+begin
+  obj := Create_Type() as ISDOTypeEx;
+  CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+  obj.setUsedFlag(False);
+    CheckEquals(False,obj.isUsed());
+
+  obj.setUsedFlag(True);
+    CheckEquals(True,obj.isUsed());
+    ok := False;
+    try
+      obj.setAlias('azerty_qwerty');
+    except
+      on e : ESDOUnsupportedOperationException do begin
+        ok := True;
+      end;
+    end;
+    Check(ok,'Modify an used type.');
+end;
+
+{$IFDEF HAS_SDO_SHORT}
+{ TSDOShortType_Test }
+
+function TSDOShortType_Test.Create_Type() : ISDOType;
+begin
+  Result := TSDOShortType.Create(get_datafactory()) as ISDOType;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+initialization
+  RegisterTest(TSDOBooleanType_Test.GetTestSuitePath(),TSDOBooleanType_Test.Suite);
+  RegisterTest(TSDOByteType_Test.GetTestSuitePath(),TSDOByteType_Test.Suite);
+{$IFDEF HAS_SDO_BYTES}
+  RegisterTest(TSDOBytesType_Test.GetTestSuitePath(),TSDOBytesType_Test.Suite);
+{$ENDIF HAS_SDO_BYTES}
+  RegisterTest(TTSDOChangeSummaryType_Test.GetTestSuitePath(),TTSDOChangeSummaryType_Test.Suite);
+{$IFDEF HAS_SDO_CHAR}
+  RegisterTest(TSDOCharacterType_Test.GetTestSuitePath(),TSDOCharacterType_Test.Suite);
+{$ENDIF HAS_SDO_CHAR}
+  RegisterTest(TSDODateTimeType_Test.GetTestSuitePath(),TSDODateTimeType_Test.Suite);
+{$IFDEF HAS_SDO_DOUBLE}
+  RegisterTest(TSDODoubleType_Test.GetTestSuitePath(),TSDODoubleType_Test.Suite);
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+  RegisterTest(TSDOFloatType_Test.GetTestSuitePath(),TSDOFloatType_Test.Suite);
+{$ENDIF HAS_SDO_FLOAT}
+  RegisterTest(TSDOIntegerType_Test.GetTestSuitePath(),TSDOIntegerType_Test.Suite);
+{$IFDEF HAS_SDO_LONG}
+  RegisterTest(TSDOLongType_Test.GetTestSuitePath(),TSDOLongType_Test.Suite);
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+  RegisterTest(TSDOShortType_Test.GetTestSuitePath(),TSDOShortType_Test.Suite);
+{$ENDIF HAS_SDO_SHORT}
+  RegisterTest(TSDOStringType_Test.GetTestSuitePath(),TSDOStringType_Test.Suite);
+  RegisterTest(TSDOObjectType_Test.GetTestSuitePath(),TSDOObjectType_Test.Suite);
+  RegisterTest(TSDOUserDefinedSimpleType_Test.GetTestSuitePath(),TSDOUserDefinedSimpleType_Test.Suite);
+  RegisterTest(TSDOBaseDataFactory_Test.GetTestSuitePath(),TSDOBaseDataFactory_Test.Suite);
+
+end.

+ 805 - 0
packages/fcl-sdo/tests/test_suite/test_utils.pas

@@ -0,0 +1,805 @@
+{$INCLUDE sdo_global.inc}
+unit test_utils;
+
+interface
+uses SysUtils
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , sdo_types, sdo_linked_list ;
+
+type
+
+  TDoubleLinkedList_Test = class(TTestCase)
+  published
+    procedure test_Create();
+    procedure All_1();
+    procedure All_2();
+  end;
+
+  TLinkedListIterator_Test = class(TTestCase)
+  published
+    procedure All_1();
+    procedure All_2();
+    procedure Bookmark;
+    procedure MoveTo();
+    procedure GetPosition();
+    procedure Eof();
+  end;
+
+  TUtilsProc_Test = class(TTestCase)
+  published
+    procedure IsStrEmpty_test();
+    procedure GetNextToken_test();
+    procedure ExtractLocalName_test();
+    procedure IsValidName_test();
+    procedure CopySimpleList_integer_test();
+  end;
+
+implementation
+uses
+  Contnrs, sdo_imp_utils, sdo, sdo_dataobjectlist, sdo_datafactory,
+  sdo_copyhelper, Math, test_suite_utils;
+
+
+const
+  SIZE_A : PtrInt = 1;
+  SIZE_B : PtrInt = 123;
+  VAL_A = 12;
+  VAL_B = -34;
+
+{ TDoubleLinkedList_Test }
+
+procedure TDoubleLinkedList_Test.All_1();
+var
+  ll : TDoubleLinkedList;
+  p0, p01 : PLinkedNode;
+  p0_val, p1_val : PPtrInt;
+begin
+  ll := TDoubleLinkedList.Create(SizeOf(PtrInt));
+  try
+    CheckEquals(True,ll.IsEmpty(),'IsEmpty()');
+    CheckEquals(Integer(0),ll.GetLength(),'GetLength()');
+    p0 := ll.InsertFirst();
+    Check(Assigned(p0),'InsertFirst()');
+    Check(p0 = ll.GetFirst(),'GetFirst()');
+    Check(p0 = ll.GetLast(),'GetLast()');
+    Check(nil=p0^.Previous,'p0^.Previous = nil');
+    Check(nil=p0^.Next,'p0^.Next = nil');
+    CheckEquals(1,ll.GetLength(),'GetLength()');
+    CheckEquals(False,ll.IsEmpty(),'IsEmpty()');
+
+    p0_val := PPtrInt(@(p0^.Data[0]));
+    CheckEquals(PtrInt(0),p0_val^);
+
+    p0_val^ := VAL_A;
+    CheckEquals(PtrInt(VAL_A),p0_val^);
+
+    p01 := ll.InsertFirst();
+    Check(Assigned(p01),'InsertFirst()');
+    Check(p01 = ll.GetFirst(),'GetFirst()');
+    Check(p0 = ll.GetLast());
+    Check(p01^.Previous=nil,'p1^.Previous=nil');
+    Check(p01^.Next=p0,'p1^.Next=p0');
+    Check(p01=p0^.Previous,'p1=p0^.Previous');
+    Check(p0^.Next=nil,'p0^.Next = nil');
+    Check(p0 <> p01,'p0 <> p1');
+    CheckEquals(2,ll.GetLength(),'GetLength()');
+    CheckEquals(PtrInt(VAL_A),p0_val^);
+    p1_val := PPtrInt(@(p01^.Data[0]));
+    CheckEquals(PtrInt(0),p1_val^);
+
+
+    ll.Remove(p01);
+    Check(ll.GetFirst() = p0);
+    Check(p0 = ll.GetFirst(),'GetFirst()');
+    Check(p0 = ll.GetLast(),'GetLast()');
+    Check(nil=p0^.Previous,'p0^.Previous = nil');
+    Check(nil=p0^.Next,'p0^.Next = nil');
+    CheckEquals(1,ll.GetLength(),'GetLength()');
+    CheckEquals(False,ll.IsEmpty(),'IsEmpty()');
+    ll.FreeBuffer(p01);
+
+    p01 := ll.InsertBefore(p0);
+    Check(Assigned(p01),'InsertFirst()');
+    Check(p01 = ll.GetFirst(),'GetFirst()');
+    Check(p0 = ll.GetLast());
+    Check(p01^.Previous=nil,'p1^.Previous=nil');
+    Check(p01^.Next=p0,'p1^.Next=p0');
+    Check(p01=p0^.Previous,'p1=p0^.Previous');
+    Check(p0^.Next=nil,'p0^.Next = nil');
+    Check(p0 <> p01,'p0 <> p1');
+    CheckEquals(2,ll.GetLength(),'GetLength()');
+    CheckEquals(PtrInt(VAL_A),p0_val^);
+    p1_val := PPtrInt(@(p01^.Data[0]));
+    CheckEquals(PtrInt(0),p1_val^);
+
+    ll.Delete(p0);
+    ll.Delete(p01);
+    CheckEquals(True,ll.IsEmpty(),'IsEmpty()');
+    CheckEquals(Integer(0),ll.GetLength(),'GetLength()');
+  finally
+    FreeAndNil(ll);
+  end;
+end;
+
+procedure TDoubleLinkedList_Test.All_2();
+var
+  ll : TDoubleLinkedList;
+  p0, p1, p2 : PLinkedNode;
+begin
+  ll := TDoubleLinkedList.Create(SizeOf(PtrInt));
+  try
+    p1 := ll.InsertFirst();
+    p0 := ll.InsertBefore(p1);
+    p2 := ll.InsertAfter(p1);
+
+    CheckEquals(False,ll.IsEmpty());
+    CheckEquals(3,ll.GetLength());
+    Check(p0 = ll.GetFirst());
+    Check(p2 = ll.GetLast());
+
+    Check(p0^.Previous = nil);
+    Check(p0^.Next = p1);
+
+    Check(p1^.Previous = p0);
+    Check(p1^.Next = p2);
+
+    Check(p2^.Previous = p1);
+    Check(p2^.Next = nil);
+
+    ll.Delete(p1);
+      CheckEquals(2,ll.GetLength());
+      Check(p0^.Previous = nil);
+      Check(p0^.Next = p2);
+      Check(p2^.Previous = p0);
+      Check(p2^.Next = nil);
+
+      ll.Delete(p2);
+        CheckEquals(1,ll.GetLength());
+        Check(p0^.Previous = nil);
+        Check(p0^.Next = nil);
+
+        ll.Delete(p0);
+        CheckEquals(True,ll.IsEmpty());
+        CheckEquals(0,ll.GetLength());
+  finally
+    FreeAndNil(ll);
+  end;
+end;
+
+procedure TDoubleLinkedList_Test.test_Create();
+var
+  ok : Boolean;
+  ll : TDoubleLinkedList;
+begin
+  ok := False;
+  try
+    TDoubleLinkedList.Create(-1);
+  except
+    on e : EListException do begin
+      ok := True;
+    end;
+  end;
+  Check(ok,'Create(-1);');
+
+  ll := TDoubleLinkedList.Create(SIZE_A);
+  try
+    CheckEquals(SIZE_A,ll.DataSize);
+  finally
+    FreeAndNil(ll);
+  end;
+  ll := TDoubleLinkedList.Create(SIZE_B);
+  try
+    CheckEquals(SIZE_B,ll.DataSize);
+  finally
+    FreeAndNil(ll);
+  end;
+end;
+
+{ TLinkedListIterator_Test }
+
+procedure TLinkedListIterator_Test.All_2();
+var
+  ll : TDoubleLinkedList;
+  c : ILinkedListCursor;
+  p0, p1, p2 : PLinkedNode;
+begin
+  ll := TDoubleLinkedList.Create(SIZE_A);
+  try
+    c := CreateIterator(ll);
+    CheckEquals(False,c.IsPosValid());
+    c.Reset();
+    CheckEquals(False,c.IsPosValid());
+    CheckEquals(False,c.MoveNext());
+    CheckEquals(False,c.IsPosValid());
+    CheckEquals(False,c.MovePrevious());
+    CheckEquals(False,c.IsPosValid());
+    CheckEquals(False,c.MoveFirst());
+    CheckEquals(False,c.IsPosValid());
+    CheckEquals(False,c.MoveLast());
+    CheckEquals(False,c.IsPosValid());
+    Check(nil = c.GetCurrent());
+
+    ll.Clear();
+    p0 := ll.InsertFirst();
+      CheckEquals(False,c.IsPosValid());
+      c.Reset();
+      CheckEquals(True,c.MoveNext());
+        CheckEquals(True,c.IsPosValid());
+      CheckEquals(False,c.MoveNext());
+        CheckEquals(True,c.IsPosValid());
+      CheckEquals(False,c.MoveNext());
+        CheckEquals(True,c.IsPosValid());
+      CheckEquals(False,c.MovePrevious());
+        CheckEquals(True,c.IsPosValid());
+      CheckEquals(False,c.MovePrevious());
+        CheckEquals(True,c.IsPosValid());
+      Check(p0 = c.GetCurrent());
+
+      CheckEquals(True,c.MoveFirst());
+      Check(p0 = c.GetCurrent());
+        CheckEquals(True,c.IsPosValid());
+      CheckEquals(True,c.MoveLast());
+      Check(p0 = c.GetCurrent());
+        CheckEquals(True,c.IsPosValid());
+
+    ll.Clear();
+    p0 := ll.InsertFirst();
+    p1 := ll.InsertAfter(p0);
+      c.Reset();
+      CheckEquals(False,c.IsPosValid());
+      CheckEquals(True,c.MoveNext());
+        Check(p0 = c.GetCurrent());
+        CheckEquals(True,c.IsPosValid());
+      CheckEquals(True,c.MoveNext());
+        Check(p1 = c.GetCurrent());
+        CheckEquals(True,c.IsPosValid());
+      CheckEquals(False,c.MoveNext());
+        Check(p1 = c.GetCurrent());
+      CheckEquals(True,c.MovePrevious());
+        Check(p0 = c.GetCurrent());
+      CheckEquals(False,c.MovePrevious());
+        Check(p0 = c.GetCurrent());
+      Check(p0 = c.GetCurrent());
+
+      CheckEquals(True,c.MoveFirst());
+      Check(p0 = c.GetCurrent());
+      CheckEquals(True,c.MoveLast());
+      Check(p1 = c.GetCurrent());
+
+    ll.Clear();
+    CheckEquals(False,c.IsPosValid());
+    p0 := ll.InsertFirst();
+    p1 := ll.InsertAfter(p0);
+    p2 := ll.InsertAfter(p1);
+      c.Reset();
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.MovePrevious());
+      Check(p0 = c.GetCurrent());
+
+      CheckEquals(True,c.MoveNext());
+      Check(p1 = c.GetCurrent());
+      CheckEquals(True,c.MovePrevious());
+      Check(p0 = c.GetCurrent());
+      CheckEquals(True,c.MoveNext());
+      Check(p1 = c.GetCurrent());
+      CheckEquals(True,c.MoveNext());
+      Check(p2 = c.GetCurrent());
+      CheckEquals(False,c.MoveNext());
+      Check(p2 = c.GetCurrent());
+
+      CheckEquals(True,c.MovePrevious()); // p2 > p1
+      CheckEquals(True,c.MovePrevious()); // p1 > p0
+      CheckEquals(False,c.MovePrevious()); // p0 = p0
+
+      CheckEquals(True,c.MoveFirst());
+      Check(p0 = c.GetCurrent());
+      CheckEquals(True,c.MoveLast());
+      Check(p2 = c.GetCurrent());
+
+    ll.Clear();
+    c.Reset();
+    CheckEquals(False,c.MoveNext());
+    CheckEquals(False,c.MovePrevious());
+    Check(nil = c.GetCurrent());
+  finally
+    ll.Free();
+  end;
+end;
+
+procedure TLinkedListIterator_Test.All_1();
+var
+  lls : TObjectList;
+  ll : TDoubleLinkedList;
+  c : ILinkedListCursor;
+  p0, p1, p2 : PLinkedNode;
+begin
+  lls := TObjectList.Create(True);
+  try
+    ll := TDoubleLinkedList.Create(SIZE_A);
+    lls.Add(ll);
+    c := CreateIterator(ll);
+    CheckEquals(True,c.Bof());
+    CheckEquals(True,c.Eof());
+    CheckEquals(False,c.MoveFirst());
+    CheckEquals(False,c.MoveLast());
+    c.Reset();
+    CheckEquals(True,c.Bof());
+    CheckEquals(True,c.Eof());
+    CheckEquals(False,c.MoveFirst());
+    CheckEquals(False,c.MoveLast());
+
+    ll := TDoubleLinkedList.Create(SIZE_A);
+    lls.Add(ll);
+    c := CreateIterator(ll);
+    p0 := ll.InsertFirst();
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+      c.Reset();
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(True,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(False,c.MoveNext());
+      CheckEquals(False,c.Bof());
+      CheckEquals(True,c.Eof());
+
+    ll := TDoubleLinkedList.Create(SIZE_A);
+    lls.Add(ll);
+    c := CreateIterator(ll);
+    p0 := ll.InsertFirst();
+    p1 := ll.InsertAfter(p0);
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+      c.Reset();
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(True,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveFirst());
+      Check(c.GetCurrent() = ll.GetFirst());
+      CheckEquals(True,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveLast());
+      Check(c.GetCurrent() = ll.GetLast());
+      CheckEquals(False,c.Bof());
+      CheckEquals(True,c.Eof());
+
+    ll := TDoubleLinkedList.Create(SIZE_A);
+    lls.Add(ll);
+    c := CreateIterator(ll);
+    CheckEquals(False,c.IsPosValid());
+    p0 := ll.InsertFirst();
+    p1 := ll.InsertAfter(p0);
+    p2 := ll.InsertAfter(p1);
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+      c.Reset();
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(True,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveFirst());
+      Check(c.GetCurrent() = ll.GetFirst());
+      CheckEquals(True,c.Bof());
+      CheckEquals(False,c.Eof());
+
+      CheckEquals(True,c.MoveLast());
+      Check(c.GetCurrent() = ll.GetLast());
+      CheckEquals(False,c.Bof());
+      CheckEquals(True,c.Eof());
+  finally
+    lls.Free();
+  end;
+end;
+
+procedure TLinkedListIterator_Test.Bookmark();
+var
+  ll : TDoubleLinkedList;
+  c : ILinkedListCursor;
+  bmk : TLinkedListBookmark;
+  oldPos : PtrInt;
+  p : PLinkedNode;
+begin
+  ll := TDoubleLinkedList.Create(SizeOf(Integer));
+  try
+    c := CreateIterator(ll);
+    p := c.GetCurrent();
+    bmk := c.GetBookmark(); oldPos := c.GetPosition();
+    CheckEquals(True,c.GotoBookmark(bmk));
+    CheckEquals(True,c.GotoBookmark(bmk));
+    CheckEquals(PtrInt(p),PtrInt(c.GetCurrent()));
+    CheckEquals(oldPos,c.GetPosition());
+
+    ll.Append();
+    ll.Append();
+    ll.Append();
+    ll.Append();
+    ll.Append();
+
+    c.MoveFirst();
+    p := c.GetCurrent();
+    bmk := c.GetBookmark(); oldPos := c.GetPosition();
+    c.MoveNext();
+    c.MoveNext();
+    CheckEquals(True,c.GotoBookmark(bmk));
+    CheckEquals(PtrInt(p),PtrInt(c.GetCurrent()));
+    CheckEquals(oldPos,c.GetPosition());
+
+    c.MoveFirst();
+    c.MoveNext();
+    c.MoveNext();
+    p := c.GetCurrent();
+    bmk := c.GetBookmark(); oldPos := c.GetPosition();
+    c.MoveLast();
+    CheckEquals(True,c.GotoBookmark(bmk));
+    CheckEquals(PtrInt(p),PtrInt(c.GetCurrent()));
+    CheckEquals(oldPos,c.GetPosition());
+
+    c.MoveLast();
+    p := c.GetCurrent();
+    bmk := c.GetBookmark(); oldPos := c.GetPosition();
+    c.MoveFirst();
+    CheckEquals(True,c.GotoBookmark(bmk));
+    CheckEquals(PtrInt(p),PtrInt(c.GetCurrent()));
+    CheckEquals(oldPos,c.GetPosition());
+  finally
+    ll.Free();
+  end;
+end;
+
+procedure TLinkedListIterator_Test.MoveTo();
+var
+  ll : TDoubleLinkedList;
+  c : ILinkedListCursor;
+  i : PtrInt;
+begin
+  ll := TDoubleLinkedList.Create(SizeOf(PtrInt));
+  try
+    c := CreateIterator(ll);
+    CheckEquals(False, c.MoveTo(0));
+    CheckEquals(False, c.MoveTo(-1));
+    CheckEquals(False, c.MoveTo(1));
+
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 0;
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 1;
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 2;
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 3;
+
+    c.MoveFirst();
+      CheckEquals(0,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+    for i := 0 to 3 do begin
+      CheckEquals(True, c.MoveTo(i));
+      CheckEquals(i,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+
+      CheckEquals(True, c.MoveFirst());
+        CheckEquals(True, c.MoveTo(i));
+        CheckEquals(i,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+      CheckEquals(True, c.MoveLast());
+        CheckEquals(True, c.MoveTo(i));
+        CheckEquals(i,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+    end;
+
+    CheckEquals(True, c.MoveTo(1));
+      CheckEquals(1,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+    c.MoveFirst();
+    CheckEquals(True, c.MoveTo(3));
+      CheckEquals(3,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+
+    CheckEquals(True, c.MoveLast());
+    CheckEquals(True, c.MoveTo(2));
+      CheckEquals(2,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+
+    CheckEquals(True, c.MoveTo(1));
+    CheckEquals(True, c.MoveTo(2));
+      CheckEquals(2,PPtrInt(@((c.GetCurrent()^.Data[0])))^);
+
+  finally
+    ll.Free();
+  end;
+end;
+
+procedure TLinkedListIterator_Test.GetPosition();
+var
+  ll : TDoubleLinkedList;
+  c : ILinkedListCursor;
+  i : PtrInt;
+begin
+  ll := TDoubleLinkedList.Create(SizeOf(PtrInt));
+  try
+    c := CreateIterator(ll);
+    CheckEquals(-1,c.GetPosition());
+    CheckEquals(False, c.MoveTo(0));
+      CheckEquals(-1,c.GetPosition());
+    CheckEquals(False, c.MoveTo(-1));
+      CheckEquals(-1,c.GetPosition());
+    CheckEquals(False, c.MoveTo(1));
+      CheckEquals(-1,c.GetPosition());
+
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 0;
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 1;
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 2;
+    PPtrInt(@((ll.Append()^.Data[0])))^ := 3;
+
+    c.Reset();
+      CheckEquals(-1,c.GetPosition());
+    c.MoveFirst();
+      CheckEquals(0,c.GetPosition());
+    for i := 0 to 3 do begin
+      CheckEquals(True, c.MoveTo(i));
+      CheckEquals(i,c.GetPosition());
+    end;
+
+    CheckEquals(True, c.MoveLast());
+      CheckEquals(Pred(ll.GetLength()),c.GetPosition());
+    c.MoveFirst();
+      CheckEquals(0,c.GetPosition());
+
+  finally
+    ll.Free();
+  end;
+end;
+
+procedure TLinkedListIterator_Test.Eof();
+var
+  lls : TObjectList;
+  ll : TDoubleLinkedList;
+  c : ILinkedListCursor;
+  p0, p1, p2 : PLinkedNode;
+begin
+  lls := TObjectList.Create(True);
+  try
+    ll := TDoubleLinkedList.Create(SIZE_A);
+    lls.Add(ll);
+    c := CreateIterator(ll);
+    CheckEquals(True,c.Eof());
+
+    p0 := ll.InsertFirst();
+      c.Reset();
+      CheckEquals(False,c.Eof());
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.Eof());
+      CheckEquals(False,c.MoveNext());
+      CheckEquals(True,c.Eof());
+
+      c.Reset();
+      CheckEquals(False,c.Eof());
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.Eof());
+      CheckEquals(False,c.MoveNext());
+      CheckEquals(True,c.Eof());
+
+      c.Reset();
+      CheckEquals(False,c.Eof());
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(True,c.Eof());
+
+    ll := TDoubleLinkedList.Create(SIZE_A);
+    lls.Add(ll);
+    c := CreateIterator(ll);
+    p0 := ll.InsertFirst();
+    p1 := ll.InsertAfter(p0);
+      c.Reset();
+      CheckEquals(False,c.Eof());
+      c.Reset();
+      CheckEquals(False,c.Eof());
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.Eof());
+      CheckEquals(True,c.MoveNext());
+      CheckEquals(False,c.Eof());
+      CheckEquals(False,c.MoveNext());
+      CheckEquals(True,c.Eof());
+
+      c.Reset();
+      CheckEquals(False,c.Eof());
+      CheckEquals(True,c.MoveLast());
+      CheckEquals(True,c.Eof());
+  finally
+    lls.Free();
+  end;
+end;
+
+{ TUtilsProc_Test }
+
+procedure TUtilsProc_Test.CopySimpleList_integer_test();
+
+  procedure check_list(const x, y : ISDODataObjectList);
+  var
+    cx, cy : ILinkedListCursor;
+  begin
+    CheckEquals(x.size(), y.size(), 'size');
+    if ( x.size() > 0 ) then begin
+      cx := x.getCursor();
+      cx.Reset();
+      cy := y.getCursor();
+      cy.Reset();
+      while cx.MoveNext() do begin
+        Check(cy.MoveNext(), 'MoveNext()');
+        CheckEquals(x.getInteger(), y.getInteger(), Format('Item #%d',[cx.GetPosition()]));
+      end;
+    end;
+  end;
+
+var
+  f : ISDODataFactory;
+  a, b : ISDODataObjectList;
+  t : ISDOType;
+  i, c : PtrInt;
+begin
+  Randomize();
+  f := TSDODataFactory.Create();
+  t := f.getType(sdo_namespace,SDOTypeDefaultTypeNames[IntegerType]);
+  a := TSDODataObjectList.Create(t);
+  b := TSDODataObjectList.Create(t);
+
+  CopySimpleList(a, b, t.getTypeEnum());
+    check_list(a, b);
+
+  c := RandomRange(1,100);
+  for i := 0 to Pred(c) do
+    a.append(RandomRange(-1234, 56789));
+  CopySimpleList(a, b, t.getTypeEnum());
+    check_list(a, b);
+end;
+
+procedure TUtilsProc_Test.ExtractLocalName_test();
+begin
+  CheckEquals('',ExtractLocalName(''));
+  CheckEquals('a',ExtractLocalName('a'));
+  CheckEquals('azerty',ExtractLocalName('azerty'));
+  CheckEquals('azerty',ExtractLocalName('ns:azerty'));
+  CheckEquals('azerty',ExtractLocalName('n:azerty'));
+  CheckEquals('azerty',ExtractLocalName(':azerty'));
+  CheckEquals('',ExtractLocalName('azerty:'));
+end;
+
+procedure TUtilsProc_Test.GetNextToken_test();
+var
+  buffer, x : string;
+  sep : Char;
+begin
+  sep := ';';
+  buffer := '';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := ';';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := ';;;';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := 'abc';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('abc', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := 'ab;cd';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('ab', x);
+    CheckEquals('cd', buffer);
+    x := GetNextToken(buffer,sep);
+    CheckEquals('cd', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := ';ab;cd';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('ab', x);
+    CheckEquals('cd', buffer);
+    x := GetNextToken(buffer,sep);
+    CheckEquals('cd', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := ';ab;;cd';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('ab', x);
+    CheckEquals(';cd', buffer);
+    x := GetNextToken(buffer,sep);
+    CheckEquals('cd', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := 'ab;cd;';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('ab', x);
+    CheckEquals('cd;', buffer);
+    x := GetNextToken(buffer,sep);
+    CheckEquals('cd', x);
+    CheckEquals('', buffer);
+
+  sep := ';';
+  buffer := 'ab;cd;de';
+    x := GetNextToken(buffer,sep);
+    CheckEquals('ab', x);
+    CheckEquals('cd;de', buffer);
+    x := GetNextToken(buffer,sep);
+    CheckEquals('cd', x);
+    CheckEquals('de', buffer);
+    x := GetNextToken(buffer,sep);
+    CheckEquals('de', x);
+    CheckEquals('', buffer);
+
+end;
+
+procedure TUtilsProc_Test.IsStrEmpty_test;
+begin
+  CheckEquals(True,IsStrEmpty(''));
+  CheckEquals(True,IsStrEmpty('  '));
+
+  CheckEquals(False,IsStrEmpty('a'));
+  CheckEquals(False,IsStrEmpty('  a'));
+  CheckEquals(False,IsStrEmpty('afghjk'));
+  CheckEquals(False,IsStrEmpty(' jhhfjjsd '));
+  CheckEquals(False,IsStrEmpty(':6789^;:,?'));
+end;
+
+procedure TUtilsProc_Test.IsValidName_test();
+begin
+  CheckEquals(True, IsValidName('_'));
+  CheckEquals(True, IsValidName('_a'));
+  CheckEquals(True, IsValidName('_1'));
+  CheckEquals(True, IsValidName('_azerty'));
+  CheckEquals(True, IsValidName('a'));
+  CheckEquals(True, IsValidName('azerty'));
+  CheckEquals(True, IsValidName('_a_z'));
+  CheckEquals(True, IsValidName('a1210'));
+
+  CheckEquals(False, IsValidName(''));
+  CheckEquals(False, IsValidName('-'));
+  CheckEquals(False, IsValidName('-a'));
+  CheckEquals(False, IsValidName('4'));
+  CheckEquals(False, IsValidName('1s'));
+  CheckEquals(False, IsValidName('-4'));
+  CheckEquals(False, IsValidName('aad-ddd'));
+  CheckEquals(False, IsValidName('zz_-'));
+  CheckEquals(False, IsValidName('['));
+  CheckEquals(False, IsValidName(']'));
+  CheckEquals(False, IsValidName('az[]'));
+  CheckEquals(False, IsValidName('l[1]'));
+  CheckEquals(False, IsValidName('dd['));
+  CheckEquals(False, IsValidName('dd]'));
+end;
+
+initialization
+  RegisterTest('utils',TDoubleLinkedList_Test.Suite);
+  RegisterTest('utils',TLinkedListIterator_Test.Suite);
+  RegisterTest('utils',TUtilsProc_Test.Suite);
+
+end.

+ 2163 - 0
packages/fcl-sdo/tests/test_suite/test_xpathhelper.pas

@@ -0,0 +1,2163 @@
+{$INCLUDE sdo_global.inc}
+unit test_xpathhelper;
+
+interface
+uses SysUtils
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , test_suite_utils, sdo, sdo_types, sdo_xpath_helper;
+
+type
+
+  TXPathScanner_Test = class(TWstBaseTest)
+  published
+    procedure simple();
+    procedure simple_number();
+    procedure composed_1();
+  end;
+
+  TXPathParser_Test = class(TWstBaseTest)
+  published
+    procedure parse_1();
+    procedure parse_2();
+    procedure parse_3();
+    procedure parse_4();
+    procedure parse_5();
+    procedure parse_6();
+    procedure parse_7();
+    procedure parse_8();
+    procedure parse_9();
+    procedure parse_10();
+  end;
+
+  TXPathProcessor_Test = class(TWstBaseTest)
+  published
+    procedure Execute_simple_object();
+    procedure Execute_simple_value_type();
+
+    procedure Execute_nested_object();
+
+    procedure Execute_equal();
+    procedure Execute_equal_bool();
+    procedure Execute_equal_byte();
+    procedure Execute_equal_date();
+    procedure Execute_equal_integer();
+    procedure Execute_equal_string();
+{$IFDEF HAS_SDO_BYTES}
+    procedure Execute_equal_bytes();
+{$ENDIF HAS_SDO_BYTES}
+{$IFDEF HAS_SDO_CHAR}
+    procedure Execute_equal_char();
+{$ENDIF HAS_SDO_CHAR}
+{$IFDEF HAS_SDO_CURRENCY}
+    procedure Execute_equal_currency();
+{$ENDIF HAS_SDO_CURRENCY}
+{$IFDEF HAS_SDO_DOUBLE}
+    procedure Execute_equal_double();
+{$ENDIF HAS_SDO_DOUBLE}
+{$IFDEF HAS_SDO_FLOAT}
+    procedure Execute_equal_float();
+{$ENDIF HAS_SDO_FLOAT}
+{$IFDEF HAS_SDO_LONG}
+    procedure Execute_equal_long();
+{$ENDIF HAS_SDO_LONG}
+{$IFDEF HAS_SDO_SHORT}
+    procedure Execute_equal_short();
+{$ENDIF HAS_SDO_SHORT}
+  end;
+
+  TXPathUtilsFunc_Test = class(TWstBaseTest)
+  published
+    procedure getXpath_func();
+  end;
+
+implementation
+
+uses
+  sdo_datafactory, sdo_date_utils, sdo_convert_helper;
+
+const
+  s_uri              = 'urn-test';
+  s_type_object_A    = 'objectA';
+  s_type_object_B    = 'objectB';
+  s_type_object_C    = 'objectC';
+  s_type_object_D    = 'objectD';
+  s_bool_prop        = 'bool_prop';            s_bool_propList      = 'bool_prop_list';
+  s_integer_prop     = 'integer_prop';         s_integer_propList   = 'integer_prop_list';
+  s_string_prop      = 'string_prop';          s_string_propList    = 'string_prop_list';
+  s_object_prop      = 'object_prop';          s_object_propList    = 'object_prop_list';
+  s_object_ref_prop  = 'object_ref_prop';
+
+{ TXPathProcessor_Test }
+
+procedure TXPathProcessor_Test.Execute_equal();
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locRes.AddType(s_uri,s_type_object_C,[]);
+    locRes.AddType(s_uri,s_type_object_D,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locRes.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locRes.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locRes.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locRes.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locRes.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab',s_uri,s_type_object_B,[pfIsContainment]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+      locRes.addProperty(locObj,'p_ac',s_uri,s_type_object_C,[pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locRes.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locRes.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locRes.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locRes.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locRes.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locRes.addProperty(locObj,'p_bc',s_uri,s_type_object_C,[pfIsContainment]);
+      locRes.addProperty(locObj,'p_bc_list',s_uri,s_type_object_C,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_C);
+      locRes.addProperty(locObj,'p_cd',s_uri,s_type_object_D,[pfIsContainment]);
+
+    Result := locRes;
+  end;
+
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Integer; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Integer;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setBoolean(s_bool_prop, ( k mod 3 ) = 0 );
+      tmp.setString(s_string_prop, Format('string %d',[k]));
+      tmp.setInteger(s_integer_prop, k);
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : TSDOInteger;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[s_integer_prop,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[s_integer_prop,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[s_integer_prop,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := -123;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[s_integer_prop,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+procedure TXPathProcessor_Test.Execute_equal_bool();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE   = BooleanType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+  begin
+    tmp := AFac.createNew(s_uri, s_type_object_B);
+    tmp.setBoolean(SIMPLE_PROP_B,True);
+    AList.append(tmp);
+    tmp := AFac.createNew(s_uri, s_type_object_B);
+    tmp.setBoolean(SIMPLE_PROP_B,False);
+    AList.append(tmp);
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : Integer;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 1;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=false]',[SIMPLE_PROP_B])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=true]',[SIMPLE_PROP_B])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+procedure TXPathProcessor_Test.Execute_equal_byte();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE   = ByteType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setByte(SIMPLE_PROP_B,k);
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : Byte;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+procedure TXPathProcessor_Test.Execute_equal_date();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE     = DateTimeType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeDate(const AIntValue : TSDOInteger) : TSDODateTime;
+  begin
+    Result.Date := 39000.0 + ( AIntValue * 100 ) + ( AIntValue * 10 ) + AIntValue;
+    Result.HourOffset := ( AIntValue mod 12 );
+    Result.MinuteOffset := ( AIntValue mod 60 );
+    Result := xsd_StrToDate(xsd_DateTimeToStr(Result,xdkDateTime),xdkDateTime);
+  end;
+
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : TSDOInteger;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setDate(SIMPLE_PROP_B,ComputeDate(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : TSDOInteger;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,xsd_DateTimeToStr(ComputeDate(i),xdkDateTime)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,xsd_DateTimeToStr(ComputeDate(i),xdkDateTime)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 56;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,xsd_DateTimeToStr(ComputeDate(i),xdkDateTime)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := -200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,xsd_DateTimeToStr(ComputeDate(i),xdkDateTime)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+procedure TXPathProcessor_Test.Execute_equal_integer();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE     = IntegerType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : TSDOInteger;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setInteger(SIMPLE_PROP_B,k);
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : TSDOInteger;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := -200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,i])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+procedure TXPathProcessor_Test.Execute_equal_string();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE     = StringType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : TSDOInteger;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setString(SIMPLE_PROP_B,Format('a sample string #%d',[k]));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : TSDOInteger;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,Format('a sample string #%d',[i])])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,Format('a sample string #%d',[i])])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,Format('a sample string #%d',[i])])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := -200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,Format('a sample string #%d',[i])])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+{$IFDEF HAS_SDO_BYTES}
+procedure TXPathProcessor_Test.Execute_equal_bytes();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE     = BytesType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeValue(const AInput : Byte) : TSDOBytes;
+  var
+    k : Integer;
+  begin
+    SetLength(Result,AInput);
+    if ( AInput > 0 ) then begin
+      for k := 1 to AInput do
+        Result[k-1] := k;
+    end;
+  end;
+  
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setBytes(SIMPLE_PROP_B,ComputeValue(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : Byte;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,200,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,BytesToString(ComputeValue(i))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,BytesToString(ComputeValue(i))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+        
+    i := 150;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,BytesToString(ComputeValue(i))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+        
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,BytesToString(ComputeValue(i))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+
+    locX.Context.SetObject(locRootObject,nil);
+    locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,'!'])));
+    locX.Execute(locExp);
+      CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+{$ENDIF HAS_SDO_BYTES}
+
+{$IFDEF HAS_SDO_CHAR}
+procedure TXPathProcessor_Test.Execute_equal_char();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE     = CharacterType;
+var
+  CHAR_LIST : array[0..( (26{a-z} + (26{A-Z}) + (10{0-9})) - 1 )] of TSDOChar;
+
+  procedure PrepareCharList();
+  var
+    k : Integer;
+  begin
+    for k := Ord('a') to Ord('z') do
+      CHAR_LIST[k - Ord('a')] := TSDOChar(k);
+    for k := Ord('A') to Ord('Z') do
+      CHAR_LIST[26 + k - Ord('A')] := TSDOChar(k);
+    for k := Ord('0') to Ord('9') do
+      CHAR_LIST[26 + 26 + k - Ord('0')] := TSDOChar(k);
+  end;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeValue(const AInput : Byte) : TSDOChar;
+  begin
+    Result := CHAR_LIST[AInput];
+  end;
+  
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setCharacter(SIMPLE_PROP_B,ComputeValue(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : Byte;
+begin
+  PrepareCharList();
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,High(CHAR_LIST),locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+
+    locX.Context.SetObject(locRootObject,nil);
+    locExp.SetRoot(ParseXPath(Format('p_ab_list[%s="%s"]',[SIMPLE_PROP_B,'!'])));
+    locX.Execute(locExp);
+      CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+{$ENDIF HAS_SDO_CHAR}
+
+{$IFDEF HAS_SDO_CURRENCY}
+procedure TXPathProcessor_Test.Execute_equal_currency();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE   = CurrencyType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeValue(const AInput : Integer) : TSDOCurrency;
+  begin
+    Result := AInput * 10000000;
+    if ( ( AInput mod 2) = 0 ) then
+      Result := -Result;
+  end;
+  
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setCurrency(SIMPLE_PROP_B,ComputeValue(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  v : TSDOCurrency;
+  j : Integer;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    j := 12; v := j;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.CurrencyToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 10; v := j;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.CurrencyToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 0; v := j;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.CurrencyToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 200; 
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.CurrencyToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+{$ENDIF HAS_SDO_CURRENCY}
+
+{$IFDEF HAS_SDO_DOUBLE}
+procedure TXPathProcessor_Test.Execute_equal_double();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE   = DoubleType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeValue(const AInput : Integer) : TSDODouble;
+  begin
+    Result := AInput * 10000000;
+    if ( ( AInput mod 2) = 0 ) then
+      Result := -Result;
+  end;
+  
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setDouble(SIMPLE_PROP_B,ComputeValue(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  v : TSDODouble;
+  j : Integer;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    j := 12; v := j;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 10; v := j;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 0; v := j;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+{$ENDIF HAS_SDO_DOUBLE}
+
+{$IFDEF HAS_SDO_FLOAT}
+procedure TXPathProcessor_Test.Execute_equal_float();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE   = FloatType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeValue(const AInput : Integer) : TSDOFloat;
+  begin
+    Result := AInput * 10000000;
+    if ( ( AInput mod 2) = 0 ) then
+      Result := -Result;
+  end;
+  
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setFloat(SIMPLE_PROP_B,ComputeValue(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  v : TSDOFloat;
+  j : Integer;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    j := 12; v := j;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 10; v := j;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 0; v := j;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(j)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(v, tmpListAB.getCursor().GetPosition());
+    j := 200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%s]',[SIMPLE_PROP_B,TSDOConvertHelper.FloatToString(ComputeValue(j))])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+{$ENDIF HAS_SDO_FLOAT}
+
+{$IFDEF HAS_SDO_LONG}
+procedure TXPathProcessor_Test.Execute_equal_long();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE   = LongType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeValue(const AInput : TSDOLong) : TSDOLong;
+  begin
+    Result := AInput * 10000000;
+    if ( ( AInput mod 2) = 0 ) then
+      Result := -Result;
+  end;
+  
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setLong(SIMPLE_PROP_B,ComputeValue(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : TSDOLong;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+{$ENDIF HAS_SDO_LONG}
+
+{$IFDEF HAS_SDO_SHORT}
+procedure TXPathProcessor_Test.Execute_equal_short();
+const
+  SIMPLE_PROP_A = 'simpleProperty_A';
+  LIST_PROP_A   = 'listProperty_A';
+  SIMPLE_PROP_B = 'simpleProperty_B';
+  PROP_TYPE   = ShortType;
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,SIMPLE_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+      locRes.addProperty(locObj,LIST_PROP_A,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,SIMPLE_PROP_B,sdo_namespace,SDOTypeDefaultTypeNames[PROP_TYPE], []);
+
+    Result := locRes;
+  end;
+
+  function ComputeValue(const AInput : TSDOShort) : TSDOShort;
+  begin
+    Result := AInput * 100 + AInput;
+    if ( ( AInput mod 2) = 0 ) then
+      Result := -Result;
+  end;
+  
+  procedure fill_p_ab_list(const AList : ISDODataObjectList; const ACount : Byte; const AFac : ISDODataFactory);
+  var
+    tmp : ISDODataObject;
+    k : Byte;
+  begin
+    for k := 0 to Pred(ACount) do begin
+      tmp := AFac.createNew(s_uri, s_type_object_B);
+      tmp.setShort(SIMPLE_PROP_B,ComputeValue(k));
+      AList.append(tmp);
+    end;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  tmpListAB : ISDODataObjectList;
+  i : TSDOShort;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpListAB := locRootObject.getList('p_ab_list');
+  fill_p_ab_list(tmpListAB,100,locFac);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    i := 12;
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 10;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 0;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpListAB.getDataObject(i)), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty('p_ab_list')), PtrUInt(locX.Context.CurrentProperty));
+        CheckEquals(i, tmpListAB.getCursor().GetPosition());
+    i := 200;
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(Format('p_ab_list[%s=%d]',[SIMPLE_PROP_B,ComputeValue(i)])));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+{$ENDIF HAS_SDO_SHORT}
+
+procedure TXPathProcessor_Test.Execute_nested_object;
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locRes.AddType(s_uri,s_type_object_C,[]);
+    locRes.AddType(s_uri,s_type_object_D,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locRes.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locRes.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locRes.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locRes.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locRes.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locRes.addProperty(locObj,'p_ab',s_uri,s_type_object_B,[pfIsContainment]);
+      locRes.addProperty(locObj,'p_ab_list',s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+      locRes.addProperty(locObj,'p_ac',s_uri,s_type_object_C,[pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_B);
+      locRes.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locRes.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locRes.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locRes.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locRes.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locRes.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locRes.addProperty(locObj,'p_bc',s_uri,s_type_object_C,[pfIsContainment]);
+      locRes.addProperty(locObj,'p_bc_list',s_uri,s_type_object_C,[pfIsMany,pfIsContainment]);
+
+    locObj := locRes.getType(s_uri,s_type_object_C);
+      locRes.addProperty(locObj,'p_cd',s_uri,s_type_object_D,[pfIsContainment]);
+
+    Result := locRes;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject, tmpAB, tmpAC, tmpAB_BC, tmpAB_BC_CD : ISDODataObject;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpAC := locRootObject.createDataObject('p_ac');
+    tmpAB := locRootObject.createDataObject('p_ab');
+      tmpAB_BC := tmpAB.createDataObject('p_bc');
+        tmpAB_BC_CD := tmpAB_BC.createDataObject('p_cd');
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    locExp.SetRoot(ParseXPath('p_ab/p_bc/p_cd'));
+    locX.Execute(locExp);
+      CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+      CheckEquals(PtrUInt(tmpAB_BC_CD), PtrUInt(locX.Context.ObjectItem));
+      CheckEquals(PtrUInt(tmpAB_BC.getProperty('p_cd')), PtrUInt(locX.Context.CurrentProperty));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    locExp.SetRoot(ParseXPath('p_ab/p_bc'));
+    locX.Execute(locExp);
+      CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+      CheckEquals(PtrUInt(tmpAB_BC), PtrUInt(locX.Context.ObjectItem));
+      CheckEquals(PtrUInt(tmpAB.getProperty('p_bc')), PtrUInt(locX.Context.CurrentProperty));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+
+  locRootObject := nil;
+    tmpAC := nil;
+    tmpAB := nil;
+      tmpAB_BC := nil;
+        tmpAB_BC_CD := nil;
+
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    tmpAC := nil;
+    tmpAB := locRootObject.createDataObject('p_ab');
+      tmpAB_BC := tmpAB.createDataObject('p_bc');
+        tmpAB_BC_CD := nil;
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath('p_ac'));
+        locX.Execute(locExp);
+          CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+          CheckEquals(PtrUInt(locRootObject.getProperty('p_ac')), PtrUInt(locX.Context.CurrentProperty));
+    locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath('p_ab/p_bc'));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpAB_BC), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(tmpAB.getProperty('p_bc')), PtrUInt(locX.Context.CurrentProperty));
+    locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath('p_ab/p_bc/p_cd'));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckNull), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(tmpAB_BC.getProperty('p_cd')), PtrUInt(locX.Context.CurrentProperty));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+procedure TXPathProcessor_Test.Execute_simple_object();
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locRes.AddType(s_uri,s_type_object_B,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locRes.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locRes.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locRes.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locRes.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locRes.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+      locRes.addProperty(locObj,s_object_prop,s_uri,s_type_object_B,[pfIsContainment]);
+      locRes.addProperty(locObj,s_object_propList,s_uri,s_type_object_B,[pfIsMany,pfIsContainment]);
+
+    Result := locRes;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+    locRootObject.setBoolean(s_bool_prop,False);
+    locRootObject.setInteger(s_integer_prop,1210);
+    locRootObject.setString(s_string_prop,'sdo-wst-azerty');
+    locRootObject.createDataObject(s_object_prop);
+
+  locX := nil;
+  locExp := TXPathExpression.Create();
+  try
+    locX := TXPathProcessor.Create();
+    locX.Context.SetObject(locRootObject,nil);
+    locExp.SetRoot(ParseXPath(s_object_prop));
+    locX.Execute(locExp);
+      CheckEquals(Ord(xckObject), Ord(locX.Context.ContentKind));
+      CheckEquals(PtrUInt(locRootObject.getDataObject(s_object_prop)), PtrUInt(locX.Context.ObjectItem));
+      CheckEquals(PtrUInt(locRootObject.getProperty(s_object_prop)), PtrUInt(locX.Context.CurrentProperty));
+  finally
+    FreeAndNil(locX);
+    FreeAndNil(locExp);
+  end;
+end;
+
+procedure TXPathProcessor_Test.Execute_simple_value_type;
+const SIMPLE_TYPE_PROPS : array[0..2] of string = ( s_bool_prop, s_integer_prop, s_string_prop);
+
+  function CreateFactory() : ISDODataFactory;
+  var
+    locObj : ISDOType;
+    locRes : ISDODataFactory;
+  begin
+    locRes := TSDODataFactory.Create() as ISDODataFactory;
+    locRes.AddType(s_uri,s_type_object_A,[]);
+    locObj := locRes.getType(s_uri,s_type_object_A);
+      locRes.addProperty(locObj,s_bool_prop,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType], []);
+      locRes.addProperty(locObj,s_bool_propList,sdo_namespace,SDOTypeDefaultTypeNames[BooleanType],[pfIsMany]);
+      locRes.addProperty(locObj,s_integer_prop,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType], []);
+      locRes.addProperty(locObj,s_integer_propList,sdo_namespace,SDOTypeDefaultTypeNames[IntegerType],[pfIsMany]);
+      locRes.addProperty(locObj,s_string_prop,sdo_namespace,SDOTypeDefaultTypeNames[StringType], []);
+      locRes.addProperty(locObj,s_string_propList,sdo_namespace,SDOTypeDefaultTypeNames[StringType],[pfIsMany]);
+
+    Result := locRes;
+  end;
+
+var
+  locFac : ISDODataFactory;
+  locExp : TXPathExpression;
+  locX : TXPathProcessor;
+  locRootObject : ISDODataObject;
+  i : PtrInt;
+  propName : string;
+begin
+  locFac := CreateFactory();
+  locRootObject := locFac.createNew(s_uri,s_type_object_A);
+
+  for i := Low(SIMPLE_TYPE_PROPS) to High(SIMPLE_TYPE_PROPS) do begin
+    propName := SIMPLE_TYPE_PROPS[i];
+    locX := nil;
+    locExp := TXPathExpression.Create();
+    try
+      locX := TXPathProcessor.Create();
+      locX.Context.SetObject(locRootObject,nil);
+      locExp.SetRoot(ParseXPath(propName));
+      locX.Execute(locExp);
+        CheckEquals(Ord(xckValue), Ord(locX.Context.ContentKind));
+        CheckEquals(PtrUInt(locRootObject), PtrUInt(locX.Context.ObjectItem));
+        CheckEquals(PtrUInt(locRootObject.getProperty(propName)), PtrUInt(locX.Context.CurrentProperty));
+    finally
+      FreeAndNil(locX);
+      FreeAndNil(locExp);
+    end;
+  end;
+end;
+
+{ TXPathScanner_Test }
+
+procedure TXPathScanner_Test.composed_1();
+var
+  locObj : TXPathScanner;
+begin
+  locObj := TXPathScanner.Create('object/@prop_a/prop_b[2]/prop_c[prop_d="azerty"]');
+  try
+    CheckEquals(Ord(xtkSymbol), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSymbol), Ord(locObj.Token));
+      CheckEquals('object',locObj.TokenString);
+    CheckEquals(Ord(xtkSlash), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSlash), Ord(locObj.Token));
+      CheckEquals('/',locObj.TokenString);
+    CheckEquals(Ord(xtkAt), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkAt), Ord(locObj.Token));
+      CheckEquals('@',locObj.TokenString);
+    CheckEquals(Ord(xtkSymbol), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSymbol), Ord(locObj.Token));
+      CheckEquals('prop_a',locObj.TokenString);
+    CheckEquals(Ord(xtkSlash), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSlash), Ord(locObj.Token));
+      CheckEquals('/',locObj.TokenString);      
+    CheckEquals(Ord(xtkSymbol), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSymbol), Ord(locObj.Token));
+      CheckEquals('prop_b',locObj.TokenString);
+    CheckEquals(Ord(xtkSquaredBraceLeft), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSquaredBraceLeft), Ord(locObj.Token));
+      CheckEquals('[',locObj.TokenString);
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+      CheckEquals(2,locObj.TokenInt);
+    CheckEquals(Ord(xtkSquaredBraceRigth), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSquaredBraceRigth), Ord(locObj.Token));
+      CheckEquals(']',locObj.TokenString);
+    CheckEquals(Ord(xtkSlash), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSlash), Ord(locObj.Token));
+      CheckEquals('/',locObj.TokenString);      
+    CheckEquals(Ord(xtkSymbol), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSymbol), Ord(locObj.Token));
+      CheckEquals('prop_c',locObj.TokenString);
+    CheckEquals(Ord(xtkSquaredBraceLeft), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSquaredBraceLeft), Ord(locObj.Token));
+      CheckEquals('[',locObj.TokenString);
+    CheckEquals(Ord(xtkSymbol), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSymbol), Ord(locObj.Token));
+      CheckEquals('prop_d',locObj.TokenString);      
+    CheckEquals(Ord(xtkEqual), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkEqual), Ord(locObj.Token));
+      CheckEquals('=',locObj.TokenString);
+    CheckEquals(Ord(xtkString), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkString), Ord(locObj.Token));
+      CheckEquals('azerty',locObj.TokenString);
+    CheckEquals(Ord(xtkSquaredBraceRigth), Ord(locObj.NextToken()));
+      CheckEquals(Ord(xtkSquaredBraceRigth), Ord(locObj.Token));
+      CheckEquals(']',locObj.TokenString);      
+  finally
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathScanner_Test.simple();
+var
+  locObj : TXPathScanner;
+begin
+  locObj := TXPathScanner.Create('');
+  try
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('null');
+  try
+    CheckEquals(Ord(xtkNull), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNull), Ord(locObj.Token));
+    CheckEquals('null', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('true');
+  try
+    CheckEquals(Ord(xtkTrue), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkTrue), Ord(locObj.Token));
+    CheckEquals('true', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('false');
+  try
+    CheckEquals(Ord(xtkFalse), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkFalse), Ord(locObj.Token));
+    CheckEquals('false', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('sampleProperty_123');
+  try
+    CheckEquals(Ord(xtkSymbol), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkSymbol), Ord(locObj.Token));
+    CheckEquals('sampleProperty_123', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('.');
+  try
+    CheckEquals(Ord(xtkPeriod), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkPeriod), Ord(locObj.Token));
+    CheckEquals('.', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('..');
+  try
+    CheckEquals(Ord(xtkDoublePeriod), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkDoublePeriod), Ord(locObj.Token));
+    CheckEquals('..', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('/');
+  try
+    CheckEquals(Ord(xtkSlash), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkSlash), Ord(locObj.Token));
+    CheckEquals('/', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('[');
+  try
+    CheckEquals(Ord(xtkSquaredBraceLeft), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkSquaredBraceLeft), Ord(locObj.Token));
+    CheckEquals('[', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create(']');
+  try
+    CheckEquals(Ord(xtkSquaredBraceRigth), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkSquaredBraceRigth), Ord(locObj.Token));
+    CheckEquals(']', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('@');
+  try
+    CheckEquals(Ord(xtkAt), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkAt), Ord(locObj.Token));
+    CheckEquals('@', locObj.TokenString);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathScanner_Test.simple_number();
+var
+  locObj : TXPathScanner;
+begin
+  locObj := TXPathScanner.Create('0');
+  try
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+    CheckEquals('0', locObj.TokenString);
+    CheckEquals(0, locObj.TokenInt);
+    CheckEquals(0.0, locObj.TokenNumber,0.01);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('-0');
+  try
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+    CheckEquals('-0', locObj.TokenString);
+    CheckEquals(0, locObj.TokenInt);
+    CheckEquals(0.0, locObj.TokenNumber,0.01);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('.0');
+  try
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+    CheckEquals('0.0', locObj.TokenString);
+    CheckEquals(0.0, locObj.TokenNumber,0.01);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('123');
+  try
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+    CheckEquals('123', locObj.TokenString);
+    CheckEquals(123, locObj.TokenInt);
+    CheckEquals(123.0, locObj.TokenNumber,0.01);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('1');
+  try
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+    CheckEquals('1', locObj.TokenString);
+    CheckEquals(1, locObj.TokenInt);
+    CheckEquals(1.0, locObj.TokenNumber,0.01);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('-123');
+  try
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+    CheckEquals('-123', locObj.TokenString);
+    CheckEquals(-123, locObj.TokenInt);
+    CheckEquals(-123.0, locObj.TokenNumber,0.01);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+  locObj := TXPathScanner.Create('-1');
+  try
+    CheckEquals(Ord(xtkNumber), Ord(locObj.NextToken()));
+    CheckEquals(Ord(xtkNumber), Ord(locObj.Token));
+    CheckEquals('-1', locObj.TokenString);
+    CheckEquals(-1, locObj.TokenInt);
+    CheckEquals(-1.0, locObj.TokenNumber,0.01);
+    CheckEquals(Ord(xtkEof), Ord(locObj.NextToken()));
+  finally
+    FreeAndNil(locObj);
+  end;
+end;
+
+{ TXPathParser_Test }
+
+procedure TXPathParser_Test.parse_1();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('object');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+        CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_10();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode, tmpNode : TXPathNode;
+begin
+  locRootNode := nil;
+  //locObj := TXPathParser.Create('object/prop_a/prop_b[2]/prop_c[prop_d="azerty"]');
+  locObj := TXPathParser.Create('prop_b[2]/prop_c[prop_d="azerty"]');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckNotNull(locNode);
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('prop_b', TXPathContextStepNode(locNode).PropertyName);
+      locNode := locNode.Next;
+        CheckNotNull(locNode);
+        CheckIs(locNode, TXPathMoveInstructionStepNode);
+        tmpNode := TXPathMoveInstructionStepNode(locNode).Distance;
+          CheckIs(tmpNode,TXPathNumberConstantNode);
+          CheckEquals(2, TXPathNumberConstantNode(tmpNode).Value, 0.01);
+        locNode := locNode.Next;
+          CheckNotNull(locNode);
+          CheckIs(locNode, TXPathContextStepNode);
+          CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+          CheckEquals('prop_c', TXPathContextStepNode(locNode).PropertyName);
+          locNode := locNode.Next;
+            CheckNotNull(locNode);
+            CheckIs(locNode, TXPathLocateInstructionStepNode);
+            locNode := TXPathLocateInstructionStepNode(locNode).Condition;
+            tmpNode := TXPathEqualNode(locNode).Left;
+              CheckIs(tmpNode, TXPathValueSymbolNode);
+              CheckEquals('prop_d', TXPathValueSymbolNode(tmpNode).Symbol);
+            tmpNode := TXPathEqualNode(locNode).Right;
+              CheckIs(tmpNode, TXPathStringConstantNode);
+              CheckEquals('azerty', TXPathStringConstantNode(tmpNode).Value);
+
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_2();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('/object');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsRoot), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('', TXPathContextStepNode(locNode).PropertyName);
+      CheckNotNull(locNode.Next);
+      locNode := locNode.Next;
+        CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+        CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+          CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_3();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('object/prop_a');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+      locNode := locNode.Next;
+        CheckNotNull(locNode);
+        CheckIs(locNode, TXPathContextStepNode);
+        CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+        CheckEquals('prop_a', TXPathContextStepNode(locNode).PropertyName);
+        CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_4();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('/');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsRoot), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('', TXPathContextStepNode(locNode).PropertyName);
+      CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_5();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('object/prop_a/');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+      locNode := locNode.Next;
+        CheckNotNull(locNode);
+        CheckIs(locNode, TXPathContextStepNode);
+        CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+        CheckEquals('prop_a', TXPathContextStepNode(locNode).PropertyName);
+        CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_6();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode, tmpNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('object/prop_a/prop_b[2]');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+      locNode := locNode.Next;
+        CheckNotNull(locNode);
+        CheckIs(locNode, TXPathContextStepNode);
+        CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+        CheckEquals('prop_a', TXPathContextStepNode(locNode).PropertyName);
+        locNode := locNode.Next;
+          CheckNotNull(locNode);
+          CheckIs(locNode, TXPathContextStepNode);
+          CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+          CheckEquals('prop_b', TXPathContextStepNode(locNode).PropertyName);
+          locNode := locNode.Next;
+            CheckNotNull(locNode);
+            CheckIs(locNode, TXPathMoveInstructionStepNode);
+            tmpNode := TXPathMoveInstructionStepNode(locNode).Distance;
+              CheckIs(tmpNode,TXPathNumberConstantNode);
+              CheckEquals(2, TXPathNumberConstantNode(tmpNode).Value, 0.01);
+            CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_7();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('@object');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+        CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_8();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('/@object');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsRoot), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('', TXPathContextStepNode(locNode).PropertyName);
+      CheckNotNull(locNode.Next);
+      locNode := locNode.Next;
+        CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+        CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+          CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+procedure TXPathParser_Test.parse_9();
+var
+  locObj : TXPathParser;
+  locRootNode, locNode : TXPathNode;
+begin
+  locRootNode := nil;
+  locObj := TXPathParser.Create('object/@prop_a');
+  try
+    locRootNode := locObj.Parse();
+    CheckNotNull(locRootNode, 'root');
+    locNode := locRootNode;
+      CheckIs(locNode, TXPathContextStepNode);
+      CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+      CheckEquals('object', TXPathContextStepNode(locNode).PropertyName);
+      locNode := locNode.Next;
+        CheckNotNull(locNode);
+        CheckIs(locNode, TXPathContextStepNode);
+        CheckEquals(Ord(xcsProperty), Ord(TXPathContextStepNode(locNode).Switch));
+        CheckEquals('prop_a', TXPathContextStepNode(locNode).PropertyName);
+        CheckNull(locNode.Next);
+  finally
+    FreeAndNil(locRootNode);
+    FreeAndNil(locObj);
+  end;
+end;
+
+{ TXPathUtilsFunc_Test }
+
+procedure TXPathUtilsFunc_Test.getXpath_func();
+var
+  locFactory : ISDODataFactory;
+
+  procedure Add_Objects(const AUri : string);
+  var
+    locObj : ISDOType;
+  begin
+    locFactory.AddType(AUri,s_type_object_C,[]);
+    locObj := locFactory.getType(AUri,s_type_object_C);
+
+    locFactory.AddType(AUri,s_type_object_B,[]);
+    locObj := locFactory.getType(AUri,s_type_object_B);
+      locFactory.addProperty(locObj,'p_bc',s_uri,s_type_object_C,[pfIsContainment]);
+      locFactory.addProperty(locObj,'p_bc_multi',s_uri,s_type_object_C,[pfIsContainment,pfIsMany]);
+
+    locFactory.AddType(AUri,s_type_object_A,[]);
+    locObj := locFactory.getType(AUri,s_type_object_A);
+      locFactory.addProperty(locObj,'p_ab',s_uri,s_type_object_B,[pfIsContainment]);
+      locFactory.addProperty(locObj,'p_ac',s_uri,s_type_object_C,[pfIsContainment]);
+  end;
+
+var
+  a , b, c0, c1, c2 : ISDODataObject;
+begin
+  locFactory := TSDODataFactory.Create() as ISDODataFactory;
+  Add_Objects(s_uri);
+  a := locFactory.createNew(s_uri,s_type_object_A);
+  b := a.createDataObject('p_ab');
+  b.createDataObject('p_bc');
+  a.createDataObject('p_ac');
+  c0 := b.createDataObject('p_bc_multi');
+  b.getList('p_bc_multi').append(c0);
+  c1 := b.createDataObject('p_bc_multi');
+  b.getList('p_bc_multi').append(c1);
+  c2 := b.createDataObject('p_bc_multi');
+  b.getList('p_bc_multi').append(c2);
+
+  CheckEquals('', getXpath(nil));
+  CheckEquals('',getXpath(a));
+  CheckEquals('p_ab',getXpath(a.getDataObject('p_ab')));
+  CheckEquals('p_ac',getXpath(a.getDataObject('p_ac')));
+  CheckEquals('p_ab/p_bc',getXpath(a.getDataObject('p_ab').getDataObject('p_bc')));
+  CheckEquals('p_ab/p_bc_multi[1]',getXpath(c1));
+  CheckEquals('p_ab/p_bc_multi[0]',getXpath(c0));
+  CheckEquals('p_ab/p_bc_multi[2]',getXpath(c2));
+end;
+
+initialization
+  RegisterTest('Helpers',TXPathScanner_Test.Suite);
+  RegisterTest('Helpers',TXPathParser_Test.Suite);
+  RegisterTest('Helpers',TXPathProcessor_Test.Suite);
+  RegisterTest('Helpers',TXPathUtilsFunc_Test.Suite);
+
+end.

+ 808 - 0
packages/fcl-sdo/tests/test_suite/test_xsdhelper.pas

@@ -0,0 +1,808 @@
+{$INCLUDE sdo_global.inc}
+unit test_xsdhelper;
+
+interface
+uses SysUtils
+{$IFDEF FPC}
+  ,fpcunit, testutils, testregistry
+{$ENDIF}
+{$IFNDEF FPC}
+  ,TestFrameWork
+{$ENDIF}
+  , sdo, sdo_types, sdo_xsd_helper ;
+
+type
+
+  TXsdHelper_Test = class(TTestCase)
+  private
+    function CreateSdoTypes() : ISDODataFactory;
+  protected
+    function ExpandFileName(const AFileName : string) : string;
+    function GetFileName() : string;
+    procedure CompareObjectType(
+      AExpected : ISDODataObject;
+      AValue : ISDOType;
+      APasTree : ISDODataObject
+    ); overload;
+    procedure CompareObjectType(
+      AExpected : ISDOType;
+      AValue : ISDODataObject;
+      APasTree : ISDODataFactory
+    ); overload;
+    procedure CompareModule(
+      AExpected : ISDODataObject;
+      AValue : ISDODataFactory;
+      APasTree : ISDODataObject
+    ); overload;
+    procedure CompareModule(
+      AExpected : string;
+      AValue : ISDODataObject;
+      APasTree : ISDODataFactory
+    ); overload;
+    procedure CompareSdoModule(
+      AExpectedFactory : ISDODataFactory;
+      AExpectedURI : string;
+      AValueFactory : ISDODataFactory
+    );
+    procedure CompareSdoTypes(AExpected, AValue : ISDOType);
+  published
+    procedure LoadFromStream();
+    procedure LoadFromFile();
+    procedure LoadFromString();
+
+    procedure GenerateString();
+    procedure GenerateStream();
+    procedure GenerateFile();
+
+    procedure LoadFromStream_open_type();
+    procedure LoadFromFile_open_type();
+    procedure GenerateString_open_type();
+    procedure GenerateStream_open_type();
+
+    procedure parse_scoped_array();
+
+    procedure TypeDerivation();
+    procedure TypeDerivation2();
+  end;
+
+implementation
+uses
+  Classes,
+{$IFDEF DELPHI}
+  xmldom, sdo_win_xml,
+{$ENDIF DELPHI}
+{$IFDEF FPC}
+  DOM, sdo_fpc_xml, XMLRead,
+{$ENDIF}
+  sdo_xsdintf,
+  test_suite_utils, sdo_datafactory, sdo_xsdparser, sdo_type, xsd_consts,
+  parserutils;
+
+
+const
+  s_uri = 'company.xsd';
+  s_EmployeeType = 'EmployeeType';
+  s_DepartmentType = 'DepartmentType';
+  s_CompanyType = 'CompanyType';
+  s_company = 'company';
+
+{ TXsdHelper_Test }
+
+procedure TXsdHelper_Test.CompareModule(
+  AExpected: ISDODataObject;
+  AValue: ISDODataFactory;
+  APasTree: ISDODataObject
+);
+var
+  i : Integer;
+  typeList : ISDODataObjectList;
+  e : ISDODataObject;
+  t : ISDOType;
+begin
+  typeList := AExpected.getList(s_type);
+  for i := 0 to Pred(typeList.size()) do begin
+    e := typeList.getDataObject(i);
+    if e.getBoolean(s_IsComplex) then begin
+      t :=  AValue.getTypes().find(AExpected.getString(sdo_xsdintf.s_NameSpace),e.getString(sdo_xsdintf.s_Name));
+      CompareObjectType(e,t,APasTree);
+    end;
+  end;
+end;
+
+procedure TXsdHelper_Test.CompareObjectType(
+  AExpected : ISDODataObject; //TPasClassType;
+  AValue : ISDOType;
+  APasTree : ISDODataObject
+);
+var
+  pasLs : ISDODataObjectList;
+  sls : ISDOPropertyList;
+  pasp : ISDODataObject;
+  sp  : ISDOProperty;
+  i, propCount : PtrInt;
+  pt, newpt : ISDODataObject;
+  alsCount, j : PtrInt;
+  ok : Boolean;
+  tmpBuffer, alLs : string;
+  parent : ISDODataObject;
+begin
+  if Assigned(AExpected) then begin
+    Check(AValue <> nil, 'Should not be nil');
+    CheckEquals(LowerCase(GetTypeNameSpace(AExpected)),LowerCase(AValue.getURI()),'URI');
+    CheckEquals(LowerCase(AExpected.getString(s_Name)),LowerCase(AValue.getName()),'Name');
+    parent := AExpected.getDataObject(s_BaseType);
+    CompareObjectType(parent,AValue.getBaseType(),APasTree);
+    if ( parent <> nil ) and
+       ( not IsNativeType(parent) )
+    then begin
+      Check(AValue.getBaseType() <> nil, AExpected.getString(s_Name) + ', BaseType() Should not be nil');
+      CheckEquals(LowerCase(AExpected.getString(s_Name)),LowerCase(AValue.getBaseType().getName()),AExpected.getString(s_Name) + ', Name');
+      CheckEquals(LowerCase(AExpected.getString(s_NameSpace)),LowerCase(AValue.getBaseType().getURI()),AExpected.getString(s_Name) + ', NameSpace');
+    end;
+
+    pasLs := AExpected.getList(s_Property);
+    sls := AValue.getProperties();
+    propCount := 0;
+    for i := 0 to Pred(pasLs.size()) do begin
+      pasp := pasLs.getDataObject(i);
+      Inc(propCount);
+      pt := pasp.getDataObject(s_DataType);
+      sp := sls.find(pasp.getString(s_Name));
+      Check( ( sp <> nil ), Format('Property not found : %s',[pasp.getString(s_Name)]));
+      CheckEquals(LowerCase(pasp.getString(s_Name)),LowerCase(sp.getName()),'Property');
+      if pt.getBoolean(s_Unresolved) then begin
+        newpt := Find(APasTree,pt.getString(s_NameSpace),pt.getString(s_Name));
+        if (newpt <> nil) then
+          pt := newpt;
+      end;
+      newpt := GetUltimeType(pt);
+      if (newpt <> nil) then
+        pt := newpt;
+      CheckEquals(
+        (pasp.getInteger(s_PropertyMaxOccurs) > 1),
+        sp.isMany(),
+        'isMany()'
+      );
+      alLs := sp.getType().getName();
+      ok := ( LowerCase(pt.getString(s_Name)) = LowerCase(sp.getType().getName()) );
+      alsCount := sp.getType().getAliasCount();
+      if ( not ok ) and ( alsCount > 0 ) then begin
+        tmpBuffer := LowerCase(pt.getString(s_Name));
+        alLs := alLs + ', ' + tmpBuffer;
+        for j := 0 to Pred(alsCount) do begin
+          if ( tmpBuffer = LowerCase(sp.getType().getAlias(j)) ) then begin
+            ok := True;
+            Break;
+          end;
+        end;
+      end;
+      CheckEquals(
+        True,
+        ok,
+        Format('Property "%s" Type name ( Alias = "%s"; PT = "%s" )',[pasp.getString(s_Name),alLs,pt.getString(s_Name)])
+      );
+    end;
+    CheckEquals(propCount,sls.getCount(),AExpected.getString(s_Name) + ', Properties count');
+  end else begin
+    Check(AValue = nil, '"nil" Expected.');
+  end;
+end;
+
+procedure TXsdHelper_Test.CompareModule(
+  AExpected: string;
+  AValue: ISDODataObject;
+  APasTree: ISDODataFactory
+);
+var
+  i : Integer;
+  typeList : ISDOTypeList;
+  e : ISDOType;
+  t : ISDODataObject;
+begin
+  typeList := APasTree.getTypes();
+  for i := 0 to Pred(typeList.getCount()) do begin
+    e := typeList.getItem(i);
+    if SameText(AExpected,e.getURI()) and e.isDataObjectType() then begin
+      t := FindInModule(AValue,e.getName());
+      CompareObjectType(e,t,APasTree);
+    end;
+  end;
+end;
+
+procedure TXsdHelper_Test.CompareObjectType(
+  AExpected: ISDOType;
+  AValue: ISDODataObject;
+  APasTree: ISDODataFactory
+);
+var
+  pasLs : ISDOPropertyList;
+  sls : ISDODataObjectList;
+  pasp : ISDOProperty;
+  sp  : ISDODataObject;
+  i, propCount : PtrInt;
+  pt, newpt : ISDOType;
+  alsCount, j : PtrInt;
+  ok : Boolean;
+  tmpBuffer, alLs : string;
+  parent : ISDOType;
+  searchingType : ISDODataObject;
+  searchingTypeProps : ISDODataObjectList;
+begin
+  if Assigned(AExpected) then begin
+    Check(AValue <> nil, 'Should not be nil');
+    CheckEquals(LowerCase(AExpected.getURI()),LowerCase(GetTypeNameSpace(AValue)),'URI');
+    CheckEquals(LowerCase(AExpected.getName()),LowerCase(AValue.getString(s_Name)),'Name');
+    parent := AExpected.getBaseType();
+    CompareObjectType(parent,AValue.getDataObject(s_BaseType),APasTree);
+
+    pasLs := AExpected.getProperties();
+    sls := AValue.getList(s_Property);
+    propCount := 0;
+    for i := 0 to Pred(pasLs.getCount()) do begin
+      pasp := pasLs.getItem(i);
+      Inc(propCount);
+      pt := pasp.getType();
+      sp := nil;
+      searchingType := AValue;
+      while (searchingType <> nil) do begin
+        searchingTypeProps := searchingType.getList(s_Property);
+        searchingTypeProps.getCursor().Reset();
+        while searchingTypeProps.getCursor().MoveNext() do begin
+          if SameText(pasp.getName(),searchingTypeProps.getDataObject().getString(s_Name)) then begin
+            sp := searchingTypeProps.getDataObject();
+            Break;
+          end;
+        end;
+        if (sp <> nil) then
+          Break;
+        searchingType := searchingType.getDataObject(s_BaseType);
+      end;
+      Check( ( sp <> nil ), Format('Property not found : %s',[pasp.getName()]));
+      CheckEquals(LowerCase(pasp.getName()),LowerCase(sp.getString(s_Name)),'Property');
+      CheckEquals(
+        pasp.isMany(),
+        (sp.getInteger(s_PropertyMaxOccurs) > 1),
+        'isMany()'
+      );
+      alLs := sp.getType().getName();
+      ok := ( LowerCase(pt.getName()) = LowerCase(sp.getDataObject(s_DataType).getString(s_Name)) );
+      alsCount := pt.getAliasCount();
+      if ( not ok ) and ( alsCount > 0 ) then begin
+        tmpBuffer := LowerCase(sp.getDataObject(s_DataType).getString(s_Name));
+        alLs := alLs + ', ' + tmpBuffer;
+        for j := 0 to Pred(alsCount) do begin
+          if ( tmpBuffer = LowerCase(pt.getAlias(j)) ) then begin
+            ok := True;
+            Break;
+          end;
+        end;
+      end;
+      CheckEquals(
+        True,
+        ok,
+        Format('Property "%s" Type name ( Alias = "%s"; PT = "%s" )',[pasp.getName() ,alLs,pt.getName()])
+      );
+    end;
+    i := 0;
+    searchingType := AValue;
+    while (searchingType <> nil) do begin
+      i := i + searchingType.getList(s_Property).size();
+      searchingType := searchingType.getDataObject(s_BaseType);
+    end;
+    CheckEquals(propCount,i,AExpected.getName() + ', Properties count');
+  end else begin
+    Check(AValue = nil, '"nil" Expected.');
+  end;
+end;
+
+procedure TXsdHelper_Test.CompareSdoModule(
+  AExpectedFactory: ISDODataFactory;
+  AExpectedURI: string;
+  AValueFactory: ISDODataFactory
+);
+var
+  etl, vtl : ISDOTypeList;
+  e, v : ISDOType;
+  i : Integer;
+begin
+  etl := AExpectedFactory.getTypes();
+  vtl := AValueFactory.getTypes();
+  for i := 0 to etl.getCount() - 1 do begin
+    e := etl.getItem(i);
+    if SameText(AExpectedURI,e.getURI()) then begin
+      v := vtl.find(AExpectedURI,e.getName());
+      Check((v <> nil),Format('type not found : "%s"',[e.getName()]));
+      CompareSdoTypes(e,v);
+    end;
+  end;
+end;
+
+procedure TXsdHelper_Test.CompareSdoTypes(AExpected, AValue: ISDOType);
+begin
+  if (AExpected= nil) then begin
+    Check(AValue = nil, 'nil expected.');
+    exit;
+  end;
+  Check(AValue <> nil);
+  CheckEquals(AExpected.getURI(),AValue.getURI(),'URI');
+  CheckEquals(AExpected.getName(),AValue.getName(),'Name');
+  Check(AExpected.getFlags() = AValue.getFlags(),'getFlags()');
+  if (AExpected.getBaseType() = nil) then begin
+    Check(AValue.getBaseType() = nil,'BaseType')
+  end else begin
+    CompareSdoTypes(AExpected.getBaseType(),AValue.getBaseType());
+  end;
+end;
+
+function TXsdHelper_Test.CreateSdoTypes() : ISDODataFactory;
+var
+  locObj : ISDOType;
+begin
+  Result := TSDODataFactory.Create() as ISDODataFactory;
+  Result.AddType(s_uri,s_EmployeeType,[]);
+  locObj := Result.getType(s_uri,s_EmployeeType);
+    Result.addProperty(locObj,'name',sdo_namespace,'string',[]);
+    Result.addProperty(locObj,'SN',sdo_namespace,'string',[]);
+    Result.addProperty(locObj,'manager',sdo_namespace,'boolean',[]);
+
+  Result.AddType(s_uri,s_DepartmentType,[]);
+  locObj := Result.getType(s_uri,s_DepartmentType);
+    Result.addProperty(locObj,'employees',s_uri,s_EmployeeType,[pfIsMany, pfIsContainment]);
+    Result.addProperty(locObj,'name',sdo_namespace,'string',[]);
+    Result.addProperty(locObj,'location',sdo_namespace,'string',[]);
+    Result.addProperty(locObj,'number',sdo_namespace,'int',[]);
+
+  Result.AddType(s_uri,s_CompanyType,[]);
+  locObj := Result.getType(s_uri,s_CompanyType);
+    Result.addProperty(locObj,'departments',s_uri,s_DepartmentType,[pfIsMany, pfIsContainment]);
+    Result.addProperty(locObj,'name',sdo_namespace,'string',[]);
+    Result.addProperty(locObj,'employeeOfTheMonth',sdo_namespace,'string',[]);
+    (locObj as ISDOTypeEx).setAlias(s_company);
+end;
+
+function TXsdHelper_Test.ExpandFileName(const AFileName: string): string;
+begin
+  Result := sdoExpandLocalFileName(TestFilesPath + AFileName);
+end;
+
+procedure TXsdHelper_Test.GenerateFile();
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locDoc : TXMLDocument;
+  locFileName : string;
+  locPasFactory : ISDODataFactory;
+begin
+  locFileName := sdoExpandLocalFileName('generatefile.xsd');
+  fct := CreateSdoTypes() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  helper.Generate(fct.getTypes(),s_uri,locFileName);
+  locTree := nil;
+  ReadXMLFile(locDoc,locFileName);
+  try
+    locPasFactory := TSDODataFactory.Create();
+    AddTypeTree(locPasFactory);
+    locTree := locPasFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+    xsdPrsr := TXsdParser.Create(locDoc,locTree,'') as IXsdPaser;
+    xsdPrsr.ParseTypes();
+    CompareModule(locTree.getDataObject(s_CurrentModule),fct,locTree);
+  finally
+    locTree := nil;
+    ReleaseDomNode(locDoc);
+  end;
+end;
+
+procedure TXsdHelper_Test.GenerateStream();
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locDoc : TXMLDocument;
+  locStream : TStringStream;
+  locPasFactory : ISDODataFactory;
+begin
+  fct := CreateSdoTypes() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  locStream := TStringStream.Create('');
+  try
+    helper.Generate(fct.getTypes(),locStream,s_uri);
+    locStream.Position := 0;
+    locTree := nil;
+    ReadXMLFile(locDoc,locStream);
+    try
+      locPasFactory := TSDODataFactory.Create();
+      AddTypeTree(locPasFactory);
+      locTree := locPasFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+      xsdPrsr := TXsdParser.Create(locDoc,locTree,'') as IXsdPaser;
+      xsdPrsr.ParseTypes();
+      CompareModule(locTree.getDataObject(s_CurrentModule),fct,locTree);
+    finally
+      locTree := nil;
+      ReleaseDomNode(locDoc);
+    end;
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXsdHelper_Test.GenerateString();
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locDoc : TXMLDocument;
+  locStream : TStringStream;
+  locBuffer : string;
+  locPasFactory : ISDODataFactory;
+begin
+  fct := CreateSdoTypes();
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  locStream := nil;
+  try
+    locBuffer := helper.Generate(fct.getTypes(),s_uri);
+    locStream := TStringStream.Create(locBuffer);
+    locStream.Position := 0;
+    locTree := nil;
+    ReadXMLFile(locDoc,locStream);
+    try
+      locPasFactory := TSDODataFactory.Create();
+      AddTypeTree(locPasFactory);
+      locTree := locPasFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+      xsdPrsr := TXsdParser.Create(locDoc,locTree,'') as IXsdPaser;
+      xsdPrsr.ParseTypes();
+      CompareModule(locTree.getDataObject(s_CurrentModule),fct,locTree);
+    finally
+      locTree := nil;
+      ReleaseDomNode(locDoc);
+    end;
+  finally
+    locStream.Free();
+  end;
+end;
+
+function TXsdHelper_Test.GetFileName() : string;
+begin
+  Result := ExpandFileName('sdo_company.xsd');
+end;
+
+procedure TXsdHelper_Test.LoadFromFile();
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locDoc : TXMLDocument;
+  locPasFactory : ISDODataFactory;
+begin
+  fct := TSDODataFactory.Create() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  helper.LoadFromFile(GetFileName());
+
+  locDoc := nil;
+  locPasFactory := TSDODataFactory.Create();
+  AddTypeTree(locPasFactory);
+  locTree := locPasFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+  try
+    ReadXMLFile(locDoc,GetFileName());
+    xsdPrsr := TXsdParser.Create(locDoc,locTree,'') as IXsdPaser;
+    xsdPrsr.ParseTypes();
+    CompareModule(locTree.getDataObject(s_CurrentModule),fct,locTree);
+  finally
+    locTree := nil;
+    ReleaseDomNode(locDoc);
+  end;
+end;
+
+procedure TXsdHelper_Test.LoadFromStream();
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locDoc : TXMLDocument;
+  locStream : TMemoryStream;
+  locPasFactory : ISDODataFactory;
+begin
+  fct := TSDODataFactory.Create() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  locStream := TMemoryStream.Create();
+  try
+    locStream.LoadFromFile(GetFileName());
+    locStream.Position := 0;
+    helper.LoadFromStream(locStream);
+
+    locDoc := nil;
+    locPasFactory := TSDODataFactory.Create();
+    AddTypeTree(locPasFactory);
+    locTree := locPasFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+    try
+      ReadXMLFile(locDoc,GetFileName());
+      xsdPrsr := TXsdParser.Create(locDoc,locTree,'') as IXsdPaser;
+      xsdPrsr.ParseTypes();
+      CompareModule(locTree.getDataObject(s_CurrentModule),fct,locTree);
+    finally
+      locTree := nil;
+      locPasFactory := nil;
+      ReleaseDomNode(locDoc);
+    end;
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXsdHelper_Test.LoadFromString();
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locDoc : TXMLDocument;
+  locStream : TMemoryStream;
+  locBuffer : TStringBufferType;
+  locPasFactory : ISDODataFactory;
+begin
+  fct := TSDODataFactory.Create() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  locStream := TMemoryStream.Create();
+  try
+    locStream.LoadFromFile(GetFileName());
+    locStream.Position := 0;
+    SetLength(locBuffer,locStream.Size);
+    locStream.Read(locBuffer[1],locStream.Size);
+    helper.LoadFromString(String(locBuffer));
+
+    locDoc := nil;
+    locPasFactory := TSDODataFactory.Create();
+    AddTypeTree(locPasFactory);
+    locTree := locPasFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+    try
+      ReadXMLFile(locDoc,GetFileName());
+      xsdPrsr := TXsdParser.Create(locDoc,locTree,'') as IXsdPaser;
+      xsdPrsr.ParseTypes();
+      CompareModule(locTree.getDataObject(s_CurrentModule),fct,locTree);
+    finally
+      locTree := nil;
+      ReleaseDomNode(locDoc);
+    end;
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXsdHelper_Test.LoadFromStream_open_type();
+const S_TEST_NS = 'urn:wst-test';
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  locStream : TMemoryStream;
+  typ : ISDOType;
+begin
+  fct := TSDODataFactory.Create() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  locStream := TMemoryStream.Create();
+  try
+    locStream.LoadFromFile(ExpandFileName('complex_class_open_type.xsd'));
+    locStream.Position := 0;
+    helper.LoadFromStream(locStream);
+    typ := fct.getType(S_TEST_NS,'TClass_1');
+      CheckEquals(True,typ.isOpenType(),'TClass_1.IsOpenType()');
+    typ := fct.getType(S_TEST_NS,'TClassSampleTypeAll');
+      CheckEquals(True,typ.isOpenType(),'TClassSampleTypeAll.IsOpenType()');
+    typ := fct.getType(S_TEST_NS,'TClass_2');
+      CheckEquals(False,typ.isOpenType(),'TClass_2.IsOpenType()');
+    typ := fct.getType(S_TEST_NS,'TClassSampleDerivedType');
+      CheckEquals(True,typ.isOpenType(),'TClassSampleDerivedType.IsOpenType()');
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXsdHelper_Test.LoadFromFile_open_type();
+const S_TEST_NS = 'urn:wst-test';
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  typ : ISDOType;
+begin
+  fct := TSDODataFactory.Create() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  helper.LoadFromFile(ExpandFileName('complex_class_open_type.xsd'));
+  typ := fct.getType(S_TEST_NS,'TClass_1');
+    CheckEquals(True,typ.isOpenType(),'TClass_1.IsOpenType()');
+  typ := fct.getType(S_TEST_NS,'TClassSampleTypeAll');
+    CheckEquals(True,typ.isOpenType(),'TClassSampleTypeAll.IsOpenType()');
+  typ := fct.getType(S_TEST_NS,'TClass_2');
+    CheckEquals(False,typ.isOpenType(),'TClass_2.IsOpenType()');
+  typ := fct.getType(S_TEST_NS,'TClassSampleDerivedType');
+    CheckEquals(True,typ.isOpenType(),'TClassSampleDerivedType.IsOpenType()');
+end;
+
+procedure TXsdHelper_Test.GenerateString_open_type();
+const S_TEST_NS = 'urn:open-type';
+var
+  helper : IXSDHelper;
+  fct, genFact : ISDODataFactory;
+  typ : ISDOType;
+  strBuffer : string;
+begin
+  genFact := TSDODataFactory.Create() as ISDODataFactory;
+  genFact.AddType(S_TEST_NS,'type_open',[tfIsOpen]);
+  genFact.AddType(S_TEST_NS,'type_notopen',[]);
+  helper := TXSDHelper.Create(genFact) as IXSDHelper;
+  strBuffer := helper.Generate(genFact.getTypes(),S_TEST_NS);
+  helper := nil;
+
+  fct := TSDODataFactory.Create() as ISDODataFactory;
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  helper.LoadFromString(strBuffer);
+  typ := fct.getType(S_TEST_NS,'type_open');
+    CheckEquals(True,typ.isOpenType(),'type_open.IsOpenType()');
+  typ := fct.getType(S_TEST_NS,'type_notopen');
+    CheckEquals(False,typ.isOpenType(),'type_notopen.IsOpenType()');
+end;
+
+procedure TXsdHelper_Test.GenerateStream_open_type;
+const S_TEST_NS = 'urn:open-type';
+var
+  helper : IXSDHelper;
+  fct, genFact : ISDODataFactory;
+  typ : ISDOType;
+  locStream : TStream;
+begin
+  genFact := TSDODataFactory.Create() as ISDODataFactory;
+  genFact.AddType(S_TEST_NS,'type_open',[tfIsOpen]);
+  genFact.AddType(S_TEST_NS,'type_notopen',[]);
+  helper := TXSDHelper.Create(genFact) as IXSDHelper;
+  locStream := TMemoryStream.Create();
+  try
+    helper.Generate(genFact.getTypes(),locStream,S_TEST_NS);
+    helper := nil;
+
+    fct := TSDODataFactory.Create() as ISDODataFactory;
+    helper := TXSDHelper.Create(fct) as IXSDHelper;
+    locStream.Position := 0;
+    helper.LoadFromStream(locStream);
+    typ := fct.getType(S_TEST_NS,'type_open');
+      CheckEquals(True,typ.isOpenType(),'type_open.IsOpenType()');
+    typ := fct.getType(S_TEST_NS,'type_notopen');
+      CheckEquals(False,typ.isOpenType(),'type_notopen.IsOpenType()');
+  finally
+    locStream.Free();
+  end;
+end;
+
+procedure TXsdHelper_Test.parse_scoped_array();
+const
+  s_xml_text =
+         '<schema targetNamespace="company.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="company.xsd">'  + sLineBreak +
+         '  <xsd:complexType name="Datarow">'  + sLineBreak +
+         '    <xsd:sequence>'  + sLineBreak +
+         '      <xsd:any processContents="lax" maxOccurs="unbounded"/>'  + sLineBreak +
+         '    </xsd:sequence>'  + sLineBreak +
+         '    <xsd:anyAttribute processContents="lax"/>'  + sLineBreak +
+         '  </xsd:complexType>'  + sLineBreak +
+         '  <xsd:complexType name="Dataset">'  + sLineBreak +
+         '    <xsd:sequence>'  + sLineBreak +
+         '      <xsd:element name="rows" type="tns:Datarow" minOccurs="0" maxOccurs="unbounded"/>'  + sLineBreak +
+         '      <xsd:any processContents="lax" maxOccurs="unbounded"/>'  + sLineBreak +
+         '    </xsd:sequence>'  + sLineBreak +
+         '    <xsd:anyAttribute processContents="lax"/>'  + sLineBreak +
+         '  </xsd:complexType>'  + sLineBreak +
+         '</schema>';
+var
+  fact : ISDODataFactory;
+  helper : IXSDHelper;
+  tl : ISDOTypeList;
+  typ : ISDOType;
+  p : ISDOProperty;
+begin
+  fact := TSDODataFactory.Create() as ISDODataFactory;
+  helper := TXSDHelper.Create(fact);
+  helper.LoadFromString(s_xml_text);
+  tl := fact.getTypes();
+  typ := tl.find(s_uri,'Datarow');
+  Check(( typ <> nil ), '"Datarow" not found');
+  CheckEquals(True, typ.isOpenType(), 'Datarow.isOpenType()');
+  typ := tl.find(s_uri,'Dataset');
+  Check(( typ <> nil ), '"Dataset" not found');
+  CheckEquals(True, typ.isOpenType(), 'Dataset.isOpenType()');
+  p := typ.getProperties().find('rows');
+  Check(( p <> nil ), 'Property not found : "rows"');
+  CheckEquals(True,p.isMany());
+  Check(p.getType().equals(fact.getType(s_uri,'Datarow')));
+end;
+
+procedure TXsdHelper_Test.TypeDerivation();
+  function CreateTypes(): ISDODataFactory;
+  var
+    f : ISDODataFactory;
+  begin
+    f := TSDODataFactory.Create();
+    f.AddType(s_uri,'typeA',[]);
+      f.AddType(s_uri,'typeAA',[]); f.setBaseType(s_uri,'typeAA',s_uri,'typeA');
+      f.AddType(s_uri,'typeAB',[]); f.setBaseType(s_uri,'typeAB',s_uri,'typeA');
+        f.AddType(s_uri,'typeABA',[]); f.setBaseType(s_uri,'typeABA',s_uri,'typeAB');
+
+    f.addProperty(s_uri,'typeAA','xi',sdo_namespace,'Int',[pfIsAttribute]);
+    f.addProperty(s_uri,'typeAA','xs',sdo_namespace,'String',[]);
+    f.addProperty(s_uri,'typeAB','bi',sdo_namespace,'Int',[]);
+    f.addProperty(s_uri,'typeAB','bs',sdo_namespace,'String',[pfIsAttribute]);
+    f.addProperty(s_uri,'typeABA','bb',sdo_namespace,'Boolean',[pfIsAttribute]);
+    f.addProperty(s_uri,'typeABA','bx',sdo_namespace,'Bytes',[]);
+    Result := f;
+  end;
+
+var
+  helper : IXSDHelper;
+  fct : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locDoc : TXMLDocument;
+  locFileName : string;
+  locPasFactory : ISDODataFactory;
+begin
+  locFileName := sdoExpandLocalFileName('typederivation.xsd');
+  fct := CreateTypes();
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  helper.Generate(fct.getTypes(),s_uri,locFileName);
+  locTree := nil;
+  ReadXMLFile(locDoc,locFileName);
+  try
+    locPasFactory := TSDODataFactory.Create();
+    AddTypeTree(locPasFactory);
+    locTree := locPasFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+    xsdPrsr := TXsdParser.Create(locDoc,locTree,'') as IXsdPaser;
+    xsdPrsr.ParseTypes();
+    CompareModule(s_uri,FindModule(locTree,s_uri),fct);
+  finally
+    locTree := nil;
+    ReleaseDomNode(locDoc);
+  end;
+end;
+
+procedure TXsdHelper_Test.TypeDerivation2();
+  function CreateTypes(): ISDODataFactory;
+  var
+    f : ISDODataFactory;
+  begin
+    f := TSDODataFactory.Create();
+    f.AddType(s_uri,'typeA',[]);
+      f.AddType(s_uri,'typeAA',[]); f.setBaseType(s_uri,'typeAA',s_uri,'typeA');
+      f.AddType(s_uri,'typeAB',[]); f.setBaseType(s_uri,'typeAB',s_uri,'typeA');
+        f.AddType(s_uri,'typeABA',[]); f.setBaseType(s_uri,'typeABA',s_uri,'typeAB');
+
+    f.addProperty(s_uri,'typeAA','xi',sdo_namespace,'Int',[pfIsAttribute]);
+    f.addProperty(s_uri,'typeAA','xs',sdo_namespace,'String',[]);
+    f.addProperty(s_uri,'typeAB','bi',sdo_namespace,'Int',[]);
+    f.addProperty(s_uri,'typeAB','bs',sdo_namespace,'String',[pfIsAttribute]);
+    f.addProperty(s_uri,'typeABA','bb',sdo_namespace,'Boolean',[pfIsAttribute]);
+    f.addProperty(s_uri,'typeABA','bx',sdo_namespace,'Bytes',[]);
+    Result := f;
+  end;
+
+var
+  helper : IXSDHelper;
+  fct, fctLoaded : ISDODataFactory;
+  xsdPrsr : IXsdPaser;
+  locTree : ISDODataObject;
+  locFileName : string;
+begin
+  locFileName := sdoExpandLocalFileName('typederivation2.xsd');
+  fct := CreateTypes();
+  helper := TXSDHelper.Create(fct) as IXSDHelper;
+  helper.Generate(fct.getTypes(),s_uri,locFileName);
+
+  fctLoaded := TSDODataFactory.Create();
+  helper := TXSDHelper.Create(fctLoaded) as IXSDHelper;
+  helper.LoadFromFile(locFileName);
+  CompareSdoModule(fct,s_uri,fctLoaded);
+end;
+
+initialization
+  RegisterTest('Helpers',TXsdHelper_Test.Suite);
+
+end.

+ 1314 - 0
packages/fcl-sdo/tests/test_suite/test_xsdparser.pas

@@ -0,0 +1,1314 @@
+{$INCLUDE sdo_global.inc}
+unit test_xsdparser;
+
+interface        
+
+uses
+  Classes, SysUtils,
+{$IFDEF FPC}
+  fpcunit, testutils, testregistry, DOM, XmlRead, sdo_fpc_xml,
+{$ELSE}
+  TestFrameWork, xmldom, sdo_win_xml,
+{$ENDIF}
+  sdo, sdo_types, sdo_xsdparser;
+
+type
+
+  { TTest_CustomXsdParser }
+
+  TTest_CustomXsdParser = class(TTestCase)
+  protected
+    function LoadEmptySchema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadSimpleType_Enum_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadSimpleType_Enum_Embedded_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadSimpleType_AliasToNativeType_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    
+    function LoadComplexType_Class_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_Class_default_values(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_Class_properties_extended_metadata(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_Class_properties_extended_metadata2(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_Class_Embedded_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_Class_Extend_Simple_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_Class_OpenType(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_Class_FalseArray(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+
+    function LoadComplexType_ArraySequence_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_ArraySequence_ItemName_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    function LoadComplexType_ArraySequence_Embedded_Schema(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+    //function LoadComplexType_Array_soaparray() : ISDODataObject;virtual;abstract;
+
+    function load_class_property_composed_name(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+
+    function load_schema_import(var AFactory : ISDODataFactory) : ISDODataObject;virtual;abstract;
+  published
+    procedure EmptySchema();
+
+    procedure SimpleType_Enum();
+    procedure SimpleType_Enum_Embedded();
+    procedure SimpleType_AliasToNativeType();
+
+    procedure ComplexType_Class();
+    procedure ComplexType_Class_default_values();
+    procedure ComplexType_Class_properties_extended_metadata();
+    procedure ComplexType_Class_properties_extended_metadata2();
+    procedure ComplexType_Class_Embedded();
+    procedure ComplexType_Class_Extend_Simple_Schema();
+    procedure ComplexType_Class_open_type_any();
+    procedure ComplexType_Class_open_extension_type_any();
+    procedure ComplexType_Class_open_extension_type_anyAttribute();
+    procedure ComplexType_Class_sequence_open_type_anyAttribute();
+    procedure ComplexType_Class_all_open_type_anyAttribute();
+    procedure ComplexType_Class_FalseArray();
+
+    procedure ComplexType_ArraySequence();
+    procedure ComplexType_ArraySequence_ItemName_Schema();
+    procedure ComplexType_ArraySequence_Embedded();
+    //procedure ComplexType_Array_soaparray();
+
+    procedure class_property_composed_name();
+
+    procedure schema_import();      
+  end;      
+
+  { TTest_XsdParser }
+
+  TTest_XsdParser = class(TTest_CustomXsdParser)
+  private
+    function ParseDoc(var AFactory : ISDODataFactory; const ADoc : string) : ISDODataObject;
+  protected
+    function LoadEmptySchema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+
+    function LoadSimpleType_Enum_Schema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadSimpleType_Enum_Embedded_Schema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadSimpleType_AliasToNativeType_Schema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+
+    function LoadComplexType_Class_Schema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_Class_default_values(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_Class_properties_extended_metadata(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_Class_properties_extended_metadata2(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_Class_Embedded_Schema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_Class_Extend_Simple_Schema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_Class_OpenType(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_Class_FalseArray(var AFactory : ISDODataFactory) : ISDODataObject;override;
+
+    function LoadComplexType_ArraySequence_Schema(var AFactory : ISDODataFactory) : ISDODataObject;override;
+    function LoadComplexType_ArraySequence_ItemName_Schema(var AFactory : ISDODataFactory) : ISDODataObject; override;
+    function LoadComplexType_ArraySequence_Embedded_Schema(var AFactory : ISDODataFactory) : ISDODataObject; override;
+    //function LoadComplexType_Array_soaparray() : ISDODataObject;override;
+
+    function load_class_property_composed_name(var AFactory : ISDODataFactory) : ISDODataObject;override;
+
+    function load_schema_import(var AFactory : ISDODataFactory) : ISDODataObject;override;  
+  end;
+
+implementation
+uses
+  xsd_consts, sdo_xsdintf, test_suite_utils, sdo_datafactory, locators, sdo_imp_utils;
+
+const
+  x_complexType_SampleArrayIntFieldType     = 'TArrayIntFieldType';
+  x_complexType_SampleArrayItemType         = 'TArrayItemType';
+  
+  x_complexType_SampleCollectionComplexType = 'TComplexType';
+  x_complexType_SampleCollectionCollectionComplexType = 'TCollectionComplexType';
+  x_complexType_SampleCollectionItemType    = 'TCollectionItemType';
+
+  x_complexType_SampleDerivedType           = 'TClassSampleDerivedType';
+  x_complexType_SampleClassType             = 'TClassSampleType';
+  x_complexType_SampleClassTypeA            = 'TClassSampleTypeA';
+  x_complexType_SampleClassTypeAll          = 'TClassSampleTypeAll';
+  x_complexType_SampleClass                 = 'TClassSample';
+
+  x_complexType_SampleRecordType             = 'TRecordSampleType';
+  x_complexType_SampleRecordTypeAll          = 'TRecordSampleTypeAll';
+  x_complexType_SampleRecord                 = 'TRecordSample';
+
+  x_complexType_array_sequence      = 'complex_array_sequence';
+  x_complexType_array_sequence_embedded  = 'complex_array_sequence_embedded';
+  x_complexType_array_sequence_collection      = 'complex_array_sequence_collection';
+  x_complexType_array_soaparray      = 'complex_array_soaparray';
+  
+  x_complexType_class               = 'complex_class';
+  x_complexType_class_default       = 'complex_class_default';
+  x_complexType_class_properties_extended_metadata = 'class_properties_extended_metadata';
+  x_complexType_extend_simple = 'complex_class_extend_simple';
+  x_complexType_class_embedded      = 'complex_class_embedded';
+
+  x_empty                 = 'empty';
+
+  x_enumSample            = 'EnumSample';
+  x_enumSampleType        = 'EnumSampleType';
+    x_enumSampleLIST_COUNT = 7;
+    x_enumSampleLIST      : array[0..( x_enumSampleLIST_COUNT - 1 )] of string = ( 'esOne', 'esTwo', 'esThree', 'begin', 'finally', 'True', 'False' );
+  x_simpleTypeAliasString = 'AliasString';
+  x_simpleTypeAliasInt    = 'AliasInt';
+  x_simpleTypeAliasWideString = 'AliasWideString';
+  x_simpleType            = 'simpletype';
+  x_simpleTypeEmbedded    = 'simpletype_embedded';
+  x_simpletypeNativeAlias = 'simpletypeNativeAlias';
+
+  x_targetNamespace       = 'urn:wst-test';
+
+
+  x_byteField  = 'byteField';
+  x_charField  = 'charField';
+  x_classField = 'classField';
+  x_enumField  = 'enumField';
+  x_field      = 'field';
+  x_floatField = 'floatField';
+  x_intField   = 'intField';
+  x_longField  = 'longField';
+  x_strField   = 'strField';
+
+  x_intAtt     = 'intAtt';
+  x_strAtt     = 'strAtt';
+
+  x_Item       = 'Item';
+
+
+function LoadXmlFile(const AFileName : string) : TXMLDocument;
+begin
+  Result := nil;
+  ReadXMLFile(Result,AFileName);
+end;
+
+{ TTest_CustomXsdParser }
+
+procedure TTest_CustomXsdParser.EmptySchema();
+var
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  mdl : ISDODataObject;
+begin
+  tr := LoadEmptySchema(fact);
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_empty,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(0,mdl.getList(s_Type).size());
+end;
+
+procedure TTest_CustomXsdParser.SimpleType_Enum();
+var
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  i : Integer;
+begin
+  tr := LoadSimpleType_Enum_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_simpleType,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(1,mdl.getList(s_Type).size());
+  elt := Find(tr,x_enumSampleType);
+    CheckNotNull(elt,x_enumSampleType);
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    CheckEquals(x_enumSampleType,elt.getString(s_Name));
+    Check(elt.getList(s_EnumValue).size() > 0,'Should have enums');
+    CheckEquals(x_enumSampleLIST_COUNT,elt.getList(s_EnumValue).size());
+    for i := 0 to Pred(x_enumSampleLIST_COUNT) do
+      CheckEquals(x_enumSampleLIST[i],elt.getList(s_EnumValue).getString(i));
+
+  elt := Find(tr,x_enumSample);
+    CheckNotNull(elt,x_enumSample);
+    CheckEquals(x_enumSample,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_VARIABLE,elt.getByte(s_ElementKind),s_ElementKind);
+    CheckNotNull(elt.getDataObject(s_DataType));
+    CheckEquals(x_enumSampleType, elt.getDataObject(s_DataType).getString(s_Name));
+end;
+
+procedure TTest_CustomXsdParser.SimpleType_Enum_Embedded();
+var   
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  i : Integer;
+begin
+  tr := LoadSimpleType_Enum_Embedded_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_simpleTypeEmbedded,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(1,mdl.getList(s_Type).size());
+  elt := Find(tr,x_enumSampleType);
+    CheckNotNull(elt,x_enumSampleType);
+    CheckEquals(x_enumSampleType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    Check(elt.getList(s_EnumValue).size() > 0,'Should have enums');
+    CheckEquals(x_enumSampleLIST_COUNT,elt.getList(s_EnumValue).size());
+    for i := 0 to Pred(x_enumSampleLIST_COUNT) do
+      CheckEquals(x_enumSampleLIST[i],elt.getList(s_EnumValue).getString(i));
+end;
+
+procedure TTest_CustomXsdParser.SimpleType_AliasToNativeType();
+var    
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+begin
+  tr := LoadSimpleType_AliasToNativeType_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_simpletypeNativeAlias,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(2,mdl.getList(s_Variable).size());
+  elt := Find(tr,x_simpleTypeAliasString);
+    CheckNotNull(elt,x_simpleTypeAliasString);
+    CheckEquals(x_simpleTypeAliasString,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_VARIABLE,elt.getByte(s_ElementKind),s_ElementKind);
+    CheckNotNull(elt.getDataObject(s_DataType));
+    CheckEquals('string',elt.getDataObject(s_DataType).getString(s_Name));
+
+  elt := Find(tr,x_simpleTypeAliasInt);
+    CheckNotNull(elt,x_simpleTypeAliasInt);
+    CheckEquals(x_simpleTypeAliasInt,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_VARIABLE,elt.getByte(s_ElementKind),s_ElementKind);
+    CheckNotNull(elt.getDataObject(s_DataType));
+    CheckEquals('int',elt.getDataObject(s_DataType).getString(s_Name));
+end;
+
+type
+  TPropertyType = ( ptField, ptAttribute );
+const
+  PropertyType_Att : array[TPropertyType] of Boolean = ( False, True );
+procedure TTest_CustomXsdParser.ComplexType_Class();
+var
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(const AName,ATypeName : string; const AFieldType : TPropertyType);
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+  end;
+
+var
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  prpLs : ISDODataObjectList;
+begin
+  tr := LoadComplexType_Class_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_complexType_class,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(3,mdl.getList(s_Type).size());
+  CheckEquals(1,mdl.getList(s_Variable).size());
+  elt := Find(tr,x_complexType_SampleClassType);
+    CheckNotNull(elt,x_complexType_SampleClassType);
+    CheckEquals(x_complexType_SampleClassType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(8,prpLs.size());
+      CheckProperty(x_intField,'int',ptField);
+      CheckProperty(x_strField,'string',ptField);
+      CheckProperty(x_floatField,'float',ptField);
+      CheckProperty(x_byteField,'byte',ptField);
+      CheckProperty(x_charField,'char',ptField);
+      CheckProperty(x_longField,'long',ptField);
+      CheckProperty(x_strAtt,'string',ptAttribute);
+      CheckProperty(x_intAtt,'int',ptAttribute);
+
+
+  elt := Find(tr,x_complexType_SampleClass);
+    CheckNotNull(elt,x_complexType_SampleClass);
+    CheckEquals(x_complexType_SampleClass,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_VARIABLE,elt.getByte(s_ElementKind),s_ElementKind);
+    CheckNotNull(elt.getDataObject(s_DataType));
+    CheckEquals(x_complexType_SampleClassType, elt.getDataObject(s_DataType).getString(s_Name));
+
+  elt := Find(tr,x_complexType_SampleClassTypeAll);
+    CheckNotNull(elt,x_complexType_SampleClassTypeAll);
+    CheckEquals(x_complexType_SampleClassTypeAll,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(8,prpLs.size());
+      CheckProperty(x_intField,'int',ptField);
+      CheckProperty(x_strField,'string',ptField);
+      CheckProperty(x_floatField,'float',ptField);
+      CheckProperty(x_byteField,'byte',ptField);
+      CheckProperty(x_charField,'char',ptField);
+      CheckProperty(x_longField,'long',ptField);
+      CheckProperty(x_strAtt,'string',ptAttribute);
+      CheckProperty(x_intAtt,'int',ptAttribute);
+
+  elt := Find(tr,x_complexType_SampleDerivedType);
+    CheckNotNull(elt,x_complexType_SampleDerivedType);
+    CheckEquals(x_complexType_SampleDerivedType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+    CheckNotNull(clsType.getDataObject(s_BaseType));
+    CheckEquals(x_complexType_SampleClassType,clsType.getDataObject(s_BaseType).getString(s_Name));
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(4,prpLs.size());
+      CheckProperty(x_intField + 'Ex','int',ptField);
+      CheckProperty(x_strField + 'Ex','string',ptField);
+      CheckProperty(x_strAtt + 'Ex','string',ptAttribute);
+      CheckProperty(x_intAtt + 'Ex','int',ptAttribute);
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_Embedded();
+var
+  tr : ISDODataObject;
+  nestedClassName, nestedEnumName : string;
+
+  procedure CheckProperty(
+    const AName,ATypeName : string;
+    const AFieldType : TPropertyType;
+    const AClsType : ISDODataObject
+  );
+  var
+    prp : ISDODataObject;
+  begin
+    prp := AClsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[AClsType.getString(s_Name),AName,s_IsAttribute]));
+  end;
+
+  procedure CheckEmbeddedClassType();
+  var
+    e : ISDODataObject;
+    prpLst : ISDODataObjectList;
+    nestedClsType : ISDODataObject;
+  begin
+    nestedClassName := Format('%s_%s_Type',[x_complexType_SampleClassType,x_classField]);
+    e := Find(tr,nestedClassName);
+      CheckNotNull(e,nestedClassName);
+      CheckEquals(nestedClassName,e.getString(s_Name));
+      CheckEquals(ELEMENT_KIND_TYPE,e.getByte(s_ElementKind),s_ElementKind);
+      nestedClsType := e;
+        prpLst := nestedClsType.getList(s_Property);
+      CheckEquals(4,prpLst.size(),nestedClassName + '  properties count.');
+        CheckProperty(x_intField + 'E','int',ptField,nestedClsType);
+        CheckProperty(x_strField + 'E','string',ptField,nestedClsType);
+        CheckProperty(x_strAtt + 'E','string',ptAttribute,nestedClsType);
+        CheckProperty(x_intAtt + 'E','int',ptAttribute,nestedClsType);
+  end;
+  
+  procedure CheckEmbeddedEnum();
+  var
+    e : ISDODataObject;
+    enumType : ISDODataObject;
+    k : Integer;
+  begin
+    nestedEnumName := Format('%s_%s_Type',[x_complexType_SampleClassType,x_enumField]);
+    e := Find(tr,nestedEnumName);
+      CheckNotNull(e,nestedEnumName);
+      CheckEquals(nestedEnumName,e.getString(s_Name));
+      CheckEquals(ELEMENT_KIND_TYPE,e.getByte(s_ElementKind),s_ElementKind);
+      enumType := e;
+      CheckEquals(x_enumSampleLIST_COUNT,enumType.getList(s_EnumValue).size());
+      for k := 0 to Pred(x_enumSampleLIST_COUNT) do
+        CheckEquals(x_enumSampleLIST[k],enumType.getList(s_EnumValue).getString(k));
+  end;
+
+var        
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  clsType : ISDODataObject;
+  elt : ISDODataObject;
+  prpLs : ISDODataObjectList;
+begin
+  tr := LoadComplexType_Class_Embedded_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_complexType_class_embedded,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(3,mdl.getList(s_Type).size()); 
+
+  CheckEmbeddedClassType();
+  CheckEmbeddedEnum();
+
+  elt := Find(tr,x_complexType_SampleClassType);
+    CheckNotNull(elt,x_complexType_SampleClassType);
+    CheckEquals(x_complexType_SampleClassType,elt.getString(s_Name));
+    //CheckIs(elt,TPasClassType);
+    clsType := elt;
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(9,prpLs.size());
+      CheckProperty(x_intField,'int',ptField,clsType);
+      CheckProperty(x_strField,'string',ptField,clsType);
+      CheckProperty(x_floatField,'float',ptField,clsType);
+      CheckProperty(x_byteField,'byte',ptField,clsType);
+      CheckProperty(x_longField,'long',ptField,clsType);
+      CheckProperty(x_strAtt,'string',ptAttribute,clsType);
+      CheckProperty(x_intAtt,'int',ptAttribute,clsType);
+      CheckProperty(x_classField,nestedClassName,ptField,clsType);
+      CheckProperty(x_enumField,nestedEnumName,ptField,clsType);
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_Extend_Simple_Schema();
+var
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(const AName,ATypeName : string; const AFieldType : TPropertyType);
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+  end;
+
+var
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  prpLs : ISDODataObjectList;
+begin
+  tr := LoadComplexType_Class_Extend_Simple_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_complexType_extend_simple,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(2,mdl.getList(s_Type).size());
+  elt := Find(tr,x_complexType_SampleClassType);
+    CheckNotNull(elt,x_complexType_SampleClassType);
+    CheckEquals(x_complexType_SampleClassType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      CheckNotNull(clsType.getDataObject(s_BaseType),'AncestorType is null');
+      Check(Find(tr,XSD_NAME_SPACE,'string') = clsType.getDataObject(s_BaseType));
+
+    prpLs := clsType.getList(s_Property);
+    CheckEquals(1,prpLs.size());
+      CheckProperty(x_intField,'int',ptAttribute);
+
+
+  elt := Find(tr,x_complexType_SampleClassTypeA);
+    CheckNotNull(elt,x_complexType_SampleClassTypeA);
+    CheckEquals(x_complexType_SampleClassTypeA,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      CheckNotNull(clsType.getDataObject(s_BaseType),'AncestorType is null');
+      Check(Find(tr,XSD_NAME_SPACE,'base64Binary') = clsType.getDataObject(s_BaseType));
+
+    prpLs := clsType.getList(s_Property);
+    CheckEquals(1,prpLs.size());
+      CheckProperty(x_floatField,'float',ptAttribute);
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_open_type_any();
+var     
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  strBuffer : string;
+  ls : TStringList;
+begin
+  tr := LoadComplexType_Class_OpenType(fact);
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  elt := Find(tr,'TClass_1');
+  CheckNotNull(elt,'TClass_1');
+  CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+  clsType := elt;
+  strBuffer := FindTag(clsType,Format('%s#%s',[s_xs,s_any]));
+  Check(Length(strBuffer) > 0, s_any);
+  ls := TStringList.Create();
+  try
+    ls.Delimiter := ';';
+    ls.DelimitedText := strBuffer;
+    CheckEquals('lax',ls.Values[s_processContents]);
+    CheckEquals('0',ls.Values[s_minOccurs]);
+    CheckEquals(s_unbounded,ls.Values[s_maxOccurs]);
+  finally
+    ls.Free();
+  end;
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_open_extension_type_any();
+var    
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  strBuffer : string;
+  ls : TStringList;
+begin
+  tr := LoadComplexType_Class_OpenType(fact);
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  elt := Find(tr,'TClassSampleDerivedType');
+  CheckNotNull(elt,'TClassSampleDerivedType');
+  CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+  clsType := elt;
+  strBuffer := FindTag(clsType,Format('%s#%s',[s_xs,s_any]));
+  Check(Length(strBuffer) > 0, s_any);
+  ls := TStringList.Create();
+  try
+    ls.Delimiter := ';';
+    ls.DelimitedText := strBuffer;
+    CheckEquals('skip',ls.Values[s_processContents]);
+    CheckEquals(s_unbounded,ls.Values[s_maxOccurs]);
+  finally
+    ls.Free();
+  end;
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_open_extension_type_anyAttribute();
+var        
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  strBuffer : string;
+  ls : TStringList;
+begin
+  tr := LoadComplexType_Class_OpenType(fact);
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  elt := Find(tr,'TClassSampleDerivedType');
+  CheckNotNull(elt,'TClassSampleDerivedType');
+  CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+  clsType := elt;
+  strBuffer := FindTag(clsType,Format('%s#%s',[s_xs,s_anyAttribute]));
+  Check(Length(strBuffer) > 0, s_anyAttribute);
+  ls := TStringList.Create();
+  try
+    ls.Delimiter := ';';
+    ls.DelimitedText := strBuffer;
+    CheckEquals('lax',ls.Values[s_processContents]);
+  finally
+    ls.Free();
+  end;
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_sequence_open_type_anyAttribute();
+var          
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  strBuffer : string;
+  ls : TStringList;
+begin
+  tr := LoadComplexType_Class_OpenType(fact);
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  elt := Find(tr,'TClass_1');
+  CheckNotNull(elt,'TClass_1');
+  CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+  clsType := elt;
+  strBuffer := FindTag(clsType,Format('%s#%s',[s_xs,s_anyAttribute]));
+  Check(Length(strBuffer) > 0, s_anyAttribute);
+  ls := TStringList.Create();
+  try
+    ls.Delimiter := ';';
+    ls.DelimitedText := strBuffer;
+    CheckEquals('strict',ls.Values[s_processContents]);
+  finally
+    ls.Free();
+  end;
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_all_open_type_anyAttribute();
+var      
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  strBuffer : string;
+  ls : TStringList;
+begin
+  tr := LoadComplexType_Class_OpenType(fact);
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  elt := Find(tr,'TClassSampleTypeAll');
+  CheckNotNull(elt,'TClassSampleTypeAll');
+  CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+  clsType := elt;                                      
+  strBuffer := FindTag(clsType,Format('%s#%s',[s_xs,s_anyAttribute]));
+  Check(Length(strBuffer) > 0, s_anyAttribute);
+  ls := TStringList.Create();
+  try
+    ls.Delimiter := ';';
+    ls.DelimitedText := strBuffer;
+    CheckEquals('skip',ls.Values[s_processContents]);
+  finally
+    ls.Free();
+  end;
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_FalseArray();
+var
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(const AName,ATypeName : string; const AFieldType : TPropertyType);
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+  end;
+
+var                    
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  prpLs : ISDODataObjectList;
+  prp : ISDODataObject;
+begin
+  tr := LoadComplexType_Class_FalseArray(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals('complex_class_false_array',mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(2,mdl.getList(s_Type).size());
+  elt := Find(tr,x_complexType_SampleClassType);
+    CheckNotNull(elt,x_complexType_SampleClassType);
+    CheckEquals(x_complexType_SampleClassType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(2,prpLs.size());
+      CheckProperty(x_intField,'int',ptField);
+      CheckProperty(x_strField,'string',ptField);
+
+  elt := Find(tr,x_complexType_SampleDerivedType);
+    CheckNotNull(elt,x_complexType_SampleDerivedType);
+    CheckEquals(x_complexType_SampleDerivedType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+    CheckNotNull(clsType.getDataObject(s_BaseType));
+    CheckEquals(x_complexType_SampleClassType,clsType.getDataObject(s_BaseType).getString(s_Name));
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(1,prpLs.size());
+      prp := prpLs.getDataObject(0);
+      Check(prp.getInteger(s_PropertyMaxOccurs) > 1);
+      CheckEquals(x_intField + 'Ex', prp.getString(s_Name));
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_ArraySequence();
+var
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(
+    const AName,
+          ATypeName  : string;
+    const AFieldType : TPropertyType;
+    const AIsMulti   : Boolean = False
+  );
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+      if AIsMulti then
+        Check(prp.getInteger(s_PropertyMaxOccurs) > 1)
+      else
+        CheckEquals(1, prp.getInteger(s_PropertyMaxOccurs))  ;
+  end;
+
+var
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  prpLs : ISDODataObjectList;
+  nestedClassName : string;
+begin
+  tr := LoadComplexType_ArraySequence_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_complexType_array_sequence,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(3,mdl.getList(s_Type).size());
+  elt := Find(tr,x_complexType_SampleArrayIntFieldType);
+    CheckNotNull(elt,x_complexType_SampleArrayIntFieldType);
+    CheckEquals(x_complexType_SampleArrayIntFieldType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+    CheckEquals(1,clsType.getList(s_Property).size());
+    CheckProperty(x_intField,'int',ptField,True);
+
+  nestedClassName := Format('%s_%s_Type',[x_complexType_SampleArrayItemType,x_Item]);
+  elt := Find(tr,nestedClassName);
+    CheckNotNull(elt,nestedClassName);
+    CheckEquals(nestedClassName,elt.getString(s_Name),'Item Name');
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(8,prpLs.size());
+      CheckProperty(x_intField,'int',ptField);
+      CheckProperty(x_strField,'string',ptField);
+      CheckProperty(x_floatField,'float',ptField);
+      CheckProperty(x_byteField,'byte',ptField);
+      CheckProperty(x_charField,'char',ptField);
+      CheckProperty(x_longField,'long',ptField);
+      CheckProperty(x_strAtt,'string',ptAttribute);
+      CheckProperty(x_intAtt,'int',ptAttribute);
+
+  elt := Find(tr,x_complexType_SampleArrayItemType);
+    CheckNotNull(elt,x_complexType_SampleArrayItemType);
+    CheckEquals(x_complexType_SampleArrayItemType,elt.getString(s_Name), 'Array name');
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+    CheckProperty(x_Item,nestedClassName,ptField,True);
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_ArraySequence_ItemName_Schema();
+var
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(
+    const AName,
+          ATypeName  : string;
+    const AFieldType : TPropertyType;
+    const AIsMulti   : Boolean = False
+  );
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+      if AIsMulti then
+        Check(prp.getInteger(s_PropertyMaxOccurs) > 1)
+      else
+        CheckEquals(1, prp.getInteger(s_PropertyMaxOccurs))  ;
+  end;
+
+var
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+begin
+  tr := LoadComplexType_ArraySequence_ItemName_Schema(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals('array_sequence_item_name',mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(2,mdl.getList(s_Type).size());
+  elt := Find(tr,'ArrayOfEmailAddress');
+    CheckNotNull(elt,'ArrayOfEmailAddress');
+    CheckEquals('ArrayOfEmailAddress',elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      CheckProperty('EmailAddress','EmailAddress',ptField,True);
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_ArraySequence_Embedded();
+var
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(
+    const AName,
+          ATypeName  : string;
+    const AFieldType : TPropertyType;
+    const AIsMulti   : Boolean = False
+  );
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+      if AIsMulti then
+        Check(prp.getInteger(s_PropertyMaxOccurs) > 1)
+      else
+        CheckEquals(1, prp.getInteger(s_PropertyMaxOccurs))  ;
+  end;
+
+var
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  nestedClassName : string;
+begin
+    tr := LoadComplexType_ArraySequence_Schema(fact);
+
+    mdl := FindModule(tr,x_targetNamespace);
+    CheckNotNull(mdl);
+    CheckEquals(x_complexType_array_sequence,mdl.getString(s_Name));
+    CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+    CheckEquals(3,mdl.getList(s_Type).size());
+    elt := Find(tr,x_complexType_SampleArrayIntFieldType);
+      CheckNotNull(elt,x_complexType_SampleArrayIntFieldType);
+      CheckEquals(x_complexType_SampleArrayIntFieldType,elt.getString(s_Name));
+      CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+      clsType := elt;
+      CheckProperty(x_intField,'int',ptField,True);
+
+    nestedClassName := Format('%s_%s_Type',[x_complexType_SampleArrayItemType,x_Item]);
+    elt := Find(tr,nestedClassName);
+      CheckNotNull(elt,nestedClassName);
+      CheckEquals(nestedClassName,elt.getString(s_Name),'Item Name');
+      CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+      clsType := elt;
+      CheckEquals(8,clsType.getList(s_Property).size());
+        CheckProperty(x_intField,'int',ptField);
+        CheckProperty(x_strField,'string',ptField);
+        CheckProperty(x_floatField,'float',ptField);
+        CheckProperty(x_byteField,'byte',ptField);
+        CheckProperty(x_charField,'char',ptField);
+        CheckProperty(x_longField,'long',ptField);
+        CheckProperty(x_strAtt,'string',ptAttribute);
+        CheckProperty(x_intAtt,'int',ptAttribute);
+
+    elt := Find(tr,x_complexType_SampleArrayItemType);
+      CheckNotNull(elt,x_complexType_SampleArrayItemType);
+      CheckEquals(x_complexType_SampleArrayItemType,elt.getString(s_Name), 'Array name');
+      CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+      clsType := elt;
+      CheckProperty(x_Item,nestedClassName,ptField,True);
+end;
+
+{procedure TTest_CustomXsdParser.ComplexType_Array_soaparray();
+var
+  tr : ISDODataObject;
+  mdl : TPasModule;
+  ls : TList;
+  elt : TPasElement;
+  arrayType : TPasArrayType;
+begin
+  tr := LoadComplexType_Array_soaparray();
+  try
+    mdl := FindModule(tr,x_targetNamespace);
+    CheckNotNull(mdl);
+    CheckEquals(x_complexType_array_soaparray,mdl.getString(s_Name));
+    CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+    ls := mdl.InterfaceSection.Declarations;
+    CheckEquals(1,ls.Count);
+    elt := tr.FindElement(x_complexType_SampleArrayIntFieldType);
+      CheckNotNull(elt,x_complexType_SampleArrayIntFieldType);
+      CheckEquals(x_complexType_SampleArrayIntFieldType,elt.Name);
+      CheckEquals(x_complexType_SampleArrayIntFieldType,tr.GetExternalName(elt));
+      CheckIs(elt,TPasArrayType);
+      arrayType := elt as TPasArrayType;
+      CheckNotNull(arrayType.ElType);
+      CheckEquals('int',tr.GetExternalName(arrayType.ElType));
+      CheckEquals('item',tr.GetArrayItemName(arrayType));
+      CheckEquals('item',tr.GetArrayItemExternalName(arrayType));
+
+    CheckNull(tr.FindElementNS('Array','http://schemas.xmlsoap.org/wsdl/'));
+  finally
+    tr.Free();
+  end;
+end;
+
+procedure TTest_CustomXsdParser.class_widestring_property();
+const s_class_name = 'TSampleClass';
+var
+  clsType : TPasClassType;
+  tr : ISDODataObject;
+
+  procedure CheckProperty(const AName,ATypeName,ADeclaredTypeName : string; const AFieldType : TPropertyType);
+  var
+    prp : TPasProperty;
+  begin
+    prp := FindMember(clsType,AName) as TPasProperty;
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.Name);
+      CheckEquals(AName,tr.GetExternalName(prp));
+      CheckNotNull(prp.VarType);
+      CheckEquals(ATypeName,prp.VarType.Name,'TypeName');
+      CheckEquals(ADeclaredTypeName,tr.GetExternalName(prp.VarType),'DeclaredTypeName');
+      CheckEquals(PropertyType_Att[AFieldType],tr.IsAttributeProperty(prp));
+  end;
+
+var
+  mdl : TPasModule;
+  elt : TPasElement;
+begin
+  tr := load_class_widestring_property();
+  try
+    mdl := tr.FindModule('class_widestring_property');
+    CheckNotNull(mdl,'class_widestring_property');
+    elt := tr.FindElement(s_class_name);
+      CheckNotNull(elt,s_class_name);
+      CheckEquals(s_class_name,elt.Name);
+      CheckEquals(s_class_name,tr.GetExternalName(elt));
+      CheckIs(elt,TPasClassType);
+      clsType := elt as TPasClassType;
+      CheckProperty('elementProp','WideString','string',ptField);
+      CheckProperty('elementAtt','WideString','string',ptAttribute);
+  finally
+    tr.Free();
+  end;
+end;}
+
+procedure TTest_CustomXsdParser.ComplexType_Class_default_values();
+var
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(
+    const AName,
+          ATypeName : string;
+    const AFieldType : TPropertyType;
+    const ADefault : string
+  );
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+      CheckEquals(ADefault,prp.getString(s_DefaultValue),Format('%s.%s, default',[clsType.getString(s_Name),AName]));
+  end;
+
+var
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  prpLs : ISDODataObjectList;
+begin
+  tr := LoadComplexType_Class_default_values(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_complexType_class_default,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(1,mdl.getList(s_Type).size());
+  elt := Find(tr,x_complexType_SampleClassType);
+    CheckNotNull(elt,x_complexType_SampleClassType);
+    CheckEquals(x_complexType_SampleClassType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(8,prpLs.size());
+      CheckProperty(x_intField,'int',ptField,'1210');
+      CheckProperty(x_strField,'string',ptField,'azerty');
+      CheckProperty(x_floatField,'float',ptField,'1234');
+      CheckProperty(x_byteField,'byte',ptField,'23');
+      CheckProperty(x_charField,'char',ptField,'i');
+      CheckProperty(x_longField,'long',ptField,'567');
+      CheckProperty(x_strAtt,'string',ptAttribute,'attribute azerty');
+      CheckProperty(x_intAtt,'int',ptAttribute,'789');
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_properties_extended_metadata();
+var
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+
+  procedure CheckProperty(
+    const AName,
+          ATypeName : string;
+    const AFieldType : TPropertyType;
+    const ADefault : string;
+    const AExtMetaDataNameSpace,
+          AExtMetaDataLocalName,
+          AExtMetaDataValue : string
+  );
+  var
+    prp : ISDODataObject;
+    locExtMeta : string;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+      CheckEquals(ADefault,prp.getString(s_DefaultValue),Format('%s.%s, default',[clsType.getString(s_Name),AName]));
+      locExtMeta := Format('%s#%s',[AExtMetaDataNameSpace,AExtMetaDataLocalName]);
+      if not IsStrEmpty(locExtMeta) then
+        CheckEquals(AExtMetaDataValue, FindTag(prp,locExtMeta), 'extended metadata');
+  end;
+
+var
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  prpLs : ISDODataObjectList;
+begin
+  tr := LoadComplexType_Class_properties_extended_metadata(fact);
+
+  mdl := FindModule(tr,x_targetNamespace);
+  CheckNotNull(mdl);
+  CheckEquals(x_complexType_class_properties_extended_metadata,mdl.getString(s_Name));
+  CheckEquals(x_targetNamespace,mdl.getString(s_NameSpace));
+  CheckEquals(1,mdl.getList(s_Type).size());
+  elt := Find(tr,x_complexType_SampleClassType);
+    CheckNotNull(elt,x_complexType_SampleClassType);
+    CheckEquals(x_complexType_SampleClassType,elt.getString(s_Name));
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      prpLs := clsType.getList(s_Property);
+    CheckEquals(5,prpLs.size());
+      CheckProperty(x_intField,'int',ptField,'', 'uri-4','a','1210');
+        CheckProperty(x_intField,'int',ptField,'', 'uri-4','b','uri-5#xx');
+      CheckProperty(x_strField,'string',ptField,'azerty', 'uri-4','a', 'http://www.w3.org/2001/XMLSchema#int');
+      CheckProperty(x_strAtt,'string',ptAttribute,'attribute azerty', 'uri-4','a', 'optional');
+      CheckProperty(x_intAtt,'int',ptAttribute,'', '', '', '');
+end;
+
+procedure TTest_CustomXsdParser.ComplexType_Class_properties_extended_metadata2();
+const s_ProjectType = 'ProjectType';
+var         
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  clsType : ISDODataObject;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+  p : ISDODataObject;
+begin
+  tr := LoadComplexType_Class_properties_extended_metadata2(fact);
+  mdl := FindModule(tr,'uri:sample');
+  CheckNotNull(mdl);
+  elt := Find(tr,s_ProjectType);
+    CheckNotNull(elt,s_ProjectType);
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+      p := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr('ProjectLeader')]));
+      CheckNotNull(p,'Property non found : "ProjectLeader"');
+      CheckEquals('uri:sample#Person', FindTag(p,'commonj.sdo#propertyType'), 'extended metadata');
+
+      p := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr('ProjectLeaderArray')]));
+      CheckNotNull(p,'Property non found : "ProjectLeaderArray"');
+      CheckEquals('uri:sample#Person', FindTag(p,'commonj.sdo#propertyType'), 'extended metadata');
+end;
+
+procedure TTest_CustomXsdParser.class_property_composed_name();
+const s_class_name = 'TSampleClass';
+var
+  clsType : ISDODataObject;
+  tr : ISDODataObject;
+
+  procedure CheckProperty(
+    const AName,
+          ATypeName      : string;
+    const AFieldType     : TPropertyType
+  );
+  var
+    prp : ISDODataObject;
+  begin
+    prp := clsType.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr(AName)]));
+      CheckNotNull(prp);
+      CheckEquals(AName,prp.getString(s_Name));
+      CheckNotNull(prp.getDataObject(s_DataType));
+      CheckEquals(ATypeName,prp.getDataObject(s_DataType).getString(s_Name));
+      CheckEquals(PropertyType_Att[AFieldType],prp.getBoolean(s_IsAttribute),Format('%s.%s, %s',[clsType.getString(s_Name),AName,s_IsAttribute]));
+  end;
+
+var
+  fact :ISDODataFactory;
+  mdl : ISDODataObject;
+  elt : ISDODataObject;
+begin
+  tr := load_class_property_composed_name(fact);
+  mdl := FindModule(tr,'urn_sample');
+  CheckNotNull(mdl,'urn_sample');
+  elt := Find(tr,s_class_name);
+    CheckNotNull(elt,s_class_name);
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    clsType := elt;
+    CheckProperty('one-prop','string',ptField);
+    CheckProperty('one-two-prop','string',ptAttribute);
+end;
+
+procedure TTest_CustomXsdParser.schema_import();
+const
+  s_base_namespace = 'urn:base-library';
+  s_base_type = 'SampleBase_Type';
+  s_second_namespace = 'urn:second-library';
+  s_second_type = 'Second_Type';
+var     
+  fact :ISDODataFactory;
+  tr : ISDODataObject;
+  mdl : ISDODataObject;
+  elt, prpElt : ISDODataObject;
+  baseType, scdClass : ISDODataObject;
+begin
+  tr := load_schema_import(fact);
+
+  mdl := FindModule(tr,s_base_namespace);
+  CheckNotNull(mdl,s_base_namespace);
+  CheckEquals(1,mdl.getList(s_Type).size());
+  elt := Find(tr,s_base_namespace,s_base_type);
+    CheckNotNull(elt,s_base_type);
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    baseType := elt;
+
+  mdl := FindModule(tr,s_second_namespace);
+  CheckNotNull(mdl,s_second_namespace);
+  CheckEquals(1,mdl.getList(s_Type).size());
+  elt := Find(tr,s_second_namespace,s_second_type);
+    CheckNotNull(elt,s_second_type);
+    CheckEquals(ELEMENT_KIND_TYPE,elt.getByte(s_ElementKind),s_ElementKind);
+    scdClass := elt;
+    prpElt := scdClass.getDataObject(Format('%s[%s = %s]',[s_Property,s_Name,QuotedStr('SampleProperty')]));
+    CheckNotNull(prpElt);
+    Check(baseType = prpElt.getDataObject(s_DataType));
+end;
+
+
+
+{ TTest_XsdParser }
+
+function TTest_XsdParser.ParseDoc(var AFactory : ISDODataFactory; const ADoc: string): ISDODataObject;
+var
+  locDoc : TXMLDocument;
+  prs : IXsdPaser;
+  prsCtx : IParserContext;
+  fileName : string;
+begin
+  if (AFactory = nil) then begin
+    AFactory := TSDODataFactory.Create();
+    AddTypeTree(AFactory);
+  end;
+  fileName := sdoExpandLocalFileName(XsdTestFilesPath + ADoc + '.xsd');
+  locDoc := LoadXmlFile(fileName);
+  try
+    Result := AFactory.CreateNew(s_XsdParserNS,s_TypeTreeType);
+    prs := TXsdParser.Create(locDoc,Result,ADoc);
+    prsCtx := prs as IParserContext;
+    prsCtx.SetDocumentLocator(TFileDocumentLocator.Create(ExtractFilePath(fileName)));
+    prs.ParseTypes();
+  finally
+    ReleaseDomNode(locDoc);
+  end;
+end;
+
+function TTest_XsdParser.LoadEmptySchema(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_empty);
+end;
+
+function TTest_XsdParser.LoadSimpleType_Enum_Schema(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_simpleType);
+end;
+
+function TTest_XsdParser.LoadSimpleType_Enum_Embedded_Schema(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_simpleTypeEmbedded);
+end;
+
+function TTest_XsdParser.LoadSimpleType_AliasToNativeType_Schema(var AFactory : ISDODataFactory) : ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_simpletypeNativeAlias);
+end;
+
+function TTest_XsdParser.LoadComplexType_Class_Schema(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_complexType_class);
+end;
+
+function TTest_XsdParser.LoadComplexType_Class_Embedded_Schema(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_complexType_class_embedded);
+end;
+
+function TTest_XsdParser.LoadComplexType_Class_Extend_Simple_Schema(var AFactory : ISDODataFactory) : ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_complexType_extend_simple);
+end;
+
+function TTest_XsdParser.LoadComplexType_Class_OpenType(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, 'complex_class_open_type');
+end;
+
+function TTest_XsdParser.LoadComplexType_ArraySequence_Schema(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_complexType_array_sequence);
+end;
+
+function TTest_XsdParser.LoadComplexType_ArraySequence_Embedded_Schema(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_complexType_array_sequence_embedded);
+end;
+
+{function TTest_XsdParser.LoadComplexType_Array_soaparray() : ISDODataObject;
+begin
+  Result := ParseDoc(x_complexType_array_soaparray);
+end; }
+
+function TTest_XsdParser.LoadComplexType_Class_default_values(var AFactory : ISDODataFactory) : ISDODataObject;
+begin
+  Result := ParseDoc(AFactory,x_complexType_class_default);
+end;
+
+function TTest_XsdParser.LoadComplexType_Class_properties_extended_metadata(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_complexType_class_properties_extended_metadata);
+end;
+
+function TTest_XsdParser.LoadComplexType_Class_properties_extended_metadata2(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, x_complexType_class_properties_extended_metadata + '_2');
+end;
+
+function TTest_XsdParser.load_class_property_composed_name(var AFactory : ISDODataFactory) : ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, 'class_property_composed_name');  
+end;
+
+function TTest_XsdParser.load_schema_import(var AFactory : ISDODataFactory): ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, 'import_second_library');
+end;
+
+function TTest_XsdParser.LoadComplexType_ArraySequence_ItemName_Schema(var AFactory : ISDODataFactory) : ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, 'array_sequence_item_name');
+end;
+
+function TTest_XsdParser.LoadComplexType_Class_FalseArray(var AFactory : ISDODataFactory) : ISDODataObject;
+begin
+  Result := ParseDoc(AFactory, 'complex_class_false_array');
+end;
+
+
+initialization
+  RegisterTest('XSD parser',TTest_XsdParser.Suite);
+
+end.