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.ModelUtils;
006import org.biopax.paxtools.model.BioPAXElement;
007import org.biopax.paxtools.model.Model;
008import org.biopax.paxtools.model.level3.Complex;
009import org.biopax.paxtools.model.level3.EntityReference;
010import org.biopax.paxtools.model.level3.PhysicalEntity;
011import org.biopax.paxtools.model.level3.SimplePhysicalEntity;
012import org.biopax.paxtools.util.AccessibleSet;
013
014import java.util.HashMap;
015import java.util.HashSet;
016import java.util.Map;
017import java.util.Set;
018
019/**
020 * @author Emek Demir
021 */
022public class Grouper
023{
024        private static final Log log = LogFactory.getLog(Grouper.class);
025
026        Map<BioPAXElement, Group> element2GroupMap = new HashMap<BioPAXElement, Group>();
027
028        AccessibleSet<Group> groups = new AccessibleSet<Group>();
029
030        Map<BioPAXElement, Set<Group>> delegated = new HashMap<BioPAXElement, Set<Group>>();
031
032
033        Set<EntityReference> ersToBeGrouped ;
034
035        Set<Complex> complexesToBeGrouped;
036
037        public static GroupMap inferGroups(Model model)
038        {
039                ModelUtils.normalizeGenerics(model);
040                Grouper grouper =new Grouper();
041                return new GroupMap(grouper.inferGroups(model, grouper));
042        }
043
044        private Map<BioPAXElement, Group> inferGroups(Model model, Grouper grouper)
045        {
046                ersToBeGrouped = new HashSet<EntityReference>(model.getObjects(EntityReference.class));
047                complexesToBeGrouped = new HashSet<Complex>(model.getObjects(Complex.class));
048
049                for (EntityReference er : ersToBeGrouped)
050                {
051                        addIfNotNull(er, inferGroupFromER(er, model));
052                }
053                for (Complex complex : complexesToBeGrouped)
054                {
055                        addIfNotNull(complex, inferGroupFromComplex(complex, model));
056                }
057
058                return element2GroupMap;
059
060        }
061
062        private void addIfNotNull(BioPAXElement element, final Group group)
063        {
064                if (group != null)
065                {
066                        Group equivalentGroup = groups.access(group);
067                        if (equivalentGroup == null)
068                        {
069                                equivalentGroup = group;
070                                groups.add(equivalentGroup);
071                        } else
072                        {
073                                equivalentGroup.sources.addAll(group.sources);
074                        }
075                        element2GroupMap.put(element, equivalentGroup);
076                }
077
078        }
079
080        private Group inferGroupFromComplex(Complex complex, Model model)
081        {
082                Group group = new Group(true, complex);
083                Set<PhysicalEntity> PElvlMembers = complex.getMemberPhysicalEntity();
084                if (PElvlMembers.isEmpty())
085                {
086                        for (PhysicalEntity component : complex.getComponent())
087                        {
088                                if (component instanceof SimplePhysicalEntity)
089                                {
090                                        EntityReference er = this.element2GroupMap.get(component);
091                                        if(er==null)
092                                                 er = ((SimplePhysicalEntity) component).getEntityReference();
093
094                                        if (er != null)
095                                        {
096                                                group.addMember(er);
097                                        } else
098                                        {
099                                                addOrDelegate(component, group);
100                                        }
101                                } else if (component instanceof Complex)
102                                {
103                                        addOrDelegate(component, group);
104                                }
105                        }
106                } else
107                {
108                        //If this is a reactome generic it should not have any components?
109                        if (!complex.getComponent().isEmpty())
110                        {
111                                log.debug("Generic complex with both membership types (" + complex.getRDFId() + "). Skipping.");
112                        } else
113                        {
114                                group = new Group(false, complex);
115                                group.genericClass = Complex.class;
116                                for (PhysicalEntity member : PElvlMembers)
117                                {
118                                        if (member instanceof Complex)
119                                        {
120                                                addOrDelegate(member, group);
121                                        } else
122                                        {
123                                                log.debug("Non complex PE member for complex (" + member.getRDFId() + "->" + complex
124                                                                .getRDFId() +
125                                                         "). Skipping");
126                                        }
127                                }
128
129                        }
130                }
131                Set<Group> groups = delegated.get(complex);
132                if (groups != null)
133                {
134                        for (Group owner : groups)
135                        {
136                                owner.addSubgroup(group);
137                        }
138                }
139                ModelUtils.copySimplePointers(model, complex, group);
140                return group;
141        }
142
143        private void addOrDelegate(BioPAXElement member, Group owner)
144        {
145                Group subgroup = element2GroupMap.get(member);
146                if (subgroup != null) owner.addSubgroup(subgroup);
147                else
148                {
149                        Set<Group> groups = delegated.get(member);
150                        if (groups == null)
151                        {
152                                groups = new HashSet<Group>();
153                                delegated.put(member, groups);
154                        }
155                        groups.add(owner);
156                }
157        }
158
159        private Group inferGroupFromER(EntityReference element, Model model)
160        {
161                Group group = new Group(false, element);
162
163                for (EntityReference member : element.getMemberEntityReference())
164                {
165                        if(group.genericClass==null)
166                        {
167                                group.genericClass = member.getModelInterface();
168                        }
169                        group.addMember(member);
170                }
171
172                Set<Group> owners = delegated.get(element);
173                if (owners != null)
174                {
175                        for (Group owner : owners)
176                        {
177                                owner.addSubgroup(group);
178                        }
179                }
180                ModelUtils.copySimplePointers(model, element, group);
181                return group.isEmpty() ? null : group;
182        }
183}