
it.tidalwave.bluebill.taxonomy.mobile.impl.SimpleTaxonomyFactory Maven / Gradle / Ivy
/***********************************************************************************************************************
*
* blueBill Mobile - Android - 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/mobile
* SCM: https://java.net/hg/bluebill-mobile~android-src
*
**********************************************************************************************************************/
package it.tidalwave.bluebill.taxonomy.mobile.impl;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.text.Collator;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.io.BufferedReader;
import java.io.Reader;
import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import it.tidalwave.util.Id;
import it.tidalwave.bluebill.taxonomy.mobile.Taxon;
import it.tidalwave.bluebill.taxonomy.mobile.Taxonomy;
import it.tidalwave.bluebill.taxonomy.mobile.Taxon.Rank;
import it.tidalwave.bluebill.taxonomy.mobile.TaxonomyFactory;
/***********************************************************************************************************************
*
* @author Fabrizio Giudici
* @version $Id$
*
**********************************************************************************************************************/
public class SimpleTaxonomyFactory implements TaxonomyFactory
{
private static final Logger log = LoggerFactory.getLogger(SimpleTaxonomyFactory.class);
private static final Map NAME_MAP_BY_RANK = new HashMap();
/* package */ static final SortedMap LOCALE_MAP_BY_CODE = new TreeMap();
private final Map> nameBagsByLanguage = new HashMap>();
static
{
NAME_MAP_BY_RANK.put(Rank.CLASS, "Class");
NAME_MAP_BY_RANK.put(Rank.ORDER, "Order");
NAME_MAP_BY_RANK.put(Rank.FAMILY, "Family");
NAME_MAP_BY_RANK.put(Rank.GENUS, "Genus");
NAME_MAP_BY_RANK.put(Rank.SPECIES, "Species");
NAME_MAP_BY_RANK.put(Rank.SUBSPECIES, "Subspecies");
final String[] languageCodes = { "af", "en", "en_us", "it", "de", "da", "no", "fi", "sv", "fr", "fr_ca", "es", "nl" };
for (final String languageCode : languageCodes)
{
LOCALE_MAP_BY_CODE.put(languageCode, new Locale(languageCode));
}
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
private final Comparator taxonComparator = new Comparator()
{
final Collator collator = Collator.getInstance();
public int compare (final @Nonnull Taxon taxon1, final @Nonnull Taxon taxon2)
{
return collator.compare(taxon1.getScientificName(), taxon2.getScientificName());
}
};
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
public Taxonomy loadTaxonomy (final @Nonnull Reader r)
throws Exception
{
log.info("loadTaxonomy({})", r);
final BufferedReader br = new BufferedReader(r);
final StringBuilder builder = new StringBuilder();
for (;;)
{
final String line = br.readLine();
if (line == null)
{
break;
}
builder.append(line);
}
final String string = builder.toString();
final JSONObject rootObject = new JSONObject(string);
final JSONObject jsonTaxonomy = rootObject.getJSONObject("Taxonomy");
final SimpleTaxonomy taxonomy = new SimpleTaxonomy(jsonTaxonomy.getString("name"));
scan(taxonomy, null, jsonTaxonomy, 0);
final Set ranks = new HashSet(taxonomy.taxonListMapByRank.keySet());
ranks.remove(Rank.SPECIES);
ranks.remove(Rank.SUBSPECIES);
for (final Rank rank : ranks)
{
final List taxa = taxonomy.taxonListMapByRank.get(rank);
Collections.sort(taxa, taxonComparator);
}
log.info(">>>> languages: {}", nameBagsByLanguage.keySet());
for (final Entry> entry : nameBagsByLanguage.entrySet())
{
final Locale locale = new Locale(entry.getKey());
taxonomy.namesBagByLocale.put(locale, new LocalizedNamesBag(locale, entry.getValue()));
}
nameBagsByLanguage.clear();
return taxonomy;
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
@Nonnull
private List extends Taxon> scan (final @Nonnull SimpleTaxonomy taxonomy,
final @Nonnull SimpleTaxon parent,
final @Nullable JSONObject jsonParent,
final @Nonnull int rankLevel)
throws JSONException
{
final Rank rank = Rank.values()[rankLevel];
final List children = new ArrayList();
final String childName = NAME_MAP_BY_RANK.get(rank);
final JSONArray jsonChildren = jsonParent.optJSONArray(childName);
if (jsonChildren != null)
{
for (int i = 0; i < jsonChildren.length(); i++)
{
final JSONObject jsonChild = jsonChildren.getJSONObject(i);
// FIXME: id should be mandatory, but unfortunately Aves hasn't in EBNItalia 2003
final Id id = new Id(jsonChild.optString("id"));
final SimpleTaxon child = new SimpleTaxon(taxonomy, id, jsonChild.getString("name"), rank, parent);
for (final Locale locale : LOCALE_MAP_BY_CODE.values())
{
addDisplayName(jsonChild, child, locale);
}
children.add(child);
taxonomy.taxonMapById.put(id, child);
if (rankLevel < Rank.values().length - 1)
{
// final List extends Taxon> scan = scan(taxonomy, child, jsonChild, level + 1);
final List scan = scan(taxonomy, child, jsonChild, rankLevel + 1);
child.children.addAll(scan);
}
}
}
List taxa = taxonomy.taxonListMapByRank.get(rank);
if (taxa == null)
{
taxa = children;
}
else
{
taxa.addAll(children);
}
taxonomy.taxonListMapByRank.put(rank, taxa);
return children;
}
/*******************************************************************************************************************
*
*
******************************************************************************************************************/
private void addDisplayName (final @Nonnull JSONObject jsonObject,
final @Nonnull Taxon taxon,
final @Nonnull Locale locale)
{
final String languageCode = "lang_" + locale.getLanguage();
final String displayName = jsonObject.optString(languageCode);
if ((displayName != null) && !displayName.equals(""))
{
final String language = locale.getLanguage();
Map nameBag = nameBagsByLanguage.get(language);
if (nameBag == null)
{
nameBag = new HashMap();
nameBagsByLanguage.put(language, nameBag);
}
nameBag.put(taxon.getId(), displayName);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy