padl.kernel.impl.AbstractGenericContainerOfConstituents.java Source code

Java tutorial

Introduction

Here is the source code for padl.kernel.impl.AbstractGenericContainerOfConstituents.java

Source

/*******************************************************************************
 * Copyright (c) 2001-2014 Yann-Gal Guhneuc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Yann-Gal Guhneuc and others, see in file; API and its implementation
 ******************************************************************************/
package padl.kernel.impl;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.commons.lang.ArrayUtils;
import padl.event.ElementEvent;
import padl.event.EntityEvent;
import padl.event.IEvent;
import padl.event.IModelListener;
import padl.event.InvokeEvent;
import padl.kernel.Constants;
import padl.kernel.IAbstractModel;
import padl.kernel.IConstituent;
import padl.kernel.IConstituentOfEntity;
import padl.kernel.IConstituentOfModel;
import padl.kernel.IConstituentOfOperation;
import padl.kernel.IContainer;
import padl.kernel.IEntity;
import padl.kernel.IFilter;
import padl.kernel.INavigable;
import padl.kernel.IObservable;
import padl.kernel.IOperation;
import padl.kernel.IPackage;
import padl.kernel.exception.ModelDeclarationException;
import padl.path.IConstants;
import padl.util.Util;
import util.io.ProxyConsole;

/**
 * @author Yann-Gal Guhneuc
 * @since 2004/04/09
 */
// Sebastien Colladon 23/04/2012 : Change the visibility to public to
// allow other project to extend from this class in the particular case 
// of Eclipse bundle loader (avoid IllegalAccessError).
// TODO Is "public" necessary?
public abstract class AbstractGenericContainerOfConstituents implements Serializable {

    private static class GenericObservable implements Serializable {
        private static final long serialVersionUID = 198074990982735832L;
        // Yann 2010/10/10: DB4O
        // Used to be:
        //   private final List listOfModelListeners =
        // I removed the final to make DB4O works...
        // TODO: Understand how to keep it final with DB4O!
        private Set listOfModelListeners = new HashSet(GenericContainerConstants.INITIAL_SIZE_GENERIC_OBSERVABLE);

        public final boolean addModelListener(final IModelListener aModelListener) {

            return this.listOfModelListeners.add(aModelListener);
        }

        public final boolean addModelListeners(final List aListOfModelListeners) {

            final Iterator iterator = aListOfModelListeners.iterator();
            boolean result = false;
            while (iterator.hasNext()) {
                result |= this.addModelListener((IModelListener) iterator.next());
            }
            return result;
        }

        public final void fireModelChange(final String eventType, final IEvent modelEvent) {

            if (this.listOfModelListeners.size() > 0) {
                // First, I look for the method corresponding to the event type.
                final Method[] methods = IModelListener.class.getDeclaredMethods();
                Method eventMethod = null;
                for (int i = 0; i < methods.length && eventMethod == null; i++) {
                    if (methods[i].getName().equals(eventType)) {
                        eventMethod = methods[i];
                    }
                }

                // Second, I notify the listeners with the appropriate event.
                if (eventMethod != null) {
                    final Iterator iterator = this.listOfModelListeners.iterator();
                    while (iterator.hasNext()) {
                        final IModelListener listener = (IModelListener) iterator.next();
                        if (listener != null) {
                            try {
                                eventMethod.invoke(listener, new Object[] { modelEvent });
                            } catch (final IllegalAccessException iae) {
                                iae.printStackTrace(ProxyConsole.getInstance().errorOutput());
                            } catch (final InvocationTargetException ite) {
                                ite.printStackTrace(ProxyConsole.getInstance().errorOutput());
                            }
                        }
                    }
                }
            }
        }

        public Iterator getIteratorOnModelListeners() {
            return this.listOfModelListeners.iterator();
        }

        protected List getModelListeners() {
            return new ArrayList(this.listOfModelListeners);
        }

        public final void removeModelListener(final IModelListener aModelListener) {

            this.listOfModelListeners.remove(aModelListener);
        }

