001package org.biopax.paxtools.impl.level3;
002
003import org.apache.commons.logging.Log;
004import org.apache.commons.logging.LogFactory;
005import org.biopax.paxtools.model.level3.BiochemicalPathwayStep;
006import org.biopax.paxtools.model.level3.Conversion;
007import org.biopax.paxtools.model.level3.Process;
008import org.biopax.paxtools.model.level3.StepDirection;
009import org.biopax.paxtools.util.IllegalBioPAXArgumentException;
010import org.hibernate.annotations.Cache;
011import org.hibernate.annotations.*;
012import org.hibernate.search.annotations.Indexed;
013
014import javax.persistence.Entity;
015import javax.persistence.*;
016import java.util.AbstractSet;
017import java.util.Iterator;
018import java.util.NoSuchElementException;
019import java.util.Set;
020
021@Entity @Proxy(proxyClass = BiochemicalPathwayStep.class) @Indexed @DynamicUpdate @DynamicInsert
022@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
023public class BiochemicalPathwayStepImpl extends PathwayStepImpl implements BiochemicalPathwayStep
024{
025        private Conversion stepConversion;
026
027        private StepDirection stepDirection;
028
029        private Set<Process> stepProcess = new StepProcessSet();
030
031        private Log log = LogFactory.getLog(BiochemicalPathwayStepImpl.class);
032
033        public BiochemicalPathwayStepImpl()
034        {
035
036        }
037
038        //
039        // utilityClass interface implementation
040        //
041        ////////////////////////////////////////////////////////////////////////////
042        @Transient
043        public Class<? extends BiochemicalPathwayStep> getModelInterface()
044        {
045                return BiochemicalPathwayStep.class;
046        }
047
048        //
049        // biochemicalPathwayStep interface implementation
050        //
051        ////////////////////////////////////////////////////////////////////////////
052
053
054        //trivial private setter/getter for ORM frameworks only
055        @ManyToOne(targetEntity = ConversionImpl.class) Conversion getStepConversionX()
056        {
057                return stepConversion;
058        }
059
060        void setStepConversionX(Conversion conversion)
061        {
062                this.stepConversion = conversion;
063        }
064
065        // Property stepConversion
066        @Transient
067        public Conversion getStepConversion()
068        {
069                return stepConversion;
070        }
071
072        /**
073         * {@inheritDoc}
074         */
075        public void setStepConversion(Conversion highLander)
076
077        {
078                if (this.stepConversion != null)
079                {
080                        if (this.stepConversion == highLander) 
081                                return;
082                        else { 
083                                synchronized (this.stepConversion) {
084                                        this.stepConversion.getStepProcessOf().remove(this);
085                                }
086                        }
087                }
088                
089                this.stepConversion = highLander; //can be null!
090                
091                if(this.stepConversion != null) {
092                        synchronized (this.stepConversion) {
093                                this.stepConversion.getStepProcessOf().add(this);
094                        }
095                }
096
097        }
098
099        @Override
100        public void addStepProcess(Process process)
101        {
102                if (process instanceof Conversion)
103                {
104                        if (this.stepConversion == null || this.stepConversion == process)
105                        {
106                                log.debug("Ignoring request to add a Conversion as stepProcess");
107                        } else
108                        {
109                                throw new IllegalBioPAXArgumentException(
110                                        "Biochemical Pathway Step can have only one conversion. Did you want to use" +
111                                                "the setStepConversion method? ");
112                        }
113                }
114                super.addStepProcess(process);
115        }
116
117        // Property STEP-DIRECTION
118
119        @Enumerated(EnumType.STRING)
120        public StepDirection getStepDirection()
121        {
122                return stepDirection;
123        }
124
125        public void setStepDirection(StepDirection newSTEP_DIRECTION)
126        {
127                stepDirection = newSTEP_DIRECTION;
128        }
129
130        @Transient @Override public Set<Process> getStepProcess()
131        {
132                return stepProcess;
133        }
134
135
136        private class StepProcessSet extends AbstractSet<Process>
137        {
138                @Override public Iterator<Process> iterator()
139                {
140                        final Iterator<Process> proci = BiochemicalPathwayStepImpl.super.getStepProcess().iterator();
141
142                        return new Iterator<Process>()
143                        {
144                                boolean procEnd = false;
145
146                                @Override public boolean hasNext()
147                                {
148                                        return proci.hasNext() || !(procEnd || stepConversion == null);
149                                }
150
151                                @Override public Process next()
152                                {
153                                        if (procEnd) throw new NoSuchElementException();
154                                        if (proci.hasNext()) return proci.next();
155                                        else
156                                        {
157                                                procEnd = true;
158                                                if (stepConversion == null) throw new NoSuchElementException();
159                                                else return stepConversion;
160                                        }
161                                }
162
163                                @Override public void remove()
164                                {
165                                        throw new UnsupportedOperationException();
166                                }
167                        };
168                }
169
170                @Override public int size()
171                {
172                        return BiochemicalPathwayStepImpl.super.getStepProcess().size() + (stepConversion == null ? 0 : 1);
173                }
174
175                @Override public boolean contains(Object o)
176                {
177                        return o != null && ((stepConversion != null && stepConversion.equals(o)) || BiochemicalPathwayStepImpl
178                                        .super.getStepProcess().contains(o));
179                }
180
181        }
182}