commit 731fe9ff0a45796b8a652cd43c5bc65de6410f3a
Author: Andreas Müller <a.mueller@bgbm.org>
Date:   Thu Sep 1 10:47:39 2011 +0000

    Cleaning up name cache strategies and updating javadoc

diff --git a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/BotanicalName.java b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/BotanicalName.java
index 5c92ce9593..2a432a9035 100644
--- a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/BotanicalName.java
+++ b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/name/BotanicalName.java
@@ -314,7 +314,9 @@ public class BotanicalName extends NonViralName<BotanicalName> implements Clonea
 
 	
 	/**
-	 * @param name
+	 * Checks if this name is an autonym.<BR>
+	 * An autonym is a taxon name that has equal specific and infra specific epithets.<BR>
+	 * {@link http://ibot.sav.sk/icbn/frameset/0010Ch2Sec1a006.htm#6.8. Vienna Code �6.8}
 	 * @return true, if name has Rank, Rank is below species and species epithet equals infraSpeciesEpithtet, else false
 	 */
 	@Override
diff --git a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BacterialNameDefaultCacheStrategy.java b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BacterialNameDefaultCacheStrategy.java
index 62364e7674..7fb6cd97d2 100644
--- a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BacterialNameDefaultCacheStrategy.java
+++ b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BacterialNameDefaultCacheStrategy.java
@@ -21,8 +21,8 @@ import eu.etaxonomy.cdm.model.name.BacterialName;
  *
  */
 public class BacterialNameDefaultCacheStrategy<NAME extends BacterialName> extends NonViralNameDefaultCacheStrategy<NAME> implements  INonViralNameCacheStrategy<NAME> {
+	private static final long serialVersionUID = 7369285557176649585L;
 	private static final Logger logger = Logger.getLogger(BacterialNameDefaultCacheStrategy.class);
-	
 	final static UUID uuid = UUID.fromString("b97cf0af-2f97-487e-8d06-cbe924f3222a");
 	
 	static {
diff --git a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BotanicNameDefaultCacheStrategy.java b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BotanicNameDefaultCacheStrategy.java
index eec8019789..11a7bb9729 100644
--- a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BotanicNameDefaultCacheStrategy.java
+++ b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/BotanicNameDefaultCacheStrategy.java
@@ -46,6 +46,7 @@ public class BotanicNameDefaultCacheStrategy<T extends BotanicalName> extends No
 	 * @param exAuthor the ex-author
 	 * @return
 	 */
+	@Override
 	protected String getAuthorAndExAuthor(INomenclaturalAuthor author, INomenclaturalAuthor exAuthor){
 		String result = "";
 		String authorString = "";
diff --git a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategy.java b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategy.java
index f9db6d53bc..675bd95d2f 100644
--- a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategy.java
+++ b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategy.java
@@ -23,6 +23,7 @@ import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
 import eu.etaxonomy.cdm.model.agent.Team;
 import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.Representation;
+import eu.etaxonomy.cdm.model.name.BotanicalName;
 import eu.etaxonomy.cdm.model.name.HybridRelationship;
 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
@@ -36,11 +37,12 @@ import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImplRegExBase;
 
 
 /**
- * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName> interface.
- * The method actually implements a cache strategy for botanical names so no method has to be overwritten by
+ * This class is a default implementation for the INonViralNameCacheStrategy<T extends NonViralName> 
+ * interface.<BR>
+ * The method implements a cache strategy for botanical names so no method has to be overwritten by
  * a subclass for botanic names.
- * Where differing from this Default BotanicNameCacheStrategy other subclasses should overwrite the existing methods
- * e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
+ * Where differing from this default botanic name strategy other subclasses should overwrite the
+ * existing methods, e.g. a CacheStrategy for zoological names should overwrite getAuthorAndExAuthor
  * @author a.mueller
  */
 /**
@@ -157,8 +159,7 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 	}
 
 
-	public void setBasionymAuthorCombinationAuthorSeperator(
-			CharSequence basionymAuthorCombinationAuthorSeperator) {
+	public void setBasionymAuthorCombinationAuthorSeperator( CharSequence basionymAuthorCombinationAuthorSeperator) {
 		BasionymAuthorCombinationAuthorSeperator = basionymAuthorCombinationAuthorSeperator;
 	}
 
@@ -179,160 +180,6 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		}
 	}
 
-	
-	
-	public String getTitleCache_OLD(T nonViralName) {
-		if (nonViralName == null){
-			return null;
-		}
-		
-		if (nonViralName.isProtectedTitleCache()){
-			return nonViralName.getTitleCache();
-		}
-		String result = "";
-		if (nonViralName.isHybridFormula()){
-			//hybrid formula
-			result = null;
-			String hybridSeparator = " " + NonViralNameParserImplRegExBase.hybridSign + " ";
-			List<HybridRelationship> rels = nonViralName.getOrderedChildRelationships();
-			for (HybridRelationship rel: rels){
-				result = CdmUtils.concat(hybridSeparator, result, rel.getParentName().getTitleCache()).trim();
-			}
-			return result;
-		}else if (nonViralName.isAutonym()){
-			//Autonym
-			result = handleAutonym(nonViralName);
-		}else{ //not Autonym
-			String nameCache = nonViralName.getNameCache();  //OLD: CdmUtils.Nz(getNameCache(nonViralName));
-			if (nameIncludesAuthorship(nonViralName)){
-				String authorCache = CdmUtils.Nz(getAuthorshipCache(nonViralName));
-				result = CdmUtils.concat(NameAuthorSeperator, nameCache, authorCache);
-			}else{
-				result = nameCache;
-			}
-		}
-		return result;
-	}
-
-
-	/**
-	 * Creates a string from tagged text.
-	 * @param tags
-	 * @return
-	 */
-	private String createString(List<TaggedText> tags) {
-		StringBuffer result = new StringBuffer();
-		
-		boolean isSeparator;
-		boolean wasSeparator = true;  //true for start tag
-		for (TaggedText tag: tags){
-			isSeparator = tag.getType().equals(TagEnum.separator);
-			if (! wasSeparator && ! isSeparator ){
-				result.append(" ");
-			}
-			result.append(tag.getText());
-			wasSeparator = isSeparator;
-		}
-		return result.toString();
-	}
-
-
-	/**
-	 * @param nonViralName
-	 * @param speciesPart
-	 * @return
-	 */
-	private List<TaggedText> handleTaggedAutonym(T nonViralName) {
-		
-		//species part
-		List<TaggedText> tags = getSpeciesTaggedNameCache(nonViralName);
-		
-		//author
-		//TODO should this include basionym authors and ex authors
-		INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
-		String authorPart = "";
-		if (author != null){
-			authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
-		}
-		INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
-		String basAuthorPart = "";
-		if (basAuthor != null){
-			basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
-		}
-		if (! "".equals(basAuthorPart)){
-			authorPart = "("+ basAuthorPart +") " + authorPart;
-		}
-		if (StringUtils.isNotBlank(authorPart)){
-			tags.add(new TaggedText(TagEnum.authors, authorPart));
-		}
-		
-		
-		//infra species marker
-		if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraSpecific()){
-			//TODO handle exception
-			logger.warn("Rank for autonym does not exist or is not lower than species !!");
-		}else{
-			String infraSpeciesMarker = nonViralName.getRank().getAbbreviation();
-			if (StringUtils.isNotBlank(infraSpeciesMarker)){
-				tags.add(new TaggedText(TagEnum.rank, infraSpeciesMarker));
-			}
-		}
-		
-		//infra species
-		String infraSpeciesPart = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim().replace("null", "");
-		if (StringUtils.isNotBlank(infraSpeciesPart)){
-			tags.add(new TaggedText(TagEnum.name, infraSpeciesPart));
-		}
-		
-		return tags;
-	}
-	
-	/**
-	 * @param nonViralName
-	 * @param speciesPart
-	 * @return
-	 */
-	private String handleAutonym(T nonViralName) {
-		String result;
-		String speciesPart = getSpeciesNameCache(nonViralName);
-		//TODO should this include basionym authors and ex authors
-		INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
-		String authorPart = "";
-		if (author != null){
-			authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
-		}
-		INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
-		String basAuthorPart = "";
-		if (basAuthor != null){
-			basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
-		}
-		if (! "".equals(basAuthorPart)){
-			authorPart = "("+ basAuthorPart +") " + authorPart;
-		}
-		String infraSpeciesPart = (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()));
-
-		String infraSpeciesSeparator = "";
-		if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraSpecific()){
-			//TODO handle exception
-			logger.warn("Rank for autonym does not exist or is not lower than species !!");
-		}else{
-			infraSpeciesSeparator = nonViralName.getRank().getAbbreviation();
-		}
-		
-		result = CdmUtils.concat(" ", new String[]{speciesPart, authorPart, infraSpeciesSeparator, infraSpeciesPart});
-		result = result.trim().replace("null", "");
-		return result;
-	}
-	
-	protected boolean nameIncludesAuthorship(NonViralName<?> nonViralName){
-		Rank rank = nonViralName.getRank();
-		if (rank != null && rank.isSpeciesAggregate()){
-			return false;
-		}else{
-			return true;
-		}
-	}
-	
 	/* (non-Javadoc)
 	 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getFullTitleCache(eu.etaxonomy.cdm.model.name.TaxonNameBase)
 	 */
