use of org.eclipse.emf.common.util.AbstractTreeIterator in project n4js by eclipse.
the class N4JSUnloader method getAllProperContents.
/**
* Traverse the contents of the object that is contained in the {@link ObjectToFragment}. The string builder is used
* as an accumulating parameter. That is, during the traversal it will be used and trimmed again. This allows to
* reuse the underlying char array which is already copied when the fragment is turned into a string.
*
* The fragments use the very same notation as described in
* {@link InternalEObject#eURIFragmentSegment(EStructuralFeature, EObject)}.
*
* The implementation from {@link ResourceImpl} uses a {@link SegmentSequence} rather than a {@link StringBuilder}.
* Since we have to concatenate the string in the end anyway.
*/
private static Iterator<ObjectToFragment> getAllProperContents(ObjectToFragment eObject, final StringBuilder result) {
// we inherit from the AbstractTreeIterator which will help us getting a proper pre-order traversal
return new AbstractTreeIterator<ObjectToFragment>(eObject, false) {
/* don't resolve containment proxies */
@Override
public Iterator<ObjectToFragment> getChildren(Object parent) {
final EObject current = ((ObjectToFragment) parent).object;
final EStructuralFeature[] containments = containmentFeatures(current);
if (containments == null || containments.length == 0) {
// no containment features found, exit
return Iterators.emptyIterator();
}
// we have at least one containment feature - append the fragment delimiter '/'
result.append('/');
// and concatenate all the iterators for the children
return Iterators.concat(getFeatureIterators(current, containments));
}
/**
* Returns an iterator of iterators. Each nested iterator covers a single containment feature. If the
* feature is multi valued, the nested iterator has as many values as are set on the feature.
*/
private Iterator<Iterator<ObjectToFragment>> getFeatureIterators(EObject current, EStructuralFeature[] containments) {
return new AbstractIterator<Iterator<ObjectToFragment>>() {
/**
* The length of the string builder before something was added by this traversing iterator.
*/
private final int prevLength = result.length();
private int featureIdx = 0;
@Override
protected Iterator<ObjectToFragment> computeNext() {
while (featureIdx < containments.length) {
EStructuralFeature containment = containments[featureIdx];
featureIdx++;
// only consider features that have values
if (current.eIsSet(containment)) {
// reset the string builder
result.setLength(prevLength);
// append the @ sign and the feature name
// '@<feature-name>'
result.append('@').append(containment.getName());
// compute the contained values
return newValueIterator(containment);
}
}
return endOfData();
}
/**
* Returns an iterator for the values that are assigned to the given containment feature.
*/
private Iterator<ObjectToFragment> newValueIterator(EStructuralFeature feature) {
if (feature.isMany()) {
// add the dot as the delimiter between feature name and index in the list
result.append('.');
// compute the value indexes
return newManyValueIterator((List<?>) current.eGet(feature));
} else {
// no dot is added for single valued features
return newSingleValueIterator((EObject) current.eGet(feature));
}
}
/**
* Finalize the fragment for the given instance and return a singleton iterator for it.
*/
private Iterator<ObjectToFragment> newSingleValueIterator(EObject value) {
ObjectToFragment objectToFragment = new ObjectToFragment(value, result.toString());
return Iterators.singletonIterator(objectToFragment);
}
/**
* Traverse the list of values and return the feature indexes along with the values.
*/
private AbstractIterator<ObjectToFragment> newManyValueIterator(final List<?> values) {
return new AbstractIterator<ObjectToFragment>() {
/**
* The length of the string builder before something was added by this traversing iterator.
*/
private final int prevLengthBeforeIdx = result.length();
/**
* The index in the value list.
*/
private int valueIdx = 0;
@Override
protected ObjectToFragment computeNext() {
if (valueIdx < values.size()) {
EObject value = (EObject) values.get(valueIdx);
result.setLength(prevLengthBeforeIdx);
result.append(valueIdx);
valueIdx++;
return new ObjectToFragment(value, result.toString());
}
return endOfData();
}
};
}
};
}
private EStructuralFeature[] containmentFeatures(final EObject current) {
return ((EClassImpl.FeatureSubsetSupplier) current.eClass().getEAllStructuralFeatures()).containments();
}
};
}
Aggregations