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