Search in sources :

Example 1 with AbstractTreeIterator

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();
        }
    };
}
Also used : AbstractTreeIterator(org.eclipse.emf.common.util.AbstractTreeIterator) EObject(org.eclipse.emf.ecore.EObject) InternalEObject(org.eclipse.emf.ecore.InternalEObject) EStructuralFeature(org.eclipse.emf.ecore.EStructuralFeature) Iterator(java.util.Iterator) AbstractTreeIterator(org.eclipse.emf.common.util.AbstractTreeIterator) AbstractIterator(com.google.common.collect.AbstractIterator) EObject(org.eclipse.emf.ecore.EObject) InternalEObject(org.eclipse.emf.ecore.InternalEObject) List(java.util.List) AbstractIterator(com.google.common.collect.AbstractIterator)

Aggregations

AbstractIterator (com.google.common.collect.AbstractIterator)1 Iterator (java.util.Iterator)1 List (java.util.List)1 AbstractTreeIterator (org.eclipse.emf.common.util.AbstractTreeIterator)1 EObject (org.eclipse.emf.ecore.EObject)1 EStructuralFeature (org.eclipse.emf.ecore.EStructuralFeature)1 InternalEObject (org.eclipse.emf.ecore.InternalEObject)1