Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » NPE while eSetting eContainingClass(NullPointerException at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDerivedStructuralFeatureID)
NPE while eSetting eContainingClass [message #1759465] Tue, 11 April 2017 21:15 Go to next message
Edoaurd Batot is currently offline Edoaurd BatotFriend
Messages: 90
Registered: March 2015
Member
Hi,

I'm manipulating some EMF structure and I get the following NPE :
------------------ The NPE -----------------
Exception in thread "main" java.lang.NullPointerException
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDerivedStructuralFeatureID(BasicEObjectImpl.java:1493)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eGet(BasicEObjectImpl.java:1008)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eGet(BasicEObjectImpl.java:1003)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eGet(BasicEObjectImpl.java:998)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eOpenSet(BasicEObjectImpl.java:1140)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDynamicSet(BasicEObjectImpl.java:1119)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eDynamicSet(BasicEObjectImpl.java:1112)
at org.eclipse.emf.ecore.impl.EOperationImpl.eSet(EOperationImpl.java:957)
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:1071)
at coocl.ocl.Contrainte.mutate(Contrainte.java:670)
at coocl.ocl.Program.mutate(Program.java:511)
at oclruler.genetics.Population.createRandomPopulation(Population.java:188)
at CoOCL_Batch.main(CoOCL_Batch.java:77)
-------------------------------------------
The snippet is :

EOperation eop = Program.getEOperation("oclIsTypeOf");
eop.[b]eSet[/b](
  eop.eClass().getEStructuralFeature("eContainingClass"), 
  ((EOperation)otherEop.getReferredOperation()).eContainer()
);


Note that :
- The reference to the feature is right : featureID is 10,
- otherEop object is right and give the expected OclAny_Class when asked about the container of its referred operation.
- the debugger show that it's ok up to that call :
BasicEObjectImpl.[b]eOpenSet[/b](EStructuralFeature eFeature, Object newValue) 


There, eFeature and newValue look allright but the "openFeature" is not found and a null propagate until explosion.

I've seen in many posts a problem related to the nullity of the feature passed in parameter to the eSet method. But here the feature is not null.

Anybody knows what's wrong ?
Anybody knows how to change an eContainingClass feature ?



