001package org.biopax.paxtools.io.sif.level3;
002
003import org.apache.commons.logging.Log;
004import org.apache.commons.logging.LogFactory;
005import org.biopax.paxtools.controller.PathAccessor;
006import org.biopax.paxtools.model.BioPAXElement;
007import org.biopax.paxtools.model.level3.*;
008import org.biopax.paxtools.util.EquivalenceGrouper;
009
010import java.util.HashSet;
011import java.util.List;
012import java.util.Map;
013import java.util.Set;
014
015/**
016 * @author Emek Demir // todo annotate
017 */
018public class Simplify
019{
020        private static Log log = LogFactory.getLog(Simplify.class);
021
022        private static PathAccessor complexPath = new PathAccessor("Complex/component*");
023
024        private static PathAccessor memberPath = new PathAccessor("PhysicalEntity/memberPhysicalEntity*");
025
026        public static boolean entityHasAChange(BioPAXElement element, Conversion conv, GroupMap map,
027                        Set<PEStateChange> changeSet, Map<Conversion, Set<EntityReference>> extendedControls)
028        {
029                SimplePhysicalEntity left = null;
030                SimplePhysicalEntity right = null;
031                PhysicalEntity leftRoot = null;
032                PhysicalEntity rightRoot = null;
033
034                if (element == null)
035                {
036                        if (log.isWarnEnabled()) log.warn("Skipping ");
037                        return false;
038                }
039
040                for (PhysicalEntity pe : conv.getLeft())
041                {
042                        left = getAssociatedState(element, pe, map);
043                        if (left != null)
044                        {
045                                leftRoot = pe;
046                                break;
047                        }
048                }
049                for (PhysicalEntity pe : conv.getRight())
050                {
051                        right = getAssociatedState(element, pe, map);
052                        if (right != null)
053                        {
054                                rightRoot = pe;
055                                break;
056                        }
057                }
058
059                if (left == null || right == null || !leftRoot.equals(rightRoot))
060                {
061                        if (changeSet != null)
062                        {
063                                changeSet.add(new PEStateChange(left, right, leftRoot, rightRoot, element, conv));
064                                //Match ER-level generics. - do not exist in Reactome -so TODO for now.
065                                if (extendedControls != null) captureExtendedControls(conv, extendedControls, leftRoot, rightRoot);
066                        }
067
068                        return true;
069                }
070                return false;
071        }
072
073
074        private static void captureExtendedControls(Conversion conv, Map<Conversion,
075                        Set<EntityReference>> extendedControls,
076                        PhysicalEntity leftRoot, PhysicalEntity rightRoot)
077        {
078                if (leftRoot instanceof Complex || rightRoot instanceof Complex)
079                {
080                        if (conv.getControlledOf().isEmpty()) //?? Todo check this
081                        {
082                                Set<SimplePhysicalEntity> leftSpe = new HashSet<SimplePhysicalEntity>();
083                                getSimpleMembers(leftRoot, leftSpe);
084                                EquivalenceGrouper<SimplePhysicalEntity> leftComps =
085                                                new EquivalenceGrouper<SimplePhysicalEntity>(leftSpe);
086
087                                Set<SimplePhysicalEntity> rightSpe = new HashSet<SimplePhysicalEntity>();
088                                getSimpleMembers(rightRoot, rightSpe);
089
090                                EquivalenceGrouper rightComps = new EquivalenceGrouper<SimplePhysicalEntity>(rightSpe);
091                                leftComps.getBuckets().retainAll(rightComps.getBuckets());
092
093                                for (List<SimplePhysicalEntity> bucket : leftComps.getBuckets())
094                                {
095                                        SimplePhysicalEntity pe = bucket.get(0);
096                                        Set<EntityReference> erSet = extendedControls.get(conv);
097                                        if (erSet == null)
098                                        {
099                                                erSet = new HashSet<EntityReference>();
100                                                extendedControls.put(conv, erSet);
101                                        }
102                                        erSet.add(pe.getEntityReference());
103                                }
104                        }
105                }
106
107        }
108
109
110        public static void getSimpleMembers(PhysicalEntity root, Set<SimplePhysicalEntity> value)
111        {
112                if (root != null)
113                {
114                        if (root instanceof Complex)
115                        {
116                                Complex complex = (Complex) root;
117                                for (PhysicalEntity component : complex.getComponent())
118                                {
119                                        getSimpleMembers(component, value);
120                                }
121                        }
122
123                        if (root.getMemberPhysicalEntity().isEmpty())
124                        {
125                                if (root instanceof SimplePhysicalEntity) value.add((SimplePhysicalEntity) root);
126                        } else
127                        {
128                                for (PhysicalEntity generic : root.getMemberPhysicalEntity())
129                                {
130                                        getSimpleMembers(generic, value);
131                                }
132                        }
133
134                }
135        }
136
137
138        private static SimplePhysicalEntity getAssociatedState(BioPAXElement element, PhysicalEntity pe, GroupMap map)
139        {
140                if (pe instanceof Complex)
141                {
142                        for (PhysicalEntity component : ((Complex) pe).getComponent())
143                        {
144                                SimplePhysicalEntity viaComplex = getAssociatedState(element, component, map);
145                                if (viaComplex != null)
146                                {
147                                        return viaComplex;
148                                }
149                        }
150                } else if (checkEntity(map, pe, element)) return (SimplePhysicalEntity) pe;
151                for (PhysicalEntity member : pe.getMemberPhysicalEntity())
152                {
153                        SimplePhysicalEntity viaGeneric = getAssociatedState(element, member, map);
154                        if (viaGeneric != null) return viaGeneric;
155                }
156                return null;
157        }
158
159        private static boolean checkEntity(GroupMap map, PhysicalEntity pe, BioPAXElement element)
160        {
161                return pe instanceof SimplePhysicalEntity &&
162                       (element.equals(((SimplePhysicalEntity) pe).getEntityReference())) ||
163                       element.equals(map.getEntityReferenceOrGroup(pe));
164        }
165
166        public static boolean entityHasAChange(BioPAXElement target, Conversion conv, GroupMap groupMap,
167                        Set<PEStateChange> peStateChanges)
168        {
169                return entityHasAChange(target, conv, groupMap, peStateChanges, null);
170        }
171}