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      @Override
65      public Collection<String> getAlternativeIds() {
66          return getAnnotations( HAS_ALTERNATE_ID ).stream().map( AnnotationProperty::getContents ).collect( Collectors.toSet() );
67      }
68  
69      @Override
70      public Collection<AnnotationProperty> getAnnotations() {
71          Collection<AnnotationProperty> annots = new HashSet<>();
72          StmtIterator iterator = ontResource.listProperties();
73          // this is a little slow because we have to go through all statements for the term.
74          while ( iterator.hasNext() ) {
75              Statement state = iterator.next();
76              JenaUtils.as( state.getPredicate(), com.hp.hpl.jena.ontology.AnnotationProperty.class )
77                      .map( r -> new AnnotationPropertyImpl( r, state.getObject() ) )
78                      .ifPresent( annots::add );
79          }
80          return annots;
81      }
82  
83      @Override
84      public Collection<AnnotationProperty> getAnnotations( String propertyUri ) {
85          Collection<AnnotationProperty> annots = new HashSet<>();
86          Property alternate = ResourceFactory.createProperty( propertyUri );
87          StmtIterator it = this.ontResource.listProperties( alternate );
88          while ( it.hasNext() ) {
89              Statement state = it.next();
90              JenaUtils.as( state.getPredicate(), com.hp.hpl.jena.ontology.AnnotationProperty.class )
91                      .map( r -> new AnnotationPropertyImpl( r, state.getObject() ) )
92                      .ifPresent( annots::add );
93          }
94          return annots;
95      }
96  
97      @Nullable
98      @Override
99      public AnnotationProperty getAnnotation( String propertyUri ) {
100         Statement state = ontResource.getProperty( ResourceFactory.createProperty( propertyUri ) );
101         if ( state != null ) {
102             return JenaUtils.as( state.getPredicate(), com.hp.hpl.jena.ontology.AnnotationProperty.class )
103                     .map( r -> new AnnotationPropertyImpl( r, state.getObject() ) )
104                     .orElse( null );
105         }
106         return null;
107     }
108 
109     @Override
110     public Collection<OntologyTerm> getChildren( boolean direct, boolean includeAdditionalProperties, boolean keepObsoletes ) {
111         return JenaUtils.getChildren( ontResource.getOntModel(), Collections.singleton( ontResource ), direct, includeAdditionalProperties ? additionalRestrictions : null )
112                 .stream()
113                 .map( o -> new OntologyTermImpl( o, additionalRestrictions ) )
114                 .filter( o -> keepObsoletes || !o.isObsolete() )
115                 .collect( Collectors.toSet() );
116     }
117 
118     /*
119      * (non-Javadoc)
120      *
121      * @see ubic.gemma.ontology.OntologyTerm#getComment()
122      */
123     @Override
124     public String getComment() {
125         String comment = this.ontResource.getComment( null );
126         return comment == null ? "" : comment;
127     }
128 
129     @Override
130     public Collection<OntologyIndividual> getIndividuals( boolean direct ) {
131         return this.ontResource.listInstances( direct )
132                 .filterKeep( where( OntResource::isIndividual ) )
133                 .mapWith( r -> ( OntologyIndividual ) new OntologyIndividualImpl( r.asIndividual(), additionalRestrictions ) )
134                 .toSet();
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 }