[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]
Subject: [sdo] [SDO-56]: Need to improve anyType support so as not to use awrapping Data Object for simple types
(We'd like to optionally map xsd:anyType to java.lang.Object instead of commonj.sdo.DataObject): Currently xsd:anyType is mapped to the abstract type commonj.sdo.DataObject. When passing data in a anyType element, the java object you'd recieve back is commonj.sdo.DataObject whether the passed data is simple or complex type. We'd like the ability to specify the following behavior for xsd:anyType (preferably using annotations): * When the data passed to the xsdType element is simple content (String, Integer, ...), the we'd like the serialization to follow the mapping rules for the simple content and get back: java.langString, java.lang.Integer, ... * When the data passed to the xsdType element is complex content, the we'd like the serialization to follow the mapping rules for that complete type and get back an SDO object representing the content. * The java type for a xsd:anyType should be java.lang.Object. MySampleSDO sampleSDO = ... Object value = sampleSDO.getMyAnyTypeProperty(); value = java.lang.String if what's sent in myAnyTypeProperty has xsi:type="xsd:string". value = MyDataObject if what's sent in myAnyTypeProperty has xsi:type="MyDataObject". We'd like this to be resolved in 2.1 release. Frank Budinsky [31/May/06 04:54 PM] I have a few questions. Given an anyType property like this: Property myAnyTypeProperty = ... Are you proposing a new special Type for it? For example, what would the following return? 1) myAnyTypeProperty.getType().getName() 2) myAnyTypeProperty.getType().getURI() 3) myAnyTypeProperty.getType().isDataType() 4) myAnyTypeProperty.isContainment() It seems to me that this property will be very special, and will need special handling all over the place. For example, won't things like CopyHelper, etc. need to have special case (instanceof check) for this kind of property? Steve Brodsky [01/Jun/06 06:26 AM] The following should be all that is needed to support this issue: 1) <element type="xsd:any" sdo:dataType="sdo:Object"> maps to Property type=sdo:Object containment=true 2) add a special case to the Property constraint "Property.containment has no effect unless type.dataType=false" that containment is also enforced when property.type==sdo:Object 3) corner case #4 is now handled and can be removed Steve Brodsky [09/Aug/06 09:01 PM] Resolve as Steve's comment above. Ron Barack [10/Aug/06 04:51 PM] In this approach, can we distinguish between simple types that have the same java instance class. For instance, between a element that had "xsi:type="xs:QName" and one that had "xsi:type="xs:string"? In the 2.01 spec, this case was handle by inserting a wrapper DataObject that served as the value of the property itself, and had a single property to contain the simple value. As awkward as this approach is, it at least provided a place where the concrete simple type. Omar Halaseh [10/Aug/06 07:30 PM] We should add a comment in the spec that when adding the sdo:dataType="sdo:Object" annotation to map xsd:any to java.lang.Object, one will not be able to determine the type of the simple type using instanceof in the case where more than one simple type map to the same java type. Examples: These XSD types all map to java.lang.String: dateTime, duration, gDay, gMonth, gMonthDay, gYear, gYearMonth, ID, IDREF, QName, ... Frank Budinsky [13/Oct/06 04:03 PM] Spec update complete - see column Q of latest version of SDO2.1_JIRA_spec_impacts_2006mmdd.xls for details. Frank Budinsky [09/May/07 07:32 PM] This decision was overturned - see (The new containment=true for xsd:anyType with dataType="sdo:Object" feature may break existing code). (The new containment=true for xsd:anyType with dataType="sdo:Object" feature may break existing code): There is lots of code that navigates data graphs by checking for containment properties. For example: Property property = dataObject.getType().getProperty("propertyName"); if (property.isContainment()) { DataObject child = dataObject.getDataObject("propertyName"); ... } The above code may fail on xsd:anyType if we map it to a property with containment=true, because the value of a "containment" property may not be a DataObject. This new feature is optional (you don't "need" to use it), but nevertheless, using it as currently defined will cause exisitng code to break. Ron Barack [25/Oct/06 08:21 PM] Does the spec actually say that properties with datatypes as types are not containment? Was one guarenteed that the above code would work under 2.01? I would say that, if anything, datatypes should always be contained as they certainly are not referenced. Frank Budinsky [25/Oct/06 09:56 PM] The spec says this: Property.isContainment() returns true if the Property is a containment reference and the printDataObject() example in the spec does this: if (value != null && property.isContainment()) { // For containment properties, display the value with printDataObject Type type = property.getType(); String typeName = type.getName(); System.out.println( margin + propertyName + " (" +typeName+ "):"); printDataObject((DataObject) value, indent + 1); } So yes, I'd say the 2.0.1 spec guaranteed it to work. Even if this wasn't a guaranteed breaking change, I would say that we've introduced a major usability issue with this feature. Navigating data graphs is a very common operation. Where we used to be able to simply navigate through containment properties, we'd now need to first get the value and then check if it is an insanceof DataObject before navigating down the graph. I don't see a solution to this issue. I think we may need to reject this change. Maybe we can come up with another way to handle the initial requirement of being able to get and set a simple value of an anyType property. Maybe we could do this by adding automatic DataObject wrappering to the conversions that are supported, e.g., someObject.setBoolean(anyTypeProperty, true); Ron Barack [27/Oct/06 10:15 AM] I'm wondering if the code snippet in the problem description is really broken under 2.1. If the value is not a data object, getDataObject() must return null, right. Isn't it true that all get<T>()'s avoid throwing exceptions so that clients can "avoid defensive programming"? In this case, the code must simply check if the value is null (which it must do anyway, so this is no extra burden on the programmer). So the question is, what is really the problem here? Ron Barack [27/Oct/06 10:40 AM] But of course the code on page 126, which Frank references above, is still broken, as the value is retrieved with get() and then simply casted to DO. And getDataObject(int) and getDataObject(Property) still throw exceptions, so although the example is working, we would get a problem if the code iterated using the indices. Or did we decide something different the other we, as we discussed SDO-136? Could please enter the resolution into the JIRA? Frank Budinsky [27/Oct/06 04:22 PM] Ron, you really should be a lawyer I entered in (Various clarifications/ rewordings for the spec.) the resolution that we agreed to last week for the get<T>(String) issue. My notes from the meeting said that we agreed that get<T>(String) should throw ClassCastException if the conversion can't be done, but otherwise it doesn't throw exceptions. That's how I wrote it up. Let me know if you think I misunderstood. With that resolution, I'd say my example at the top of this issue would fail (throw ClassCastException). Regardless of that particular example, as you point out, there are many other examples that will fail. Frank Budinsky [27/Oct/06 10:54 PM] Here is a concrete proposal. We add Object <--> DataObject as another supported conversion. DataHelper.convert() can now be used to allow you set an anyType property with a value that may be either simple or a DataObject: Object someValue = ... // may be a DataObject or may be a simple value, e.g., Integer. myDO.set(myAnyTypeProperty, dataHelper.convert(myAnyTypeProperty, someValue)); The dataHelper.convert() call will wrap someValue in a DataObject if it is not already an instanceof DataObject. Otherwise, it just returns someValue. To read back the value without the wrapper, you just do the opposite: Object retrievedValue = dataHelper.convert(objectType, myDO.get(myAnyTypeProperty)); // retrievedValue will be either a DataObject or the unwrapped simple type I don't think we need to mandate exactly how simple types get wrapped, we can leave that up to the implementation. I think we should say: When converting from Object to DataObject: 1. if the Object is an instanceof DataObject, return the same Object. 2. otherwise, wrap the Object in in a DataObject either using a value property or as sequence text. When converting from DataObject to Object: 1. if the DataObject contains only a dataType property named "value", return it. 2. otherwise, if the DataObject contains a single text sequence entry, return it as a String value 3. otherwise, return the DataObject itself. Given that all DataTypes extend from Object, I think that this also means that users will be able to call any getXXX/setXXX method and get the wrappering there as well: myDO.setFloat(myAnyTypeProperty, 0.99); float result = myDO.getFloat(myAnyTypeProperty); // result will be 0.99 Omar Halaseh [28/Oct/06 01:38 AM] Then would this still work with (We'd like to optionally map xsd:anyType to java.lang.Object instead of commonj.sdo.DataObject) sdo:dataType="sdo:Object" annotation? I want to use the annotation above so the Object<-->DataObject conversion occurs implicitly. This way, I get the option of getting back java.lang.Object which could be a simple type in anyType or a DataObject in the case of a complexType in anyType. But now anyonw who wants to cast the anyProperty value must be careful to check the annotation value before casting. Can you please confirm? Frank Budinsky [30/Oct/06 08:08 PM] Then would this still work with (We'd like to optionally map xsd:anyType to java.lang.Object instead of commonj.sdo.DataObject) sdo:dataType="sdo:Object" annotation? No. Using the sdo:dataType="sdo:Object" annotation will work the same as in SDO 2.0.1. It will map it to a dataType=true property with instance class java.lang.Object. You can get/set the value with either a simple value or a DataObject, but when you serialize it, if it is a DataObject value, it will not be nested (contained). It will instead serialize it as anyURI reference to the DataObject, which must be contained somewhere else. If you want it to be contained, then you have no choice but to use the default mapping of anyType to DataObject. You need to wrapper simple values in a DataObject, but the conversion methods I'm proposing above, let the user avoid dealing with the wrapper. It would be quite reasonable for a code generator to provide an option to generate Object versions of the static get/set methods, which also automatically do the conversion. For example: Object getMyAnyTypeProperty() { return dataHelper.convert(objectType, myAnyTypeProperty); } instead of the normal (return DataObject) pattern: DataObject getMyAnyTypeProperty() { return myAnyTypeProperty; } Clients calling this static API wouldn't need to know about the DataObject warpper. Note that the only thing that must not change is that the value passed into and returned form DataObject.set() and DataObject.get() methods (i.e., the primitive non-converting methods) must be a DataObject for a proper anyType property. If this isn't the case, we will break the SDO containment model. Blaise Doughan [01/Nov/06 09:55 PM] I would say that, if anything, datatypes should always be contained as they certainly are not referenced. For the above are datatypes contained or referenced? My original assumption is that they were contained but from Frank's posts I believe they might be referenced (not contained). Frank Budinsky [01/Nov/06 10:41 PM] Blaise, You are right, dataTypes are contained. Sorry if my comment was a little confusing. What I was referring to is the special case of an sdo:Object type property having a DataObject value. The point I was making is reflected in the definition of type Object in sdoModel.xsd: <xsd:simpleType name="Object" sdoJava:instanceClass="java.lang.Object"> <!-- Only the schema for schemas is allowed to restrict anySimpleType. <xsd:restriction base="xsd:anySimpleType"/> The equivalent declaration is a union of the predefined XSD data types. --> <xsd:union memberTypes="xsd:anyURI xsd:base64Binary xsd:boolean xsd:byte xsd:date xsd:dateTime xsd:decimal xsd:double xsd:duration xsd:ENTITIES xsd:ENTITY xsd:float xsd:gDay xsd:gMonth xsd:gMonthDay xsd:gYear xsd:gYearMonth xsd:hexBinary xsd:ID xsd:IDREF xsd:IDREFS xsd:int xsd:integer xsd:language xsd:long xsd:Name xsd:NCName xsd:negativeInteger xsd:NMTOKEN xsd:NMTOKENS xsd:nonNegativeInteger xsd:nonPositiveInteger xsd:normalizedString xsd:NOTATION xsd:positiveInteger xsd:QName xsd:short xsd:string xsd:time xsd:token xsd:unsignedByte xsd:unsignedInt xsd:unsignedLong xsd:unsignedShort"/> </xsd:simpleType> Notice that the union includes anyURI and IDREF. In the case that the value is a DataObject it needs to serialize a reference to the DataObject. For example: <someObject> <someAnyTypeProperty>...someURI_or_IDREF...</someAnyTypeProperty> ... </someObject> For normal dataType values, you'd always get the contained value, for example: <someObject> <someAnyTypeProperty>99.9</someAnyTypeProperty> </someObject> I hope this clarifies what I was trying to say. Ron Barack [01/Nov/06 11:23 PM] Frank, could you clarify your clarification: if I have a property p, and p.getType().isDataType() is true, then p.getContainment() must be false, correct? Because otherwise, the code examples you gave above will not work. So DataTypes are not contained, right? Frank Budinsky [02/Nov/06 12:01 AM] My goodness ... I'm really doing a very bad job of clarifying here Yes, you are right Ron. I thought that Blaise was asking about XML element containment vs SDO property containment. Two different things. In SDO, the concept of containment only applies to DataObjects, it has no meaning with dataTypes. But in XML, a dataType will still be serialized as a contained element (unless it's serialized as an attribute, of course). I thought that was what Blaise was talking about when I answered his question. I hope this helps. Blaise Doughan [02/Nov/06 05:17 PM] Yes, you are right Ron. I thought that Blaise was asking about XML element containment vs SDO property containment. Two different things. In SDO, the concept of containment only applies to DataObjects, it has no meaning with dataTypes. But in XML, a dataType will still be serialized as a contained element (unless it's serialized as an attribute, of course). I thought that was what Blaise was talking about when I answered his question. Is this really what users will expect? I find that SDO follows the XML model with very few exceptions. My understanding was that the significance of isContainment was to determine if the content was inlined or available through a reference (not a short cut to determine if the child was a DataObject). If isContainment works the same for DOs and data types then we could come up with a decent solution for anyType, if containment is only for DOs then the anyType solutions become awkward. Frank Budinsky [08/Nov/06 06:27 PM] I'm planning to make the following update to the document: 1. Reverse the changes that were made for (We'd like to optionally map xsd:anyType to java.lang.Object instead of commonj.sdo.DataObject). 2. Clarify that isContainment() always returns false for data type properties. 3. Add DataObject <--> Object as another supported conversion. Please let me know if I've missed anything. I'm sorry to be so inflexible on this one, but IBM can absolutely not live with the earlier resolution to (We'd like to optionally map xsd:anyType to java.lang.Object instead of commonj.sdo.DataObject). P.S. Another insight on SDO Property.containment: Property.containment really was never intended to have anything to do DataTypes. It's not about XML containment, but rather, DataObject containment. DataObject containment has special semantic meaning ... when a DataObject is added to a containment property, it will be removed from any other container that it may be in. This never happens with DataTypes. DataObject also has the methods getContainer() and getContainmentProperty(), which is navigating up containment properties. Again, this doesn't apply to DataTypes. Omar Halaseh [09/Nov/06 08:52 PM] Oracle position on this issue is to keep it they way it is documented in the latest spec Java-SDO-Spec-v2.1.0-FINAL_20061108.doc: ==When an element of anyType is used with xsi:type specifying simple content, a wrapper DataObject must be ==used with a property named "value" and type of SDO >>Object that is set to the wrapped type. For example, ==<element name="e" type="anyType"> and a document <e xsi:type="xsd:int">5</e> results in a wrapper ==DataObject where the value property is set to the Integer with value 5. We do not wish to expose convenience conversion methods between DataObject and simple types at this time. In 3.0 we need to revisit this issue and propose a cleaner solution. I will submit a 3.0 JIRA to track this. Notice: This email message, together with any attachments, may contain information of BEA Systems, Inc., its subsidiaries and affiliated entities, that may be confidential, proprietary, copyrighted and/or legally privileged, and is intended solely for the use of the individual or entity named in this message. If you are not the intended recipient, and have received this message in error, please immediately return this by email and then delete it.
[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]