Re: NPE while eSetting eContainingClass [message #1759477 is a reply to message #1759465] Tue, 11 April 2017 22:21 Go to previous messageGo to next message
Ed Merks is currently online Ed MerksFriend
Messages: 29135
Registered: July 2009
Senior Member
I'm not sure why you're trying to do it reflectively when there is generated API for doing this...

Of course if you tried to do it via the API, you'd notice there is no setEContainingClass method and you'd notice the getEContainingClass method is documented like this
   * @model opposite="eOperations" resolveProxies="false" changeable="false"
   * @generated
   */
  EClass getEContainingClass();
I.e., it's not a changeable feature so you can't call eSet on it and there is no generated setter you can call either.

In other words, you can modify the eContainingClass of an EOperation only by modifying the opposite, i.e, by adding it to the eOperations of the EClass that you want as the container of the EOperation.
Re: NPE while eSetting eContainingClass [message #1759482 is a reply to message #1759477] Wed, 12 April 2017 08:01 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 5586
Registered: July 2009
Senior Member
Hi

If you are doing magic things to the OCL AST by using eSet, because you just love eSet, you take responsibility for replicating the true usage of eSet.

I suggest that you investigate each problem by following the call path of a regular call before replacing it.

Regards

Ed Willink
Re: NPE while eSetting eContainingClass [message #1759524 is a reply to message #1759477] Wed, 12 April 2017 06:26 Go to previous messageGo to next message
Edoaurd Batot is currently offline Edoaurd BatotFriend
Messages: 90
Registered: March 2015
Member
Ed Merks wrote on Tue, 11 April 2017 22:21
I'm not sure why you're trying to do it reflectively when there is generated API for doing this...

Of course if you tried to do it via the API, you'd notice there is no setEContainingClass method and you'd notice the getEContainingClass method is documented like this
   * @model opposite="eOperations" resolveProxies="false" changeable="false"
   * @generated
   */
  EClass getEContainingClass();
I.e., it's not a changeable feature so you can't call eSet on it and there is no generated setter you can call either.

In other words, you can modify the eContainingClass of an EOperation only by modifying the opposite, i.e, by adding it to the eOperations of the EClass that you want as the container of the EOperation.


Ok. If I prefer the eSet it's because it allows way more indepth modification and also dynamic instantitation using String (instead of method calls). You can also overpass scope limitations (private/protected).

Anyways, - thanks for telling me the eContainingClass is not changeable - Now I wonder why such limitation ? Smile
(Note that copying the object I manipulate using EcoreUtil.copy() has removed its eContainginClass)

And also, why is that I get a NullPointer and not the assertion : "The feature '" + eStructuralFeature.getName() + "' is not a valid feature" ?


Thanks,
Edouard

PS : Ed willing, I am sincerly annoyed with you and your patriarchist tone. I don't need morale and all you get acting so with me is compassion for the poor kids you may have. So please, if you might keep your mouth shut for a while, it would be much appreciated.
Re: NPE while eSetting eContainingClass [message #1759531 is a reply to message #1759482] Wed, 12 April 2017 07:24 Go to previous messageGo to next message
Ed Merks is currently online Ed MerksFriend
Messages: 29135
Registered: July 2009
Senior Member
I don't get your eSet comment. It can do no more and no less than the generated API. The code you show is certainly not more readable, not more efficient, and of course has way less static checking for correctness. So it's a very strange preference you have. Kind of inexplicable.

We intentionally not want modification of the container references. All the corresponding opposites are multi-valued so it seems better to consider where in the list you're adding?
Of course creating a copy doesn't copy the container otherwise you'd never be able to copy just part of a tree.

Yes, dynamic models would throw an exception. In the generated model we could generate cases for such things, but in the end that's just more byte code with little real value, except to help make silly code fail in a less silly way.
Re: NPE while eSetting eContainingClass [message #1759539 is a reply to message #1759531] Wed, 12 April 2017 16:17 Go to previous messageGo to next message
Edoaurd Batot is currently offline Edoaurd BatotFriend
Messages: 90
Registered: March 2015
Member
Comments follow.

I don't get your eSet comment. It can do no more and no less than the generated API. The code you show is certainly not more readable, not more efficient, and of course has way less static checking for correctness. So it's a very strange preference you have. Kind of inexplicable.

Well, I had in the past some surprises with the features I could change via eSet, but not via the API. I might remember wrong. But then I used to change the features dynamically using their list of features and using eSet became a habit. If it's more or less readable I don't know - this is about standards.
I don't mind the inexplicable perspective, I live with it Smile I'm trying to make a clear point though, sorry.



We intentionally not want modification of the container references. All the corresponding opposites are multi-valued so it seems better to consider where in the list you're adding?

That is correct, yes.



Of course creating a copy doesn't copy the container otherwise you'd never be able to copy just part of a tree.


I get that. My code is intricated in some genetic programming and deep/shallow copy is a nightmare. Anyways, thanks, I did the trick using oldEOperation.eContainer.getEOperations.add(newEOperation).
Thanks.



Yes, dynamic models would throw an exception. In the generated model we could generate cases for such things, but in the end that's just more byte code with little real value, except to help make silly code fail in a less silly way.


Well, it doesn't add value to the one(s) who know(s) the issue. But it is still a brutal NPE - I'm not the first one with that trouble (the unchangeable NPE-prone property).
Qualitatively speaking, if we consider the ease of comprehension of the code, it's not that useless to take it into consideration.
Re: NPE while eSetting eContainingClass [message #1759540 is a reply to message #1759539] Wed, 12 April 2017 16:37 Go to previous message
German Vega is currently offline German VegaFriend
Messages: 44
Registered: December 2015
Member
Hello,

Regarding your comment on the thrown exception

Quote:
And also, why is that I get a NullPointer and not the assertion : "The feature '" + eStructuralFeature.getName() + "' is not a valid feature" ?


You seem to be using an old version of EMF, given the line numbers in your stack trace I would say 2.9.

In EMF version 2.9 this is the implementation of BasicEObjectImpl.eOpenSet
  public void eOpenSet(EStructuralFeature eFeature, Object newValue) 
  {
    EStructuralFeature openFeature = ExtendedMetaData.INSTANCE.getAffiliation(eClass(), eFeature);
    if (openFeature != null)
    {
      if (!FeatureMapUtil.isFeatureMap(openFeature))
      {
        openFeature = ExtendedMetaData.INSTANCE.getGroup(openFeature);
      }
      FeatureMap featureMap = (FeatureMap)eGet(openFeature);
      ((FeatureMap.Internal)featureMap).set(eFeature, newValue);
    }
    else
    {
      throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature");
    }
  }



If you look at EMF version 2.12, the implementation of BasicEObjectImpl.eOpenSet has been changed to
  public void eOpenSet(EStructuralFeature eFeature, Object newValue) 
  {
    EStructuralFeature openFeature = ExtendedMetaData.INSTANCE.getAffiliation(eClass(), eFeature);
    if (openFeature != null)
    {
      if (!FeatureMapUtil.isFeatureMap(openFeature))
      {
        openFeature = ExtendedMetaData.INSTANCE.getGroup(openFeature);
        if (openFeature == null)
        {
          throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature");
        }
      }
      FeatureMap featureMap = (FeatureMap)eGet(openFeature);
      ((FeatureMap.Internal)featureMap).set(eFeature, newValue);
    }
    else
    {
      throw new IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature");
    }
  }


As you can see, in the newer version an additional test has been added, and you would get an informative IllegalArgumentException("The feature '" + eFeature.getName() + "' is not a valid changeable feature");

Do you have any particular constraint to use this old version of EMF?

regards

German Vega
Previous Topic:[CDO/Papyrus] Marte profile issue
Next Topic:Edit: problems with copy and paste containment
Goto Forum:
  


Current Time: Wed Jan 24 06:05:54 GMT 2018

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

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