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