        public final void removeModelListeners(final List aListOfModelListeners) {

            final Iterator iterator = aListOfModelListeners.iterator();
            while (iterator.hasNext()) {
                this.removeModelListener((IModelListener) iterator.next());
            }
        }
    }

    private class NonConcurrentIterator implements Iterator, Serializable {
        private static final long serialVersionUID = 1209788683542287364L;

        // Cannot be Singleton and member class!?
        //   private static NonConcurrentConstituentIterator UniqueInstance;
        //   public Iterator getInstance() {
        //      if (NonConcurrentConstituentIterator.UniqueInstance == null) {
        //         NonConcurrentConstituentIterator.UniqueInstance =
        //            new NonConcurrentConstituentIterator();
        //      }
        //      return NonConcurrentConstituentIterator.UniqueInstance;
        //   }

        private int expectedModCount = 0;
        private int index = 0;

        public NonConcurrentIterator() {
        }

        public boolean hasNext() {
            final boolean hasNext = this.index < AbstractGenericContainerOfConstituents.this.size;
            if (!hasNext) {
                AbstractGenericContainerOfConstituents.this.nciIterating--;
            } else {
                AbstractGenericContainerOfConstituents.this.nciIterating++;
            }
            return hasNext;
        }

        public Object next() {
            try {
                if (this.expectedModCount != AbstractGenericContainerOfConstituents.this.nciModCount) {
                    AbstractGenericContainerOfConstituents.this.nciIterating--;
                    throw new ConcurrentModificationException();
                }
                final Object next = AbstractGenericContainerOfConstituents.this.constituents[this.index];
                this.index++;
                AbstractGenericContainerOfConstituents.this.nciIterating++;
                return next;
            } catch (final IndexOutOfBoundsException e) {
                AbstractGenericContainerOfConstituents.this.nciIterating--;
                throw new NoSuchElementException();
            }
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

        private void reset() {
            this.expectedModCount = AbstractGenericContainerOfConstituents.this.nciModCount;
            this.index = 0;
        }
    }

    private static final long serialVersionUID = -2006341987649472498L;

    // Yann 2004/12/13: Performances
    // When loading huge AOL file, it seems that:
    // this.doesContainConstituentWithID(aConstituent.getConstituentID())
    // is a performance bottleneck because of the many (maaany!)
    // instances of Iterator built. I cannot replace the list by a
    // hashtable which key is the actor ID because the list must be
    // sorted to ensure similar behavior on different platforms.
    // So, I cache the actor in a second list.
    //
    // Yann 2009/04/28: Performances (bis)
    // I replaced these caches by using maps of constituents.
    // private List actorsIDCache = new ArrayList();
    // private List actorsNameCache = new ArrayList();
    //
    // Yann 2009/04/28: Performances (bis)
    // I use a TreeMap that is an ordered HashMap...
    // to make it easier to test the code and to
    // guarantee that, whatever the insertion, the
    // constituent will be ordered.
    //
    // Yann 2009/05/03: Performances (ter)
    // I now manage my own array of constituents,
    // I make it grow from prime number to prime
    // number using an indice.
    protected IConstituent[] constituents;
    // protected ConstituentIterator constituentIterator;
    // Yann 2010/10/10: DB4O
    // Used to be:
    // protected final INavigable containerConsitituent;
    // I removed the final to make DB4O works...
    // TODO Understand how to keep it final with DB4O!
    // TODO Why "protected" fields?
    protected INavigable containerConsitituent;
    private int indexInPrimeNumbersArray;
    private NonConcurrentIterator nciInstance;
    private int nciIterating;
    private int nciModCount;
    // Yann 2013/07/18: Fragile-base class!
    // There is no reason for this class to inherit from GenericObservable,
    // it better delegates appropriate calls to an instance of this class.
    // Besides, delegation allows implementing a "smart" algorithm to
    // propagate the adding of a listener to constituents including in this
    // container :-) See the test TestListeners.
    private GenericObservable observable;
    protected int size;
    private int uniqueID;

    public AbstractGenericContainerOfConstituents(final INavigable aContainerConstituent) {

        this.containerConsitituent = aContainerConstituent;
        this.nciInstance = new NonConcurrentIterator();
        this.observable = new GenericObservable();
        this.resetListOfConstituents();
    }

