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. ";
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<TaggedText> getTaggedText(TaxonRelationship taxonRelationship, boolean reverse, List<Language> 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<TaggedText> getTaggedText(TaxonRelationship taxonRelationship, boolean inverse, List<Language> languages) {
+ return getTaggedText(taxonRelationship, inverse, languages, false);
+ }
+
+ public List<TaggedText> getTaggedText(TaxonRelationship taxonRelationship, boolean inverse,
+ List<Language> languages, boolean withoutName) {
if (taxonRelationship == null){
return null;
}
TaxonRelationshipType type = taxonRelationship.getType();
- boolean isMisapplied = type == null ? false : type.isMisappliedNameOrInvalidDesignation() && 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;
}
- boolean isDoubtful = taxonRelationship.isDoubtful() || relatedTaxon.isDoubtful();
- String doubtfulStr = isDoubtful ? "?" : "";
+
+ String doubtfulTaxonStr = relatedTaxon.isDoubtful() ? DOUBTFUL_TAXON_MARKER : "";
+ String doubtfulRelationStr = taxonRelationship.isDoubtful() ? "?" : "";
TaxonName name = relatedTaxon.getName();
-// List<TaggedText> tags = new ArrayList<>();
TaggedTextBuilder builder = new TaggedTextBuilder();
//rel symbol
- String symbol = getSymbol(type, reverse, languages);
+ String symbol = doubtfulRelationStr + getSymbol(type, inverse, languages);
builder.add(TagEnum.symbol, symbol);
//name
- if (isMisapplied){
- //starting quote
- String startQuote = " " + doubtfulStr + QUOTE_START;
- builder.addSeparator(startQuote);// .add(TaggedText.NewSeparatorInstance(startQuote));
-
- //name cache
- List<TaggedText> nameCacheTags = getNameCacheTags(name);
- builder.addAll(nameCacheTags);
-
- //end quote
- String endQuote = QUOTE_END;
- builder.add(TagEnum.postSeparator, endQuote);
+ if (!withoutName){
+ if (isMisapplied){
+ //starting quote
+ String startQuote = " " + doubtfulTaxonStr + QUOTE_START;
+ builder.addSeparator(startQuote);
+
+ //name cache
+ List<TaggedText> 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<TaggedText> nameCacheTags = getNameTitleCacheTags(name);
+ builder.addAll(nameCacheTags);
+ }
}else{
- builder.addSeparator(" " + doubtfulStr);
- //name full title cache
- List<TaggedText> nameCacheTags = getNameTitleCacheTags(name);
- builder.addAll(nameCacheTags);
+ if (isNotBlank(doubtfulTaxonStr)){
+ builder.addSeparator(" " + doubtfulTaxonStr);
+ }
}
-
- //sensu (+ Separatoren?)
+ //sec/sensu (+ Separatoren?)
if (isNotBlank(relatedTaxon.getAppendedPhrase())){
builder.addWhitespace();
builder.add(TagEnum.appendedPhrase, relatedTaxon.getAppendedPhrase());
}
- List<TaggedText> secTags = getSensuTags(relatedTaxon.getSec(), relatedTaxon.getSecMicroReference(),
+ List<TaggedText> secTags = getReferenceTags(relatedTaxon.getSec(), relatedTaxon.getSecMicroReference(),
/* isMisapplied,*/ false);
if (!secTags.isEmpty()) {
builder.addSeparator(isMisapplied? SENSU_SEPARATOR : SEC_SEPARATOR);
// //, non author
if (isMisapplied && name != null){
- if (name.getCombinationAuthorship() != null && isNotBlank(name.getCombinationAuthorship().getNomenclaturalTitle())){
- builder.addSeparator(NON_SEPARATOR);
- builder.add(TagEnum.authors, name.getCombinationAuthorship().getNomenclaturalTitle());
- }else if (isNotBlank(name.getAuthorshipCache())){
+ if (isNotBlank(name.getAuthorshipCache())){
builder.addSeparator(NON_SEPARATOR);
builder.add(TagEnum.authors, name.getAuthorshipCache().trim());
}
}
- List<TaggedText> relSecTags = getSensuTags(taxonRelationship.getCitation(),
+ //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);
+ }
+ }
+
+ //rel sec
+ List<TaggedText> relSecTags = getReferenceTags(taxonRelationship.getCitation(),
taxonRelationship.getCitationMicroReference(),true);
if (!relSecTags.isEmpty()){
builder.addSeparator(isSynonym ? SYN_SEC : isMisapplied ? ERR_SEC : REL_SEC);
return builder.getTaggedText();
}
- private List<TaggedText> getSensuTags(Reference ref, String detail, /*boolean isSensu,*/ boolean isRelation) {
+ private List<TaggedText> getReferenceTags(Reference ref, String detail, /*boolean isSensu,*/ boolean isRelation) {
List<TaggedText> 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
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();
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 ? TeamDefaultCacheStrategy.STD_TEAM_CONCATINATION : TeamDefaultCacheStrategy.FINAL_TEAM_CONCATINATION;
- result = CdmUtils.concat(separator, result, name);
- index++;
- }
- if (team.isHasMoreMembers()){
- //TODO or et al.???
- result += TeamDefaultCacheStrategy.ET_AL_TEAM_CONCATINATION_FULL + "al.";
- }
- return result;
- }
- }
-
-
- /**
- * @param name
- * @return
- */
private List<TaggedText> getNameCacheTags(TaxonName name) {
- List<TaggedText> result = name.getCacheStrategy().getTaggedName(name);
+ List<TaggedText> result = name.cacheStrategy().getTaggedName(name);
return result;
}
private List<TaggedText> getNameTitleCacheTags(TaxonName name) {
//TODO full title?
- List<TaggedText> result = name.getCacheStrategy().getTaggedFullTitle(name);
+ List<TaggedText> 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<Language> languages) {
+ private String getSymbol(TaxonRelationshipType type, boolean inverse, List<Language> 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;
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);
}