package name.abuchen.portfolio.model; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.UUID; import name.abuchen.portfolio.model.Classification.Assignment; public class Taxonomy { public static class Visitor { public void visit(Classification classification) {} public void visit(Classification classification, Assignment assignment) {} } private transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); private String id; private String name; private List<String> dimensions; private Classification root; public Taxonomy() { // needed for xstream de-serialization } public Taxonomy(String name) { this(UUID.randomUUID().toString(), name); } /* package */ Taxonomy(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } /* package */void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { propertyChangeSupport.firePropertyChange("name", this.name, this.name = name); //$NON-NLS-1$ } public List<String> getDimensions() { return dimensions; } public void setDimensions(List<String> dimensions) { this.dimensions = dimensions; } public Classification getRoot() { return root; } public void setRootNode(Classification node) { this.root = node; } public Classification getClassificationById(String id) { if (id == null) return null; LinkedList<Classification> stack = new LinkedList<Classification>(); stack.addAll(getRoot().getChildren()); while (!stack.isEmpty()) { Classification c = stack.removeFirst(); if (id.equals(c.getId())) return c; stack.addAll(c.getChildren()); } return null; } public List<Classification> getClassifications(final InvestmentVehicle vehicle) { final List<Classification> answer = new ArrayList<Classification>(); foreach(new Visitor() { @Override public void visit(Classification classification, Assignment assignment) { if (vehicle.equals(assignment.getInvestmentVehicle())) answer.add(classification); } }); return answer; } public List<Classification> getAllClassifications() { List<Classification> answer = new ArrayList<Classification>(); foreach(new Visitor() { @Override public void visit(Classification classification) { answer.add(classification); } }); return answer; } public int getHeigth() { return getHeight(root); } private int getHeight(Classification classification) { int answer = 0; for (Classification c : classification.getChildren()) answer = Math.max(getHeight(c), answer); return 1 + answer; } public void foreach(Visitor visitor) { root.accept(visitor); } /** * Returns a full copy of the taxonomy including all assignments but with * newly generated UUIDs. */ public Taxonomy copy() { Taxonomy copy = new Taxonomy(this.name); if (this.dimensions != null) copy.setDimensions(new ArrayList<>(this.dimensions)); copy.setRootNode(this.root.copy()); return copy; } private Object readResolve() { propertyChangeSupport = new PropertyChangeSupport(this); return this; } public void addPropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(listener); } public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener(propertyName, listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { propertyChangeSupport.removePropertyChangeListener(listener); } }