Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 328180

Summary: ArrayIndexOutOfBoundsException using Dynamic EMF
Product: [Modeling] EMF Reporter: Flavio Donze <flavio.donze>
Component: TeneoAssignee: Martin Taal <mtaal>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Flavio Donze CLA 2010-10-19 16:58:25 EDT
Build Identifier: 1.1.2.v201006151458

I have a dynamic model which extends part of a static model.
I'm receiving the following exception trying to store an object:

java.lang.ArrayIndexOutOfBoundsException: 6
	at org.eclipse.emf.ecore.impl.BasicEObjectImpl$EPropertiesHolderBaseImpl.dynamicGet(BasicEObjectImpl.java:159)
	at org.eclipse.emf.teneo.hibernate.mapping.property.EcoreAccess.getManyEFeatureValue(EcoreAccess.java:50)
	at com.softmodeler.service.impl.NlsObjectService.create(NlsObjectService.java:92)
...

The model object I try to store has this structure:

BasicObjectNls (from static model)
- id
- locale
- objectId

DataObjectNls (dynamic)
- name
- description

DocumentNls (dynamic)
- parts !containment 0..n Reference

Storing the object without the DocumentNls.parts reference works totally fine.

I did some debugging and I found that EcoreAccess.getManyEFeatureValue() uses the wrong feature id.
EcoreAccess.getFeatureId() returns the actuall feature id but calls dynamicGet().

BasicEObjectImpl.eDynamicFeatureID()
return eClass().getFeatureID(eStructuralFeature) - eStaticFeatureCount();

EcoreAccess.getFeatureId()
return owner.eClass().getFeatureID(eFeature);

I was looking for a fix and think
return owner.eGet(eFeature);
in getManyEFeatureValue() would solve the problem.

On the other side, I can't figure out why getValueHolder is called. Maybe for a special case?

Reproducible: Always
Comment 1 Flavio Donze CLA 2010-10-22 08:24:42 EDT
As additional information, updated to version 1.1.2.v201009161849. Still same exception.
Comment 2 Flavio Donze CLA 2010-10-27 08:25:49 EDT
I imported the sources and changed the following:

/** Sets an elist using the passed feature */
public static void setManyEFeatureValue(EStructuralFeature eFeature, Object value, BasicEObjectImpl owner) {
	owner.eSet(eFeature, value);
	//		final DynamicValueHolder dvh = getValueHolder(owner);
	//		dvh.dynamicSet(getFeatureId(owner, eFeature), value);
}

/** Gets an elist using the passed feature */
public static EList<?> getManyEFeatureValue(EStructuralFeature eFeature, BasicEObjectImpl owner) {
	//		final DynamicValueHolder dvh = getValueHolder(owner);
	//		return (EList<?>) dvh.dynamicGet(getFeatureId(owner, eFeature));
	return (EList<?>) owner.eGet(eFeature);
}

This got rid of the Exception and seems to work fine so far, but as stated earlier I don't know what getValueHolder(owner) is all about.
Comment 3 Martin Taal CLA 2010-11-04 01:21:03 EDT
Hi Flavio,
I tried to reproduce this by having the same type of inheritance as you defined (so static extended by a dynamic and then again extended by a dynamic). With me it does not fail, this can happen because accidentally the feature ids are correctly computed.

What do you mean with this:
>>> I found that EcoreAccess.getManyEFeatureValue() uses the wrong feature id.
>>> EcoreAccess.getFeatureId() returns the actuall feature id but calls dynamicGet().

can you debug how the feature id is computed in this case? I think that's where the key of the issue can be found. 

gr. Martin
Comment 4 Flavio Donze CLA 2010-11-04 11:51:28 EDT
Hi Martin

As I see it the problem is that EcoreAccess.getFeatureId() returns the feature id/index calculated with the static and dynamic features together. For example DocumentNls.parts = 6.

DynamicValueHolder in my case is then BasicEObjectImpl.EPropertiesHolderImpl, dynamicGet() and dynamicSet() expects then the dynamic feature id which would be 3.

The parameter of the get and set method is called dynamicFeatureID and commented as:
@param dynamicFeatureID the feature's index in the cached dynamic values.

BasicEObjectImpl.EPropertiesHolderImpl holds an array eSettings[], it's size is 4 and on position 3 is the actual content of DocumentNls.parts.
To get the value eSettings[dynamicFeatureID] is done, which then throws the exception with dynamicFeatureID being 6.

You can't reproduce this? It only happens when having EFeatures in the dynamic object. DocumentNls.parts is a non containment 0..n Reference.
Comment 5 Flavio Donze CLA 2010-11-04 12:04:12 EDT
Some additional information.

BasicEObjectImpl.eGet(int featureID, boolean resolve, boolean coreType)

does the following:
int dynamicFeatureID = featureID - eStaticFeatureCount();

so the dynamicFeatureID is the id subtracted with the static feature count.
In my case 
featureID=6
eStaticFeatureCount()=3
results in dynamicFeatureID=3
Comment 6 Martin Taal CLA 2010-11-05 05:24:01 EDT
My mistake, I could reproduce it now, I have committed a fix and doing a build right away.

gr. Martin
Comment 7 Martin Taal CLA 2010-11-05 05:53:35 EDT
A new build is available, can you try it and let me know if it solved? Thanks!
gr. Martin
Comment 8 Flavio Donze CLA 2010-11-05 06:40:35 EDT
Hi Martin

WORKS! Thanks a lot for fixing!
Comment 9 Martin Taal CLA 2010-11-05 07:41:02 EDT
Good to hear!

gr. Martin