@@ -346,65 +193,6 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 			return result;
 		}
 	}
-	
-	
-	public String getFullTitleCache_OLD(T nonViralName) {
-		//null
-		if (nonViralName == null){
-			return null;
-		}
-		//full title cache
-		if (nonViralName.isProtectedFullTitleCache() == true) {
-			return nonViralName.getFullTitleCache();
-		}
-		
-		String result = "";
-		//title cache
-		String titleCache = nonViralName.getTitleCache();   // OLD: getTitleCache(nonViralName);
-		
-		String microReference = nonViralName.getNomenclaturalMicroReference();
-		INomenclaturalReference ref = nonViralName.getNomenclaturalReference();
-		String referenceBaseCache = null;
-		if (ref != null){
-			INomenclaturalReference nomenclaturalReference = HibernateProxyHelper.deproxy(ref, INomenclaturalReference.class);
-			nomenclaturalReference.setCacheStrategy(nomenclaturalReference.getType().getCacheStrategy());
-			referenceBaseCache = nomenclaturalReference.getNomenclaturalCitation(microReference);
-		}
-		
-		//make nomenclatural status
-		String ncStatusCache = "";
-		Set<NomenclaturalStatus> ncStati = nonViralName.getStatus();
-		Iterator<NomenclaturalStatus> iterator = ncStati.iterator();
-		while (iterator.hasNext()) {
-			NomenclaturalStatus ncStatus = (NomenclaturalStatus)iterator.next();
-			// since the NewInstance method of nomencatural status allows null as parameter
-			// we have to check for null values here
-			String suffix = "not defined";
-			if(ncStatus.getType() != null){
-				NomenclaturalStatusType statusType =  ncStatus.getType();
-				Language lang = Language.LATIN();
-				Representation repr = statusType.getRepresentation(lang);
-				if (repr != null){
-					suffix = repr.getAbbreviatedLabel();
-				}else{
-					String message = "No latin representation available for nom. status. " + statusType.getTitleCache();
-					logger.warn(message);
-					throw new IllegalStateException(message);
-				}
-			}else if(ncStatus.getRuleConsidered() != null && ! ncStatus.getRuleConsidered().equals("")){
-				suffix = ncStatus.getRuleConsidered();
-			}
-			ncStatusCache = ", " + suffix;
-		}
-		String refConcat = " ";
-		if (referenceBaseCache != null && ! referenceBaseCache.trim().startsWith("in ")){
-			refConcat = ", ";
-		}
-		result = CdmUtils.concat(refConcat, titleCache, referenceBaseCache);
-		result = CdmUtils.concat("", result, ncStatusCache);
-		return result;
-	}
-	
 
 	
 	/**
@@ -421,50 +209,30 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		}
 	}
 	
-	public String getNameCache_OLD(T nonViralName) {
-		if (nonViralName == null){
-			return null;
-		}
-		String result;
-		Rank rank = nonViralName.getRank();
-		
-		if (nonViralName.isProtectedNameCache()){
-			result = nonViralName.getNameCache();
-		}else if (rank == null){
-			result = getRanklessNameCache(nonViralName);
-//		}else if (nonViralName.isInfragenericUnranked()){
-//			result = getUnrankedInfragenericNameCache(nonViralName);
-		}else if (rank.isInfraSpecific()){
-			result = getInfraSpeciesNameCache(nonViralName);
-		}else if (rank.isSpecies()){
-			result = getSpeciesNameCache(nonViralName);
-		}else if (rank.isInfraGeneric()){
-			result = getInfraGenusNameCache(nonViralName);
-		}else if (rank.isGenus()){
-			result = getGenusOrUninomialNameCache(nonViralName);
-		}else if (rank.isSupraGeneric()){
-			result = getGenusOrUninomialNameCache(nonViralName);
-		}else{ 
-			logger.warn("Name Strategy for Name (UUID: " + nonViralName.getUuid() +  ") not yet implemented");
-			result = "";
-		}
-		return result;
-	}
-
 
-	private String getUnrankedInfragenericNameCache(T nonViralName) {
-		String result;
-		Rank rank = nonViralName.getRank();
-		if (rank.isSpeciesAggregate()){
-			return getSpeciesAggregateCache(nonViralName);
+	/**
+	 * Creates a string from tagged text.
+	 * @param tags
+	 * @return
+	 */
+	protected String createString(List<TaggedText> tags) {
+		StringBuffer result = new StringBuffer();
+		
+		boolean isSeparator;
+		boolean wasSeparator = true;  //true for start tag
+		for (TaggedText tag: tags){
+			isSeparator = tag.getType().equals(TagEnum.separator);
+			if (! wasSeparator && ! isSeparator ){
+				result.append(" ");
+			}
+			result.append(tag.getText());
+			wasSeparator = isSeparator;
 		}
-		String infraGenericMarker = rank.getAbbreviation();
-		result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();
-		result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");
-		result = addAppendedPhrase(result, nonViralName).trim();
-		return result; 
+		return result.toString();
 	}
