001package org.biopax.paxtools.pattern.constraint; 002 003import org.biopax.paxtools.model.BioPAXElement; 004import org.biopax.paxtools.model.level3.Conversion; 005import org.biopax.paxtools.model.level3.ConversionDirectionType; 006import org.biopax.paxtools.model.level3.PhysicalEntity; 007import org.biopax.paxtools.pattern.Match; 008import org.biopax.paxtools.pattern.util.Blacklist; 009import org.biopax.paxtools.pattern.util.RelType; 010 011import java.util.Collection; 012import java.util.Collections; 013import java.util.HashSet; 014import java.util.Set; 015 016/** 017 * Given Conversion and its one of the participants (at the left or right), traverses to either 018 * the participants at the other side or the same side. 019 * 020 * var0 is a PE (PE1) 021 * var1 is a Conv 022 * var2 is a PE (PE2) 023 * 024 * Prerequisite: PE1 is either at left or right of Conv 025 * 026 * @author Ozgun Babur 027 */ 028public class ConversionSide extends ConstraintAdapter 029{ 030 /** 031 * Same side or other side; 032 */ 033 Type sideType; 034 035 /** 036 * Type of the relation of the participant. It is either input or output. 037 */ 038 RelType relType; 039 040 /** 041 * Constructor. 042 * 043 * @param type side type (same side or the other) 044 */ 045 public ConversionSide(Type type) 046 { 047 this(type, null, null); 048 } 049 050 /** 051 * Constructor. The relType parameter is using during blacklisting, and only if the blacklist is 052 * not null. 053 * 054 * @param type side type 055 * @param blacklist blacklist of ubiquitous molecules 056 * @param relType relationship type (used together with and during blacklisting) 057 */ 058 public ConversionSide(Type type, Blacklist blacklist, RelType relType) 059 { 060 super(3, blacklist); 061 062 if (type == null) 063 { 064 throw new IllegalArgumentException("The \"type\" parameter cannot be null."); 065 } 066 067 this.sideType = type; 068 this.relType = relType; 069 } 070 071 /** 072 * This is a generative constraint. 073 * @return true 074 */ 075 @Override 076 public boolean canGenerate() 077 { 078 return true; 079 } 080 081 /** 082 * Checks which side is the first PhysicalEntity, and gathers participants on either the other 083 * side or the same side. 084 * @param match current pattern match 085 * @param ind mapped indices 086 * @return participants at the desired side 087 */ 088 @Override 089 public Collection<BioPAXElement> generate(Match match, int... ind) 090 { 091 assertIndLength(ind); 092 093 PhysicalEntity pe1 = (PhysicalEntity) match.get(ind[0]); 094 Conversion conv = (Conversion) match.get(ind[1]); 095 096 Set<PhysicalEntity> parts; 097 098 if (conv.getLeft().contains(pe1)) 099 { 100 parts = sideType == Type.OTHER_SIDE ? conv.getRight() : conv.getLeft(); 101 } 102 else if (conv.getRight().contains(pe1)) 103 { 104 parts = sideType == Type.SAME_SIDE ? conv.getRight() : conv.getLeft(); 105 } 106 else throw new IllegalArgumentException( 107 "The PhysicalEntity has to be a participant of the Conversion."); 108 109 if (blacklist == null) return new HashSet<BioPAXElement>(parts); 110 else 111 { 112 ConversionDirectionType dir = getDirection(conv); 113 114 if ((dir == ConversionDirectionType.LEFT_TO_RIGHT && ((relType == RelType.INPUT && parts != conv.getLeft()) || (relType == RelType.OUTPUT && parts != conv.getRight()))) || 115 (dir == ConversionDirectionType.RIGHT_TO_LEFT && ((relType == RelType.INPUT && parts != conv.getRight()) || (relType == RelType.OUTPUT && parts != conv.getLeft())))) 116 return Collections.emptySet(); 117 118 return new HashSet<BioPAXElement>(blacklist.getNonUbiques(parts, relType)); 119 } 120 } 121 122 /** 123 * This enum tells if the user want to traverse towards other side of the conversion or stay at 124 * the same side. 125 */ 126 public enum Type 127 { 128 OTHER_SIDE, 129 SAME_SIDE 130 } 131}