Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » EMF or Teneo: Unable to not specify optional enumeration
EMF or Teneo: Unable to not specify optional enumeration [message #1112353] Thu, 19 September 2013 13:27 Go to next message
Rob Mising name is currently offline Rob Mising nameFriend
Messages: 118
Registered: July 2010
Senior Member
Hi Ed, Martin,

I wasn't sure which camp this falls into, as the problem is highlighted when I was doing some testing with Teneo - but the fix I think is possible, is in the EMF Templates.

If I have a schema as follows (Simplified version of what I was running):

	<xsd:simpleType name="TreadPattern" ecore:name="TreadPattern">
		<xsd:restriction base="xsd:string">
			<xsd:enumeration value="WAVYLINES" ecore:name="WAVYLINES"/>
			<xsd:enumeration value="CRISSCROSS" ecore:name="CRISSCROSS"/>
			<xsd:enumeration value="SPIRALS" ecore:name="SPIRALS"/>
		</xsd:restriction>
	</xsd:simpleType>
	<xsd:complexType name="Wheel" ecore:name="Wheel">
		<xsd:sequence>
			<xsd:element name="diameter" minOccurs="0" maxOccurs="1" ecore:name="diameter">
				<xsd:simpleType>
					<xsd:restriction base="xsd:integer">
						<xsd:totalDigits value="10"/>
					</xsd:restriction>
				</xsd:simpleType>
			</xsd:element>
			<xsd:element name="tyre" type="Tyre" minOccurs="1" maxOccurs="1" ecore:name="tyre"/>
		</xsd:sequence>
	</xsd:complexType>
	<xsd:complexType name="Tyre" ecore:name="Tyre">
		<xsd:sequence>
			<xsd:element name="treadPattern" type="tns3:TreadPattern" minOccurs="0" maxOccurs="1" ecore:name="treadPattern"/>
		</xsd:sequence>
	</xsd:complexType>
	<xsd:element name="WheelElement" type="Wheel"/>
	<xsd:element name="TyreElement" type="Tyre"/>


So the treadPattern is an optional element of type enumeration.

If I construct and then persist a Wheel, where there is a Tyre (required as part of the schema) but there is no tread pattern specified (as it is optional).

When it goes to persist it I get an exception:

Caused by: java.lang.IllegalArgumentException: The value 'null' is not a valid enumerator of 'TreadPattern'
	at com.example.gdcomp.impl.GdcompFactoryImpl.createTreadPatternFromString(GdcompFactoryImpl.java:705)
	at com.example.gdcomp.impl.GdcompFactoryImpl.createTreadPatternObjectFromString(GdcompFactoryImpl.java:1726)
	at com.example.gdcomp.impl.GdcompFactoryImpl.createFromString(GdcompFactoryImpl.java:224)
	at org.eclipse.emf.teneo.hibernate.mapping.DefaultToStringUserType.deepCopy(DefaultToStringUserType.java:77)
	at org.hibernate.type.CustomType.deepCopy(CustomType.java:179)
	at org.hibernate.type.TypeFactory.deepCopy(TypeFactory.java:374)
	at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:280)
	at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
	at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
	at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:508)
	at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:500)


This is because the create...FromString method is trying to convert a value that is "null", and the existing template will throw an exception if null is passed into it.

public TreadPattern createTreadPatternFromString(EDataType eDataType, String initialValue)
  {
    TreadPattern result = TreadPattern.get(initialValue);
    if (result == null) throw new IllegalArgumentException("The value '" + initialValue + "' is not a valid enumerator of '" + eDataType.getName() + "'");
    return result;
  }


