@@ -0,0 +1,3488 @@
+package etomica.species;%0A%0Aimport etomica.atom.AtomType;%0Aimport etomica.chem.elements.IElement;%0A%0Aimport java.util.*;%0A%0Apublic final class SpeciesManager %7B%0A%0A    private final ISpecies%5B%5D speciesArray;%0A    private final int atomTypeCount;%0A    private final boolean isPureAtoms;%0A%0A    // TODO should it be public? would need to handle setIndex%0A    private SpeciesManager(ISpecies%5B%5D speciesArray) %7B%0A        this.speciesArray = speciesArray;%0A        this.atomTypeCount = Arrays.stream(speciesArray).mapToInt(ISpecies::getUniqueAtomTypeCount).sum();%0A        this.isPureAtoms = Arrays.stream(speciesArray).allMatch(s -%3E s.getLeafAtomCount() == 1);%0A    %7D%0A%0A    public static Builder builder() %7B%0A        return new Builder();%0A    %7D%0A%0A    public ISpecies%5B%5D getSpeciesArray() %7B%0A        return this.speciesArray;%0A    %7D%0A%0A    public ISpecies getSpecies(int idx) %7B%0A        return speciesArray%5Bidx%5D;%0A    %7D%0A%0A    public int getSpeciesCount() %7B%0A        return this.speciesArray.length;%0A    %7D%0A%0A    public int getAtomTypeCount() %7B%0A        return this.atomTypeCount;%0A    %7D%0A%0A    public boolean isPureAtoms() %7B%0A        return this.isPureAtoms;%0A    %7D%0A%0A    public static class Builder %7B%0A        private final Map%3CString, IElement%3E elementSymbols = new HashMap%3C%3E();%0A        private final List%3CISpecies%3E speciesList = new ArrayList%3C%3E();%0A        private int atomTypeCount = 0;%0A%0A        public SpeciesManager build() %7B%0A            return new SpeciesManager(speciesList.toArray(new ISpecies%5B0%5D));%0A        %7D%0A%0A        public Builder addSpecies(ISpecies species) %7B%0A            Objects.requireNonNull(species);%0A            if (speciesList.contains(species)) %7B%0A                throw new IllegalArgumentException(%22Species is already added: %22 + species);%0A            %7D%0A%0A            species.setIndex(speciesList.size());%0A            speciesList.add(species);%0A%0A            for (AtomType atomType : species.getUniqueAtomTypes()) %7B%0A                atomType.setIndex(atomTypeCount);%0A                atomTypeCount++;%0A%0A                IElement newElement = atomType.getElement();%0A                elementSymbols.merge(newElement.getSymbol(), newElement, (oldElement, newEl) -%3E %7B%0A                    if (oldElement != newEl) %7B%0A                        throw new IllegalStateException(%0A                                %22Element symbol %22 + newEl.getSymbol() + %22 already exists in this simulation as a different element%22%0A                        );%0A                    %7D%0A                    return newEl;%0A                %7D);%0A            %7D%0A%0A            return this;%0A        %7D%0A%0A        public Builder addSpecies(ISpecies... species) %7B%0A            Arrays.stream(species).forEach(this::addSpecies);%0A            return this;%0A        %7D%0A%0A        /**%0A         * Method to allow generation of unique string to identify Elements in the Simulation.%0A         *%0A         * @param symbolBase the base string.%0A         * @return an Element symbol starting with symbolBase that does not yet%0A         * exist in the Simulation.  Return values will be like %22base0, base1, base2...%22%0A         */%0A        public String makeUniqueElementSymbol(String symbolBase) %7B%0A            int n = 0;%0A            while (elementSymbols.containsKey(symbolBase + n)) %7B%0A                n++;%0A            %7D%0A            // reserve this symbol so future calls to makeUniqueElementSymbol won't return it%0A            // this will get replaced by the actual Element when it gets added%0A            elementSymbols.put(symbolBase + n, null);%0A            return symbolBase + n;%0A        %7D%0A%0A    %7D%0A%7D%0A

Add initial implementation of SpeciesManager and Builder