X-Git-Url: https://dev.e-taxonomy.eu/gitweb/cdmlib.git/blobdiff_plain/d7909683449f2bde52923c5145896676094c0e25..0419bfc2491affab84f490c0a49fd48e96537478:/cdmlib-model/src/main/java/eu/etaxonomy/cdm/format/taxon/TaxonRelationshipFormatter.java diff --git a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/format/taxon/TaxonRelationshipFormatter.java b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/format/taxon/TaxonRelationshipFormatter.java index f098184891..d4671949f5 100644 --- a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/format/taxon/TaxonRelationshipFormatter.java +++ b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/format/taxon/TaxonRelationshipFormatter.java @@ -11,31 +11,36 @@ package eu.etaxonomy.cdm.format.taxon; import java.util.ArrayList; import java.util.List; -import org.codehaus.plexus.util.StringUtils; +import org.apache.commons.lang3.StringUtils; -import eu.etaxonomy.cdm.common.CdmUtils; +import eu.etaxonomy.cdm.common.UTF8; import eu.etaxonomy.cdm.model.agent.Person; import eu.etaxonomy.cdm.model.agent.Team; import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase; import eu.etaxonomy.cdm.model.common.CdmBase; import eu.etaxonomy.cdm.model.common.Language; -import eu.etaxonomy.cdm.model.common.Representation; import eu.etaxonomy.cdm.model.name.TaxonName; import eu.etaxonomy.cdm.model.reference.Reference; import eu.etaxonomy.cdm.model.taxon.Taxon; import eu.etaxonomy.cdm.model.taxon.TaxonRelationship; import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType; +import eu.etaxonomy.cdm.model.term.Representation; import eu.etaxonomy.cdm.ref.TypedEntityReference; import eu.etaxonomy.cdm.strategy.cache.TagEnum; import eu.etaxonomy.cdm.strategy.cache.TaggedText; +import eu.etaxonomy.cdm.strategy.cache.TaggedTextBuilder; +import eu.etaxonomy.cdm.strategy.cache.agent.PersonDefaultCacheStrategy; +import eu.etaxonomy.cdm.strategy.cache.agent.TeamDefaultCacheStrategy; /** + * Formatter for TaxonRelationships. + * * @author a.mueller * @since 13.08.2018 - * */ public class TaxonRelationshipFormatter { + private static final String DOUBTFUL_TAXON_MARKER = "?" + UTF8.NARROW_NO_BREAK; private static final String REL_SEC = ", rel. sec. "; private static final String ERR_SEC = ", err. sec. "; private static final String SYN_SEC = ", syn. sec. "; @@ -46,106 +51,150 @@ public class TaxonRelationshipFormatter { private static final String AUCT = "auct."; private static final String SENSU_SEPARATOR = " sensu "; private static final String SEC_SEPARATOR = " sec. "; + private static final String PRO_PARTE_SEPARATOR = ", "; private static final String DETAIL_SEPARATOR = ": "; private static final String INVERT_SYMBOL = "<-"; //TODO private static final String UNDEFINED_SYMBOL = "??"; //TODO - public List getTaggedText(TaxonRelationship taxonRelationship, boolean reverse, List languages) { + private static TaxonRelationshipFormatter instance; + +// ************************* FACTORY ************************/ + + public static TaxonRelationshipFormatter NewInstance(){ + return new TaxonRelationshipFormatter(); + } + + public static TaxonRelationshipFormatter INSTANCE(){ + if (instance == null){ + instance = NewInstance(); + } + return instance; + } + +// ******************* CONSTRUCTOR ************************/ + + private TaxonRelationshipFormatter(){} + +// ********************** METHODS ***************************/ + + public List getTaggedText(TaxonRelationship taxonRelationship, boolean inverse, List languages) { + return getTaggedText(taxonRelationship, inverse, languages, false); + } + + public List getTaggedText(TaxonRelationship taxonRelationship, boolean inverse, + List languages, boolean withoutName) { if (taxonRelationship == null){ return null; } TaxonRelationshipType type = taxonRelationship.getType(); - boolean isMisapplied = type == null ? false : type.isAnyMisappliedName() && reverse; + boolean isMisapplied = (type == null ? false : type.isMisappliedName() && inverse); boolean isSynonym = type == null? false : type.isAnySynonym(); - Taxon relatedTaxon = reverse? taxonRelationship.getFromTaxon() + Taxon relatedTaxon = inverse? taxonRelationship.getFromTaxon() : taxonRelationship.getToTaxon(); if (relatedTaxon == null){ return null; } + + String doubtfulTaxonStr = relatedTaxon.isDoubtful() ? DOUBTFUL_TAXON_MARKER : ""; + String doubtfulRelationStr = taxonRelationship.isDoubtful() ? "?" : ""; + TaxonName name = relatedTaxon.getName(); - List tags = new ArrayList<>(); + TaggedTextBuilder builder = new TaggedTextBuilder(); //rel symbol - String symbol = getSymbol(type, reverse, languages); - tags.add(TaggedText.NewInstance(TagEnum.symbol, symbol)); - - //whitespace - tags.add(TaggedText.NewWhitespaceInstance()); + String symbol = doubtfulRelationStr + getSymbol(type, inverse, languages); + builder.add(TagEnum.symbol, symbol); //name - if (isMisapplied){ - //starting quote - String startQuote = QUOTE_START; - tags.add(TaggedText.NewSeparatorInstance(startQuote)); - - //name cache - List nameCacheTags = getNameCacheTags(name); - tags.addAll(nameCacheTags); - - //end quote - String endQuote = QUOTE_END; - tags.add(TaggedText.NewSeparatorInstance(endQuote)); + if (!withoutName){ + if (isMisapplied){ + //starting quote + String startQuote = " " + doubtfulTaxonStr + QUOTE_START; + builder.addSeparator(startQuote); + + //name cache + List nameCacheTags = getNameCacheTags(name); + builder.addAll(nameCacheTags); + + //end quote + String endQuote = QUOTE_END; + builder.add(TagEnum.postSeparator, endQuote); + }else{ + builder.addSeparator(" " + doubtfulTaxonStr); + //name full title cache + List nameCacheTags = getNameTitleCacheTags(name); + builder.addAll(nameCacheTags); + } }else{ - //name title cache - //TODO fullTitle? - List nameCacheTags = getNameTitleCacheTags(name); - tags.addAll(nameCacheTags); + if (isNotBlank(doubtfulTaxonStr)){ + builder.addSeparator(" " + doubtfulTaxonStr); + } } - - //sensu (+ Separatoren?) + //sec/sensu (+ Separatoren?) if (isNotBlank(relatedTaxon.getAppendedPhrase())){ - tags.add(TaggedText.NewWhitespaceInstance()); - tags.add(TaggedText.NewInstance(TagEnum.appendedPhrase, relatedTaxon.getAppendedPhrase())); + builder.addWhitespace(); + builder.add(TagEnum.appendedPhrase, relatedTaxon.getAppendedPhrase()); } - List secTags = getSensuTags(relatedTaxon.getSec(), relatedTaxon.getSecMicroReference(), isMisapplied); + List secTags = getReferenceTags(relatedTaxon.getSec(), relatedTaxon.getSecMicroReference(), + /* isMisapplied,*/ false); if (!secTags.isEmpty()) { - tags.add(TaggedText.NewSeparatorInstance(isMisapplied? SENSU_SEPARATOR : SEC_SEPARATOR)); - tags.addAll(secTags); + builder.addSeparator(isMisapplied? SENSU_SEPARATOR : SEC_SEPARATOR); + builder.addAll(secTags); }else if (isBlank(relatedTaxon.getAppendedPhrase())) { if (isMisapplied){ - tags.add(TaggedText.NewWhitespaceInstance()); + builder.addWhitespace(); //TODO type unclear sensuReference(?) - tags.add(TaggedText.NewInstance(TagEnum.authors, AUCT)); + builder.add(TagEnum.appendedPhrase, AUCT); }else{ - tags.add(TaggedText.NewSeparatorInstance(SEC_SEPARATOR + UNKNOWN_SEC)); + builder.addSeparator(SEC_SEPARATOR + UNKNOWN_SEC); } } // //, non author if (isMisapplied && name != null){ - if (name.getCombinationAuthorship() != null){ - tags.add(TaggedText.NewSeparatorInstance(NON_SEPARATOR)); - //TODO add nom. ref. author tags - }else if (isNotBlank(name.getAuthorshipCache())){ - tags.add(TaggedText.NewSeparatorInstance(NON_SEPARATOR)); - tags.add(TaggedText.NewInstance(TagEnum.authors, name.getAuthorshipCache().trim())); + if (isNotBlank(name.getAuthorshipCache())){ + builder.addSeparator(NON_SEPARATOR); + builder.add(TagEnum.authors, name.getAuthorshipCache().trim()); + } + } + + //p.p. + if (isMisapplied) { + if (isProParteMAN(type, inverse)) { + builder.addSeparator(PRO_PARTE_SEPARATOR); + symbol = "p.p."; + builder.add(TagEnum.symbol, symbol); + } else if (isPartialMAN(type, inverse)) { + builder.addSeparator(PRO_PARTE_SEPARATOR); + symbol = "part."; + builder.add(TagEnum.symbol, symbol); } } - //TODO tagEnum for relSec? - List relSecTags = getSensuTags /*getCitationTags*/(taxonRelationship.getCitation(), - taxonRelationship.getCitationMicroReference(), false); + //rel sec + List relSecTags = getReferenceTags(taxonRelationship.getCitation(), + taxonRelationship.getCitationMicroReference(),true); if (!relSecTags.isEmpty()){ - TaggedText relSecSeparatorToag = TaggedText.NewSeparatorInstance(isSynonym ? SYN_SEC : isMisapplied ? ERR_SEC : REL_SEC); - tags.add(relSecSeparatorToag); - tags.addAll(relSecTags); + builder.addSeparator(isSynonym ? SYN_SEC : isMisapplied ? ERR_SEC : REL_SEC); + builder.addAll(relSecTags); } - return tags; + return builder.getTaggedText(); } - private List getSensuTags(Reference ref, String detail, boolean isSensu) { + private List getReferenceTags(Reference ref, String detail, /*boolean isSensu,*/ boolean isRelation) { List result = new ArrayList<>(); String secRef; if (ref != null){ - TeamOrPersonBase author = ref.getAuthorship(); + TeamOrPersonBase author = CdmBase.deproxy(ref.getAuthorship()); + //TODO distinguish linked and unlinked usage, // if reference is not linked short citation should only be used // if both author and year exists, also initials should be added in this case @@ -153,12 +202,11 @@ public class TaxonRelationshipFormatter { if (ref.isProtectedTitleCache() == false && author != null && isNotBlank(author.getTitleCache())){ - //TODO move to authorFormatter - String familyNames = getFamilyNames(author); - if (isNotBlank(familyNames)){ - secRef = familyNames; + if (author.isInstanceOf(Person.class)){ + secRef = PersonDefaultCacheStrategy.INSTANCE().getFamilyTitle((Person)author); }else{ - secRef = ref.getAuthorship().getTitleCache(); + //#9624 + secRef = TeamDefaultCacheStrategy.INSTANCE_ET_AL_2().getFamilyTitle((Team)author); } if (isNotBlank(ref.getYear())){ secRef += " " + ref.getYear(); @@ -166,136 +214,69 @@ public class TaxonRelationshipFormatter { }else{ secRef = ref.getTitleCache(); } - TagEnum secType = isSensu? TagEnum.sensuReference : TagEnum.secReference; + TagEnum secType = /*isSensu? TagEnum.sensuReference : */ isRelation? TagEnum.relSecReference : TagEnum.secReference; TaggedText refTag = TaggedText.NewInstance(secType, secRef); - refTag.setEntityReference(new TypedEntityReference<>(CdmBase.deproxy(ref.getClass()), ref.getUuid(), secRef)); + refTag.setEntityReference(new TypedEntityReference<>(CdmBase.deproxy(ref).getClass(), ref.getUuid())); result.add(refTag); } if (isNotBlank(detail)){ result.add(TaggedText.NewSeparatorInstance(DETAIL_SEPARATOR)); - //TODO do we need a sensu micro reference?? - TagEnum detailType = isSensu? TagEnum.sensuMicroReference : TagEnum.secMicroReference; + TagEnum detailType = /*isSensu? TagEnum.sensuMicroReference : */ isRelation? TagEnum.relSecMicroReference :TagEnum.secMicroReference; TaggedText microTag = TaggedText.NewInstance(detailType, detail); result.add(microTag); } return result; } - /** - * @param author - * @return - */ - private String getFamilyNames(TeamOrPersonBase author) { - if (author.isInstanceOf(Person.class)){ - Person person = CdmBase.deproxy(author, Person.class); - return isNotBlank(person.getFamilyName())? person.getFamilyName() : null; - }else{ - Team team = CdmBase.deproxy(author, Team.class); - String result = null; - int n = team.getTeamMembers().size(); - int index = 0; - if (team.isHasMoreMembers()){ - n++; - } - for (Person member : team.getTeamMembers()){ - String name = isNotBlank(member.getFamilyName())? member.getFamilyName(): member.getTitleCache(); - String separator = index < n ? ", " : " & "; - result = CdmUtils.concat(separator, result, name); - index++; - } - if (team.isHasMoreMembers()){ - //TODO or et al.??? - result += " & al."; - } - return result; - } - } - - - /** - * @param sec - * @param secMicroReference - * @return - */ - private List getCitationTags(Reference ref, String secMicroReference) { - List result = new ArrayList<>(); - String secRef; - - if (ref != null){ - //copied from TaxonBaseDefaultCacheStrategy - if (ref.isProtectedTitleCache() == false && - ref.getCacheStrategy() != null && - ref.getAuthorship() != null && - isNotBlank(ref.getAuthorship().getTitleCache()) && - isNotBlank(ref.getYear())){ - secRef = ref.getCacheStrategy().getCitation(ref); - }else{ - secRef = ref.getTitleCache(); - } - //TODO do we need a sensuReference type? - TaggedText refTag = TaggedText.NewInstance(TagEnum.secReference, secRef); - refTag.setEntityReference(new TypedEntityReference<>(ref.getClass(), ref.getUuid(), secRef)); - result.add(refTag); - } - if (isNotBlank(secMicroReference)){ - result.add(TaggedText.NewSeparatorInstance(DETAIL_SEPARATOR)); - TaggedText microTag = TaggedText.NewInstance(TagEnum.secMicroReference, secMicroReference); - result.add(microTag); - } - return result; - } - - - /** - * @param name - * @return - */ private List getNameCacheTags(TaxonName name) { - List result = name.getCacheStrategy().getTaggedName(name); + List result = name.cacheStrategy().getTaggedName(name); return result; } private List getNameTitleCacheTags(TaxonName name) { //TODO full title? - List result = name.getCacheStrategy().getTaggedTitle(name); + List result = name.cacheStrategy().getTaggedFullTitle(name); return result; } - /** * @param type the taxon relationship type - * @param reverse is the relationship used reverse + * @param inverse is the relationship used inverse * @param languages list of preferred languages * @return the symbol for the taxon relationship */ - private String getSymbol(TaxonRelationshipType type, boolean reverse, List languages) { + private String getSymbol(TaxonRelationshipType type, boolean inverse, List languages) { if (type == null){ return UNDEFINED_SYMBOL; } //symbol - String symbol = reverse? type.getInverseSymbol():type.getSymbol(); + String symbol = inverse? type.getInverseSymbol():type.getSymbol(); if (isNotBlank(symbol)){ + //handle p.p. MAN specific #10082 + if (isProParteMAN(type, inverse) || isPartialMAN(type, inverse)) { + return TaxonRelationshipType.MISAPPLIED_NAME_FOR().getInverseSymbol(); + } return symbol; } boolean isSymmetric = type.isSymmetric(); //symmetric inverted symbol - String invertedSymbol = reverse? type.getSymbol() : type.getInverseSymbol(); + String invertedSymbol = inverse? type.getSymbol() : type.getInverseSymbol(); if (isSymmetric && isNotBlank(invertedSymbol)){ return invertedSymbol; } //abbrev label - Representation representation = reverse? type.getPreferredRepresentation(languages): type.getPreferredInverseRepresentation(languages); + Representation representation = inverse? type.getPreferredRepresentation(languages): type.getPreferredInverseRepresentation(languages); String abbrevLabel = representation.getAbbreviatedLabel(); if (isNotBlank(abbrevLabel)){ return abbrevLabel; } //symmetric inverted abbrev label - Representation invertedRepresentation = reverse? type.getPreferredInverseRepresentation(languages):type.getPreferredRepresentation(languages); + Representation invertedRepresentation = inverse? type.getPreferredInverseRepresentation(languages):type.getPreferredRepresentation(languages); String invertedAbbrevLabel = invertedRepresentation.getAbbreviatedLabel(); if (isSymmetric && isNotBlank(invertedAbbrevLabel)){ return invertedAbbrevLabel; @@ -314,6 +295,14 @@ public class TaxonRelationshipFormatter { return UNDEFINED_SYMBOL; } + private boolean isPartialMAN(TaxonRelationshipType type, boolean inverse) { + return inverse && type.getUuid().equals(TaxonRelationshipType.uuidPartialMisappliedNameFor); + } + + private boolean isProParteMAN(TaxonRelationshipType type, boolean inverse) { + return inverse && type.getUuid().equals(TaxonRelationshipType.uuidProParteMisappliedNameFor); + } + private boolean isNotBlank(String str) { return StringUtils.isNotBlank(str); }