001package org.biopax.paxtools.pattern.constraint; 002 003import org.biopax.paxtools.controller.PathAccessor; 004import org.biopax.paxtools.model.BioPAXElement; 005import org.biopax.paxtools.model.level3.*; 006import org.biopax.paxtools.pattern.Match; 007import org.biopax.paxtools.pattern.util.Blacklist; 008import org.biopax.paxtools.pattern.util.RelType; 009 010import java.util.Collection; 011import java.util.Collections; 012import java.util.HashSet; 013import java.util.Set; 014 015/** 016 * After traversing a PhysicalEntity and the Conversion it participates, this constraint takes us to 017 * the Control. The given relation between PhysicalEntity and Conversion is used to filter out 018 * unrelated controls. 019 * 020 * Var0 - PhysicalEntity (participant) 021 * Var1 - Conversion 022 * Var2 - related Control 023 * 024 * @author Ozgun Babur 025 */ 026public class RelatedControl extends ConstraintAdapter 027{ 028 /** 029 * Relation type between PhysicalEntity and Conversion. 030 */ 031 RelType peType; 032 033 /** 034 * Accessor to controller of Control recursively. 035 */ 036 PathAccessor controlledOf = new PathAccessor("Conversion/controlledOf*:Control"); 037 038 /** 039 * Constructor with the relation type between PhysicalEntity and Conversion. 040 * @param peType relation type between PhysicalEntity and Conversion 041 */ 042 public RelatedControl(RelType peType) 043 { 044 this(peType, null); 045 } 046 047 /** 048 * Constructor with the relation type between PhysicalEntity and Conversion, and the blacklist. 049 * @param peType relation type between PhysicalEntity and Conversion 050 * @param blacklist to detect ubiquitous small molecules 051 */ 052 public RelatedControl(RelType peType, Blacklist blacklist) 053 { 054 super(3, blacklist); 055 this.peType = peType; 056 } 057 058 /** 059 * This is a generative constraint. 060 * @return true 061 */ 062 @Override 063 public boolean canGenerate() 064 { 065 return true; 066 } 067 068 /** 069 * According to the relation between PhysicalEntity and the Conversion, checks of the Control is 070 * relevant. If relevant it is retrieved. 071 * @param match current pattern match 072 * @param ind mapped indices 073 * @return related controls 074 */ 075 @Override 076 public Collection<BioPAXElement> generate(Match match, int... ind) 077 { 078 PhysicalEntity pe = (PhysicalEntity) match.get(ind[0]); 079 Conversion conv = (Conversion) match.get(ind[1]); 080 081 if (!((peType == RelType.INPUT && getConvParticipants(conv, RelType.INPUT).contains(pe)) || 082 (peType == RelType.OUTPUT && getConvParticipants(conv, RelType.OUTPUT).contains(pe)))) 083 throw new IllegalArgumentException("peType = " + peType + 084 ", and related participant set does not contain this PE. Conv dir = " + 085 getDirection(conv) + " conv.id=" + conv.getRDFId() + " pe.id=" +pe.getRDFId()); 086 087 boolean rightContains = conv.getRight().contains(pe); 088 boolean leftContains = conv.getLeft().contains(pe); 089 090 assert rightContains || leftContains : "PE is not a participant."; 091 092 Set<BioPAXElement> result = new HashSet<BioPAXElement>(); 093 094 ConversionDirectionType avoidDir = (leftContains && rightContains) ? null : peType == RelType.OUTPUT ? 095 (leftContains ? ConversionDirectionType.LEFT_TO_RIGHT : ConversionDirectionType.RIGHT_TO_LEFT) : 096 (rightContains ? ConversionDirectionType.LEFT_TO_RIGHT : ConversionDirectionType.RIGHT_TO_LEFT); 097 098 for (Object o : controlledOf.getValueFromBean(conv)) 099 { 100 Control ctrl = (Control) o; 101 ConversionDirectionType dir = getDirection(conv, ctrl); 102 103 if (avoidDir != null && dir == avoidDir) continue; 104 105 // don't collect this if the pe is ubique in the context of this control 106 if (blacklist != null && blacklist.isUbique(pe, conv, dir, peType)) continue; 107 108 result.add(ctrl); 109 } 110 return result; 111 } 112 113}