001package org.biopax.paxtools.controller;
002
003
004import org.apache.commons.logging.Log;
005import org.apache.commons.logging.LogFactory;
006import org.biopax.paxtools.model.BioPAXElement;
007import org.biopax.paxtools.model.Model;
008import org.biopax.paxtools.util.Filter;
009
010import java.util.HashSet;
011import java.util.Set;
012
013/**
014 * This is a utility class for traversing over the dependent objects of a biopax element, based on
015 * property editors
016 */
017public class Traverser
018{
019// ------------------------------ FIELDS ------------------------------
020
021        protected final EditorMap editorMap;
022
023        protected Visitor visitor;
024
025        protected Filter<PropertyEditor>[] filters;
026
027        private final static Log log = LogFactory.getLog(Traverser.class);
028
029
030// --------------------------- CONSTRUCTORS ---------------------------
031
032        /**
033         * The full constructor.
034         * @param editorMap is used for looking up properties to traverse
035         * @param visitor is a visitor element that determines the action on reaching a biopax element during traversal
036         * @param filters limits the type of properties that are traversed.
037         */
038        public Traverser(EditorMap editorMap, Visitor visitor, Filter<PropertyEditor>... filters)
039        {
040                this.editorMap = editorMap;
041                this.visitor = visitor;
042                this.filters = filters;
043        }
044
045// -------------------------- SETTERS/GETTERS ------------------------
046
047
048        public void setVisitor(Visitor visitor)
049        {
050                this.visitor = visitor;
051        }
052
053        public Visitor getVisitor()
054        {
055                return visitor;
056        }
057
058// -------------------------- OTHER METHODS --------------------------
059
060        /**
061         * Traverse and visit {@link Visitor} all properties of the element.
062         * This method does not traverse iteratively to the values.
063         * @param element BioPAX element to be traversed
064         * @param model to be traversed, but not necessarily (depends on the Visitor implementation).
065         * @param <D> actual BioPAX type which properties and inherited properties will be used
066         */
067        public <D extends BioPAXElement> void traverse(D element, Model model)
068        {
069                Set<PropertyEditor> editors = editorMap.getEditorsOf(element);
070
071                if (editors == null)
072                {
073                        log.warn("No editors for : " + element.getModelInterface());
074                        return;
075                }
076                for (PropertyEditor<? super D,?> editor : editors)
077                {
078                        if (filter(editor))
079                        {
080                                Set<?> valueSet = editor.getValueFromBean(element);
081                                if (!valueSet.isEmpty())
082                    traverseElements(element, model, editor, valueSet);
083            }
084                }
085        }
086
087    protected void traverseElements(BioPAXElement element, Model model, PropertyEditor<?,?> editor, Set<?> valueSet)
088    {
089        for (Object value : new HashSet<Object>(valueSet))
090        {
091                visitor.visit(element, value, model, editor);
092        }
093    }
094
095
096    protected boolean filter(PropertyEditor<?, ?> editor)
097        {
098                for (Filter<PropertyEditor> filter : filters)
099                {
100                        if (!filter.filter(editor))
101                        {
102                                return false;
103                        }
104                }
105                return true;
106        }
107}
108