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  /**
38   * Represents a class in an ontology
39   *
40   * @author Paul
41   */
42  class OntologyTermImpl extends AbstractOntologyResource implements OntologyTerm {
43  
44      private static final String HAS_ALTERNATE_ID = "http://www.geneontology.org/formats/oboInOwl#hasAlternativeId";
45  
46      /**
47       * Ontology class underlying this term.
48       */
49      private final OntClass ontResource;
50  
51      /**
52       * Extra sets of properties to use when navigating parents and children of a term.
53       */
54      private final Set<Restriction> additionalRestrictions;
55  
56      public OntologyTermImpl( OntClass resource, Set<Restriction> additionalRestrictions ) {
57          super( resource );
58          this.ontResource = resource;
59          this.additionalRestrictions = additionalRestrictions;
60      }
61  
62      @Override
63      public Collection<String> getAlternativeIds() {
64          return getAnnotations( HAS_ALTERNATE_ID ).stream().map( AnnotationProperty::getContents ).collect( Collectors.toSet() );
65      }
66  
67      @Override
68      public Collection<AnnotationProperty> getAnnotations() {
69          Collection<AnnotationProperty> annots = new HashSet<>();
70          StmtIterator iterator = ontResource.listProperties();
71          // this is a little slow because we have to go through all statements for the term.
72          while ( iterator.hasNext() ) {
73              Statement state = iterator.next();
74              JenaUtils.as( state.getPredicate(), com.hp.hpl.jena.ontology.AnnotationProperty.class )
75                      .map( r -> new AnnotationPropertyImpl( r, state.getObject() ) )
76                      .ifPresent( annots::add );
77          }
78          return annots;
79      }
80  
81      @Override
82      public Collection<AnnotationProperty> getAnnotations( String propertyUri ) {
83          Collection<AnnotationProperty> annots = new HashSet<>();
84          Property alternate = ResourceFactory.createProperty( propertyUri );
85          StmtIterator it = this.ontResource.listProperties( alternate );
86          while ( it.hasNext() ) {
87              Statement state = it.next();
88              JenaUtils.as( state.getPredicate(), com.hp.hpl.jena.ontology.AnnotationProperty.class )
89                      .map( r -> new AnnotationPropertyImpl( r, state.getObject() ) )
90                      .ifPresent( annots::add );
91          }
92          return annots;
93      }
94  
95      @Nullable
96      @Override
97      public AnnotationProperty getAnnotation( String propertyUri ) {
98          Statement state = ontResource.getProperty( ResourceFactory.createProperty( propertyUri ) );
99          if ( state != null ) {
100             return JenaUtils.as( state.getPredicate(), com.hp.hpl.jena.ontology.AnnotationProperty.class )
101                     .map( r -> new AnnotationPropertyImpl( r, state.getObject() ) )
102                     .orElse( null );
103         }
104         return null;
105     }
106 
107     @Override
108     public Collection<OntologyTerm> getChildren( boolean direct, boolean includeAdditionalProperties, boolean keepObsoletes ) {
109         return JenaUtils.getChildren( ontResource.getOntModel(), Collections.singleton( ontResource ), direct, includeAdditionalProperties ? additionalRestrictions : null )
110                 .stream()
111                 .map( o -> new OntologyTermImpl( o, additionalRestrictions ) )
112                 .filter( o -> keepObsoletes || !o.isObsolete() )
113                 .collect( Collectors.toSet() );
114     }
115 
116     /*
117      * (non-Javadoc)
118      *
119      * @see ubic.gemma.ontology.OntologyTerm#getComment()
120      */
121     @Override
122     public String getComment() {
123         String comment = this.ontResource.getComment( null );
124         return comment == null ? "" : comment;
125     }
126 
127     @Override
128     public Collection<OntologyIndividual> getIndividuals( boolean direct ) {
129         return this.ontResource.listInstances( direct )
130                 .filterKeep( new PredicateFilter<>( OntResource::isIndividual ) )
131                 .mapWith( r -> ( OntologyIndividual ) new OntologyIndividualImpl( r.asIndividual(), additionalRestrictions ) )
132                 .toSet();
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 
236     public OntClass getOntClass() {
237         return ontResource;
238     }
239 }