    public AbstractGenericContainerOfConstituents(final INavigable aContainerConstituent,
            final int anInitialCapacity) {

        this.containerConsitituent = aContainerConstituent;
        this.nciInstance = new NonConcurrentIterator();
        this.observable = new GenericObservable();
        this.resetListOfConstituents(anInitialCapacity);
    }

    public void addConstituent(final IConstituent aConstituent) {
        // Yann 2009/05/06: Path
        // After having removed a constituent from a model,
        // I make sure that I "reset" its path so that I can
        // add it to another model. Also, I will test when
        // adding a constituent if it does not include path
        // information to prevent two models to share
        // constituents, maybe the clone process should be
        // involved too... I'll think about it later.
        // Yann 2010/04/29: Path!
        // I share the same default package across
        // models but it does not matter because the
        // model name does not matter.
        if (ArrayUtils.contains(aConstituent.getPath(), IConstants.ABSTRACT_MODEL_SYMBOL)
                && !Arrays.equals(aConstituent.getID(), Constants.DEFAULT_PACKAGE_ID)) {

            final StringBuffer buffer = new StringBuffer();
            buffer.append("Shared constituent: ");
            buffer.append(aConstituent.getID());
            buffer.append(" (");
            buffer.append(aConstituent.getClass());
            buffer.append(") in ");
            buffer.append(this.getClass());
            buffer.append(
                    "\nRemove this consituent from its origin model first before adding it to the current model.");
            throw new ModelDeclarationException(buffer.toString());
        }

        if (this.doesContainConstituentWithID(aConstituent.getID())) {
            final StringBuffer buffer = new StringBuffer();
            buffer.append(this.getClass().getName());
            buffer.append(" reports a duplicate constituent \"");
            buffer.append(aConstituent.getID());
            buffer.append("\" (");
            buffer.append(aConstituent.getClass().getName());
            buffer.append(") in \"");
            buffer.append(this.containerConsitituent.getPath());
            buffer.append("\" (");
            buffer.append(this.containerConsitituent.getClass().getName());
            buffer.append(')');
            throw new ModelDeclarationException(buffer.toString());
        }

        this.directlyAddConstituent(aConstituent);
    }

    public void addModelListener(final IModelListener aModelListener) {
        // Yann 2016/09/18: Recursion!
        // I make sure that I recurse into the sub-constituents of
        // this constituent iff it was the first time that I added
        // this particular listener to this constituent.
        if (this.observable.addModelListener(aModelListener)) {
            // Yann 2013/07/18: Delegation!
            // Now that I properly delegate to a GenericObservable object,
            // I can use this delegation to also properly propagate the
            // addition of any listener. I don't need to use a visitor
            // because the addModelListener(IModelListener) will recursively
            // add the listener to all the children of each constituent.
            // Yann 2015/09/01: Listeners!
            // Finally, getting it right: model listeners are for models 
            // *only* but are propagated to all constituents of the models!
            for (int i = 0; i < this.size; i++) {
                final IConstituent constituent = this.constituents[i];
                if (constituent instanceof IObservable) {
                    ((IObservable) constituent).addModelListener(aModelListener);
                }
                if (constituent instanceof IPrivateModelObservable) {
                    ((IPrivateModelObservable) constituent).addModelListener(aModelListener);
                }
            }
        }
    }

    public void addModelListeners(final List aListOfModelListeners) {
        final Iterator iterator = aListOfModelListeners.iterator();
        while (iterator.hasNext()) {
            final IModelListener listener = (IModelListener) iterator.next();
            this.addModelListener(listener);
        }
    }

