/* Copyright (C) 2009 Diego Darriba This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package es.uvigo.darwin.prottest.util.collection; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Properties; import pal.alignment.Alignment; import pal.tree.Tree; import es.uvigo.darwin.prottest.model.Model; import es.uvigo.darwin.prottest.util.comparator.ModelWeightComparator; import es.uvigo.darwin.prottest.util.exception.ProtTestInternalException; import es.uvigo.darwin.prottest.util.factory.ProtTestFactory; /** * An common interface for substitution models, that includes * some specific operations to work with model collections. * * @author Diego Darriba * @version 3.0 */ public abstract class ModelCollection implements List<Model>, Serializable { protected Alignment alignment; /** The serialVersionUID. */ private static final long serialVersionUID = 515892620727410572L; /** The set of all models inside the collection. */ protected List<Model> allModels; public Alignment getAlignment() { return alignment; } /** * Instantiates a new model collection. */ public ModelCollection(Alignment alignment) { this.alignment = alignment; allModels = new ArrayList<Model>(); } /** * Instantiates a new model collection with the array of models. */ public ModelCollection(Model[] models, Alignment alignment) { this.alignment = alignment; for (Model model : models) { checkAlignment(model); } allModels = new ArrayList<Model>(); allModels.addAll(Arrays.asList(models)); } /** * Instantiates a new model collection with another model collection. */ public ModelCollection(ModelCollection mc) { this.alignment = mc.getAlignment(); allModels = new ArrayList<Model>(); allModels.addAll(mc); } /** * Creates a new model and adds it to the collection. * * @param matrix the substitution matrix name * @param distribution the distribution of the model * @param modelProperties the model specific properties * * @return true, if successfully added the model to the iterator */ public boolean addModel(String matrix, int distribution, Properties modelProperties, Alignment alignment, Tree tree, int ncat) { Model model = ProtTestFactory.getInstance().createModel(matrix, distribution, modelProperties, alignment, tree, ncat); boolean toAdd = !allModels.contains(model); if (toAdd) { checkAlignment(model); toAdd &= allModels.add(model); } return toAdd; } /** * Adds a substitution model to the collection. * * @param model the substitution model to add * * @return true, if successfully added the model to the iterator */ public boolean addModel(Model model) { boolean toAdd = !allModels.contains(model); if (toAdd) { checkAlignment(model); toAdd &= allModels.add(model); } return toAdd; } /** * Adds the models result of combine each matrix with each distribution. * There will be MxD new models in the iterator, where * M is the number of matrices * D is the number of distributions * * @param matrices collection of all the substitution matrices * @param distributions collection of all the distributions * @param modelProperties the model properties * * @return true, if successfully added all models */ public boolean addModelCartesian(Collection<String> matrices, Collection<Integer> distributions, Properties modelProperties, Alignment alignment, Tree tree, int ncat) { boolean allDone = true; boolean plusF = Boolean.parseBoolean( modelProperties.getProperty( Model.PROP_PLUS_F, "false")); Properties modelPropertiesFalse = new Properties(); Properties modelPropertiesTrue = new Properties(); modelPropertiesFalse.setProperty(Model.PROP_PLUS_F, "false"); modelPropertiesTrue.setProperty(Model.PROP_PLUS_F, "true"); for (String matrix : matrices) { for (Integer distribution : distributions) { allDone &= addModel(matrix, distribution, modelPropertiesFalse, alignment, tree, ncat); if (plusF) { allDone &= addModel(matrix, distribution, modelPropertiesTrue, alignment, tree, ncat); } } } return allDone; } /** * Gets the weight of the collection. This attribute is only used in * order to heuristically sort models. * * @return the whole weight of the collection */ public int getWeight(ModelWeightComparator mwc) { int weight = 0; for (Model model : allModels) { weight += mwc.getWeight(model); } return weight; } /* (non-Javadoc) * @see java.util.List#size() */ public int size() { return allModels.size(); } // public abstract void printModelsSorted(char sortBy, PrintWriter out) // throws ProtTestInternalException; /* (non-Javadoc) * @see java.util.List#add(java.lang.Object) */ public boolean add(Model e) { return allModels.add(e); } /* (non-Javadoc) * @see java.util.List#add(int, java.lang.Object) */ public void add(int index, Model element) { allModels.add(index, element); } /* (non-Javadoc) * @see java.util.List#addAll(java.util.Collection) */ public boolean addAll(Collection<? extends Model> c) { return allModels.addAll(c); } /* (non-Javadoc) * @see java.util.List#addAll(int, java.util.Collection) */ public boolean addAll(int index, Collection<? extends Model> c) { return allModels.addAll(index, c); } /* (non-Javadoc) * @see java.util.List#clear() */ public void clear() { allModels.clear(); } /* (non-Javadoc) * @see java.util.List#contains(java.lang.Object) */ public boolean contains(Object o) { return allModels.contains(o); } /* (non-Javadoc) * @see java.util.List#containsAll(java.util.Collection) */ public boolean containsAll(Collection<?> c) { return allModels.containsAll(c); } /* (non-Javadoc) * @see java.util.List#get(int) */ public Model get(int index) { return allModels.get(index); } /* (non-Javadoc) * @see java.util.List#indexOf(java.lang.Object) */ public int indexOf(Object o) { return allModels.indexOf(o); } /* (non-Javadoc) * @see java.util.List#isEmpty() */ public boolean isEmpty() { return allModels.isEmpty(); } /* (non-Javadoc) * @see java.util.List#iterator() */ public Iterator<Model> iterator() { return allModels.iterator(); } /* (non-Javadoc) * @see java.util.List#lastIndexOf(java.lang.Object) */ public int lastIndexOf(Object o) { return allModels.lastIndexOf(o); } /* (non-Javadoc) * @see java.util.List#listIterator() */ public ListIterator<Model> listIterator() { return allModels.listIterator(); } /* (non-Javadoc) * @see java.util.List#listIterator(int) */ public ListIterator<Model> listIterator(int index) { return allModels.listIterator(index); } /* (non-Javadoc) * @see java.util.List#remove(java.lang.Object) */ public boolean remove(Object o) { return allModels.remove(o); } /* (non-Javadoc) * @see java.util.List#remove(int) */ public Model remove(int index) { return allModels.remove(index); } /* (non-Javadoc) * @see java.util.List#removeAll(java.util.Collection) */ public boolean removeAll(Collection<?> c) { return allModels.removeAll(c); } /* (non-Javadoc) * @see java.util.List#retainAll(java.util.Collection) */ public boolean retainAll(Collection<?> c) { return allModels.retainAll(c); } /* (non-Javadoc) * @see java.util.List#set(int, java.lang.Object) */ public Model set(int index, Model element) { return allModels.set(index, element); } /* (non-Javadoc) * @see java.util.List#subList(int, int) */ public List<Model> subList(int fromIndex, int toIndex) { return allModels.subList(fromIndex, toIndex); } /* (non-Javadoc) * @see java.util.List#toArray() */ public Object[] toArray() { return allModels.toArray(); } /* (non-Javadoc) * @see java.util.List#toArray(T[]) */ public <T> T[] toArray(T[] a) { return allModels.toArray(a); } private void checkAlignment(Model model) { if (this.alignment == null) { throw new ProtTestInternalException("Internal error: Alignment is not initialized"); } else if (!model.checkAlignment(this.alignment)) { throw new ProtTestInternalException("Different alignments among model collection"); } } @Override public ModelCollection clone() { return new SingleModelCollection(this); } }