/* * Eoulsan development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public License version 2.1 or * later and CeCILL-C. This should be distributed with the code. * If you do not have a copy, see: * * http://www.gnu.org/licenses/lgpl-2.1.txt * http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.txt * * Copyright for this code is held jointly by the Genomic platform * of the Institut de Biologie de l'École normale supérieure and * the individual authors. These should be listed in @author doc * comments. * * For more information on the Eoulsan project and its aims, * or to join the Eoulsan Google group, visit the home page * at: * * http://outils.genomique.biologie.ens.fr/eoulsan * */ package fr.ens.biologie.genomique.eoulsan.translators; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; /** * This class define a translator with create unique identifier from another * translator and a array of identifiers. * @since 2.0 * @author Laurent Jourdren */ public class UniqueIdentifierTranslator extends AbstractTranslator { private static final String DEFAULT_FIELD = "UniqueId"; private final Map<String, String> mapUniqueId = new HashMap<>(); private final Map<String, String> reverseMapUniqueId = new HashMap<>(); private List<String> fields; private String newFieldName = DEFAULT_FIELD; private final Translator translator; /** * Get an ordered list of the translator fields * @return an ordered list of the translator fields. */ @Override public List<String> getFields() { return this.fields; } /** * Get a translation for a feature * @param id Identifier of the feature * @param field the field to get * @return An array with the annotation of the Feature */ @Override public String translateField(final String id, final String field) { final String translatedId = this.mapUniqueId.get(id); if (this.newFieldName.equals(field)) { return translatedId; } return this.translator.translateField(translatedId, field); } /** * Test if the link information is available for the field * @param field Field to test * @return true if link information is available */ @Override public boolean isLinkInfo(final String field) { return this.translator.isLinkInfo(field); } /** * Get link information. * @param translatedId Translated id * @param field field of the id * @return a link for the translated id */ @Override public String getLinkInfo(final String translatedId, final String field) { return this.translator.getLinkInfo(translatedId, field); } // // Other methods // private void translateIds(final List<String> ids, final String field) { final Translator translator = this.translator; Map<String, String> translation = new HashMap<>(); Map<String, Integer> translationCount = new HashMap<>(); final String fieldName = field == null ? translator.getDefaultField() : field; for (String row : ids) { String t = translator.translateField(row, fieldName); if (t == null || "".equals(t)) { t = row; } translation.put(row, t); if (translationCount.containsKey(t)) { int count = translationCount.get(t); translationCount.put(t, ++count); } else { translationCount.put(t, 1); } } Map<String, Integer> translationCurrentCount = new HashMap<>(); for (Map.Entry<String, String> e : translation.entrySet()) { final String row = e.getKey(); final String t = e.getValue(); int count = translationCount.get(t); if (count > 1) { String postfix; if (translationCurrentCount.containsKey(t)) { int currentCount = translationCurrentCount.get(t); currentCount++; translationCurrentCount.put(t, currentCount); postfix = "#" + currentCount; } else { translationCurrentCount.put(t, 1); postfix = "#1"; } translation.put(row, t + postfix); } } for (final String id : ids) { final String newId = translation.get(id); this.mapUniqueId.put(newId, id); this.reverseMapUniqueId.put(id, newId); } } /** * Update the fields from the input translator. */ public void updateFields() { List<String> tFields = this.translator.getFields(); if (tFields == null) { this.fields = Collections.singletonList(this.newFieldName); } else { // this.fields = new String[tFields.length + 1]; this.fields = new ArrayList<>(); this.fields.add(this.newFieldName); // System.arraycopy(tFields, 0, this.fields, 1, tFields.size()); this.fields.addAll(tFields); } } /** * Set the name of the new field of the translator. * @param newFieldName the name of new field */ public void setNewFieldName(final String newFieldName) { if (newFieldName == null) { this.newFieldName = DEFAULT_FIELD; } else { this.newFieldName = newFieldName; } } /** * Get the reverse translator for this translator. * @return a reverse translator */ @Override public Translator getReverseTranslator() { return new AbstractTranslator() { @Override public List<String> getFields() { return Collections .singletonList(UniqueIdentifierTranslator.this.newFieldName); } @Override public String translateField(final String id, final String field) { if (UniqueIdentifierTranslator.this.newFieldName.equals(field)) { return UniqueIdentifierTranslator.this.reverseMapUniqueId.get(id); } return null; } }; } /** * Get the default field of a translator. * @param translator a translator * @return the default field or null if the translator is null or if there is * no default field for the translator */ private static String getTranslatorDefaultField(final Translator translator) { if (translator == null) { throw new NullPointerException("Translator argument can't is null."); } return translator.getDefaultField(); } // // Constructor // /** * Public constructor. * @param ids Identifier to set unique * @param translator Translator to use */ public UniqueIdentifierTranslator(final List<String> ids, final Translator translator) { this(ids, translator, getTranslatorDefaultField(translator), null); } /** * Public constructor. * @param ids Identifier to set unique * @param translator Translator to use * @param translatorField field of the translator to use */ public UniqueIdentifierTranslator(final List<String> ids, final Translator translator, final String translatorField) { this(ids, translator, translatorField, null); } /** * Public constructor. * @param ids Identifier to set unique * @param translator Translator to use * @param translatorField field of the translator to use * @param newFieldName the name of new field */ public UniqueIdentifierTranslator(final List<String> ids, final Translator translator, final String translatorField, final String newFieldName) { if (ids == null) { throw new NullPointerException("Identifiers can't be null"); } if (translator == null) { throw new NullPointerException("Translator can't be null"); } this.translator = translator; translateIds(Collections.unmodifiableList(ids), translatorField); setNewFieldName(newFieldName); updateFields(); } public UniqueIdentifierTranslator(String[] ids, final Translator translator) { this(Arrays.asList(ids), translator); } }