/**
  * This method is called when a used handler factory disappears. This method is synchronized to
  * avoid concurrent calls to method modifying the factory state.
  *
  * @param reference the leaving service reference.
  * @param service the handler factory object.
  * @see
  *     org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference,
  *     java.lang.Object)
  */
 public synchronized void removedService(ServiceReference reference, Object service) {
   // Look for the implied reference and invalid the handler identifier
   for (Object m_requiredHandler : m_requiredHandlers) {
     RequiredHandler req = (RequiredHandler) m_requiredHandler;
     if (reference.equals(req.getReference())) {
       req.unRef(); // This method will unget the service.
       computeFactoryState();
       return; // The factory can be used only once.
     }
   }
 }
 /**
  * This will be called on each
  *
  * <ul>
  *   <li>update to the Component configuration (activate, deactivate)
  *   <li>updates on the SolrCore
  * </ul>
  *
  * on any detected change it will update the registered EnhancementEngine.
  *
  * <p>This also initialises the FST configuration.
  *
  * @param reference the ServiceRefernece for the SolrServer or <code>null</code> in case the
  *     service is no longer available.
  * @param server the SolrServer (or <code>null</code>
  */
 protected void updateEngineRegistration(ServiceReference reference, SolrServer server) {
   log.info(" ... updateEngineRegistration for {}: {}", getClass().getSimpleName(), engineName);
   if (reference != null && server == null) {
     server = solrServerTracker.getService(reference);
   }
   if (reference == null && this.indexReference == null) {
     // unregisterEngine(); //unregister existing
     return; // and return
   }
   BundleContext bundleContext = this.bundleContext;
   synchronized (this) { // init one after the other in case of multiple calls
     SolrCore core;
     IndexConfiguration indexConfig; // the indexConfig build by this call
     try { // try to init - finally unregisterEngine
       if (bundleContext == null) { // already deactivated
         return; // NOTE: unregistering is done in finally block
       }
       if (reference != null) {
         if (reference.equals(this.solrServerReference)) {
           // use the current core
           core = solrCore;
         } else { // get the SolrCore from the EmbeddedSolrServer
           core = getSolrCore(server);
         }
       } else { // SolrCore not available
         core = null;
       }
       if (core == null) { // no SolrCore
         log.info("   - SolrCore {} present", this.solrCore == null ? "not yet" : "no longer");
         return; // NOTE: unregistering is done in finally block
       } // else - we do have a SolrCore
       // File fstDir = new File(dataDir,"fst");
       // now collect the FST configuration
       indexConfig = new IndexConfiguration(fstConfig, core, fieldEncoding);
       indexConfig.setTypeField(solrTypeField);
       indexConfig.setRankingField(solrRankingField);
       // set fields parsed in the activate method
       indexConfig.setExecutorService(fstCreatorService);
       indexConfig.setRedirectField(null); // TODO add support
       // NOTE: the FST cofnig is processed even if the SolrCore has not changed
       //      because their might be config changes and/or new FST files in the
       //      FST directory of the SolrCore.
       indexConfig.setFstDirectory(getFstDirectory(core, fstFolder));
       // set the DocumentCacheFactory
       if (entityCacheSize > 0) {
         indexConfig.setEntityCacheManager(new FastLRUCacheManager(entityCacheSize));
       } // else no entityCache is used
       if (skipAltTokensConfig != null) {
         indexConfig.setSkipAltTokens(skipAltTokensConfig);
       }
       // create a new searcher for creating FSTs
       if (!indexConfig.activate()) {
         log.warn(
             "Processing of the FST configuration was not successfull "
                 + "for any language. See WARN level loggings for more details!");
         log.warn(
             "  ... FstLinkingEnigne wiht name {} will be registered but"
                 + "be inactive as there seam to be no data for linking available"
                 + "in the SolrCore {} (dir: {})",
             new Object[] {engineName, core.getName(), core.getCoreDescriptor().getInstanceDir()});
       } else { // some FST corpora initialised
         if (log.isInfoEnabled()) { // log the initialised languages
           Set<String> langSet = new HashSet<String>(indexConfig.getCorpusLanguages());
           if (langSet.remove(null)) { // replace the null for the default language
             langSet.add(""); // with an empty string
           }
           String[] langArray = langSet.toArray(new String[langSet.size()]);
           Arrays.sort(langArray, String.CASE_INSENSITIVE_ORDER);
           log.info(" ... initialised FST corpora for languages {}", Arrays.toString(langArray));
         }
       }
     } finally {
       // in any case (even an Exception) ensure that the current
       // engine registration is unregistered and the currently used
       // SolrCore is unregistered!
       unregisterEngine();
     }
     // check if we need to create some FST files
     for (CorpusInfo fstInfo : indexConfig.getCorpora()) {
       // check if the fst does not exist and the fstInfo allows creation
       if (!fstInfo.fst.exists() && fstInfo.allowCreation) {
         // create a task on the FST corpus creation service
         fstCreatorService.execute(new CorpusCreationTask(indexConfig, fstInfo));
       }
     }
     // set the default linking corpora
     String defaultLanguage = entityLinkerConfig.getDefaultLanguage();
     if (defaultLanguage == null) {
       defaultLanguage = ""; // FST uses an empty string for the default
     }
     CorpusInfo defaultCoprous = indexConfig.getCorpus(defaultLanguage);
     if (defaultCoprous != null) {
       log.info(
           " ... set '{}' as default FST Corpus: {}", defaultCoprous.language, defaultCoprous);
       indexConfig.setDefaultCorpus(defaultCoprous);
     } else {
       log.info("  ... no corpus for default language {} available", defaultCoprous);
     }
     // set the index configuration to the field;
     this.indexConfig = indexConfig;
     FstLinkingEngine engine =
         new FstLinkingEngine(engineName, indexConfig, textProcessingConfig, entityLinkerConfig);
     String[] services =
         new String[] {EnhancementEngine.class.getName(), ServiceProperties.class.getName()};
     log.info(" ... register {}: {}", engine.getClass().getSimpleName(), engineName);
     this.engineRegistration = bundleContext.registerService(services, engine, engineMetadata);
     this.solrServerReference = reference;
     this.solrCore = core;
   }
 }