    private void addUniqueIDToEnclosedConstituent(final IConstituent aConstituent) {
        // Yann 2006/02/24: UniqueID...
        // I need a UniqueID for IMethodInvocation and IParemeter in IMethod
        // and for any IRelationship in IEntity. So, when using the method
        // concretelyAddConstituent(), I take care of the unique ID.

        this.uniqueID++;
        if (this instanceof AbstractGenericContainerOfConstituents && aConstituent instanceof Constituent) {

            final char[] uniqueID = String.valueOf(this.uniqueID).toCharArray();
            final int endIndexExclusive = aConstituent.getDisplayID().indexOf(Constants.NUMBER_SEPARATOR);
            final char[] constituentID;
            if (endIndexExclusive > 0) {
                constituentID = ArrayUtils.subarray(aConstituent.getID(), 0, endIndexExclusive);
            } else {
                constituentID = aConstituent.getID();
            }
            final char[] newID = new char[constituentID.length + Constants.NUMBER_SEPARATOR.length()
                    + uniqueID.length];
            System.arraycopy(constituentID, 0, newID, 0, constituentID.length);
            System.arraycopy(Constants.NUMBER_SEPARATOR.toCharArray(), 0, newID, constituentID.length,
                    Constants.NUMBER_SEPARATOR.length());
            System.arraycopy(uniqueID, 0, newID, constituentID.length + Constants.NUMBER_SEPARATOR.length(),
                    uniqueID.length);
            ((Constituent) aConstituent).setID(newID);

            // Yann 2009/06/06: Path!
            // I don't forget to update the path accordingly...
            ((Constituent) aConstituent).setPath(newID);
        }
    }

    private void broadcastAdditionOfConstituent(final IConstituent aConstituent) {
        // Yann 2004/04/09: Listener!
        // It is now the responsibility of this class to manage
        // the listeners and to send the appropriate events when
        // a change occurs.
        // Yann 2006/03/08: Listeners...
        // I recursively add the listeners to the constituent that I add...
        if (aConstituent instanceof IObservable) {
            ((IObservable) aConstituent).addModelListeners(this.observable.getModelListeners());
        }
        if (aConstituent instanceof IPrivateModelObservable) {
            ((IPrivateModelObservable) aConstituent).addModelListeners(this.observable.getModelListeners());
        }

        // Yann 2005/10/07: Packages!
        // I should distinguish among entities and packages...
        // Yann 2015/07/16: Law and Order!
        // Aha, this code was too simplistic... The example was
        // adding a IGlobalFunction (from CPP), which is both
        // an entity and a method, into a class... I do not want
        // to add this method as a top-level entity, because I
        // want to add it to a class, not a package or model...
        // So, rather than to trigger the notification on the
        // type of the added constituent, I do that now in the 
        // type of the receiving container and in reverse order.
        if (this.containerConsitituent instanceof IOperation) {
            this.fireModelChange(IModelListener.INVOKE_ADDED, new InvokeEvent(
                    (IContainer) this.containerConsitituent, (IConstituentOfOperation) aConstituent));
        } else if (this.containerConsitituent instanceof IEntity) {
            this.fireModelChange(IModelListener.ELEMENT_ADDED,
                    new ElementEvent((IContainer) this.containerConsitituent, (IConstituentOfEntity) aConstituent));
        } else if (this.containerConsitituent instanceof IPackage) {
            this.fireModelChange(IModelListener.ENTITY_ADDED,
                    new EntityEvent((IContainer) this.containerConsitituent, (IConstituentOfModel) aConstituent));
        } else if (this.containerConsitituent instanceof IAbstractModel) {
            this.fireModelChange(IModelListener.ENTITY_ADDED,
                    new EntityEvent((IContainer) this.containerConsitituent, (IConstituentOfModel) aConstituent));
        }
    }

