blob: 5e09854927d89a3fdf0d3dad5d99f593ae7c387b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
* Eike Stepper - (390845) Make the URIInitializingIterator a little more extensible
*******************************************************************************/
package org.eclipse.emf.compare.scope;
import static java.util.Collections.emptyIterator;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ForwardingIterator;
import com.google.common.collect.Iterators;
import java.util.Iterator;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
* This implementation of an {@link IComparisonScope} can be provided specific filters to filter out parts of
* the Notifiers' content lists.
*
* @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
*/
public class FilterComparisonScope extends AbstractComparisonScope {
/**
* This will be used in order to determine the filter that should be used to filter the EObjects' content
* list of unnecessary values.
*/
protected Predicate<? super EObject> eObjectContentFilter = Predicates.alwaysTrue();
/**
* This will be used in order to determine the filter that should be used to filter the Resources' content
* list of unnecessary values.
*/
protected Predicate<? super EObject> resourceContentFilter = Predicates.alwaysTrue();
/**
* This will be used in order to determine the filter that should be used to filter the ResourceSets'
* content list of unnecessary values.
*/
protected Predicate<? super Resource> resourceSetContentFilter = Predicates.alwaysTrue();
/**
* This will instantiate a scope with left, right and origin Notifiers defined.
*
* @param left
* The left root of this comparison.
* @param right
* The right root of this comparison.
* @param origin
* The common ancestor of <code>left</code> and <code>right</code>. May be <code>null</code>.
*/
public FilterComparisonScope(Notifier left, Notifier right, Notifier origin) {
super(left, right, origin);
}
/**
* {@inheritDoc}
* <p>
* This default implementation will only return the {@link Resource}s directly contained by
* {@link ResourceSet} which match the {@link #resourceSetContentFilter} predicate.
* </p>
*
* @see org.eclipse.emf.compare.scope.IComparisonScope#getCoveredResources(org.eclipse.emf.ecore.resource.ResourceSet)
*/
public Iterator<? extends Resource> getCoveredResources(ResourceSet resourceSet) {
if (resourceSet == null) {
return emptyIterator();
}
final Iterator<Resource> allResources = resourceSet.getResources().iterator();
final Iterator<Resource> filter = Iterators.filter(allResources, resourceSetContentFilter);
final Iterator<Resource> uriInitializingIt = new URIInitializingIterator<Resource>(filter);
return Iterators.unmodifiableIterator(uriInitializingIt);
}
/**
* {@inheritDoc}
* <p>
* This default implementation will return all direct and indirect content of the given {@link Resource},
* filtering out those {@link EObject}s that do not match {@link #resourceContentFilter}.
* </p>
*
* @see org.eclipse.emf.compare.scope.IComparisonScope#getCoveredEObjects(org.eclipse.emf.ecore.resource.Resource)
*/
public Iterator<? extends EObject> getCoveredEObjects(Resource resource) {
if (resource == null) {
return emptyIterator();
}
final Iterator<EObject> properContent = EcoreUtil.getAllProperContents(resource, false);
final Iterator<EObject> filter = Iterators.filter(properContent, resourceContentFilter);
final Iterator<EObject> uriInitializingIt = new URIInitializingIterator<EObject>(resource, filter);
return Iterators.unmodifiableIterator(uriInitializingIt);
}
/**
* {@inheritDoc}
* <p>
* This default implementation will return all direct and indirect content of the given {@link EObject},
* filtering out those {@link EObject}s that do not match {@link #eObjectContentFilter}.
* </p>
*
* @see org.eclipse.emf.compare.scope.IComparisonScope#getChildren(org.eclipse.emf.ecore.EObject)
*/
public Iterator<? extends EObject> getChildren(EObject eObject) {
if (eObject == null) {
return emptyIterator();
}
final Iterator<EObject> properContent = EcoreUtil.getAllProperContents(eObject, false);
final Iterator<EObject> filter = Iterators.filter(properContent, eObjectContentFilter);
final Iterator<EObject> uriInitializingIt = new URIInitializingIterator<EObject>(eObject, filter);
return Iterators.unmodifiableIterator(uriInitializingIt);
}
/**
* This can be used to set the filter that should be used to filter the EObjects' content list of
* unnecessary values. By default, we will use an "always true" predicate : the list won't be filtered out
* unless this is called with a new filter.
*
* @param newContentFilter
* The filter that should be used for EObject content filtering.
*/
public void setEObjectContentFilter(Predicate<? super EObject> newContentFilter) {
this.eObjectContentFilter = newContentFilter;
}
/**
* This can be used to set the filter that should be used to filter the Resources' content list of
* unnecessary values. By default, we will return an "always true" predicate : the list won't be filtered
* out unless this is called with a new filter.
*
* @param resourceContentFilter
* The filter that should be used for Resource content filtering.
*/
public void setResourceContentFilter(Predicate<? super EObject> resourceContentFilter) {
this.resourceContentFilter = resourceContentFilter;
}
/**
* This can be used to set the filter that should be used to filter the ResourceSets' content list of
* unnecessary values. By default, we will return an "always true" predicate : the list won't be filtered
* out unless this called with a new filter.
*
* @param resourceSetContentFilter
* The filter that should be used for ResourceSet content filtering.
*/
public void setResourceSetContentFilter(Predicate<? super Resource> resourceSetContentFilter) {
this.resourceSetContentFilter = resourceSetContentFilter;
}
/**
* Tries and register the URI of the given object as one of this scope's resources. Note that we only
* consider EObjects and Resources.
*
* @param <T>
* Type of this object.
* @param obj
* eObject for which we
*/
protected <T> void addUri(T obj) {
if (obj instanceof Resource) {
addUri((Resource)obj);
} else if (obj instanceof EObject) {
addUri((EObject)obj);
}
}
/**
* Registers the namespace and resource URI from the given <code>eObject</code>.
*
* @param eObject
* The given <code>eObject</code>.
*/
protected void addUri(EObject eObject) {
final Resource res = eObject.eResource();
if (res != null) {
getResourceURIs().add(res.getURI().toString());
}
getNsURIs().add(eObject.eClass().getEPackage().getNsURI());
}
/**
* Registers the resource URI from the given <code>resource</code>.
*
* @param resource
* The given <code>resource</code>.
*/
protected void addUri(Resource resource) {
getResourceURIs().add(resource.getURI().toString());
}
/**
* This iterator enables to add in the iteration the initialization of the namespace and resource uris
* set.
*
* @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
* @param <T>
* The kind of object to iterate on.
*/
private class URIInitializingIterator<T> extends ForwardingIterator<T> {
/** The origin iterator. */
private Iterator<T> delegate;
/**
* Constructor.
*
* @param delegate
* The origin iterator.
*/
URIInitializingIterator(Iterator<T> delegate) {
this.delegate = delegate;
}
/**
* Constructor.
*
* @param resource
* The resource containing the elements to iterate on.
* @param delegate
* The origin iterator.
*/
URIInitializingIterator(Resource resource, Iterator<T> delegate) {
this.delegate = delegate;
addUri(resource);
}
/**
* Constructor.
*
* @param eObject
* The EObject containing the elements to iterate on.
* @param delegate
* The origin iterator.
*/
URIInitializingIterator(EObject eObject, Iterator<T> delegate) {
this.delegate = delegate;
addUri(eObject);
}
/**
* {@inheritDoc}
*
* @see com.google.common.collect.ForwardingIterator#delegate()
*/
@Override
protected Iterator<T> delegate() {
return delegate;
}
/**
* {@inheritDoc}
*
* @see com.google.common.collect.ForwardingIterator#next()
*/
@Override
public T next() {
T obj = super.next();
addUri(obj);
return obj;
}
}
}