La balise anyType est traitée de la même manière que les autres types complexes par les API SDO.
Les seules différences entre anyType et les autres types complexes sont dans leurs données d'instance et la sérialisation/désérialisation, qui doivent être des concepts internes pour l'objet métier uniquement, et déterminant si les données mappées vers ou depuis le champ sont valides. Les types complexes sont limités à un type unique : Client, Adresse, etc. La balise anyType, cependant, permet n'importe quel objet de données quel que soit le type. Si maxOccurs > 1, chaque objet de données de la liste peut être d'un type différent.
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://AnyType"> <xsd:complexType name="AnyType"> <xsd:sequence> <xsd:element name="person" type="xsd:anyType"/> </xsd:sequence> </xsd:complexType> </xsd:schema> <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://Customer"> <xsd:complexType name="Customer"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema> <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://Employee" targetNamespace="http://Employee"> <xsd:complexType name="Employee"> <xsd:sequence> <xsd:element name="id" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema> DataObject anyType = ... DataObject customer = ... DataObject employee = ... // Définir la personne sur Customer anyType.set("person", customer); // Les données d'instance seront un client // Affiche "Customer" System.out.println(anyType.getDataObject("person").getName()); // Définir la personne sur Employee anyType.set("person", employee); // Les données d'instance seront un employé // Affiche "Employee" System.out.println(anyType.getDataObject("person").getName());
Comme anySimpleType, anyType utilise l'élément xsi:type lors de la sérialisation afin d'assurer que le type d'objet de données voulu est conservé lorsqu'il est désérialisé. Ainsi, si vous le définissez sur "Customer", le XML se présente comme suit :
<?xml version="1.0" encoding="UTF-8"?> <p:AnyType xsi:type="p:AnyType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:customer="http://Customer" xmlns:p="http://AnyType"> <person xsi:type="customer:Customer"> <name>foo</name> </person> </p:AnyType>
Et, si vous le définissez sur "Employee" :
<?xml version="1.0" encoding="UTF-8"?> <p:AnyType xsi:type="p:AnyType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:employee="http://Employee" xmlns:p="http://AnyType"> <person xsi:type="employee:Employee"> <id>foo</id> </person> </p:AnyType>
La balise AnyType permet également de définir des valeurs de type simple par le biais d'objets de données encapsuleurs. Ces objets de données encapsuleurs possèdent une propriété unique appelée "value" (élément) qui contient la valeur de type simple. Les API SDO ont été écrasées pour encapsuler et désencapsuler automatiquement ces objets de données de types simples et encapsuleurs lorsque les API de <Type>get/set<> sont utilisées. Les API get/set de transtypage non-type n'effectueront pas cet encapsulage.
DataObject anyType = ... // Appeler une API de <Type> set sur une propriété anyType entraîne la création automatique // d'un objet de données encapsuleur anyType.setString("person", "foo"); // Les API get/set classiques ne sont pas écrasées, et renverront donc // l'objet de données encapsuleur DataObject wrapped = anyType.get("person"); // L'objet de données encapsulé aura la propriété "value" // Affiche "foo" System.out.println(wrapped.getString("value")); // L'API de <Type> get désencapsulera automatiquement l'objet de données // Affiche "foo" System.out.println(anyType.getString("person"));
Lorsque l'objet de données encapsuleur est sérialisé, il est sérialisé de la même manière qu'un mappage anySimpleType de classes d'instance Java™ en types XSD dans le champ xsi:type. Ce paramètre doit donc être sérialisé de la manière suivante :
<?xml version="1.0" encoding="UTF-8"?> <p:AnyType xsi:type="p:AnyType" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:p="http://AnyType"> <person xsi:type="xsd:string">foo</person> </p:AnyType>
Si aucun élément xsi:type n'est donné ou si un élément xsi:type incorrect est donné, une exception est émise. En plus de l'encapsulage automatique, l'encapsuleur peut être créé manuellement pour être utilisé avec l'API set() via BOFactory createDataTypeWrapper(Type, Object), où Type est le type simple de SDO des données à encapsuler et Object représente les données à encapsuler.
Type stringType = boType.getType("http://www.w3.org/2001/XMLSchema", "string"); DataObject stringType = boFactory.createByMessage(stringType, "foo");
Pour déterminer si un objet de données est du type encapsuleur, l'élément BOType isDataTypeWrapper(Type) peut être appelé.
DataObject stringType = ... boolean isWrapper = boType.isDataTypeWrapper(stringType.getType());
Pour les autres types complexes, pour pouvoir déplacer les données d'un champ à l'autre, les données doivent être du même type. La balise AnyType peut contenir n'importe quel type complexe, mais un déplacement direct sans mappage peut être basé sur les données d'instance dans le champ ou non.
Vous pouvez utiliser l'URI et le Nom du type de propriété pour déterminer si une propriété est du type anyType. Il s'agira de "commonj.sdo" et "DataObject". Toutes les données sont valides pour être insérées dans une balise anyType. Les règles de mappage sont donc les suivantes :