    private void broadcastRemovalOfConstituent(final IConstituent aConstituent) {
        // Yann 2004/04/09: Listener!
        // It is now the responsibility of this class to manage
        // the listeners and to send the appropriate events when
        // a change occurs.
        // Yann 2006/03/08: Listeners...
        // I recursively remove the listeners to the constituent that I
        // remove...
        if (aConstituent instanceof IObservable) {
            ((IObservable) aConstituent).removeModelListeners(this.observable.getModelListeners());
        }
        if (aConstituent instanceof IPrivateModelObservable) {
            ((IPrivateModelObservable) aConstituent).removeModelListeners(this.observable.getModelListeners());
        }

        // Yann 2005/10/07: Packages!
        // I should distinguish among entities and packages...
        if (aConstituent instanceof IConstituentOfModel) {
            this.fireModelChange(IModelListener.ENTITY_REMOVED,
                    new EntityEvent((IContainer) this.containerConsitituent, (IConstituentOfModel) aConstituent));
        } else if (aConstituent instanceof IConstituentOfEntity) {
            this.fireModelChange(IModelListener.ELEMENT_REMOVED,
                    new ElementEvent((IContainer) this.containerConsitituent, (IConstituentOfEntity) aConstituent));
        } else if (aConstituent instanceof IConstituentOfOperation) {
            this.fireModelChange(IModelListener.INVOKE_REMOVED, new InvokeEvent(
                    (IContainer) this.containerConsitituent, (IConstituentOfOperation) aConstituent));
        }
    }

    private final void directlyAddConstituent(final IConstituent aConstituent) {
        // Yann 2004/12/20: Test and order II!
        // This method is used to add method invocations to
        // constructors and methods only because method
        // invocations must not be sorted.

        final int minCapacity = this.size + 1;
        final int oldCapacity = this.constituents.length;
        if (minCapacity > oldCapacity) {
            this.indexInPrimeNumbersArray++;
            int newCapacity;
            if (this.indexInPrimeNumbersArray < GenericContainerConstants.NUMBER_OF_PRIME_NUMBERS) {
                newCapacity = GenericContainerConstants.PRIME_NUMBERS[this.indexInPrimeNumbersArray];
            } else {
                newCapacity = oldCapacity
                        + GenericContainerConstants.PRIME_NUMBERS[GenericContainerConstants.NUMBER_OF_PRIME_NUMBERS
                                / 2];
            }
            if (newCapacity < minCapacity) {
                newCapacity = minCapacity;
            }

            final IConstituent[] oldData = this.constituents;
            this.constituents = new IConstituent[newCapacity];
            System.arraycopy(oldData, 0, this.constituents, 0, this.size);
        }
        this.constituents[this.size] = aConstituent;
        this.size++;
        this.nciModCount++;

        this.updatePathUponAddition(this.containerConsitituent, aConstituent);
        this.directlyAddConstituentExtra(aConstituent);
        this.broadcastAdditionOfConstituent(aConstituent);
    }

    protected void directlyAddConstituentExtra(final IConstituent aConstituent) {
        // Default behaviour: do nothing.
    }

    // Sbastien Colladon 24/04/2012 : Visibility set to public...If you have
    // more than one ClassLoader then the only methods you can invoke on classes
    // from other ClassLoaders are public ones because private, package and
    // protected methods are all inaccessible due to being in a different
    // package (even when their package has the same name).
    public final void directlyAddConstituentWithUniqueID(final IConstituent aConstituent) {

        // Yann 2006/02/24: UniqueID...
        // I need a UniqueID for IMethodInvocation and IParemeter in IMethod
        // and for any IRelationship in IEntity. So, when using the method
        // concretelyAddConstituent(), I take care of the unique ID.
        this.addUniqueIDToEnclosedConstituent(aConstituent);
        this.directlyAddConstituent(aConstituent);
    }

    public boolean doesContainConstituentWithID(final char[] anID) {
        for (int i = 0; i < this.size; i++) {
            final IConstituent constituent = this.constituents[i];
            if (Arrays.equals(constituent.getID(), anID)) {
                return true;
            }
        }
        return false;
    }

    public boolean doesContainConstituentWithName(final char[] aName) {
        return this.getConstituentFromName(aName) != null;
    }

    public void fireModelChange(final String anEventType, final IEvent anEvent) {
        this.observable.fireModelChange(anEventType, anEvent);
    }

    public Iterator getConcurrentIteratorOnConstituents() {
        // Yann 2005/10/12: Iterator!
        // I replace the list with an iterator, but this
        // is a major bottleneck in some specific case!
        // TODO: Implement my own "smart" iterator which
        // could be tightly linked with the AbstractContainer
        // class to prevent too many memory allocation (Singleton).
        // (The name of the method is deliberate for consistency
        // and also as a joke :-).)
        final IConstituent[] copyOfConstituents = new IConstituent[this.size];
        System.arraycopy(this.constituents, 0, copyOfConstituents, 0, this.size);
        return Arrays.asList(copyOfConstituents).iterator();
    }

