/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.core.util;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
/**
* The ModelObjectCollector is a simple utility used to return all EObject instances
* in a specified org.eclipse.emf.ecore.resource.Resource. The implementation is
* intended to efficiently walk the model while tolerating ConcurrentModificationException
* if the resource is modified while the EObject instances are collected.
* @since 8.0
*/
public class ModelObjectCollector {
private final Resource resource;
private final Class eObjectType;
private List result;
/**
* Construct an instance of ModelObjectCollector
* @param resource the emf resource to process
* @since 4.2
*/
public ModelObjectCollector(final Resource resource) {
this(resource, null);
}
/**
* Construct an instance of ModelObjectCollector
* @param resource the emf resource to process
* @param objectType the Class that the collected EObjects must be instances of
* @since 4.2
*/
public ModelObjectCollector(final Resource resource,
final Class objectType) {
super();
this.resource = resource;
this.eObjectType = objectType;
this.result = null;
}
/**
* Return a list of all <code>EObject</code> instances in the resource.
*/
public List getEObjects() {
if (this.result == null) {
this.result = new ArrayList();
final Object[] children = this.resource.getContents().toArray();
for (int i = 0; i != children.length; ++i) {
final Object obj = children[i];
if ( obj instanceof EObject ) {
this.result.add(obj);
addChildrenToList( (EObject)obj, this.result );
}
}
// If a specific type of EObject is requested, filter out all instances
// that are not of the correct type.
if (this.eObjectType != null) {
for (final Iterator iter = this.result.iterator(); iter.hasNext();) {
final EObject obj = (EObject)iter.next();
if ( !this.eObjectType.isInstance(obj) ) {
iter.remove();
}
}
}
}
return this.result;
}
private static void addChildrenToList( final EObject eObject, final List contents ) {
if (eObject == null || contents == null) {
return;
}
int currentIndex = contents.size();
try {
List children = eObject.eContents();
for (final Iterator iter = children.iterator(); iter.hasNext();) {
final Object obj = iter.next();
if ( obj instanceof EObject ) {
contents.add(obj);
}
}
} catch (ConcurrentModificationException err) {
for (int i = currentIndex, n = contents.size(); i < n; i++) {
contents.remove(i);
}
final Object[] children = eObject.eContents().toArray();
for (int i = 0; i != children.length; ++i) {
final Object obj = children[i];
if ( obj instanceof EObject ) {
contents.add(obj);
}
}
}
for (int i = currentIndex, n = contents.size(); i < n; i++) {
final EObject obj = (EObject)contents.get(i);
addChildrenToList(obj,contents);
}
}
}