I have managed to work around this problem by adding to the FactoryClass.javajet template, so that it checks for null as an argument - and return null in this case rather than throw an exception. (Approx line 346)

	public <%=genDataType.getImportedParameterizedObjectInstanceClassName()%> create<%=genDataType.getName()%>FromString(<%=genModel.getImportedName("org.eclipse.emf.ecore.EDataType")%> eDataType, String initialValue)
	{
    <%if (genDataType instanceof GenEnum) {%>
      <%if (genPackage.isDataTypeConverters()) {%>
		return create<%=genDataType.getName()%>(initialValue);
      <%} else {%>
<%// ** START CUSTOM CHANGE ** %>
        // If the argument passed in is null, return null
        if( initialValue == null )
        {
        	return null;
        }
<%// ** END CUSTOM CHANGE ** %>
		<%=((GenEnum)genDataType).getImportedInstanceClassName()%> result = <%=((GenEnum)genDataType).getImportedInstanceClassName()%>.get(initialValue);
		if (result == null) throw new IllegalArgumentException("The value '" + initialValue + "' is not a valid enumerator of '" + eDataType.getName() + "'");<%=genModel.getNonNLS()%><%=genModel.getNonNLS(2)%><%=genModel.getNonNLS(3)%>
		return result;
      <%}%>


I would be very interested to hear both of your thoughts, and if this change is a safe one to make?

Thanks, Rob



Re: EMF or Teneo: Unable to not specify optional enumeration [message #1112368 is a reply to message #1112353] Thu, 19 September 2013 13:51 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Rob,

I'll wait for Martin to comment. From a purely EMF point of view,
EEnums are treated like primitive types that don't support a null
value. I.e., an EAttribute of type EEnum can't return a null value
from the getter and even trying to set it to null will set it to the
feature's default value which will be the first EEnumLiteral unless
another literal is explicitly set as the EAttribute's default. So I'm
not sure where the null comes from; of course I see the call from
deepCopy, but I can't comment on why it has null as a literal value...


On 19/09/2013 3:27 PM, Rob Mising name wrote:
> Hi Ed, Martin,
>
> I wasn't sure which camp this falls into, as the problem is
> highlighted when I was doing some testing with Teneo - but the fix I
> think is possible, is in the EMF Templates.
>
> If I have a schema as follows (Simplified version of what I was running):
>
> <xsd:simpleType name="TreadPattern" ecore:name="TreadPattern">
> <xsd:restriction base="xsd:string">
> <xsd:enumeration value="WAVYLINES" ecore:name="WAVYLINES"/>
> <xsd:enumeration value="CRISSCROSS" ecore:name="CRISSCROSS"/>
> <xsd:enumeration value="SPIRALS" ecore:name="SPIRALS"/>
> </xsd:restriction>
> </xsd:simpleType>
> <xsd:complexType name="Wheel" ecore:name="Wheel">
> <xsd:sequence>
> <xsd:element name="diameter" minOccurs="0" maxOccurs="1"
> ecore:name="diameter">
> <xsd:simpleType>
> <xsd:restriction base="xsd:integer">
> <xsd:totalDigits value="10"/>
> </xsd:restriction>
> </xsd:simpleType>
> </xsd:element>
> <xsd:element name="tyre" type="Tyre" minOccurs="1"
> maxOccurs="1" ecore:name="tyre"/>
> </xsd:sequence>
> </xsd:complexType>
> <xsd:complexType name="Tyre" ecore:name="Tyre">
> <xsd:sequence>
> <xsd:element name="treadPattern" type="tns3:TreadPattern"
> minOccurs="0" maxOccurs="1" ecore:name="treadPattern"/>
> </xsd:sequence>
> </xsd:complexType>
> <xsd:element name="WheelElement" type="Wheel"/>
> <xsd:element name="TyreElement" type="Tyre"/>
>
> So the treadPattern is an optional element of type enumeration.
>
> If I construct and then persist a Wheel, where there is a Tyre
> (required as part of the schema) but there is no tread pattern
> specified (as it is optional).
>
> When it goes to persist it I get an exception:
>
>
> Caused by: java.lang.IllegalArgumentException: The value 'null' is not
> a valid enumerator of 'TreadPattern'
> at
> com.example.gdcomp.impl.GdcompFactoryImpl.createTreadPatternFromString(GdcompFactoryImpl.java:705)
> at
> com.example.gdcomp.impl.GdcompFactoryImpl.createTreadPatternObjectFromString(GdcompFactoryImpl.java:1726)
> at
> com.example.gdcomp.impl.GdcompFactoryImpl.createFromString(GdcompFactoryImpl.java:224)
> at
> org.eclipse.emf.teneo.hibernate.mapping.DefaultToStringUserType.deepCopy(DefaultToStringUserType.java:77)
> at org.hibernate.type.CustomType.deepCopy(CustomType.java:179)
> at org.hibernate.type.TypeFactory.deepCopy(TypeFactory.java:374)
> at
> org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:280)
> at
> org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
> at
> org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
> at
> org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
> at
> org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
> at
> org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
> at
> org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
> at
> org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:508)
> at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:500)
>
>
> This is because the create...FromString method is trying to convert a
> value that is "null", and the existing template will throw an
> exception if null is passed into it.
>
> public TreadPattern createTreadPatternFromString(EDataType eDataType,
> String initialValue)
> {
> TreadPattern result = TreadPattern.get(initialValue);
> if (result == null) throw new IllegalArgumentException("The value
> '" + initialValue + "' is not a valid enumerator of '" +
> eDataType.getName() + "'");
> return result;
> }
>
>
> I have managed to work around this problem by adding to the
> FactoryClass.javajet template, so that it checks for null as an
> argument - and return null in this case rather than throw an
> exception. (Approx line 346)
>
> public
> <%=genDataType.getImportedParameterizedObjectInstanceClassName()%>
> create<%=genDataType.getName()%>FromString(<%=genModel.getImportedName("org.eclipse.emf.ecore.EDataType")%>
> eDataType, String initialValue)
> {
> <%if (genDataType instanceof GenEnum) {%>
> <%if (genPackage.isDataTypeConverters()) {%>
> return create<%=genDataType.getName()%>(initialValue);
> <%} else {%>
> <%// ** START CUSTOM CHANGE ** %>
> // If the argument passed in is null, return null
> if( initialValue == null )
> {
> return null;
> }
> <%// ** END CUSTOM CHANGE ** %>
> <%=((GenEnum)genDataType).getImportedInstanceClassName()%> result =
> <%=((GenEnum)genDataType).getImportedInstanceClassName()%>.get(initialValue);
> if (result == null) throw new IllegalArgumentException("The
> value '" + initialValue + "' is not a valid enumerator of '" +
> eDataType.getName() +
> "'");<%=genModel.getNonNLS()%><%=genModel.getNonNLS(2)%><%=genModel.getNonNLS(3)%>
> return result;
> <%}%>
>
>
> I would be very interested to hear both of your thoughts, and if this
> change is a safe one to make?
>
> Thanks, Rob
>
>
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: EMF or Teneo: Unable to not specify optional enumeration [message #1112374 is a reply to message #1112368] Thu, 19 September 2013 14:05 Go to previous messageGo to next message
Rob Mising name is currently offline Rob Mising nameFriend
Messages: 118
Registered: July 2010
Senior Member
Ed Merks wrote on Thu, 19 September 2013 14:51

I'll wait for Martin to comment. From a purely EMF point of view,
EEnums are treated like primitive types that don't support a null
value. I.e., an EAttribute of type EEnum can't return a null value
from the getter and even trying to set it to null will set it to the
feature's default value which will be the first EEnumLiteral unless
another literal is explicitly set as the EAttribute's default. So I'm
not sure where the null comes from; of course I see the call from
deepCopy, but I can't comment on why it has null as a literal value...


Hi Ed,

Thanks for the speedy reply. I know it would not be ideal (or pure in the EMF world), but do you think doing the template change locally on my system would be OK (and safe) in this case? (Just as a temporary work-around)

Thanks

Rob
Re: EMF or Teneo: Unable to not specify optional enumeration [message #1112383 is a reply to message #1112374] Thu, 19 September 2013 14:43 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Rob,

No, I don't imagine your work around would cause problems. It's a
scenario I don't expect would normally arise and I can't forsee anything
would be broken because of a failure to throw an exception rather than
returning null.


On 19/09/2013 4:05 PM, Rob Mising name wrote:
> Ed Merks wrote on Thu, 19 September 2013 14:51
>> I'll wait for Martin to comment. From a purely EMF point of view,
>> EEnums are treated like primitive types that don't support a null
>> value. I.e., an EAttribute of type EEnum can't return a null value
>> from the getter and even trying to set it to null will set it to the
>> feature's default value which will be the first EEnumLiteral unless
>> another literal is explicitly set as the EAttribute's default. So
>> I'm not sure where the null comes from; of course I see the call from
>> deepCopy, but I can't comment on why it has null as a literal value...
>
>
> Hi Ed,
>
> Thanks for the speedy reply. I know it would not be ideal (or pure in
> the EMF world), but do you think doing the template change locally on
> my system would be OK (and safe) in this case? (Just as a temporary
> work-around)
>
> Thanks
>
> Rob
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: EMF or Teneo: Unable to not specify optional enumeration [message #1112518 is a reply to message #1112383] Thu, 19 September 2013 20:42 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
Hi Rob,
It seems that Teneo does not recognize the datatype as an enum (therefore the default string user type is being used it
seems). Teneo has a EnumUserType and a EnumUserIntegerType for enums. Can you make a small model which shows the same
error? (looks like a bug)

gr. Martin

On 09/19/2013 04:43 PM, Ed Merks wrote:
> Rob,
>
> No, I don't imagine your work around would cause problems. It's a scenario I don't expect would normally arise and I
> can't forsee anything would be broken because of a failure to throw an exception rather than returning null.
>
>
> On 19/09/2013 4:05 PM, Rob Mising name wrote:
>> Ed Merks wrote on Thu, 19 September 2013 14:51
>>> I'll wait for Martin to comment. From a purely EMF point of view, EEnums are treated like primitive types that don't
>>> support a null value. I.e., an EAttribute of type EEnum can't return a null value from the getter and even trying
>>> to set it to null will set it to the feature's default value which will be the first EEnumLiteral unless another
>>> literal is explicitly set as the EAttribute's default. So I'm not sure where the null comes from; of course I see
>>> the call from deepCopy, but I can't comment on why it has null as a literal value...
>>
>>
>> Hi Ed,
>>
>> Thanks for the speedy reply. I know it would not be ideal (or pure in the EMF world), but do you think doing the
>> template change locally on my system would be OK (and safe) in this case? (Just as a temporary work-around)
>>
>> Thanks
>>
>> Rob
>>
>


--

With Regards, Martin Taal

Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@xxxxxxxx - mtaal@xxxxxxxx
Web: www.springsite.com - www.elver.org
Re: EMF or Teneo: Unable to not specify optional enumeration [message #1112830 is a reply to message #1112518] Fri, 20 September 2013 08:26 Go to previous message
Rob Mising name is currently offline Rob Mising nameFriend
Messages: 118
Registered: July 2010
Senior Member
Martin Taal wrote on Thu, 19 September 2013 21:42
Hi Rob,
It seems that Teneo does not recognize the datatype as an enum (therefore the default string user type is being used it
seems). Teneo has a EnumUserType and a EnumUserIntegerType for enums. Can you make a small model which shows the same
error? (looks like a bug)


Hi Martin,

The eCore would look something like the one attached

Hope that's OK

Rob
Previous Topic:Cross reference adapter resolves proxy although it shouldn't?
Next Topic:EMF context menu: Command for specific element
Goto Forum:
  


Current Time: Thu Apr 25 11:44:12 GMT 2024

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

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

Back to the top