001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021
022package org.biojava.ontology; 
023 
024import java.util.Arrays;
025import java.util.Set;
026import java.util.TreeSet;
027
028import org.biojava.bio.Annotation;
029import org.biojava.utils.AbstractChangeable;
030import org.biojava.utils.ChangeEvent;
031import org.biojava.utils.ChangeForwarder;
032import org.biojava.utils.ChangeSupport;
033import org.biojava.utils.ChangeType;
034
035/**
036 * A term in an ontology which identifies another ontology.
037 *
038 * <p>
039 * This Term type has an associated ontology. It is meant to represent that
040 * ontology so that you can reason over them. For example, you could add
041 * information to an Ontology containing an OntologyTerm stating how the
042 * OntologyTerm's Ontology relates to other entities. This allows
043 * classifications of Ontologies to be built. You could say that GO is a
044 * biological ontology, as is SO or perhaps declare something about the source
045 * of the information.
046 * </p>
047 *
048 * @author Thomas Down
049 * @author Matthew Pocock
050 * @since 1.4
051 */
052
053public interface OntologyTerm extends Term {
054    /**
055     * Get the remote ontology referenced by this term
056     */
057    
058    public Ontology getOntology();
059    
060    /**
061     * Simple in-memory implementation of a remote ontology term.
062     *
063     * This can be used to implement Ontology.importTerm
064     */
065    
066    public final static class Impl
067    extends AbstractChangeable
068    implements OntologyTerm, java.io.Serializable {
069        private final Ontology ontology;
070        private final Ontology target;
071        private transient ChangeForwarder forwarder;
072        private Set synonyms;
073        
074        public Impl(Ontology ontology, Ontology target) {
075            this(ontology, target, null);
076        }
077         
078        public Impl(Ontology ontology, Ontology target, Object[] synonyms) {
079            if (ontology == null) {
080                throw new NullPointerException("The ontology may not be null");
081            }
082            if (target == null) {
083                throw new NullPointerException("The targetted ontology may not be null");
084            }
085            this.ontology = ontology;
086            this.target = target;
087            
088            this.synonyms = new TreeSet();
089            if (synonyms!=null) this.synonyms.addAll(Arrays.asList(synonyms));
090        }
091
092        public void addSynonym(Object synonym) {
093            this.synonyms.add(synonym);
094        }
095        
096        public void removeSynonym(Object synonym) {
097            this.synonyms.remove(synonym);
098        }
099        
100        public Object[] getSynonyms() {
101            return this.synonyms.toArray();
102        }
103        
104        public String getName() {
105            return target.getName();
106        }
107                
108        public String getDescription() {
109            return target.getDescription();
110        }
111        public void setDescription(String description) {
112             target.setDescription(description);
113        }
114        
115        public Ontology getOntology() {
116            return ontology;
117        }
118        
119        public Ontology getTargetOntology() {
120            return target;
121        }
122        
123        public String toString() {
124            return "Remote ontology: " + getName();
125        }
126        
127        public Annotation getAnnotation() {
128            return Annotation.EMPTY_ANNOTATION;
129        }
130        
131        public ChangeSupport getChangeSupport(ChangeType ct) {
132            ChangeSupport cs = super.getChangeSupport(ct);
133            forwarder = new ChangeForwarder(this, cs) {
134                protected ChangeEvent generateEvent(ChangeEvent cev) {
135                    return new ChangeEvent(
136                        getSource(),
137                        ChangeType.UNKNOWN,
138                        target,
139                        null,
140                        cev
141                    );
142                }
143            } ;
144            target.addChangeListener(forwarder, ChangeType.UNKNOWN);
145            return cs;
146        }
147    }
148}