    public Iterator getConcurrentIteratorOnConstituents(final IFilter aFilter) {
        // Yann 2005/10/12: Iterator!
        // I replace the list with an iterator, but this
        // is a major bottleneck in some specific case!
        // TODO: Implement my own "smart" iterator which
        // could be tightly linked with the AbstractContainer
        // class to prevent too many memory allocation (Singleton).
        final IConstituent[] copyOfConstituents = new IConstituent[this.size];
        System.arraycopy(this.constituents, 0, copyOfConstituents, 0, this.size);
        return Util.getFilteredConstituentsIterator(copyOfConstituents, this.size, aFilter);
    }

    public Iterator getConcurrentIteratorOnConstituents(final java.lang.Class aConstituentType) {
        // Yann 2005/10/12: Iterator!
        // I replace the list with an iterator, but this
        // is a major bottleneck in some specific case!
        // TODO: Implement my own "smart" iterator which
        // could be tightly linked with the AbstractContainer
        // class to prevent too many memory allocation (Singleton).
        // (The name of the method is deliberate for consistency
        // and also as a joke :-).)
        final IConstituent[] copyOfConstituents = new IConstituent[this.size];
        System.arraycopy(this.constituents, 0, copyOfConstituents, 0, this.size);
        return Util.getTypedConstituentsIterator(copyOfConstituents, this.size, aConstituentType);
    }

    public IConstituent getConstituentFromID(final char[] anID) {
        // Yann 2004/12/13: Performances
        // I cached the actorID to improve performance
        // (to avoid creating instances of Iterator over and over again).
        // I can now you the cached value to give me the index of the
        // constituent in the list of actors.
        // Yann 2009/04/29: Dirty!
        // I went back to this solution of using an iterator because
        // I am now storing the iterator :-)
        final Iterator iterator = this.getIteratorOnConstituents();
        while (iterator.hasNext()) {
            final IConstituent constituent = (IConstituent) iterator.next();
            if (Arrays.equals(constituent.getID(), anID)) {
                return constituent;
            }
        }
        return null;
    }

    public IConstituent getConstituentFromID(final String anID) {
        return this.getConstituentFromID(anID.toCharArray());
    }

    public IConstituent getConstituentFromName(final char[] aName) {
        // Yann 2007/11/21: Performances
        // I cached the actorName to improve performance
        // (to avoid creating instances of Iterator over and over again).
        // I can now you the cached value to give me the index of the
        // constituent in the list of actors.
        // Yann 2009/04/29: Dirty!
        // I went back to this solution of using an iterator because
        // I am now storing the iterator :-)
        final Iterator iterator = this.getIteratorOnConstituents();
        while (iterator.hasNext()) {
            final IConstituent constituent = (IConstituent) iterator.next();
            if (Arrays.equals(constituent.getName(), aName)) {
                return constituent;
            }
        }
        return null;
    }

    public IConstituent getConstituentFromName(final String aName) {
        return this.getConstituentFromName(aName.toCharArray());
    }

    public Iterator getIteratorOnConstituents() {
        // Yann 2005/10/12: Iterator!
        // I replace the list with an iterator, but this
        // is a major bottleneck in some specific case!
        // I should implement my own "smart" iterator which
        // could be tightly linked with the AbstractContainer
        // class to prevent too many memory allocation (Singleton).
        //   this.constituentIterator.reset();
        //   return this.constituentIterator;
        // Yann 2013/07/11: Embedded iterators!
        // I cannot all the time return the same instance of the
        // iterator for the case where two iterations are embedded
        // in one another... So, I keep track whether someone is
        // iterating and, if there is someone, I create a new
        // instance. This is a different case than comodification
        // and thus cannot be treated similarly. 
        if (this.nciIterating > 0) {
            this.nciInstance = new NonConcurrentIterator();
            this.nciInstance.reset();
            return this.nciInstance;
        } else {
            this.nciInstance.reset();
            return this.nciInstance;
        }
    }

