001package org.biopax.paxtools.controller; 002 003import org.apache.commons.logging.Log; 004import org.apache.commons.logging.LogFactory; 005import org.biopax.paxtools.model.BioPAXElement; 006import org.biopax.paxtools.util.IllegalBioPAXArgumentException; 007 008import java.util.HashSet; 009import java.util.Set; 010 011/** 012 * This class is a transitive decorator for PropertyAccessors. BioPAX has transitive properties, 013 * such as: memberEntityReference, memberEntityFeature, memberPhysicalEntity, component. 014 * These all represent nested containment relationships. 015 * 016 * When decorating a suitable property accessor this accessor will traverse the whole nesting hierarchy and bring all 017 * children( or if inverse parents). For example when used on a {@link org.biopax.paxtools.model.level3.Complex#getComponent()} 018 * it will not only return the immediate components but also the components of the components. 019 */ 020public class TransitivePropertyAccessor<R extends BioPAXElement, D extends R> extends DecoratingPropertyAccessor<D, R> 021{ 022 private final static Log log = LogFactory.getLog(TransitivePropertyAccessor.class); 023 024 private TransitivePropertyAccessor(PropertyAccessor<D, R> accessor) 025 { 026 super(accessor); 027 } 028 029 @Override public Set<? extends R> getValueFromBean(D bean) throws IllegalBioPAXArgumentException 030 { 031 Set<R> values = new HashSet<R>(); 032 033 transitiveGet(bean, values); 034 return values; 035 } 036 037 038 private void transitiveGet(D bean, Set<R> values) 039 { 040 Set<? extends R> valuesFromBean = impl.getValueFromBean(bean); 041 for (R value : valuesFromBean) 042 { 043 if(values.add(value)) 044 { 045 //if(impl.getDomain().isInstance(value)) - unnecessary as the impl does that check 046 transitiveGet((D) value, values); 047 } 048 else { 049 //report loop 050 log.debug("Escaped an inf. loop (" + impl+ ") at " + value.getRDFId()); 051 } 052 } 053 } 054 055 public static < R extends BioPAXElement, D extends R> TransitivePropertyAccessor<R, D> create( 056 PropertyAccessor<D, R> pa) 057 { 058 return new TransitivePropertyAccessor<R,D>(pa); 059 } 060 061}