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