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