View Javadoc
1   /*
2    * The baseCode project
3    *
4    * Copyright (c) 2013 University of British Columbia
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
12   * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
13   * specific language governing permissions and limitations under the License.
14   */
15  package ubic.basecode.ontology.jena;
16  
17  import com.hp.hpl.jena.ontology.OntClass;
18  import com.hp.hpl.jena.ontology.OntResource;
19  import com.hp.hpl.jena.ontology.Restriction;
20  import com.hp.hpl.jena.rdf.model.*;
21  import com.hp.hpl.jena.util.iterator.ExtendedIterator;
22  import ubic.basecode.ontology.model.AnnotationProperty;
23  import ubic.basecode.ontology.model.OntologyIndividual;
24  import ubic.basecode.ontology.model.OntologyRestriction;
25  import ubic.basecode.ontology.model.OntologyTerm;
26  
27  import javax.annotation.Nullable;
28  import java.util.Collection;
29  import java.util.Collections;
30  import java.util.HashSet;
31  import java.util.Set;
32  import java.util.stream.Collectors;
33  
34  import static ubic.basecode.ontology.jena.JenaUtils.where;
35  
36  /**
37   * Represents a class in an ontology
38   *
39   * @author Paul
40   */
41  class OntologyTermImpl extends AbstractOntologyResource implements OntologyTerm {
42  
43      private static final String HAS_ALTERNATE_ID = "http://www.geneontology.org/formats/oboInOwl#hasAlternativeId";
44  
45      /**
46       * Ontology class underlying this term.
47       */
48      private final OntClass ontResource;
49  
50      /**
51       * Extra sets of properties to use when navigating parents and children of a term.
52       */
53      private final Set<Restriction> additionalRestrictions;
54  
55      public OntologyTermImpl( OntClass resource, @Nullable Set<Restriction> additionalRestrictions ) {
56          super( resource );
57          this.ontResource = resource;
58          this.additionalRestrictions = additionalRestrictions;
59      }
60  
61      public OntologyTermImpl( OntClass resource, Set<Restriction> additionalRestrictions, double score ) {
62          super( resource, score );
63          this.ontResource = resource;
64          this.additionalRestrictions = additionalRestrictions;
65      }
66  
67      @Override
68      public Collection<String> getAlternativeIds() {
69          Collection<String> results = new HashSet<>();
70  
71          Property alternate = ResourceFactory.createProperty( HAS_ALTERNATE_ID );
72          StmtIterator it = this.ontResource.listProperties( alternate );
73          while ( it.hasNext() ) {
74              Statement statement = it.next();
75              results.add( statement.asTriple().getMatchObject().getLiteralLexicalForm() );
76          }
77  
78          return results;
79  
80      }
81  
82      @Override
83      public Collection<AnnotationProperty> getAnnotations() {
84          Collection<AnnotationProperty> annots = new HashSet<>();
85          StmtIterator iterator = ontResource.listProperties();
86          // this is a little slow because we have to go through all statements for the term.
87          while ( iterator.hasNext() ) {
88              Statement state = iterator.next();
89              OntResource res = state.getPredicate().as( OntResource.class );
90              if ( res.isAnnotationProperty() ) {
91                  com.hp.hpl.jena.ontology.AnnotationProperty p = res.asAnnotationProperty();
92                  RDFNode n = state.getObject();
93                  annots.add( new AnnotationPropertyImpl( p, n ) );
94              }
95          }
96          return annots;
97      }
98  
99      @Override
100     public Collection<OntologyTerm> getChildren( boolean direct, boolean includeAdditionalProperties, boolean keepObsoletes ) {
101         return JenaUtils.getChildren( ontResource.getOntModel(), Collections.singleton( ontResource ), direct, includeAdditionalProperties ? additionalRestrictions : null )
102                 .stream()
103                 .map( o -> new OntologyTermImpl( o, additionalRestrictions ) )
104                 .filter( o -> keepObsoletes || !o.isObsolete() )
105                 .collect( Collectors.toSet() );
106     }
107 
108     /*
109      * (non-Javadoc)
110      *
111      * @see ubic.gemma.ontology.OntologyTerm#getComment()
112      */
113     @Override
114     public String getComment() {
115         String comment = this.ontResource.getComment( null );
116         return comment == null ? "" : comment;
117     }
118 
119     @Override
120     public Collection<OntologyIndividual> getIndividuals( boolean direct ) {
121         return this.ontResource.listInstances( direct )
122                 .filterKeep( where( OntResource::isIndividual ) )
123                 .mapWith( r -> ( OntologyIndividual ) new OntologyIndividualImpl( r.asIndividual(), additionalRestrictions ) )
124                 .toSet();
125     }
126 
127     @Override
128     public String getLocalName() {
129         return ontResource.getLocalName();
130     }
131 
132     @Override
133     public Object getModel() {
134         return ontResource.getModel();
135     }
136 
137     @Override
138     public Collection<OntologyTerm> getParents( boolean direct, boolean includeAdditionalProperties, boolean keepObsoletes ) {
139         return JenaUtils.getParents( ontResource.getOntModel(), Collections.singleton( ontResource ), direct, includeAdditionalProperties ? additionalRestrictions : null )
140                 .stream()
141                 .map( o -> new OntologyTermImpl( o, additionalRestrictions ) )
142                 .filter( o -> keepObsoletes || !o.isObsolete() )
143                 .collect( Collectors.toSet() );
144     }
145 
146     /**
147      *
148      */
149     @Override
150     public Collection<OntologyRestriction> getRestrictions() {
151         /*
152          * Remember that restrictions are superclasses.
153          */
154         Collection<OntologyRestriction> result = new HashSet<>();
155         ExtendedIterator<OntClass> iterator = ontResource.listSuperClasses( false );
156         while ( iterator.hasNext() ) {
157             OntClass c = iterator.next();
158             if ( c.isRestriction() ) {
159                 result.add( RestrictionFactory.asRestriction( c.asRestriction(), additionalRestrictions ) );
160             }
161         }
162 
163         // Check superclasses for any ADDITIONAL restrictions.
164         iterator = ontResource.listSuperClasses( false );
165         while ( iterator.hasNext() ) {
166             OntClass c = iterator.next();
167 
168             try {
169                 c.asRestriction(); // throw it away, we already processed it above.
170             } catch ( Exception e ) {
171                 // not a restriction, but a superclass that might have restrictions
172                 ExtendedIterator<OntClass> supClassesIt = c.listSuperClasses( false );
173                 loop:
174                 while ( supClassesIt.hasNext() ) {
175                     OntClass sc = supClassesIt.next();
176                     Restriction sr;
177                     try {
178                         sr = sc.asRestriction();
179 
180                         // only add it if the class doesn't already have one.
181                         OntologyRestriction candidateRestriction = RestrictionFactory.asRestriction( sr, additionalRestrictions );
182                         for ( OntologyRestriction restr : result ) {
183                             if ( restr.getRestrictionOn().equals( candidateRestriction.getRestrictionOn() ) )
184                                 continue loop;
185                         }
186                         result.add( candidateRestriction );
187 
188                     } catch ( Exception ex ) {
189                         // superclass isn't a restriction.
190                     }
191                 }
192             }
193 
194         }
195 
196         return result;
197     }
198 
199     /*
200      * (non-Javadoc)
201      *
202      * @see ubic.gemma.analysis.ontology.OntologyTerm#getTerm()
203      */
204     @Override
205     public String getTerm() {
206         String res = getLabel();
207         if ( res == null ) {
208             res = ontResource.toString();
209         }
210         return res;
211     }
212 
213     @Override
214     public boolean isObsolete() {
215         return super.isObsolete() || ontResource.hasSuperClass( OBO.ObsoleteClass );
216     }
217 
218     /*
219      * (non-Javadoc)
220      *
221      * @see ubic.gemma.analysis.ontology.OntologyTerm#isRoot()
222      */
223     @Override
224     public boolean isRoot() {
225         return getParents( true, true, true ).isEmpty();
226     }
227 
228     /*
229      * (non-Javadoc)
230      *
231      * @see ubic.basecode.ontology.model.OntologyTerm#isTermObsolete()
232      */
233     @Override
234     public boolean isTermObsolete() {
235         return isObsolete();
236     }
237 
238     public OntClass getOntClass() {
239         return ontResource;
240     }
241 }