All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.tidalwave.bluebill.taxonomy.birds.BirdTaxonomyImporter Maven / Gradle / Ivy

The newest version!
/***********************************************************************************************************************
 *
 * blueBill Resources - open source birding
 * Copyright (C) 2009-2011 by Tidalwave s.a.s. (http://www.tidalwave.it)
 *
 ***********************************************************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 ***********************************************************************************************************************
 *
 * WWW: http://bluebill.tidalwave.it
 * SCM: https://java.net/hg/bluebill~resources-src
 *
 **********************************************************************************************************************/
package it.tidalwave.bluebill.taxonomy.birds;

import java.util.Date;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import java.util.Set;
import it.tidalwave.bluebill.taxonomy.birds.impl.PatchedDefaultMutableDisplayable;
import java.util.Locale;
import it.tidalwave.role.MutableLocalizedDisplayable;
import it.tidalwave.role.LocalizedDisplayable;
import javax.annotation.CheckForNull;
import it.tidalwave.bluebill.taxonomy.Taxon.Builder;
import it.tidalwave.util.Id;
import it.tidalwave.netbeans.util.Locator;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.io.IOException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.Serializable;
import org.openide.util.Exceptions;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryException;
import it.tidalwave.util.NotFoundException;
import it.tidalwave.bluebill.taxonomy.Taxonomy;
import it.tidalwave.bluebill.taxonomy.Taxon;
import it.tidalwave.bluebill.taxonomy.TaxonomyManager;
import it.tidalwave.util.Initializer;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Scanner;
import javax.xml.datatype.XMLGregorianCalendar;
import org.openide.util.NbBundle;
import org.openrdf.concepts.dc.DcResource;
import lombok.extern.slf4j.Slf4j;
import static it.tidalwave.bluebill.taxonomy.Taxon.Rank.*;

/***********************************************************************************************************************
 *
 * @author  Fabrizio Giudici
 * @version $Id$
 *
 **********************************************************************************************************************/