    public Iterator getIteratorOnConstituents(final IFilter aFilter) {
        // Yann 2005/10/12: Iterator!
        // I replace the list with an iterator, but this
        // is a major bottleneck in some specific case!
        // TODO: Implement my own "smart" iterator which
        // could be tightly linked with the AbstractContainer
        // class to prevent too many memory allocation (Singleton).
        // TODO: When using an array, the following implementation
        // is terribly inefficient!! Include directly the filter here.
        return Util.getFilteredConstituentsIterator(this.constituents, this.size, aFilter);
    }

    public Iterator getIteratorOnConstituents(final java.lang.Class aConstituentType) {

        // Yann 2005/10/12: Iterator!
        // I replace the list with an iterator, but this
        // is a major bottleneck in some specific case!
        // TODO: Implement my own "smart" iterator which
        // could be tightly linked with the AbstractContainer
        // class to prevent too many memory allocation (Singleton).
        // TODO: When using an array, the following implementation
        // is terribly inefficient!! Include directly the filter here.
        return Util.getTypedConstituentsIterator(this.constituents, this.size, aConstituentType);
    }

    public Iterator getIteratorOnModelListeners() {
        return this.observable.getIteratorOnModelListeners();
    }

    public int getNumberOfConstituents() {
        // Yann 2005/10/12: Iterator!
        // I replace the list with an iterator, but this
        // is a major bottleneck in some specific case!
        return this.size;
    }

    public int getNumberOfConstituents(final java.lang.Class aConstituentType) {
        // Duc-Loc 2006/01/25: Consistency
        final Iterator iterator = Util.getTypedConstituentsIterator(this.constituents, this.size, aConstituentType);

        int size = 0;
        while (iterator.hasNext()) {
            iterator.next();
            size++;
        }

        return size;
        // Ask Yann why getTypedConstituentsList() is set to private arrrggg!!!
        // Because, we don't want to give access to sensible information :-)
    }

    public void removeConstituentFromID(final char[] anID) {
        // Yann 2013/07/11: Double search
        // Why search for the constituent and then iterate through them all again...? 
        //   this.removeConstituentFromID0(this.getConstituentFromID(anID));
        this.removeConstituentFromID0(anID);
    }

    // /**
    // * This method returns a list of all the
    // * actors (instances of Entity) added to
    // *
    // * this model.
    // *
    // * @deprecated This method is dangerous because it exposes the
    // * inner working of all the constituents that are able to contains
    // * other constituents. Thus, it is now replaced with the two
    // * getIterator() and getIterator(Class aConstituentType) methods
    // * (and related methods).
    // */
    // public List listOfConstituents() {
    // return this.listOfConstituents;
    // }
    private final void removeConstituentFromID0(final char[] anID) {
        // Salima and Yann 2009/08/07: Null constituent and improvement
        // Why is this method protected when it is called only from
        //   removeConstituentFromID(final char[] anID)
        // changed to private!
        // We now check for a null value for the parameter, in case someone
        // tries to remove a constituent that does not exist in the model.
        int index = -1;
        for (int i = 0; i < this.size; i++) {
            if (Arrays.equals(this.constituents[i].getID(), anID)) {
                index = i;
                break;
            }
        }
        if (index > -1) {
            final IConstituent constituent = this.constituents[index];
            if (index < this.size - 1) {
                System.arraycopy(this.constituents, index + 1, this.constituents, index, this.size - index - 1);
            }
            this.size--;
            this.nciModCount++;

            // Yann 2015/05/24: Nullification!
            // I do not forget to nullify the position of the constituent
            // that I removed!!! Else, whenever I sort the array, I would
            // get very weird results: a small array containing only the
            // same constituent.
            this.constituents[this.size] = null;

            // Yann 2004/04/09: Listener!
            // It is now the responsibility of this class to manage
            // the listeners and to send the appropriate events when
            // a change occurs.
            // if (this instanceof IAbstractLevelModel) {
            // this.fireModelChange(
            // IModelListener.ENTITY_REMOVED,
            // new EntityEvent(
            // (IAbstractLevelModel) this,
            // (IFirstClassEntity) aConstituent));
            // }
            // else if (this instanceof IFirstClassEntity) {
            // this.fireModelChange(
            // IModelListener.ELEMENT_REMOVED,
            // new ElementEvent(
            // (IFirstClassEntity) this,
            // (IElement) aConstituent));
            // }
            // Yann 2011/06/11: Top-level entities...
            this.broadcastRemovalOfConstituent(constituent);
            this.updatePathUponRemoval(constituent);
        } else {
            throw new NoSuchElementException();
        }
    }

