Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Preventing use of Java primitive types in XSD-derived Ecore
Preventing use of Java primitive types in XSD-derived Ecore [message #511030] Fri, 29 January 2010 15:31 Go to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Hi,

I'm generating Ecore from XSD and would like to prevent the use of Java primitive types. Specifically, I would like xsd:int, xsd:boolean and xsd:double to map to Java's Integer, Boolean and Double classes, respectively, instead of the int, boolean and double primitive types.

Can someone point me in the right direction? Is doing this considered a bad idea for any reason?

Thanks,
Ben.
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #511037 is a reply to message #511030] Fri, 29 January 2010 10:52 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33141
Registered: July 2009
Senior Member
Ben,

Box types take more space so it seems not generally desirable. If you
make elements nillable, box types will be used. I suppose you could use
an ecore:type annotation to force EIntegerObject, EBooleanObject,
EDoubleObject to be used.

Ben Tenne wrote:
> Hi,
>
> I'm generating Ecore from XSD and would like to prevent the use of
> Java primitive types. Specifically, I would like xsd:int, xsd:boolean
> and xsd:double to map to Java's Integer, Boolean and Double classes,
> respectively, instead of the int, boolean and double primitive types.
>
> Can someone point me in the right direction? Is doing this considered
> a bad idea for any reason?
>
> Thanks,
> Ben.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #645046 is a reply to message #511037] Wed, 15 December 2010 11:15 Go to previous messageGo to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Thanks for your recent(!) reply Ed (I'm returning to this topic after almost a year).

I'd prefer a solution that avoids changing the XSD, as the XSDs come from outside and I need to ensure I write XML that conforms. I certainly can't change the meaning of the schema, so declaring elements as nillable is no good. Adding ecore annotations isn't out of the question, but I'd prefer to either post-process the EPackages that XSDEcoreBuilder generates, or extend XSDEcoreBuilder and override its behaviour.

My models are always derived from XSD where elements of simple types are always expressed as restrictions of the base types, rather than referring to them directly. In other words, if I had a complexType 'Car' with an element named 'cost' as a restriction of xsd:int, then I know XSDEcoreBuilder will generate both CostType and CostTypeObject EDataTypes. Car.cost will be of type CostType, given that it was not nillable in the source schema. I'm currently experimenting with the following: I iterate through the EPackages, iterating through the contained EClasses, checking each contained EAttribute. If an attribute refers to an EDataType that has int, boolean or double as its instance class, I alter the attribute to refer to the corresponding ':Object' data type. In other words, if the extended metadata for the existing type gives the name 'cost_._type', then I locate the type with name, 'cost_._type:Object' and alter the attribute to use that.

An implication of this is that if I create a Car, call setCost(null) and then save it to XML via XMLResource, I end up with an element for cost, with xsi:nil=true. This is a problem, as the XML won't match the original schema. I can get around this by cloning the Car first and calling eUnset for any attributes that have null value. It works, but feels hacky.

Perhaps it's worth describing my motivation. I don't want EMF's notion of something being 'unset'. Instead, I want to use null values to represent this. In other words, I want the caller to be able to determine that an attribute is not set by comparing it to null, rather than calling its isSet method.

Thanks in advance for any comments.

Ben.
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #645129 is a reply to message #645046] Wed, 15 December 2010 16:16 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33141
Registered: July 2009
Senior Member
Ben,

Commens below.

Ben Tenne wrote:
> Thanks for your recent(!) reply Ed (I'm returning to this topic after
> almost a year).
>
> I'd prefer a solution that avoids changing the XSD, as the XSDs come
> from outside and I need to ensure I write XML that conforms.
I wonder why you'd want to use something that's less efficient and less
convenient to use?
> I certainly can't change the meaning of the schema, so declaring
> elements as nillable is no good.
Then you'll have to deal with what does null mean, given that Integer
allows that but int can't represent it...
> Adding ecore annotations isn't out of the question, but I'd prefer
> to either post-process the EPackages that XSDEcoreBuilder generates,
> or extend XSDEcoreBuilder and override its behaviour.
I think ecore:type would work. You'd need to import Ecore.xsd to get at
EIntegerObject.
> My models are always derived from XSD where elements of simple types
> are always expressed as restrictions of the base types, rather than
> referring to them directly. In other words, if I had a complexType
> 'Car' with an element named 'cost' as a restriction of xsd:int, then I
> know XSDEcoreBuilder will generate both CostType and CostTypeObject
> EDataTypes.
The latter being used for nillable elements only...
> Car.cost will be of type CostType, given that it was not nillable in
> the source schema. I'm currently experimenting with the following: I
> iterate through the EPackages, iterating through the contained
> EClasses, checking each contained EAttribute. If an attribute refers
> to an EDataType that has int, boolean or double as its instance class,
> I alter the attribute to refer to the corresponding ':Object' data
> type. In other words, if the extended metadata for the existing type
> gives the name 'cost_._type', then I locate the type with name,
> 'cost_._type:Object' and alter the attribute to use that.
That should work, but I'd be concerned about how null is handled then...
>
> An implication of this is that if I create a Car, call setCost(null)
> and then save it to XML via XMLResource, I end up with an element for
> cost, with xsi:nil=true.
Exactly my concern.
> This is a problem, as the XML won't match the original schema. I can
> get around this by cloning the Car first and calling eUnset for any
> attributes that have null value. It works, but feels hacky.
It is, but you get what you ask for.
>
> Perhaps it's worth describing my motivation. I don't want EMF's
> notion of something being 'unset'. Instead, I want to use null values
> to represent this. In other words, I want the caller to be able to
> determine that an attribute is not set by comparing it to null, rather
> than calling its isSet method.
So probably you should make unsettable false for the very attributes for
which you're changing the type...
>
> Thanks in advance for any comments.
>
> Ben.
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #645268 is a reply to message #645129] Thu, 16 December 2010 10:39 Go to previous messageGo to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Thanks for the reply, Ed.

I understand that using a wrapper object rather than a primitive is less efficient, but it's a requirement beyond my control. I'm required to generate models where all attributes are capable of taking null and null means 'not set', rather than 'set to null'.

I've streamlined my solution a bit. Rather than post-processing the model after calling XSDEcoreBuilder, I'm extending XSDEcoreBuilder and applying some type-switching behaviour after calling the normal createFeature(...) method, like this:

    @Override
	protected EStructuralFeature createFeature(EClass class1, String name,
			EClassifier type, XSDComponent xsdComponent, int minOccurs,
			int maxOccurs) {

    	EStructuralFeature feature = super.createFeature(class1, name, type, xsdComponent, minOccurs,
				maxOccurs);

    	if (feature instanceof EAttribute) {
    		EAttribute attr = (EAttribute) feature;
    		EDataType dt = attr.getEAttributeType();
    		if (!canSupportNull(dt)) {
    			if (typeToTypeObjectMap.containsKey(dt)) {
    				EClassifier objectDT = typeToTypeObjectMap.get(dt);
    				System.out.println("Changing type of " + attr + " FROM " + attr.getEType() + " to " + objectDT);
    				attr.setEType(objectDT);
    				attr.setUnsettable(false);

    				// Set annotation to record that type has been 'wrapped'.
    				// This will be used as serialization-time to suppress
    				// writing of xsi:nil=true when the value is null.
       				EAnnotation annot = EcoreFactory.eINSTANCE.createEAnnotation();
    				annot.setSource("mysource");
    				annot.getDetails().put("wrapped", "true");
    				attr.getEAnnotations().add(annot);
    			}
    		}
    	}
    	return feature;
	}


So, any attribute that naturally maps to a type that can't take null gets switched to use the object-wrapped alternative. Notice that I also set an annotation on such attributes. This is to enable me to suppress writing of 'xmi:nil' when I serialize to XML. i.e. When given an object to serialize, I clone it first and call eUnset for any attributes that have the annotation and a value of null.

I'm not entirely comfortable with all of this, but it sounds like an acceptable solution to me. It avoids having to modify the original XSD, ensures that serialized objects will conform to the original schema and, fundamentally, satisfies the requirement that users can use !=null to see if something is set, rather than calling isSet.

Cheers,
Ben.
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #645295 is a reply to message #645268] Thu, 16 December 2010 13:49 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33141
Registered: July 2009
Senior Member
Ben,

Comments below.


Ben Tenne wrote:
> Thanks for the reply, Ed.
>
> I understand that using a wrapper object rather than a primitive is
> less efficient, but it's a requirement beyond my control. I'm required
> to generate models where all attributes are capable of taking null and
> null means 'not set', rather than 'set to null'.
I see.
>
> I've streamlined my solution a bit. Rather than post-processing the
> model after calling XSDEcoreBuilder, I'm extending XSDEcoreBuilder and
> applying some type-switching behaviour after calling the normal
> createFeature(...) method, like this:
>
>
> @Override
> protected EStructuralFeature createFeature(EClass class1, String
> name,
> EClassifier type, XSDComponent xsdComponent, int minOccurs,
> int maxOccurs) {
>
> EStructuralFeature feature = super.createFeature(class1, name,
> type, xsdComponent, minOccurs,
> maxOccurs);
>
> if (feature instanceof EAttribute) {
> EAttribute attr = (EAttribute) feature;
> EDataType dt = attr.getEAttributeType();
> if (!canSupportNull(dt)) {
> if (typeToTypeObjectMap.containsKey(dt)) {
> EClassifier objectDT = typeToTypeObjectMap.get(dt);
> System.out.println("Changing type of " + attr + "
> FROM " + attr.getEType() + " to " + objectDT);
> attr.setEType(objectDT);
> attr.setUnsettable(false);
>
> // Set annotation to record that type has been
> 'wrapped'.
> // This will be used as serialization-time to suppress
> // writing of xsi:nil=true when the value is null.
> EAnnotation annot =
> EcoreFactory.eINSTANCE.createEAnnotation();
> annot.setSource("mysource");
> annot.getDetails().put("wrapped", "true");
> attr.getEAnnotations().add(annot);
> }
> }
> }
> return feature;
> }
>
>
> So, any attribute that naturally maps to a type that can't take null
> gets switched to use the object-wrapped alternative. Notice that I
> also set an annotation on such attributes. This is to enable me to
> suppress writing of 'xmi:nil' when I serialize to XML. i.e. When given
> an object to serialize, I clone it first and call eUnset for any
> attributes that have the annotation and a value of null.
It it's not unsettable, doesn't the feature return false for
eIsSet(feature) when the value is null (which presumably is the default
value for the feature)? I.e., I'd only expect to see xsi:nil serialized
for unsettable features (or if the default value of the feature is
something other than null).
>
> I'm not entirely comfortable with all of this, but it sounds like an
> acceptable solution to me. It avoids having to modify the original
> XSD, ensures that serialized objects will conform to the original
> schema and, fundamentally, satisfies the requirement that users can
> use !=null to see if something is set, rather than calling isSet.
>
> Cheers,
> Ben.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #645300 is a reply to message #645295] Thu, 16 December 2010 14:21 Go to previous messageGo to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Ed Merks wrote on Thu, 16 December 2010 08:49

It it's not unsettable, doesn't the feature return false for
eIsSet(feature) when the value is null (which presumably is the default
value for the feature)? I.e., I'd only expect to see xsi:nil serialized
for unsettable features (or if the default value of the feature is
something other than null).



That's not the behaviour I'm seeing. It returns false initially, but after calling the setter with null (e.g. myCar.setCost(null) ) a subsequent call to eIsSet returns true.

I'm using an old version of EMF (2.4.2) and haven't verified the behaviour in a more recent version.

Cheers,
Ben.

[Updated on: Thu, 16 December 2010 15:11]

Report message to a moderator

Re: Preventing use of Java primitive types in XSD-derived Ecore [message #645310 is a reply to message #645300] Thu, 16 December 2010 15:11 Go to previous messageGo to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
I'm made some progress with this. My generated CarImpl class assigns 0, false and 0.0 to my Integer, Boolean and Double attributes, respectively, despite the fact that the Ecore model has no defaults. This explains why eIsSet is returning true, given that the logic for non-unsettable attributes is 'current value not equal to default'.

I will investigate further.
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #648840 is a reply to message #645310] Fri, 14 January 2011 17:13 Go to previous messageGo to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Right, so if I do what I've described above and switch an attribute to using the 'Object' type variant, I end up with something like this (note use of Integer instead of int) in the generated Impl:

  /**
   * The default value of the '{@link #getPlank() <em>Plank</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getPlank()
   * @generated
   * @ordered
   */
  protected static final Integer PLANK_EDEFAULT = 0;

  /**
   * The cached value of the '{@link #getPlank() <em>Plank</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @see #getPlank()
   * @generated
   * @ordered
   */
  protected Integer plank = PLANK_EDEFAULT;


Note that the default is zero, rather than null, despite no default being set in the eCore model.

Excerpt:

  <eClassifiers xsi:type="ecore:EDataType" name="PlankType" instanceClassName="int">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="name" value="plank_._type"/>
      <details key="baseType" value="http://www.eclipse.org/emf/2003/XMLType#int"/>
    </eAnnotations>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EDataType" name="PlankTypeObject" instanceClassName="java.lang.Integer">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="name" value="plank_._type:Object"/>
      <details key="baseType" value="plank_._type"/>
    </eAnnotations>
  </eClassifiers>

...

  <eClassifiers xsi:type="ecore:EClass" name="Wrap">
    <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
      <details key="name" value="Wrap"/>
      <details key="kind" value="elementOnly"/>
    </eAnnotations>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="plank" lowerBound="1" eType="//PlankTypeObject">
      <eAnnotations source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
        <details key="kind" value="element"/>
        <details key="name" value="plank"/>
        <details key="namespace" value="##targetNamespace"/>
    </eStructuralFeatures>
  </eClassifiers>


I can appreciate that this wouldn't happen under normal circumstances: Either I'd be using int and a default of zero would be fine, given that an int can't be null, or the use of Integer would have been prompted by the attribute being nillable, in which case we'd have a separate 'set' flag and the value wouldn't matter when it wasn't set. However, does that mean I'm doing something wrong, or is fair to say this a reasonable thing to do?

Next, I looked at the corresponding JET template fragment:

	/**
	 * The default value of the '{@link #<%=genFeature.getGetAccessor()%>() <em><%=genFeature.getFormattedName()%></em>}' <%=genFeature.getFeatureKind()%>.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @see #<%=genFeature.getGetAccessor()%>()
	 * @generated
	 * @ordered
	 */
        <%if (genModel.useGenerics() && genFeature.isListDataType() && genFeature.isSetDefaultValue()) {%>
	@SuppressWarnings("unchecked")
        <%}%>
	protected static final <%=genFeature.getImportedType(genClass)%> <%=genFeature.getEDefault()%><%if ("".equals(staticDefaultValue)) {%>; // TODO The default value literal "<%=genFeature.getEcoreFeature().getDefaultValueLiteral()%>" is not valid.<%} else {%> = <%=staticDefaultValue%>;<%=genModel.getNonNLS(staticDefaultValue)%><%}%>


So, it looks like the template has visibility of a variable named staticDefaultValue, and that is apparently '0' rather than 'null'. This makes me think I may have two options: (1) Work out how the generator works and alter it to make staticDefaultValue='null' in this scenario, or (2) Alter the template to somehow detect that the data type is Integer(or Boolean, or Double, etc) and always write 'null' when the feature has no default set. Neither of these seems particularly appealing.

Any thoughts much appreciated, as always!

Cheers,
Ben.
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #648849 is a reply to message #648840] Fri, 14 January 2011 17:38 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33141
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------050804010507050301000007
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit

Ben,

When I change the Library model's Book.pages right in the Ecore model to
use IntegerObject I see:

protected static final Integer PAGES_EDEFAULT = null;

But when I change the schema itself like this:

<xsd:element name="pages2" nillable="true">
<xsd:simpleType>
<xsd:restriction base="xsd:int">
</xsd:restriction>
</xsd:simpleType>
</xsd:element>

I see what you're seeing below and that doesn't seem quite right.
Please open a bugzilla.


Ben Tenne wrote:
> Right, so if I do what I've described above and switch an attribute to
> using the 'Object' type variant, I end up with something like this
> (note use of Integer instead of int) in the generated Impl:
>
>
> /**
> * The default value of the '{@link #getPlank() <em>Plank</em>}'
> attribute.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @see #getPlank()
> * @generated
> * @ordered
> */
> protected static final Integer PLANK_EDEFAULT = 0;
>
> /**
> * The cached value of the '{@link #getPlank() <em>Plank</em>}'
> attribute.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @see #getPlank()
> * @generated
> * @ordered
> */
> protected Integer plank = PLANK_EDEFAULT;
>
>
> Note that the default is zero, rather than null, despite no default
> being set in the eCore model.
>
> Excerpt:
>
>
> <eClassifiers xsi:type="ecore:EDataType" name="PlankType"
> instanceClassName="int">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
> <details key="name" value="plank_._type"/>
> <details key="baseType"
> value="http://www.eclipse.org/emf/2003/XMLType#int"/>
> </eAnnotations>
> </eClassifiers>
> <eClassifiers xsi:type="ecore:EDataType" name="PlankTypeObject"
> instanceClassName="java.lang.Integer">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
> <details key="name" value="plank_._type:Object"/>
> <details key="baseType" value="plank_._type"/>
> </eAnnotations>
> </eClassifiers>
>
> ..
>
> <eClassifiers xsi:type="ecore:EClass" name="Wrap">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
> <details key="name" value="Wrap"/>
> <details key="kind" value="elementOnly"/>
> </eAnnotations>
> <eStructuralFeatures xsi:type="ecore:EAttribute" name="plank"
> lowerBound="1" eType="//PlankTypeObject">
> <eAnnotations
> source="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">
> <details key="kind" value="element"/>
> <details key="name" value="plank"/>
> <details key="namespace" value="##targetNamespace"/>
> </eStructuralFeatures>
> </eClassifiers>
>
>
> I can appreciate that this wouldn't happen under normal circumstances:
> Either I'd be using int and a default of zero would be fine, given
> that an int can't be null, or the use of Integer would have been
> prompted by the attribute being nillable, in which case we'd have a
> separate 'set' flag and the value wouldn't matter when it wasn't set.
> However, does that mean I'm doing something wrong, or is fair to say
> this a reasonable thing to do?
>
> Next, I looked at the corresponding JET template fragment:
>
>
> /**
> * The default value of the '{@link
> #<%=genFeature.getGetAccessor()%>()
> <em><%=genFeature.getFormattedName()%></em>}'
> <%=genFeature.getFeatureKind()%>.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @see #<%=genFeature.getGetAccessor()%>()
> * @generated
> * @ordered
> */
> <%if (genModel.useGenerics() && genFeature.isListDataType() &&
> genFeature.isSetDefaultValue()) {%>
> @SuppressWarnings("unchecked")
> <%}%>
> protected static final <%=genFeature.getImportedType(genClass)%>
> <%=genFeature.getEDefault()%><%if ("".equals(staticDefaultValue)) {%>;
> // TODO The default value literal
> "<%=genFeature.getEcoreFeature().getDefaultValueLiteral()%>" is not
> valid.<%} else {%> =
> <%=staticDefaultValue%>;<%=genModel.getNonNLS(staticDefaultValue)% ><%}%>
>
>
> So, it looks like the template has visibility of a variable named
> staticDefaultValue, and that is apparently '0' rather than 'null'.
> This makes me think I may have two options: (1) Work out how the
> generator works and alter it to make staticDefaultValue='null' in this
> scenario, or (2) Alter the template to somehow detect that the data
> type is Integer(or Boolean, or Double, etc) and always write 'null'
> when the feature has no default set. Neither of these seems
> particularly appealing.
>
> Any thoughts much appreciated, as always!
>
> Cheers,
> Ben.

--------------050804010507050301000007
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
<title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
Ben,<br>
<br>
When I change the Library model's Book.pages right in the Ecore model
to use IntegerObject I see:<br>
<blockquote>  protected static final Integer PAGES_EDEFAULT = null;<br>
<br>
</blockquote>
But when I change the schema itself like this:<br>
<br>
      &lt;xsd:element name="pages2" nillable="true"&gt;<br>
         &lt;xsd:simpleType&gt;<br>
           &lt;xsd:restriction base="xsd:int"&gt;<br>
           &lt;/xsd:restriction&gt;<br>
         &lt;/xsd:simpleType&gt;<br>
      &lt;/xsd:element&gt;<br>
<br>
I see what you're seeing below and that doesn't seem quite right. 
Please open a bugzilla.<br>
<br>
<br>
Ben Tenne wrote:
<blockquote cite="mid:igpvtq$iai$1@news.eclipse.org" type="cite">Right,
so if I do what I've described above and switch an attribute to using
the 'Object' type variant, I end up with something like this (note use
of Integer instead of int) in the generated Impl:
<br>
<br>
<br>
 /**
<br>
  * The default value of the '{@link #getPlank()
&lt;em&gt;Plank&lt;/em&gt;}' attribute.
<br>
  * &lt;!-- begin-user-doc --&gt;
<br>
  * &lt;!-- end-user-doc --&gt;
<br>
  * @see #getPlank()
<br>
  * @generated
<br>
  * @ordered
<br>
  */
<br>
 protected static final Integer PLANK_EDEFAULT = 0;
<br>
<br>
 /**
<br>
  * The cached value of the '{@link #getPlank()
&lt;em&gt;Plank&lt;/em&gt;}' attribute.
<br>
  * &lt;!-- begin-user-doc --&gt;
<br>
  * &lt;!-- end-user-doc --&gt;
<br>
  * @see #getPlank()
<br>
  * @generated
<br>
  * @ordered
<br>
  */
<br>
 protected Integer plank = PLANK_EDEFAULT;
<br>
<br>
<br>
Note that the default is zero, rather than null, despite no default
being set in the eCore model.
<br>
<br>
Excerpt:
<br>
<br>
<br>
 &lt;eClassifiers xsi:type="ecore:EDataType" name="PlankType"
instanceClassName="int"&gt;
<br>
   &lt;eAnnotations
source=<a class="moz-txt-link-rfc2396E" href="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">"http:///org/eclipse/emf/ecore/util/ExtendedMetaData"</a>&gt;
<br>
     &lt;details key="name" value="plank_._type"/&gt;
<br>
     &lt;details key="baseType"
value=<a class="moz-txt-link-rfc2396E" href="http://www.eclipse.org/emf/2003/XMLType#int">"http://www.eclipse.org/emf/2003/XMLType#int"</a>/&gt;
<br>
   &lt;/eAnnotations&gt;
<br>
 &lt;/eClassifiers&gt;
<br>
 &lt;eClassifiers xsi:type="ecore:EDataType" name="PlankTypeObject"
instanceClassName="java.lang.Integer"&gt;
<br>
   &lt;eAnnotations
source=<a class="moz-txt-link-rfc2396E" href="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">"http:///org/eclipse/emf/ecore/util/ExtendedMetaData"</a>&gt;
<br>
     &lt;details key="name" value="plank_._type:Object"/&gt;
<br>
     &lt;details key="baseType" value="plank_._type"/&gt;
<br>
   &lt;/eAnnotations&gt;
<br>
 &lt;/eClassifiers&gt;
<br>
<br>
...
<br>
<br>
 &lt;eClassifiers xsi:type="ecore:EClass" name="Wrap"&gt;
<br>
   &lt;eAnnotations
source=<a class="moz-txt-link-rfc2396E" href="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">"http:///org/eclipse/emf/ecore/util/ExtendedMetaData"</a>&gt;
<br>
     &lt;details key="name" value="Wrap"/&gt;
<br>
     &lt;details key="kind" value="elementOnly"/&gt;
<br>
   &lt;/eAnnotations&gt;
<br>
   &lt;eStructuralFeatures xsi:type="ecore:EAttribute" name="plank"
lowerBound="1" eType="//PlankTypeObject"&gt;
<br>
     &lt;eAnnotations
source=<a class="moz-txt-link-rfc2396E" href="http:///org/eclipse/emf/ecore/util/ExtendedMetaData">"http:///org/eclipse/emf/ecore/util/ExtendedMetaData"</a>&gt;
<br>
       &lt;details key="kind" value="element"/&gt;
<br>
       &lt;details key="name" value="plank"/&gt;
<br>
       &lt;details key="namespace" value="##targetNamespace"/&gt;
<br>
   &lt;/eStructuralFeatures&gt;
<br>
 &lt;/eClassifiers&gt;
<br>
<br>
<br>
I can appreciate that this wouldn't happen under normal circumstances:
Either I'd be using int and a default of zero would be fine, given that
an int can't be null, or the use of Integer would have been prompted by
the attribute being nillable, in which case we'd have a separate 'set'
flag and the value wouldn't matter when it wasn't set.  However, does
that mean I'm doing something wrong, or is fair to say this a
reasonable thing to do?
<br>
<br>
Next, I looked at the corresponding JET template fragment:
<br>
<br>
<br>
    /**
<br>
     * The default value of the '{@link
#&lt;%=genFeature.getGetAccessor()%&gt;()
&lt;em&gt;&lt;%=genFeature.getFormattedName()%&a mp;gt;&lt;/em&gt;}'
&lt;%=genFeature.getFeatureKind()%&gt;.
<br>
     * &lt;!-- begin-user-doc --&gt;
<br>
     * &lt;!-- end-user-doc --&gt;
<br>
     * @see #&lt;%=genFeature.getGetAccessor()%&gt;()
<br>
     * @generated
<br>
     * @ordered
<br>
     */
<br>
       &lt;%if (genModel.useGenerics() &amp;&amp;
genFeature.isListDataType() &amp;&amp; genFeature.isSetDefaultValue())
{%&gt;
<br>
    @SuppressWarnings("unchecked")
<br>
       &lt;%}%&gt;
<br>
    protected static final
&lt;%=genFeature.getImportedType(genClass)%&gt;
&lt;%=genFeature.getEDefault()%&gt;&lt;%if
("".equals(staticDefaultValue)) {%&gt;; // TODO The default value
literal
" &lt;%=genFeature.getEcoreFeature().getDefaultValueLitera l()%&gt; " is
not valid.&lt;%} else {%&gt; =
&lt;%=staticDefaultValue%&gt;;&lt;%=genModel.get NonNLS(staticDefaultValue)%&gt;&lt;%}%&gt;
<br>
<br>
<br>
So, it looks like the template has visibility of a variable named
staticDefaultValue, and that is apparently '0' rather than 'null'. 
This makes me think I may have two options: (1) Work out how the
generator works and alter it to make staticDefaultValue='null' in this
scenario, or (2) Alter the template to somehow detect that the data
type is Integer(or Boolean, or Double, etc) and always write 'null'
when the feature has no default set. Neither of these seems
particularly appealing.
<br>
<br>
Any thoughts much appreciated, as always!
<br>
<br>
Cheers,
<br>
Ben.
<br>
</blockquote>
</body>
</html>

--------------050804010507050301000007--


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #648928 is a reply to message #648849] Sat, 15 January 2011 19:03 Go to previous messageGo to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Thanks for that, Ed.

I've taken a look at the Library example and I get the same results as you. I think the significant difference in that case is that you're switching 'pages' from 'EInt' to 'EIntegerObject', the standard pre-defined types. In my case (or any Ecore resulting from XSD via XSDEcoreBuilder) the attribute's type is custom: In my previous example, I'm switching my 'plank' attribute from 'PlankType' to 'PlankTypeObject'.

Incidentally, use of EIntegerObject wouldn't solve my problem as I generally have additional restrictions such as min/max values and patterns to consider.

Cheers,
Ben.
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #648934 is a reply to message #648928] Sat, 15 January 2011 19:35 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33141
Registered: July 2009
Senior Member
Ben,

Did you open a bugzilla?


Ben Tenne wrote:
> Thanks for that, Ed.
>
> I've taken a look at the Library example and I get the same results as
> you. I think the significant difference in that case is that you're
> switching 'pages' from 'EInt' to 'EIntegerObject', the standard
> pre-defined types. In my case (or any Ecore resulting from XSD via
> XSDEcoreBuilder) the attribute's type is custom: In my previous
> example, I'm switching my 'plank' attribute from 'PlankType' to
> 'PlankTypeObject'.
> Incidentally, use of EIntegerObject wouldn't solve my problem as I
> generally have additional restrictions such as min/max values and
> patterns to consider.
>
> Cheers,
> Ben.


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #648950 is a reply to message #648934] Sun, 16 January 2011 13:07 Go to previous messageGo to next message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
New bugzilla:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=334479

I encountered this in EMF 2.4.x, so decided to test it in 2.6 before raising a bug. As you'll see, I needed to make my datatype a restriction, as XSDEcoreBuilder in 2.6. appears to use built-in types unless you have a restriction (whereas 2.4.x would always create the pair of custom types).

Cheers,
Ben.
Re: Preventing use of Java primitive types in XSD-derived Ecore [message #649043 is a reply to message #648950] Mon, 17 January 2011 11:59 Go to previous message
Ben Tenne is currently offline Ben TenneFriend
Messages: 50
Registered: October 2009
Member
Here's a potential workaround involving an edit to the Class.javajet template.

It seems that this returns the wrong value (e.g. zero for an Integer that has no default):

genFeature.getStaticDefaultValue()


...whereas this correctly returns null when there's no default in the Ecore model and the Java type is an Object (i.e. it would return 0 for an int, but I'm always using wrapper types, so it doesn't matter):

genFeature.getEcoreFeature().getDefaultValue()


So, it seems I can get around the problem by replacing the script fragment that writes the default value:

<%=staticDefaultValue%>


...with this:

<%=(genFeature.getEcoreFeature().getDefaultValue()==null?null:staticDefaultValue)%>
Previous Topic:[CDO] Save point is not valid
Next Topic:Making a copy of a FeatureMap
Goto Forum:
  


Current Time: Thu Apr 25 15:21:50 GMT 2024

Powered by FUDForum. Page generated in 0.03893 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top