@Slf4j
public abstract class BirdTaxonomyImporter implements Serializable
  {
    protected static final LocalizedDisplayable NO_COMMON_NAMES = new PatchedDefaultMutableDisplayable();

    protected transient TaxonomyManager taxonomyManager = Locator.find(TaxonomyManager.class);

    protected transient BirdLocaleInfo birdLocaleInfo;

    protected transient final Map> childCache = new HashMap>();

    protected transient TaxonUniqueIdManager taxonUniqueIdManager;

    protected transient String sourceResourceName;

    protected final SortedSet brokenSpecies = new TreeSet();

    protected final SortedMap> speciesWithoutTranslations = new TreeMap>();

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    protected transient TaxonTranslator taxonTranslator = new TaxonTranslator()
      {
        @Override
        public void loadConfiguration()
          {
          }

        @Override
        public String fixTypos (final @Nonnull String string)
          {
            return string;
          }
      };

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    protected void initialize()
      throws IOException
      {
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public void setSourceResourceName (final @Nonnull String sourceResourceName)
      throws FileNotFoundException
      {
//        if (!sourceFile.exists())
//          {
//            throw new FileNotFoundException(sourceFile.toString());
//          }

        this.sourceResourceName = sourceResourceName;
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public void setTaxonTranslator (final @Nonnull TaxonTranslator taxonTranslator)
      {
        this.taxonTranslator = taxonTranslator;
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public void setBirdLocaleInfo (final @Nonnull BirdLocaleInfo birdLocaleInfo)
      {
        this.birdLocaleInfo = birdLocaleInfo;
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public void setIdentifierMapFile (final @Nonnull File identifierMapFile)
      throws IOException
      {
        taxonUniqueIdManager = new TaxonUniqueIdManager(identifierMapFile);
        taxonTranslator.loadConfiguration();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public SortedSet getBrokenSpecies()
      {
        return brokenSpecies;
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    public SortedMap> getSpeciesWithoutTranslations()
      {
        return Collections.unmodifiableSortedMap(speciesWithoutTranslations);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    public void init (final @Nonnull Repository repository)
      {
        taxonomyManager = Locator.find(TaxonomyManager.class);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    protected void addMissingTranslation (final @Nonnull String species, final @Nonnull String language)
      {
        List languages = speciesWithoutTranslations.get(species);

        if (languages == null)
          {
            languages = new ArrayList();
            speciesWithoutTranslations.put(species, languages);
          }

        languages.add(language);
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    protected Taxonomy createTaxonomy (final @Nonnull Repository repository,
                                       final @Nonnull String id,
                                       final @Nonnull Class bundleClass,
                                       final @Nonnull String[] languages)
      {
        final ResourceBundle bundle = NbBundle.getBundle(bundleClass);
        return taxonomyManager.createTaxonomy().withId(new Id(id)).
                                                withDisplayNames(createDisplayable("en", bundle.getString("title"))).
                                                inRepository(repository).
                                                withInitializer(new Initializer()
                                                  {
                                                    @Override
                                                    public Taxonomy initialize (Taxonomy taxonomy)
                                                      {
                                                        final DcResource dcResource = taxonomy.getLookup().lookup(DcResource.class);
                                                        add(dcResource.getDcCreators(), "authors");
//                                                                             dcResource.getDcContributors().add(null);
//                                                                            dcResource.getDcCreators().add(null);
                                                        
                                                        dcResource.setDcTitle(bundle.getString("title"));
                                                        dcResource.setDcDescription(bundle.getString("description"));
                                                        dcResource.getDcPublishers().add(bundle.getString("publishers"));
                                                        dcResource.getDcRights().add(bundle.getString("rights"));
                
                                                        final String dateAsString = bundle.getString("date");
                                                        final Scanner scanner = new Scanner(dateAsString).useDelimiter("-");
                                                        
                                                        try 
                                                          {
                                                            final XMLGregorianCalendar date = DatatypeFactory.newInstance().
                                                                    newXMLGregorianCalendarDate(scanner.nextInt(), 
                                                                                                scanner.nextInt(), 
                                                                                                scanner.nextInt(), 
                                                                                                0);
                                                            dcResource.getDcDates().add(date);
                                                          }
                                                        catch (DatatypeConfigurationException e) 
                                                          {
                                                            log.error("", e);
                                                          }

                                                        for (final String language : languages)
                                                          {
                                                            dcResource.getDcLanguages().add(language);
                                                          }

                                                        return taxonomy;
                                                      }
                                                    
                                                    private void add (final @Nonnull Set set, final @Nonnull String resourceName)
                                                      {
                                                        try
                                                          {
                                                            final String s = bundle.getString(resourceName);

                                                            if (s != null)
                                                              {
                                                                for (final String ss : s.split(","))
                                                                  {
                                                                    set.add(ss.trim());  
                                                                  }
                                                              }
                                                          }
                                                        catch (MissingResourceException e)
                                                          {
                                                            log.warn("No resource with key \"{}\"", resourceName);
                                                          }
                                                      }
                                                  }).
                                                build();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    protected Taxon createAves (final @Nonnull Taxonomy taxonomy, final @Nonnull String idPrefix)
      throws RepositoryException
      {
        return taxonomy.createTopTaxon().withScientificName("Aves").
                                         withSpecificEpythet("Aves").
                                         withId(new Id(idPrefix + "/Animalia/Chordata/Aves")).
                                         withRank(Taxon.Rank.CLASS).
                                         build();
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    protected Taxon.Builder findOrCreateSubTaxon (final @Nonnull Taxon parentTaxon,
                                                  final @Nonnull String idPrefix,
                                                  final @Nonnull String path)
      throws RepositoryException
      {
        Builder builder = findOrCreateSubTaxon(parentTaxon).withId(new Id(idPrefix + path));

        try
          {
            final String translatedPath = taxonTranslator.translated(path);

            log.info("Processing:    {}", path);

            if (!translatedPath.equals(path))
              {
                log.debug("Translated to: {}", translatedPath);
              }

//                    if (!idPrefix.equals(""))
//              {
                builder = builder.withScientificNameId(new Id(taxonUniqueIdManager.findId(translatedPath)));
//              }
          }
        catch (RuntimeException e)
          {
            brokenSpecies.add(path + ": " + e);
          }

        return builder;
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    // FIXME: move to Taxon
    // FIXME: but you can't move until you get rid of childCache, which is fundamental for performance
    @Nonnull
    private Taxon.Builder findOrCreateSubTaxon (final @Nonnull Taxon parentTaxon)
      throws RepositoryException
      {
        return new Taxon.Builder()
          {
            @Override
            public Taxon build()
              {
                Taxon taxon = null;
                Map map = childCache.get(parentTaxon);

                try
                  {
                    if (map == null)
                      {
                        map = new HashMap();
                        childCache.put(parentTaxon, map);
                        throw new NotFoundException();
                      }

                    taxon = map.get(scientificName);

                    if (taxon == null)
                      {
                        throw new NotFoundException();
                      }
        //            concept = parentConcept.findSubConcepts().name(name).result();
                  }
                catch (NotFoundException e)
                  {
                    taxon = parentTaxon.createSubTaxon().withScientificName(scientificName).
                                                         withScientificNameId(scientificNameId).
                                                         withSpecificEpythet(specificEpythet).
                                                         withDisplayNames(displayable).
                                                         withId(id).
                                                         withRank(rank).
                                                         withInitializers(initializers).
                                                         build();
                    map.put(scientificName, taxon);
                  }

                return taxon;
              }
          };
      }

    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    protected void createPath (final @Nonnull Taxon aves,
                               final @Nonnull String idPrefix,
                               final @Nonnull String orderName,
                               final @Nonnull String familyName,
                               final @Nonnull String genusName,
                               final @Nonnull String speciesName,
                               final @CheckForNull String subSpeciesName,
                               final @Nonnull LocalizedDisplayable familyCommonNames,
                               final @Nonnull LocalizedDisplayable speciesCommonNames)
      throws RuntimeException, RepositoryException
      {
        String path = "/Animalia/Chordata/Aves";
        path += "/" + orderName;
        final Taxon order = findOrCreateSubTaxon(aves, idPrefix, path).withRank(ORDER).
                                                                       withScientificName(orderName).
                                                                       withSpecificEpythet(orderName).
                                                                       build();
        path += "/" + familyName;
        final Taxon family = findOrCreateSubTaxon(order, idPrefix, path).withRank(FAMILY).
                                                                         withScientificName(familyName).
                                                                         withSpecificEpythet(familyName).
                                                                         withDisplayNames(familyCommonNames).
                                                                         build();
        path += "/" + genusName;
        final Taxon genus = findOrCreateSubTaxon(family, idPrefix, path).withRank(GENUS).
                                                                         withScientificName(genusName).
                                                                         withSpecificEpythet(genusName).
                                                                         build();
        path += "/" + speciesName;
        final Taxon species = findOrCreateSubTaxon(genus, idPrefix, path).withRank(SPECIES).
                                                                          withScientificName(genusName + " " + speciesName).
                                                                          withSpecificEpythet(speciesName).
                                                                          withDisplayNames(speciesCommonNames).
                                                                          build();

        if (subSpeciesName != null)
          {
            path += "/" + subSpeciesName;
            try
              {
                findOrCreateSubTaxon(species, idPrefix, path).withRank(SUBSPECIES).
                                                              withScientificName(genusName + " " + speciesName + " " + subSpeciesName).
                                                              withSpecificEpythet(subSpeciesName).
                                                              withDisplayNames(speciesCommonNames).
                                                              build();
              }
            catch (RuntimeException e)
              {
                brokenSpecies.add(path + ": " + e);
                throw e;
              }
          }
      }
    
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    protected static LocalizedDisplayable createDisplayable (final @Nonnull String ... info)
      {
        final MutableLocalizedDisplayable displayable = new PatchedDefaultMutableDisplayable();

        for (int i = 0; i < info.length; i += 2)
          {
            displayable.setDisplayName(info[i + 1], new Locale(info[i]));
          }

        return displayable;
      }
    
//    /*******************************************************************************************************************
//     *
//     *
//     ******************************************************************************************************************/
//    protected static void addStatement (final @Nonnull Entity entity,
//                                        final @Nonnull String predicate2,
//                                        final @Nonnull String literal2)
//      {
//        final SesameManager em = (SesameManager)ElmoManagerThreadLocal.get();
//        final LiteralManager literalManager = em.getLiteralManager();
//        final Literal literal = literalManager.getLiteral(literal2);
//        final URI predicate = new URIImpl(predicate2); // FIXME
//        try
//          {
////            final QName qName = entity.getLookup().lookup(Entity.class).getQName();
//            final QName qName = entity.getQName();
//            final Resource entityResource = em.getResourceManager().createResource(qName);
//            em.getConnection().add(entityResource, predicate, literal);
//          }
//        catch (RepositoryException e)
//          {
//            throw new RuntimeException(e);
//          }
//      }
//
    /*******************************************************************************************************************
     *
     *
     ******************************************************************************************************************/
    @Nonnull
    protected static String capitalized (final @Nonnull String string)
      {
        return string.substring(0, 1).toUpperCase() + string.substring(1).toLowerCase();
      }
  }