    public void removeModelListener(final IModelListener aModelListener) {
        this.observable.removeModelListener(aModelListener);
    }

    public void removeModelListeners(final List modelListeners) {
        this.observable.removeModelListeners(modelListeners);
    }

    public void resetListOfConstituents() {
        this.resetListOfConstituents(1);
    }

    private void resetListOfConstituents(final int anInitialCapacity) {
        // Yann 2004/04/09: Clone!
        // I make sure that a clone of an abstract level
        // model gets a new instance of an array list.
        // (See also method AbstractLevelModel.clone().)
        this.constituents = new IConstituent[GenericContainerConstants.PRIME_NUMBERS[this.indexInPrimeNumbersArray]];
        this.size = 0;
    }

    private void updatePathUponAddition(final INavigable aContainer, final IConstituent aConstituent) {

        final char[] containerPath = aContainer.getPath();
        final int startIndexInclusive = ArrayUtils.lastIndexOf(aConstituent.getPath(),
                ((Constituent) aConstituent).getPathSymbol()) + 1;
        final int endIndexExclusive = aConstituent.getPath().length;
        final char[] constituentPath = ArrayUtils.subarray(aConstituent.getPath(), startIndexInclusive,
                endIndexExclusive);

        final char[] newPath = new char[containerPath.length + 1 + constituentPath.length];
        System.arraycopy(containerPath, 0, newPath, 0, containerPath.length);
        newPath[containerPath.length] = ((Constituent) aConstituent).getPathSymbol();
        System.arraycopy(constituentPath, 0, newPath, containerPath.length + 1, constituentPath.length);
        ((Constituent) aConstituent).setPath(newPath);

        // Yann 2013/05/22: Propagation!
        // I should not forget to propagate this change 
        // iff this constituent is a container, silly!
        // I must use instanceof because there is no
        // class Container per se but Constituent plays
        // its role...
        if (aConstituent instanceof IContainer) {
            final Iterator iterator = ((IContainer) aConstituent).getIteratorOnConstituents();
            while (iterator.hasNext()) {
                final Constituent constituent = (Constituent) iterator.next();
                this.updatePathUponAddition((INavigable) aConstituent, constituent);
            }
        }
    }

    private void updatePathUponRemoval(final IConstituent aConstituent) {
        // Yann 2009/05/06: Path
        // After having removed a constituent from a model,
        // I make sure that I "reset" its path so that I can
        // add it to another model. Also, I will test when
        // adding a constituent if it does not include path
        // information to prevent two models to share
        // constituents, maybe the clone process should be
        // involved too... I'll think about it later.
        final int startIndexInclusive = ArrayUtils.lastIndexOf(aConstituent.getPath(),
                ((Constituent) aConstituent).getPathSymbol()) + 1;
        final int endIndexExclusive = aConstituent.getPath().length;
        ((Constituent) aConstituent)
                .setPath(ArrayUtils.subarray(aConstituent.getPath(), startIndexInclusive, endIndexExclusive));

        // Yann 2013/05/22: Propagation!
        // I should not forget to propagate this change 
        // iff this constituent is a container, silly!
        // I must use instanceof because there is no
        // class Container per se but Constituent plays
        // its role...
        if (aConstituent instanceof IContainer) {
            final Iterator iterator = ((IContainer) aConstituent).getIteratorOnConstituents();
            while (iterator.hasNext()) {
                final Constituent constituent = (Constituent) iterator.next();
                this.updatePathUponRemoval(constituent);
            }
        }
    }
}