4646import javax .annotation .Nullable ;
4747import java .io .IOException ;
4848import java .io .InputStream ;
49+ import java .io .InterruptedIOException ;
50+ import java .nio .channels .ClosedByInterruptException ;
4951import java .util .*;
5052import java .util .concurrent .locks .Lock ;
5153import java .util .concurrent .locks .ReadWriteLock ;
5254import java .util .concurrent .locks .ReentrantReadWriteLock ;
55+ import java .util .function .Predicate ;
5356import java .util .stream .Collectors ;
5457
5558import static ubic .basecode .ontology .jena .JenaUtils .where ;
@@ -75,6 +78,11 @@ public abstract class AbstractOntologyService implements OntologyService {
7578 additionalProperties .add ( RO .properPartOf );
7679 }
7780
81+ /* settings (applicable for next initialization) */
82+ private InferenceMode nextInferenceMode = InferenceMode .TRANSITIVE ;
83+ private boolean nextProcessImports = true ;
84+ private boolean nextSearchEnabled = true ;
85+
7886 /**
7987 * Lock used to prevent reads while the ontology is being initialized.
8088 */
@@ -83,13 +91,64 @@ public abstract class AbstractOntologyService implements OntologyService {
8391 /* internal state protected by rwLock */
8492 private OntModel model ;
8593 private Map <String , String > alternativeIDs ;
86-
8794 @ Nullable
8895 private SearchIndex index ;
89-
9096 private Set <Restriction > additionalRestrictions ;
91-
9297 private boolean isInitialized = false ;
98+ @ Nullable
99+ private InferenceMode inferenceMode = null ;
100+ @ Nullable
101+ private Boolean processImports = null ;
102+ @ Nullable
103+ private Boolean searchEnabled = null ;
104+
105+ @ Override
106+ public InferenceMode getInferenceMode () {
107+ Lock lock = rwLock .readLock ();
108+ try {
109+ lock .lock ();
110+ return this .inferenceMode != null ? this .inferenceMode : nextInferenceMode ;
111+ } finally {
112+ lock .unlock ();
113+ }
114+ }
115+
116+ @ Override
117+ public void setInferenceMode ( InferenceMode inferenceMode ) {
118+ this .nextInferenceMode = inferenceMode ;
119+ }
120+
121+ @ Override
122+ public boolean getProcessImports () {
123+ Lock lock = rwLock .readLock ();
124+ try {
125+ lock .lock ();
126+ return processImports != null ? processImports : nextProcessImports ;
127+ } finally {
128+ lock .unlock ();
129+ }
130+ }
131+
132+ @ Override
133+ public void setProcessImports ( boolean processImports ) {
134+ this .nextProcessImports = processImports ;
135+ }
136+
137+ @ Override
138+ public boolean isSearchEnabled () {
139+ Lock lock = rwLock .readLock ();
140+ try {
141+ lock .lock ();
142+ return searchEnabled != null ? searchEnabled : nextSearchEnabled ;
143+ } finally {
144+ lock .unlock ();
145+ }
146+ }
147+
148+ @ Override
149+ public void setSearchEnabled ( boolean searchEnabled ) {
150+ this .nextSearchEnabled = searchEnabled ;
151+ }
93152
94153 public void initialize ( boolean forceLoad , boolean forceIndexing ) {
95154 initialize ( null , forceLoad , forceIndexing );
@@ -108,6 +167,9 @@ private void initialize( @Nullable InputStream stream, boolean forceLoad, boolea
108167 String ontologyUrl = getOntologyUrl ();
109168 String ontologyName = getOntologyName ();
110169 String cacheName = getCacheName ();
170+ InferenceMode inferenceMode = nextInferenceMode ;
171+ boolean processImports = nextProcessImports ;
172+ boolean searchEnabled = nextSearchEnabled ;
111173
112174 // Detect configuration problems.
113175 if ( StringUtils .isBlank ( ontologyUrl ) ) {
@@ -138,8 +200,15 @@ private void initialize( @Nullable InputStream stream, boolean forceLoad, boolea
138200 if ( checkIfInterrupted () )
139201 return ;
140202
141- model = stream != null ? loadModelFromStream ( stream ) : loadModel (); // can take a while.
142- assert model != null ;
203+ try {
204+ model = stream != null ? loadModelFromStream ( stream , processImports , inferenceMode ) : loadModel ( processImports , inferenceMode ); // can take a while.
205+ } catch ( Exception e ) {
206+ if ( isCausedByInterrupt ( e ) ) {
207+ return ;
208+ } else {
209+ throw new RuntimeException ( String .format ( "Failed to load ontology model for %s." , this ), e );
210+ }
211+ }
143212
144213 // retrieving restrictions is lengthy
145214 if ( checkIfInterrupted () )
@@ -154,14 +223,22 @@ private void initialize( @Nullable InputStream stream, boolean forceLoad, boolea
154223 if ( checkIfInterrupted () )
155224 return ;
156225
157- if ( cacheName != null ) {
226+ if ( searchEnabled && cacheName != null ) {
158227 //Checks if the current ontology has changed since it was last loaded.
159228 boolean changed = OntologyLoader .hasChanged ( cacheName );
160229 boolean indexExists = OntologyIndexer .getSubjectIndex ( cacheName ) != null ;
161230 boolean forceReindexing = forceLoad && forceIndexing ;
162231 // indexing is slow, don't do it if we don't have to.
163- index = OntologyIndexer .indexOntology ( cacheName , model ,
164- forceReindexing || changed || !indexExists );
232+ try {
233+ index = OntologyIndexer .indexOntology ( cacheName , model ,
234+ forceReindexing || changed || !indexExists );
235+ } catch ( Exception e ) {
236+ if ( isCausedByInterrupt ( e ) ) {
237+ return ;
238+ } else {
239+ throw new RuntimeException ( String .format ( "Failed to generate index for %s." , this ), e );
240+ }
241+ }
165242 } else {
166243 index = null ;
167244 }
@@ -177,6 +254,9 @@ private void initialize( @Nullable InputStream stream, boolean forceLoad, boolea
177254 this .additionalRestrictions = additionalRestrictions ;
178255 this .index = index ;
179256 this .isInitialized = true ;
257+ this .inferenceMode = inferenceMode ;
258+ this .processImports = processImports ;
259+ this .searchEnabled = searchEnabled ;
180260 if ( cacheName != null ) {
181261 // now that the terms have been replaced, we can clear old caches
182262 try {
@@ -202,6 +282,21 @@ private boolean checkIfInterrupted() {
202282 return false ;
203283 }
204284
285+ private static boolean isCausedByInterrupt ( Exception e ) {
286+ return hasCauseMatching ( e , cause -> ( ( cause instanceof ParseException ) && ( ( ParseException ) cause ).getErrorNumber () == ARPErrorNumbers .ERR_INTERRUPTED ) ) ||
287+ hasCause ( e , InterruptedException .class ) ||
288+ hasCause ( e , InterruptedIOException .class ) ||
289+ hasCause ( e , ClosedByInterruptException .class );
290+ }
291+
292+ private static boolean hasCause ( Throwable t , Class <? extends Throwable > clazz ) {
293+ return hasCauseMatching ( t , clazz ::isInstance );
294+ }
295+
296+ private static boolean hasCauseMatching ( Throwable t , Predicate <Throwable > predicate ) {
297+ return predicate .test ( t ) || ( t .getCause () != null && hasCauseMatching ( t .getCause (), predicate ) );
298+ }
299+
205300 /**
206301 * Do not do this except before re-indexing.
207302 */
@@ -211,7 +306,8 @@ public void closeIndex() {
211306 }
212307
213308 @ Override
214- public Collection <OntologyIndividual > findIndividuals ( String search , boolean keepObsoletes ) throws OntologySearchException {
309+ public Collection <OntologyIndividual > findIndividuals ( String search , boolean keepObsoletes ) throws
310+ OntologySearchException {
215311 Lock lock = rwLock .readLock ();
216312 try {
217313 lock .lock ();
@@ -233,7 +329,8 @@ public Collection<OntologyIndividual> findIndividuals( String search, boolean ke
233329 }
234330
235331 @ Override
236- public Collection <OntologyResource > findResources ( String searchString , boolean keepObsoletes ) throws OntologySearchException {
332+ public Collection <OntologyResource > findResources ( String searchString , boolean keepObsoletes ) throws
333+ OntologySearchException {
237334 Lock lock = rwLock .readLock ();
238335 try {
239336 lock .lock ();
@@ -393,7 +490,8 @@ public Collection<OntologyIndividual> getTermIndividuals( String uri ) {
393490 }
394491
395492 @ Override
396- public Set <OntologyTerm > getParents ( Collection <OntologyTerm > terms , boolean direct , boolean includeAdditionalProperties , boolean keepObsoletes ) {
493+ public Set <OntologyTerm > getParents ( Collection <OntologyTerm > terms , boolean direct ,
494+ boolean includeAdditionalProperties , boolean keepObsoletes ) {
397495 Lock lock = rwLock .readLock ();
398496 try {
399497 lock .lock ();
@@ -411,7 +509,8 @@ public Set<OntologyTerm> getParents( Collection<OntologyTerm> terms, boolean dir
411509 }
412510
413511 @ Override
414- public Set <OntologyTerm > getChildren ( Collection <OntologyTerm > terms , boolean direct , boolean includeAdditionalProperties , boolean keepObsoletes ) {
512+ public Set <OntologyTerm > getChildren ( Collection <OntologyTerm > terms , boolean direct ,
513+ boolean includeAdditionalProperties , boolean keepObsoletes ) {
415514 Lock lock = rwLock .readLock ();
416515 try {
417516 lock .lock ();
@@ -463,13 +562,8 @@ public synchronized void startInitializationThread( boolean forceLoad, boolean f
463562 initializationThread = new Thread ( () -> {
464563 try {
465564 this .initialize ( forceLoad , forceIndexing );
466- } catch ( JenaException e ) {
467- if ( !( e .getCause () instanceof ParseException ) || ( ( ParseException ) e .getCause () ).getErrorNumber () != ARPErrorNumbers .ERR_INTERRUPTED ) {
468- throw e ;
469- }
470565 } catch ( Exception e ) {
471- log .error ( e .getMessage (), e );
472- this .isInitialized = false ;
566+ log .error ( "Initialization for %s failed." , e );
473567 }
474568 }, getOntologyName () + "_load_thread_" + RandomStringUtils .randomAlphanumeric ( 5 ) );
475569 // To prevent VM from waiting on this thread to shut down (if shutting down).
@@ -521,13 +615,13 @@ public void waitForInitializationThread() throws InterruptedException {
521615 * Delegates the call as to load the model into memory or leave it on disk. Simply delegates to either
522616 * OntologyLoader.loadMemoryModel( url ); OR OntologyLoader.loadPersistentModel( url, spec );
523617 */
524- protected abstract OntModel loadModel () ;
618+ protected abstract OntModel loadModel ( boolean processImports , InferenceMode inferenceMode ) throws JenaException , IOException ;
525619
526620
527621 /**
528622 * Load a model from a given input stream.
529623 */
530- protected abstract OntModel loadModelFromStream ( InputStream stream ) ;
624+ protected abstract OntModel loadModelFromStream ( InputStream stream , boolean processImports , InferenceMode inferenceMode ) throws JenaException , IOException ;
531625
532626 /**
533627 * A name for caching this ontology, or null to disable caching.
@@ -546,6 +640,10 @@ public void index( boolean force ) {
546640 log .warn ( "This ontology does not support indexing; assign a cache name to be used." );
547641 return ;
548642 }
643+ if ( !nextSearchEnabled ) {
644+ log .warn ( "Search is not enabled for this ontology." );
645+ return ;
646+ }
549647 SearchIndex index ;
550648 Lock lock = rwLock .readLock ();
551649 try {
@@ -555,6 +653,9 @@ public void index( boolean force ) {
555653 return ;
556654 }
557655 index = OntologyIndexer .indexOntology ( getCacheName (), model , force );
656+ } catch ( IOException e ) {
657+ log .error ( "Failed to generate index for {}." , this , e );
658+ return ;
558659 } finally {
559660 lock .unlock ();
560661 }
@@ -563,6 +664,7 @@ public void index( boolean force ) {
563664 try {
564665 lock .lock ();
565666 this .index = index ;
667+ this .searchEnabled = true ;
566668 } finally {
567669 lock .unlock ();
568670 }
@@ -635,9 +737,13 @@ public String toString() {
635737
636738 private Set <OntClass > getOntClassesFromTerms ( Collection <OntologyTerm > terms ) {
637739 return terms .stream ()
638- .map ( OntologyTerm ::getUri )
639- .filter ( Objects ::nonNull )
640- .map ( model ::getOntClass )
740+ .map ( o -> {
741+ if ( o instanceof OntologyTermImpl ) {
742+ return ( ( OntologyTermImpl ) o ).getOntClass ();
743+ } else {
744+ return o .getUri () != null ? model .getOntClass ( o .getUri () ) : null ;
745+ }
746+ } )
641747 .filter ( Objects ::nonNull )
642748 .collect ( Collectors .toSet () );
643749 }
0 commit comments