001package org.biopax.paxtools.io.sif.level3;
002
003import org.biopax.paxtools.impl.level3.EntityReferenceImpl;
004import org.biopax.paxtools.model.BioPAXElement;
005import org.biopax.paxtools.model.level3.EntityReference;
006
007import java.util.HashSet;
008import java.util.Map;
009import java.util.Set;
010
011/**
012 * This class represents a grouping of EntityReferences strictly used by SIF rules for handling generics and complexes.
013 *
014 * @author Emek Demir
015 */
016public class Group extends EntityReferenceImpl
017{
018        /**
019         * ER members of the group.
020         */
021        Set<EntityReference> members = new HashSet<EntityReference>();
022
023        /**
024         *  Since Group is also an ER, its members can be arbitrarily nested.
025         */
026        Set<Group> subgroups = new HashSet<Group>();
027
028        /**
029         * This value is true if this group maps to a complex, false otherwise.
030         */
031        boolean isComplex;
032
033        /**
034         * The class of the sources that this group maps
035         */
036        Class<? extends BioPAXElement> genericClass;
037
038        /**
039         * The original bpes that this group maps.
040         */
041        Set<BioPAXElement> sources;
042
043
044        /**
045         *
046         * @param type This value is true if this group maps to a complex, false otherwise.
047         * @param source The original bpes that this group maps.
048         */
049        Group(boolean type, BioPAXElement source)
050        {
051                this.isComplex = type;
052                this.sources = new HashSet<BioPAXElement>();
053                this.sources.add(source);
054        }
055
056        @Override public String getRDFId()
057        {
058                return "http://biopax.org/generated/group/" + hashCode();
059        }
060
061        @Override public boolean isEquivalent(BioPAXElement element)
062        {
063                return this.equals(element);
064        }
065
066        @Override public int equivalenceCode()
067        {
068                return hashCode();
069        }
070
071
072        public void addMember(EntityReference member)
073        {
074                this.members.add(member);
075        }
076
077        public void addSubgroup(Group subgroup)
078        {
079                if(subgroup!=this)
080                this.subgroups.add(subgroup);
081                else
082                        throw new IllegalArgumentException();
083        }
084
085        public boolean isComplex()
086        {
087                return isComplex;
088        }
089
090        @Override public boolean equals(Object o)
091        {
092                if (o == this) return true;
093                if (o != null && o instanceof Group)
094                {
095                        Group that = (Group) o;
096
097                        if (this.isEmpty())
098                        {
099                                return this.sources.equals(that.sources);
100                        }
101                        return this.isComplex == that.isComplex && this.members.equals(that.members) &&
102                               this.subgroups.equals(that.subgroups);
103                } else return false;
104        }
105
106        @Override public int hashCode()
107        {
108                int code;
109                if (this.isEmpty())
110                {
111                        code = sources.isEmpty() ? super.hashCode() : sources.hashCode();
112                } else code = members.hashCode() / 17 + this.subgroups.hashCode() / 23 + (isComplex?19:47);
113                return code;
114        }
115
116        public boolean isEmpty()
117        {
118                return this.members.isEmpty() && this.subgroups.isEmpty();
119        }
120
121        @Override public String toString()
122        {
123                StringBuilder bldr = new StringBuilder();
124                bldr.append(isComplex).append("{");
125                if (!isEmpty())
126                {
127                        for (EntityReference member : members)
128                        {
129                                bldr.append(member.getRDFId()).append(",");
130                        }
131                        for (Group subgroup : subgroups)
132                        {
133                                bldr.append(subgroup.toString()).append(",");
134                        }
135
136                        bldr.deleteCharAt(bldr.length() - 1);
137                }
138                return bldr.append("}").toString();
139
140        }
141
142        @Override
143        public Map<String, Object> getAnnotations() {
144                throw new UnsupportedOperationException("getAnnotations() is not supported " +
145                        "for this (special) BioPAXElement: " + getClass());
146        }
147
148        public String groupTypeToString()
149        {
150                if(isComplex)
151                {
152                        return "ComplexGroup";
153                }
154                else
155                {
156                        return "Generic"+ (genericClass ==null?"": genericClass.getSimpleName());
157                }
158
159        }
160
161        public Set<EntityReference> getAllSimpleMembers()
162        {
163                HashSet simples = new HashSet<EntityReference>();
164                recursivelyGetMembers(simples);
165                return simples;
166        }
167
168        private void recursivelyGetMembers(Set<EntityReference> simples)
169        {
170                for (EntityReference member : members)
171                {
172                        simples.add(member);
173                }
174                for (Group subgroup : subgroups)
175                {
176                        subgroup.recursivelyGetMembers(simples);
177                }
178        }
179
180}