-
+	
+// ******************* Authorship ******************************/	
+	
 
 	/* (non-Javadoc)
 	 * @see eu.etaxonomy.cdm.strategy.cache.INonViralNameCacheStrategy#getAuthorCache(eu.etaxonomy.cdm.model.name.NonViralName)
@@ -528,13 +296,28 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		}
 		result = exAuthorString + authorString;
 		return result;
- 
 	}
 	
-// ************* TAGGED NAME ***************************************/	
 	
+	/**
+	 * Checks if the given name should include the author in it's cached version.<BR>
+	 * This is usually the case but not for <i>species aggregates</i>.
+	 * @param nonViralName
+	 * @return
+	 */
+	protected boolean nameIncludesAuthorship(NonViralName<?> nonViralName){
+		Rank rank = nonViralName.getRank();
+		if (rank != null && rank.isSpeciesAggregate()){
+			return false;
+		}else{
+			return true;
+		}
+	}
+	
+// ************* TAGGED NAME ***************************************/	
+
 	/* (non-Javadoc)
-	 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
+	 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedFullTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
 	 */
 	@Override
 	public List<TaggedText> getTaggedFullTitle(T nonViralName) {
@@ -607,6 +390,9 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		
 	}
 		
+	/* (non-Javadoc)
+	 * @see eu.etaxonomy.cdm.strategy.cache.name.NameCacheStrategyBase#getTaggedTitle(eu.etaxonomy.cdm.model.name.TaxonNameBase)
+	 */
 	public List<TaggedText> getTaggedTitle(T nonViralName) {
 		if (nonViralName == null){
 			return null;
@@ -653,11 +439,11 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 	
 	
 	/**
-	 * Returns the name part (without author and reference) of this name in tagged mode.
+	 * Returns the tag list of the name part (without author and reference).
 	 * @param nonViralName
 	 * @return
 	 */
-	private List<TaggedText> getTaggedName(T nonViralName) {
+	public List<TaggedText> getTaggedName(T nonViralName) {
 		if (nonViralName == null){
 			return null;
 		}
@@ -691,76 +477,71 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 	}
 
 
-	//Old: may be replaced once getTagged(Full)Title is fully tested
-	/* (non-Javadoc)
-	 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
+	
+
+//***************************** PRIVATES ***************************************/
+	
+
+	/**
+	 * Returns the tag list for an autonym taxon.
+	 * 
+	 * @see NonViralName#isAutonym()
+	 * @see BotanicalName#isAutonym()
+	 * @param nonViralName
+	 * @return
 	 */
-	@Override
-	@Deprecated
-	public List<Object> getTaggedNameDeprecated(T nonViralName) {
-		List<Object> tags = new ArrayList<Object>();
+	private List<TaggedText> handleTaggedAutonym(T nonViralName) {
 		
-		if (nonViralName.isProtectedNameCache() ||
-				nonViralName.isProtectedAuthorshipCache() ||
-				nonViralName.isProtectedFullTitleCache() ||
-				nonViralName.isProtectedTitleCache()){
-			tags.add(nonViralName.getTitleCache());
-			return tags;
-		}
-		
-		// Why does it make sense to add the nameCache in case of non existing genusOrUninomial?
-//		if (nonViralName.getGenusOrUninomial() == null){
-//			tags.add(nonViralName.getNameCache());
-//		}else{
+		//species part
+		List<TaggedText> tags = getSpeciesTaggedNameCache(nonViralName);
 		
-		if (nonViralName.getGenusOrUninomial() != null) {
-			tags.add(nonViralName.getGenusOrUninomial());
+		//author
+		//TODO should this include basionym authors and ex authors
+		INomenclaturalAuthor author = nonViralName.getCombinationAuthorTeam();
+		String authorPart = "";
+		if (author != null){
+			authorPart = CdmUtils.Nz(author.getNomenclaturalTitle());
 		}
-		if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
-			tags.add(nonViralName.getSpecificEpithet());			
+		INomenclaturalAuthor basAuthor = nonViralName.getBasionymAuthorTeam();
+		String basAuthorPart = "";
+		if (basAuthor != null){
+			basAuthorPart = CdmUtils.Nz(basAuthor.getNomenclaturalTitle());
 		}
-		
-		// No autonym 
-		if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
-			tags.add(nonViralName.getRank());			
-			tags.add(nonViralName.getInfraSpecificEpithet());			
+		if (! "".equals(basAuthorPart)){
+			authorPart = "("+ basAuthorPart +") " + authorPart;
 		}
-		
-		if (nonViralName.isInfraGeneric()){
-			//TODO choose right strategy or generic approach?
-			// --- strategy 1 --- 
-					
-			if (nonViralName.getRank().isSpeciesAggregate()){
-				tags.add(nonViralName.getSpecificEpithet());
-				tags.add(getSpeciesAggregateEpithet(nonViralName));
-			}else{
-				tags.add(nonViralName.getRank());	
-				tags.add(nonViralName.getInfraGenericEpithet());	
-			}
-			// --- strategy 2 --- 
-//			tags.add('('+nvn.getInfraGenericEpithet()+')');	
+		if (StringUtils.isNotBlank(authorPart)){
+			tags.add(new TaggedText(TagEnum.authors, authorPart));
 		}
-		Team authorTeam = Team.NewInstance();
-		authorTeam.setProtectedTitleCache(true);
-		authorTeam.setTitleCache(nonViralName.getAuthorshipCache(), true);
-		tags.add(authorTeam);
 		
-		// Name is an autonym. Rank and infraspecific epitheton follow the author
-		if (nonViralName.isInfraSpecific() && nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
-			tags.add(nonViralName.getRank());			
-			tags.add(nonViralName.getInfraSpecificEpithet());			
+		
+		//infra species marker
+		if (nonViralName.getRank() == null || !nonViralName.getRank().isInfraSpecific()){
+			//TODO handle exception
+			logger.warn("Rank for autonym does not exist or is not lower than species !!");
+		}else{
+			String infraSpeciesMarker = nonViralName.getRank().getAbbreviation();
+			if (StringUtils.isNotBlank(infraSpeciesMarker)){
+				tags.add(new TaggedText(TagEnum.rank, infraSpeciesMarker));
+			}
 		}
 		
-		if(! "".equals(nonViralName.getAppendedPhrase())&& (nonViralName.getAppendedPhrase() != null)){
-			tags.add(nonViralName.getAppendedPhrase());
+		//infra species
+		String infraSpeciesPart = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet()).trim().replace("null", "");
+		if (StringUtils.isNotBlank(infraSpeciesPart)){
+			tags.add(new TaggedText(TagEnum.name, infraSpeciesPart));
 		}
 		
 		return tags;
 	}
 	
-
-//***************************** PRIVATES ***************************************/
-		
+	
+	
+	/**
+	 * Returns the tag list for rankless taxa.
+	 * @param nonViralName
+	 * @return
+	 */
 	protected List<TaggedText> getRanklessTaggedNameCache(NonViralName<?> nonViralName){
 		List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
 		String speciesEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim().replace("null", "");
@@ -777,33 +558,12 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		addAppendedTaggedPhrase(tags, nonViralName);
 		return tags;			
 	}
-	
-	protected String getRanklessNameCache(NonViralName<?> nonViralName){
-		String result = "";
-		result = (result + (CdmUtils.Nz(nonViralName.getGenusOrUninomial()))).trim().replace("null", "");
-		result += " " + (CdmUtils.Nz(nonViralName.getSpecificEpithet())).trim();
-		result += " " + (CdmUtils.Nz(nonViralName.getInfraSpecificEpithet())).trim();
-		result = result.trim().replace("null", "");
-		//result += " (rankless)";
-		result = addAppendedPhrase(result, nonViralName);
-		return result;			
-	}
-
-		
-	protected List<TaggedText> getGenusOrUninomialTaggedNameCache(NonViralName<?> nonViralName){
-		List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
-		addAppendedTaggedPhrase(tags, nonViralName);
-		return tags;
-	}
-
-	protected String getGenusOrUninomialNameCache(NonViralName<?> nonViralName){
-		String result;
-		result = getUninomialPart(nonViralName);
-		result = addAppendedPhrase(result, nonViralName).trim();
-		return result;
-	}
-
 
+	/**
+	 * Returns the tag list for the first epithet (including a hybrid sign if required).
+	 * @param nonViralName
+	 * @return
+	 */
 	private List<TaggedText> getUninomialTaggedPart(NonViralName<?> nonViralName) {
 		List<TaggedText> tags = new ArrayList<TaggedText>();
 		
@@ -819,16 +579,25 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		return tags;
 	}
 	
-	private String getUninomialPart(NonViralName<?> nonViralName) {
-		String result;
-		result = CdmUtils.Nz(nonViralName.getGenusOrUninomial()).trim();
-		if (nonViralName.isMonomHybrid()){
-			result = NonViralNameParserImplRegExBase.hybridSign + result; 
-		}
-		return result;
+	/**
+	 * Returns the tag list for an genus or higher taxon.
+	 * 
+	 * @param nonViralName
+	 * @return
+	 */
+	protected List<TaggedText> getGenusOrUninomialTaggedNameCache(NonViralName<?> nonViralName){
+		List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
+		addAppendedTaggedPhrase(tags, nonViralName);
+		return tags;
 	}
 	
-	
+	/**
+	 * Returns the tag list for an infrageneric taxon (including species aggregates).
+	 * 
+	 * @see #getSpeciesAggregateTaggedCache(NonViralName)
+	 * @param nonViralName
+	 * @return
+	 */
 	protected List<TaggedText> getInfraGenusTaggedNameCache(NonViralName<?> nonViralName){
 		Rank rank = nonViralName.getRank();
 		if (rank.isSpeciesAggregate()){
@@ -859,27 +628,12 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		return tags;
 	}
 	
-	protected String getInfraGenusNameCache(NonViralName<?> nonViralName){
-		String result;
-		Rank rank = nonViralName.getRank();
-		if (rank.isSpeciesAggregate()){
-			return getSpeciesAggregateCache(nonViralName);
-		}
-		String infraGenericMarker = "'unhandled infrageneric rank'";
-		if (rank != null){
-			try {
-				infraGenericMarker = rank.getInfraGenericMarker();
-			} catch (UnknownCdmTypeException e) {
-				infraGenericMarker = "'unhandled infrageneric rank'";
-			}
-		}
-		result = getUninomialPart(nonViralName);
-		result += " " + infraGenericMarker + " " + (CdmUtils.Nz(nonViralName.getInfraGenericEpithet())).trim().replace("null", "");
-		result = addAppendedPhrase(result, nonViralName).trim();
-		return result;
-	}
-
-//		aggr.|agg.|group
+	/**
+	 * Returns the tag list for a species aggregate (or similar) taxon.<BR>
+	 * Possible ranks for a <i>species aggregate</i> are "aggr.", "species group", ...	
+	 * @param nonViralName
+	 * @return
+	 */
 	protected List<TaggedText> getSpeciesAggregateTaggedCache(NonViralName<?> nonViralName){
 		List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
 		
@@ -888,6 +642,11 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		return tags;
 	}
 	
+	/**
+	 * Adds the aggregate tag to the tag list.
+	 * @param tags
+	 * @param nonViralName
+	 */
 	private void addSpeciesAggregateTaggedEpithet(List<TaggedText> tags, NonViralName<?> nonViralName) {
 		String marker;
 		try {
@@ -899,44 +658,35 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 			tags.add(new TaggedText(TagEnum.rank, marker));
 		}
 	}
-	
-//		aggr.|agg.|group
-	protected String getSpeciesAggregateCache(NonViralName<?> nonViralName){
-		String result = getGenusAndSpeciesPart(nonViralName);
-		
-		result += " " + getSpeciesAggregateEpithet(nonViralName);
-		result = addAppendedPhrase(result, nonViralName).trim();
-		return result;
-	}
-	
-	private String getSpeciesAggregateEpithet(NonViralName<?> nonViralName) {
-		String marker;
-		try {
-			marker = nonViralName.getRank().getInfraGenericMarker();
-		} catch (UnknownCdmTypeException e) {
-			marker = "'unknown aggregat type'";
-		}
-		return marker;
-	}
 
 	
+	/**
+	 * Returns the tag list for a species taxon.
+	 * @param nonViralName
+	 * @return
+	 */
 	protected List<TaggedText> getSpeciesTaggedNameCache(NonViralName<?> nonViralName){
 		List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
 		addAppendedTaggedPhrase(tags, nonViralName);
 		return tags;
 	}
-	
-	protected String getSpeciesNameCache(NonViralName<?> nonViralName){
-		String result = getGenusAndSpeciesPart(nonViralName);
-		result = addAppendedPhrase(result, nonViralName).trim();
-		result = result.replace("\\s\\", " ");
-		return result;
-	}
 
+	/**
+	 * Creates the tag list for an infraspecific taxon. In include is true the result will contain
+	 * @param nonViralName
+	 * @return
+	 */
 	protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName){
 		return getInfraSpeciesTaggedNameCache(nonViralName, true);
 	}
 	
+	/**
+	 * Creates the tag list for an infraspecific taxon. In include is true the result will contain
+	 * the infraspecific marker (e.g. "var.")
+	 * @param nonViralName
+	 * @param includeMarker
+	 * @return
+	 */
 	protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName<?> nonViralName, boolean includeMarker){
 		List<TaggedText> tags = getGenusAndSpeciesTaggedPart(nonViralName);
 		if (includeMarker){ 
@@ -968,27 +718,12 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		tags.add(new TaggedText(TagEnum.hybridSign, NonViralNameParserImplRegExBase.hybridSign));
 		tags.add(new TaggedText(TagEnum.separator, "")); //no whitespace separator
 	}
-	
-	protected String getInfraSpeciesNameCache(NonViralName<?> nonViralName){
-		return getInfraSpeciesNameCache(nonViralName, true);
-	}
-
-	
-	protected String getInfraSpeciesNameCache(NonViralName<?> nonViralName, boolean includeMarker){
-		String result = getGenusAndSpeciesPart(nonViralName);
-		if (includeMarker){ 
-			result += " " + (nonViralName.getRank().getAbbreviation()).trim().replace("null", "");
-		}
-		String infrSpecEpi = CdmUtils.Nz(nonViralName.getInfraSpecificEpithet());
-		if (nonViralName.isTrinomHybrid()){
-			infrSpecEpi = NonViralNameParserImplRegExBase.hybridSign + infrSpecEpi; 
-		}
-		result += " " + (infrSpecEpi).trim().replace("null", "");
-		result = addAppendedPhrase(result, nonViralName).trim();
-		return result;
-	}
-
 
+	/**
+	 * Creates the tag list for the genus and species part.
+	 * @param nonViralName
+	 * @return
+	 */
 	private List<TaggedText> getGenusAndSpeciesTaggedPart(NonViralName<?> nonViralName) {
 		//Uninomial
 		List<TaggedText> tags = getUninomialTaggedPart(nonViralName);
@@ -1017,31 +752,6 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 		return tags;
 	}
 	
-	private String getGenusAndSpeciesPart(NonViralName<?> nonViralName) {
-		String result;
-		//Uninomial
-		result = getUninomialPart(nonViralName);
-		
-		//InfraGenericEpi
-		boolean hasInfraGenericEpi = StringUtils.isNotBlank(nonViralName.getInfraGenericEpithet());
-		if (hasInfraGenericEpi){
-			String infrGenEpi = nonViralName.getInfraGenericEpithet().trim();
-			if (nonViralName.isBinomHybrid()){
-				infrGenEpi = NonViralNameParserImplRegExBase.hybridSign + infrGenEpi; 
-			}
-			result += " (" + infrGenEpi + ")";
-		}
-		//Species Epi
-		String specEpi = CdmUtils.Nz(nonViralName.getSpecificEpithet()).trim();
-		if (! hasInfraGenericEpi && nonViralName.isBinomHybrid() || 
-				hasInfraGenericEpi && nonViralName.isTrinomHybrid()){
-			specEpi = NonViralNameParserImplRegExBase.hybridSign +  specEpi; 
-		}
-		result += " " + (specEpi).replace("null", "");
-		return result;
-	}
-
-	
 	/**
 	 * Adds the tag for the appended phrase if an appended phrase exists
 	 * @param tags
@@ -1053,20 +763,6 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 			tags.add(new TaggedText(TagEnum.name, appendedPhrase));
 		}
 	}
-	
-	protected String addAppendedPhrase(String resultString, NonViralName<?> nonViralName){
-		String appendedPhrase = nonViralName ==null ? null : nonViralName.getAppendedPhrase();
-		if (resultString == null){
-			return appendedPhrase;
-		}else if(appendedPhrase == null || "".equals(appendedPhrase.trim())) {
-			return resultString;
-		}else if ("".equals(resultString)){
-			return resultString + appendedPhrase;
-		}else {
-			return resultString + " " + appendedPhrase;
-		}
-	}
-
 
 	public String getLastEpithet(T taxonNameBase) {
 		Rank rank = taxonNameBase.getRank();
@@ -1080,4 +776,92 @@ public class NonViralNameDefaultCacheStrategy<T extends NonViralName> extends Na
 			return taxonNameBase.getInfraSpecificEpithet();
 		}
 	}
+	
+// *************************** DEPRECATED ***************************************************/
+	
+
+	//Old: may be replaced once getTagged(Full)Title is fully tested
+	/* (non-Javadoc)
+	 * @see eu.etaxonomy.cdm.strategy.INameCacheStrategy#getTaggedName(eu.etaxonomy.cdm.model.common.CdmBase)
+	 */
+	@Override
+	@Deprecated
+	public List<Object> getTaggedNameDeprecated(T nonViralName) {
+		List<Object> tags = new ArrayList<Object>();
+		
+		if (nonViralName.isProtectedNameCache() ||
+				nonViralName.isProtectedAuthorshipCache() ||
+				nonViralName.isProtectedFullTitleCache() ||
+				nonViralName.isProtectedTitleCache()){
+			tags.add(nonViralName.getTitleCache());
+			return tags;
+		}
+		
+		// Why does it make sense to add the nameCache in case of non existing genusOrUninomial?
+//		if (nonViralName.getGenusOrUninomial() == null){
+//			tags.add(nonViralName.getNameCache());
+//		}else{
+		
+		if (nonViralName.getGenusOrUninomial() != null) {
+			tags.add(nonViralName.getGenusOrUninomial());
+		}
+		if (nonViralName.isSpecies() || nonViralName.isInfraSpecific()){
+			tags.add(nonViralName.getSpecificEpithet());			
+		}
+		
+		// No autonym 
+		if (nonViralName.isInfraSpecific() && ! nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
+			tags.add(nonViralName.getRank());			
+			tags.add(nonViralName.getInfraSpecificEpithet());			
+		}
+		
+		if (nonViralName.isInfraGeneric()){
+			//TODO choose right strategy or generic approach?
+			// --- strategy 1 --- 
+					
+			if (nonViralName.getRank().isSpeciesAggregate()){
+				tags.add(nonViralName.getSpecificEpithet());
+				tags.add(getSpeciesAggregateEpithet(nonViralName));
+			}else{
+				tags.add(nonViralName.getRank());	
+				tags.add(nonViralName.getInfraGenericEpithet());	
+			}
+			// --- strategy 2 --- 
+//			tags.add('('+nvn.getInfraGenericEpithet()+')');	
+		}
+		Team authorTeam = Team.NewInstance();
+		authorTeam.setProtectedTitleCache(true);
+		authorTeam.setTitleCache(nonViralName.getAuthorshipCache(), true);
+		tags.add(authorTeam);
+		
+		// Name is an autonym. Rank and infraspecific epitheton follow the author
+		if (nonViralName.isInfraSpecific() && nonViralName.getSpecificEpithet().equals(nonViralName.getInfraSpecificEpithet())){
+			tags.add(nonViralName.getRank());			
+			tags.add(nonViralName.getInfraSpecificEpithet());			
+		}
+		
+		if(! "".equals(nonViralName.getAppendedPhrase())&& (nonViralName.getAppendedPhrase() != null)){
+			tags.add(nonViralName.getAppendedPhrase());
+		}
+		
+		return tags;
+	}
+	
+	
+	/**
+	 * @deprecated use only for {@link #getTaggedNameDeprecated(NonViralName)}. Delete when the later 
+	 * is deleted.
+	 */
+	@Deprecated 
+	private String getSpeciesAggregateEpithet(NonViralName<?> nonViralName) {
+		String marker;
+		try {
+			marker = nonViralName.getRank().getInfraGenericMarker();
+		} catch (UnknownCdmTypeException e) {
+			marker = "'unknown aggregat type'";
+		}
+		return marker;
+	}
+
+	
 }
diff --git a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/ZooNameDefaultCacheStrategy.java b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/ZooNameDefaultCacheStrategy.java
index 89627ae93b..28edbe895b 100644
--- a/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/ZooNameDefaultCacheStrategy.java
+++ b/cdmlib-model/src/main/java/eu/etaxonomy/cdm/strategy/cache/name/ZooNameDefaultCacheStrategy.java
@@ -9,6 +9,7 @@
 
 package eu.etaxonomy.cdm.strategy.cache.name;
 
+import java.util.List;
 import java.util.UUID;
 
 import org.apache.log4j.Logger;
@@ -17,6 +18,7 @@ import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
 import eu.etaxonomy.cdm.model.name.NonViralName;
 import eu.etaxonomy.cdm.model.name.ZoologicalName;
+import eu.etaxonomy.cdm.strategy.TaggedText;
 
 public class ZooNameDefaultCacheStrategy <T extends ZoologicalName> extends NonViralNameDefaultCacheStrategy<T> implements  INonViralNameCacheStrategy<T> {
 	@SuppressWarnings("unused")
@@ -47,8 +49,21 @@ public class ZooNameDefaultCacheStrategy <T extends ZoologicalName> extends NonV
 		super();
 	}
 
-	
 
+
+	/**
+	 * @return Strings that separates the author part and the year part
+	 * @return
+	 */
+	public String getAuthorYearSeperator() {
+		return AuthorYearSeperator;
+	}
+
+
+	public void setAuthorYearSeperator(String authorYearSeperator) {
+		AuthorYearSeperator = authorYearSeperator;
+	}
+	
 	/* (non-Javadoc)
 	 * @see eu.etaxonomy.cdm.strategy.cache.name.NonViralNameDefaultCacheStrategy#getNonCacheAuthorshipCache(eu.etaxonomy.cdm.model.name.NonViralName)
 	 */
@@ -71,35 +86,23 @@ public class ZooNameDefaultCacheStrategy <T extends ZoologicalName> extends NonV
 		if (basionymAuthor != null || exBasionymAuthor != null || originalPublicationYear != null ){
 			String authorAndEx = getAuthorAndExAuthor(basionymAuthor, exBasionymAuthor);
 			String originalPublicationYearString = originalPublicationYear == null ? null : String.valueOf(originalPublicationYear);
-			String authorAndExAndYear = CdmUtils.concat(", ", authorAndEx, originalPublicationYearString );
+			String authorAndExAndYear = CdmUtils.concat(AuthorYearSeperator, authorAndEx, originalPublicationYearString );
 			basionymPart = BasionymStart + authorAndExAndYear +BasionymEnd;
 		}
 		if (combinationAuthor != null || exCombinationAuthor != null){
 			String authorAndEx = getAuthorAndExAuthor(combinationAuthor, exCombinationAuthor);
 			String publicationYearString = publicationYear == null ? null : String.valueOf(publicationYear);
-			authorPart = CdmUtils.concat(", ", authorAndEx, publicationYearString);
+			authorPart = CdmUtils.concat(AuthorYearSeperator, authorAndEx, publicationYearString);
 		}
 		result = CdmUtils.concat(BasionymAuthorCombinationAuthorSeperator, basionymPart, authorPart);
 		return result;
 	}
 	
 
-	/**
-	 * @return Strings that separates the author part and the year part
-	 * @return
-	 */
-	public String getAuthorYearSeperator() {
-		return AuthorYearSeperator;
-	}
-
-
-	public void setAuthorYearSeperator(String authorYearSeperator) {
-		AuthorYearSeperator = authorYearSeperator;
-	}
-	
-	protected String getInfraSpeciesNameCache(NonViralName nonViralName){
+	@Override
+	protected List<TaggedText> getInfraSpeciesTaggedNameCache(NonViralName nonViralName){
 		boolean includeMarker = ! (nonViralName.isAutonym());
-		return getInfraSpeciesNameCache(nonViralName, includeMarker);
+		return getInfraSpeciesTaggedNameCache(nonViralName, includeMarker);
 	}
 
 }
diff --git a/cdmlib-model/src/test/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategyTest.java b/cdmlib-model/src/test/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategyTest.java
index fdbe7b88ff..e2818cd817 100644
--- a/cdmlib-model/src/test/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategyTest.java
+++ b/cdmlib-model/src/test/java/eu/etaxonomy/cdm/strategy/cache/name/NonViralNameDefaultCacheStrategyTest.java
@@ -31,6 +31,7 @@ import eu.etaxonomy.cdm.model.name.Rank;
 import eu.etaxonomy.cdm.model.name.ZoologicalName;
 import eu.etaxonomy.cdm.model.reference.Reference;
 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+import eu.etaxonomy.cdm.strategy.TaggedText;
 
 /**
  * @author a.mueller
@@ -461,13 +462,14 @@ public class NonViralNameDefaultCacheStrategyTest {
 	@Test
 	public void testGetInfraGenericNames(){
 		String author = "Anyauthor";
-		NonViralName nonViralName = NonViralName.NewInstance(Rank.SUBGENUS());
+		NonViralName<?> nonViralName = NonViralName.NewInstance(Rank.SUBGENUS());
 		nonViralName.setGenusOrUninomial("Genus");
 		nonViralName.setInfraGenericEpithet("subgenus");
 		nonViralName.setAuthorshipCache(author);
 		
 		//test ordinary infrageneric
-		String subGenusNameCache = strategy.getInfraGenusNameCache(nonViralName);
+		List<TaggedText> subGenusNameCacheTagged = strategy.getInfraGenusTaggedNameCache(nonViralName);
+		String subGenusNameCache = strategy.createString(subGenusNameCacheTagged);
 		assertEquals("Subgenus name should be 'Genus subg. subgenus'.", "Genus subg. subgenus", subGenusNameCache);
 		String subGenusTitle = strategy.getTitleCache(nonViralName);
 		assertEquals("Subgenus name should be 'Genus subg. subgenus Anyauthor'.", "Genus subg. subgenus Anyauthor", subGenusTitle);
@@ -476,7 +478,10 @@ public class NonViralNameDefaultCacheStrategyTest {
 		nonViralName.setRank(Rank.SPECIESAGGREGATE());
 		nonViralName.setSpecificEpithet("myspecies");
 		nonViralName.setInfraGenericEpithet(null);
-		String aggrNameCache = strategy.getInfraGenusNameCache(nonViralName);
+		
+		List<TaggedText> aggrNameCacheTagged = strategy.getInfraGenusTaggedNameCache(nonViralName);
+		
+		String aggrNameCache = strategy.createString(aggrNameCacheTagged);
 		assertEquals("Species aggregate name should be 'Genus myspecies aggr.'.", "Genus myspecies aggr.", aggrNameCache);
 		String aggrNameTitle = strategy.getTitleCache(nonViralName);
 		Assert.assertTrue("Species aggregate should not include author information.", aggrNameTitle.indexOf(author) == -1);
@@ -490,7 +495,10 @@ public class NonViralNameDefaultCacheStrategyTest {
 		nonViralName.setRank(Rank.SPECIESAGGREGATE());
 		nonViralName.setSpecificEpithet("myspecies");
 		nonViralName.setInfraGenericEpithet("Infragenus");
-		aggrNameCache = strategy.getInfraGenusNameCache(nonViralName);
+		
+		
+		aggrNameCacheTagged = strategy.getInfraGenusTaggedNameCache(nonViralName);
+		aggrNameCache = strategy.createString(aggrNameCacheTagged);
 		assertEquals("Species aggregate name should be 'Genus (Infragenus) myspecies aggr.'.", "Genus (Infragenus) myspecies aggr.", aggrNameCache);
 		
 		aggrNameTitle = strategy.getTitleCache(nonViralName);
