/*******************************************************************************
 * Copyright (c) 2022 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text.javadoc;

import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.JavaDocRegion;
import org.eclipse.jdt.core.dom.MemberRef;
import org.eclipse.jdt.core.dom.MethodRef;
import org.eclipse.jdt.core.dom.MethodRefParameter;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TagProperty;
import org.eclipse.jdt.core.dom.TextElement;

import org.eclipse.jdt.internal.corext.dom.ASTNodes;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;

public class JavaDocSnippetStringEvaluator {

	/**
	 * Either an IMember or an IPackageFragment.
	 */
	private final IJavaElement fElement;

	public enum ReplacementStringIntervalStatus {
		/**
		 * replacement interval occurs before the given ActionElement interval
		 */
		BEFORE,
		/**
		 * replacement interval occurs after the given ActionElement interval
		 */
		AFTER,
		/**
		 * replacement interval occurs within the given ActionElement interval
		 */
		WITHIN,
		/**
		 * replacement interval contains the given ActionElement interval
		 */
		ENCOMPASS,
		/**
		 * replacement interval starts before the given ActionElement interval and ends within the ActionElement interval
		 */
		PREV_OVERLAP,
		/**
		 * replacement interval starts within the given ActionElement interval and ends after the ActionElement interval
		 */
		POST_OVERLAP,
		/**
		 * Default Value, do nothing
		 */
		DEFAULT
	}

	public class ActionElement{
		public int start;
		public int end;
		public String startTag;
		public String endTag;

		public ActionElement(int start, int end, String startTag, String endTag) {
			this.start= start;
			this.end= end;
			this.startTag= startTag;
			this.endTag= endTag;
		}

		public ReplacementStringIntervalStatus getIntervalStatus(int replacementIntervalStart, int replacementIntervalEnd) {
			ReplacementStringIntervalStatus intervalStatus= ReplacementStringIntervalStatus.DEFAULT;
			int startDiff = replacementIntervalStart - this.start;
			int endDiff = replacementIntervalEnd - this.end;

			if (this.end <= replacementIntervalStart) {
				intervalStatus= ReplacementStringIntervalStatus.AFTER;
			} else if (this.start >= replacementIntervalEnd) {
				intervalStatus= ReplacementStringIntervalStatus.BEFORE;
			} else if (startDiff <= 0 && endDiff >= 0) {
				intervalStatus= ReplacementStringIntervalStatus.ENCOMPASS;
			} else if (startDiff > 0 && endDiff < 0) {
				intervalStatus= ReplacementStringIntervalStatus.WITHIN;
			} else if (startDiff > 0) {
				intervalStatus= ReplacementStringIntervalStatus.POST_OVERLAP;
			} else if (endDiff < 0) {
				intervalStatus= ReplacementStringIntervalStatus.PREV_OVERLAP;
			}

			return intervalStatus;
		}

	}

	public class StringItem{
		public int index;
		public String tag;
		public StringItem(int index, String tag) {
			this.index= index;
			this.tag= tag;
		}
	}

	public JavaDocSnippetStringEvaluator(IJavaElement element) {
		this.fElement= element;
	}

	public void AddTagElementString(TagElement snippetTag, StringBuffer buffer) {
		if (snippetTag != null) {
			List<Object> fragments = snippetTag.fragments();
			for( Object fragment : fragments) {
				String str= ""; //$NON-NLS-1$
				if (fragment instanceof TextElement) {
					TextElement textElement= (TextElement) fragment;
					List<TagElement> tagElements= getTagElementsForTextElement(snippetTag, textElement);
					str = getModifiedString(textElement, tagElements);
				} else if (fragment instanceof JavaDocRegion) {
					JavaDocRegion region = (JavaDocRegion) fragment;
					if (region.isDummyRegion()) {
						List<TagElement> tagElements= getTagElementsForDummyJavaDocRegion(snippetTag, region);
						str = getModifiedString(region, tagElements);
					}
				} else if (fragment instanceof TagElement) {
					TagElement tagElement= (TagElement) fragment;
					List<TagElement> tagElements= getTagElementsForTagElement(snippetTag, tagElement);
					str = getModifiedString(tagElement, tagElements);
				}
				buffer.append(str);
			}
		}
	}

	private String getModifiedString(TextElement textElement, List<TagElement> tags) {
		return getModifiedString(textElement.getText(), tags);
	}

	private String getModifiedString(TagElement tagElement, List<TagElement> tags) {
		return getModifiedString(((TextElement)tagElement.fragments().get(0)).getText(), tags);
	}

	private String getModifiedString(JavaDocRegion region, List<TagElement> tags) {
		return getModifiedString(((TextElement)region.fragments().get(0)).getText(), tags);
	}

	private String getModifiedString(String str, List<TagElement> tags) {
		List<ActionElement> actionElements= new ArrayList<>();
		String modifiedStr= str;
		for (TagElement tag : tags) {
			String name= tag.getTagName();
			if (TagElement.TAG_HIGHLIGHT.equals(name)) {
				handleSnippetHighlight(modifiedStr, tag, actionElements);
			} else if (TagElement.TAG_REPLACE.equals(name)) {
				modifiedStr= handleSnippetReplace(modifiedStr, tag, actionElements);
			} else if (TagElement.TAG_LINK.equals(name)) {
				handleSnippetLink(modifiedStr, tag, actionElements);
			}
		}
		return getString( modifiedStr, actionElements);
	}

	private String getString(String str, List<ActionElement> actionElements) {
		String modifiedStr = str;
		List<StringItem> items= new ArrayList<>();
		for (ActionElement actElem : actionElements) {
			StringItem startItem = new StringItem(actElem.start, actElem.startTag);
			StringItem endItem = new StringItem(actElem.end, actElem.endTag);
			ListIterator<StringItem> iterator = items.listIterator();
			boolean endIndexAdded = false;
			boolean startIndexAdded = false;
			while (iterator.hasNext()) {
				StringItem elem= iterator.next();
				if (!endIndexAdded && elem.index < endItem.index) {
					iterator.previous();
					iterator.add(endItem);
					endIndexAdded = true;
					iterator.next();
				}
				if (!startIndexAdded && elem.index < startItem.index) {
					iterator.previous();
					iterator.add(startItem);
					startIndexAdded = true;
					iterator.next();
				}
				if (startIndexAdded && endIndexAdded) {
					break;
				}
			}
			if (!endIndexAdded) {
				items.add(endItem);
			}
			if (!startIndexAdded) {
				items.add(startItem);
			}
		}
		for (StringItem item : items) {
			modifiedStr = modifiedStr.substring(0, item.index) + item.tag + modifiedStr.substring(item.index);
		}
		return modifiedStr;
	}

	private void modifyPrevActionItemsReplacement(int replacementIntervalStart, int relacementIntervalEnd, int replacementStrNewLength, List<ActionElement> actionElements) {
		ListIterator<ActionElement> iterator = actionElements.listIterator();
		int oldLength = relacementIntervalEnd - replacementIntervalStart;
		int diff = replacementStrNewLength - oldLength;
		while (iterator.hasNext()) {
			ActionElement elem= iterator.next();
			ReplacementStringIntervalStatus intervalStatus= elem.getIntervalStatus(replacementIntervalStart, relacementIntervalEnd);
			switch(intervalStatus) {
				case AFTER:
					//do nothing., nothing needs to be done here
					break;
				case BEFORE:
					if (diff != 0) {
						elem.start+= diff;
						elem.end+= diff;
					}
					break;
				case ENCOMPASS:
					iterator.remove();
					break;
				case POST_OVERLAP:
					elem.end= replacementIntervalStart;
					break;
				case PREV_OVERLAP:
					elem.end += diff;
					elem.start = relacementIntervalEnd + diff;
					break;
				case WITHIN:
					// modify the old ActionElement to end before the replacement string start
					// Create a new Element element to start from the replacement string end
					int newEnd = elem.end + diff;
					elem.end= replacementIntervalStart;
					int newStart = relacementIntervalEnd + diff;
					ActionElement newElem= new  ActionElement(newStart, newEnd, elem.startTag, elem.endTag);
					iterator.add(newElem);
					break;
				case DEFAULT:
				default:
					break;
			}
		}
	}

	private List<TagElement> getTagElementsForTextElement(TagElement snippetTag, TextElement textElement) {
		List<TagElement> tagElements= new ArrayList<>();
		List<JavaDocRegion> regions= snippetTag.tagRegionsStartingAtTextElement(textElement);
		List<JavaDocRegion> masterList= snippetTag.tagRegionsContainingTextElement(textElement);
		masterList.removeAll(regions);
		for (JavaDocRegion region : masterList) {
			for (Object tagObj : region.tags()) {
				tagElements.add((TagElement) tagObj);
			}
		}
		for (JavaDocRegion region : regions) {
			for (Object tagObj : region.tags()) {
				if (tagObj instanceof TagElement) {
					TagElement tagElem= (TagElement) tagObj;
					Object prop= tagElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
					if (prop instanceof Integer) {
						int val = ((Integer)prop).intValue();
						ListIterator<TagElement> listIterator= tagElements.listIterator();
						TagElement addBefore= null;
						while (listIterator.hasNext()) {
				           TagElement tElem=  listIterator.next();
				           Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
				           if (prop2 instanceof Integer) {
				        	   int val2 = ((Integer)prop2).intValue();
				        	   if (val2 > val) {
				        		   addBefore= tElem;
				        		   break;
				        	   }
				           }
				        }
						if (addBefore == null) {
							tagElements.add(tagElem);
						} else {
							tagElements.add(tagElements.indexOf(addBefore), tagElem);
						}
					}
				}
			}
		}
		return tagElements;
	}

	private List<TagElement> getTagElementsForDummyJavaDocRegion(TagElement snippetTag, JavaDocRegion javaDocRegion) {
		List<TagElement> tagElements= new ArrayList<>();
		TextElement textElement= (TextElement) javaDocRegion.fragments().get(0);
		List<JavaDocRegion> regions= snippetTag.tagRegionsStartingAtTextElement(textElement);
		List<JavaDocRegion> masterList= snippetTag.tagRegionsContainingTextElement(textElement);
		masterList.removeAll(regions);
		for (JavaDocRegion region : masterList) {
			for (Object tagObj : region.tags()) {
				tagElements.add((TagElement) tagObj);
			}
		}
		regions.add(javaDocRegion);
		for (JavaDocRegion region : regions) {
			for (Object tagObj : region.tags()) {
				if (tagObj instanceof TagElement) {
					TagElement tagElem= (TagElement) tagObj;
					Object prop= tagElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
					if (prop instanceof Integer) {
						int val = ((Integer)prop).intValue();
						ListIterator<TagElement> listIterator= tagElements.listIterator();
						TagElement addBefore= null;
						while (listIterator.hasNext()) {
				           TagElement tElem=  listIterator.next();
				           Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
				           if (prop2 instanceof Integer) {
				        	   int val2 = ((Integer)prop2).intValue();
				        	   if (val2 > val) {
				        		   addBefore= tElem;
				        		   break;
				        	   }
				           }
				        }
						if (addBefore == null) {
							tagElements.add(tagElem);
						} else {
							tagElements.add(tagElements.indexOf(addBefore), tagElem);
						}
					}
				}
			}
		}

		return tagElements;
	}

	private List<TagElement> getTagElementsForTagElement(TagElement snippetTag, TagElement tag) {
		List<TagElement> tagElements= new ArrayList<>();
		TextElement textElement= (TextElement) tag.fragments().get(0);
		List<JavaDocRegion> regions= snippetTag.tagRegionsStartingAtTextElement(textElement);
		List<JavaDocRegion> masterList= snippetTag.tagRegionsContainingTextElement(textElement);
		masterList.removeAll(regions);
		for (JavaDocRegion region : masterList) {
			for (Object tagObj : region.tags()) {
				tagElements.add((TagElement) tagObj);
			}
		}
		for (JavaDocRegion region : regions) {
			for (Object tagObj : region.tags()) {
				if (tagObj instanceof TagElement) {
					TagElement tagElem= (TagElement) tagObj;
					Object prop= tagElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
					if (prop instanceof Integer) {
						int val = ((Integer)prop).intValue();
						ListIterator<TagElement> listIterator= tagElements.listIterator();
						TagElement addBefore= null;
						while (listIterator.hasNext()) {
				           TagElement tElem=  listIterator.next();
				           Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
				           if (prop2 instanceof Integer) {
				        	   int val2 = ((Integer)prop).intValue();
				        	   if (val2 > val) {
				        		   addBefore= tElem;
				        		   break;
				        	   }
				           }
				        }
						if (addBefore == null) {
							tagElements.add(tagElem);
						} else {
							tagElements.add(tagElements.indexOf(addBefore), tagElem);
						}
					}
				}
			}
		}
		Object prop3= tag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
		if (prop3 instanceof Integer) {
			int val = ((Integer)prop3).intValue();
			ListIterator<TagElement> listIterator= tagElements.listIterator();
			TagElement addBefore= null;
			while (listIterator.hasNext()) {
		          TagElement tElem=  listIterator.next();
		          Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
		          if (prop2 instanceof Integer) {
		       	   int val2 = ((Integer)prop2).intValue();
		       	   if (val2 > val) {
		       		   addBefore= tElem;
		       		   break;
		       	   }
		          }
		       }
			if (addBefore == null) {
				tagElements.add(tag);
			} else {
				tagElements.add(tagElements.indexOf(addBefore), tag);
			}
		}
		return tagElements;
	}

	private void handleSnippetHighlight(String text, TagElement tagElement, List<ActionElement> actionElements) {
		try {
			List<? extends TagProperty> tagProperties= tagElement.tagProperties();
			String defHighlight= getHighlightHtmlTag(tagProperties);
			String startDefHighlight = '<' + defHighlight + '>';
			String endDefHighlight = "</" + defHighlight + '>'; //$NON-NLS-1$
			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
			Pattern regexPattern = null;
			if (regExValue != null) {
				regexPattern = Pattern.compile(regExValue);
			}
			if (regexPattern != null) {
				Matcher matcher = regexPattern.matcher(text);
				while (matcher.find()) {
					actionElements.add(new ActionElement(matcher.start(), matcher.end(), startDefHighlight, endDefHighlight));
				}
			} else if (subStringValue != null) {
				int startIndex = 0;
				while ((startIndex = text.indexOf(subStringValue, startIndex)) != -1) {
					actionElements.add(new ActionElement(startIndex, startIndex + subStringValue.length(), startDefHighlight, endDefHighlight));
					startIndex += subStringValue.length();
				}
			} else {
				actionElements.add(new ActionElement(0, text.length(), startDefHighlight, endDefHighlight));
			}
			return;
		} catch (PatternSyntaxException e) {
			// do nothing
		}
		return;
	}

	private String handleSnippetReplace(String text, TagElement tagElement, List<ActionElement> actionElements) {
		try {
			List<? extends TagProperty> tagProperties= tagElement.tagProperties();
			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
			String substitution = getPropertyValue("replacement", tagProperties); //$NON-NLS-1$
			Pattern regexPattern = null;
			if (regExValue != null) {
				regexPattern = Pattern.compile(regExValue);
			}
			String modifiedText = text;
			if (regexPattern != null) {
				Matcher matcher = regexPattern.matcher(modifiedText);
				StringBuilder strBuild= new StringBuilder();
				int finalMatchIndex = 0;
				while (matcher.find()) {
					finalMatchIndex = matcher.end();
					modifyPrevActionItemsReplacement(matcher.start(), matcher.end(), substitution.length(), actionElements);
					matcher.appendReplacement(strBuild, substitution);
				}
				modifiedText = strBuild.toString() + modifiedText.substring(finalMatchIndex);
			} else if (subStringValue != null) {
				int startIndex = 0;
				while ((startIndex = modifiedText.indexOf(subStringValue, startIndex)) != -1) {
					modifyPrevActionItemsReplacement(startIndex, startIndex+ subStringValue.length(), substitution.length(), actionElements);
					modifiedText = modifiedText.substring(0, startIndex) + substitution + modifiedText.substring(startIndex + subStringValue.length());
					startIndex += substitution.length() ;
				}
			} else {
				actionElements.clear();
				modifiedText = substitution;
			}
			return modifiedText;
		} catch (PatternSyntaxException e) {
			// do nothing
		}
		return text;
	}


	private void handleSnippetLink(String text, TagElement tagElement, List<ActionElement> actionElements) {
		try {
			List<? extends TagProperty> tagProperties= tagElement.tagProperties();
			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
			String additionalStartTag= getLinkHtmlTag(tagProperties);
			String additionalEndTag= ""; //$NON-NLS-1$
			if (additionalStartTag.length() > 0) {
				additionalEndTag= "</" + additionalStartTag + '>'; //$NON-NLS-1$
				additionalStartTag= '<' + additionalStartTag + '>';
			}
			ASTNode target = getPropertyNodeValue("target", tagProperties); //$NON-NLS-1$
			String linkRefTxt = getLinkRef(target);
			String startDefLink = linkRefTxt + additionalStartTag;
			String endDefLink = additionalEndTag+"</a>"; //$NON-NLS-1$
			Pattern regexPattern = null;
			if (regExValue != null) {
				regexPattern = Pattern.compile(regExValue);
			}
			String modifiedText = text;
			if (regexPattern != null) {
				Matcher matcher = regexPattern.matcher(modifiedText);
				while (matcher.find()) {
					actionElements.add(new ActionElement(matcher.start(), matcher.end(), startDefLink, endDefLink));
				}
			} else if (subStringValue != null) {
				int startIndex = 0;
				while ((startIndex = modifiedText.indexOf(subStringValue, startIndex)) != -1) {
					actionElements.add(new ActionElement(startIndex, startIndex+ subStringValue.length(), startDefLink, endDefLink));
					startIndex = startIndex+ subStringValue.length() ;
				}
			} else {
				String subText = modifiedText.trim();
				if (subText.length() < text.length()) {
					int startIndex = text.indexOf(subText);
					actionElements.add(new ActionElement(startIndex, startIndex + subText.length(), startDefLink, endDefLink));
				}
			}
			return;
		} catch (PatternSyntaxException e) {
			// do nothing
		}
		return;
	}

	private String getLinkRef(ASTNode node) {
		String str= ""; //$NON-NLS-1$
		String refTypeName= null;
		String refMemberName= null;
		String[] refMethodParamTypes= null;
		String[] refMethodParamNames= null;
		if (node instanceof Name) {
			Name name = (Name) node;
			refTypeName= name.getFullyQualifiedName();
		} else if (node instanceof MemberRef) {
			MemberRef memberRef= (MemberRef) node;
			Name qualifier= memberRef.getQualifier();
			refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
			refMemberName= memberRef.getName().getIdentifier();
		} else if (node instanceof MethodRef) {
			MethodRef methodRef= (MethodRef) node;
			Name qualifier= methodRef.getQualifier();
			refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
			refMemberName= methodRef.getName().getIdentifier();
			List<MethodRefParameter> params= methodRef.parameters();
			int ps= params.size();
			refMethodParamTypes= new String[ps];
			refMethodParamNames= new String[ps];
			for (int i= 0; i < ps; i++) {
				MethodRefParameter param= params.get(i);
				refMethodParamTypes[i]= ASTNodes.asString(param.getType());
				SimpleName paramName= param.getName();
				if (paramName != null)
					refMethodParamNames[i]= paramName.getIdentifier();
			}
		}

		if (refTypeName != null) {
			str +="<a href='"; //$NON-NLS-1$
			try {
				String scheme= JavaElementLinks.JAVADOC_SCHEME;
				String uri= JavaElementLinks.createURI(scheme, fElement, refTypeName, refMemberName, refMethodParamTypes);
				str += uri;
			} catch (URISyntaxException e) {
				JavaPlugin.log(e);
			}
			str += "'>"; //$NON-NLS-1$
		}
		return str;
	}

	private String getLinkHtmlTag(List<? extends ASTNode> tagProperties) {
		String defaultTag= "code"; //$NON-NLS-1$
		if (tagProperties != null) {
			for (ASTNode node : tagProperties) {
				if (node instanceof TagProperty) {
					TagProperty tagProp = (TagProperty) node;
					if ("type".equals(tagProp.getName())) { //$NON-NLS-1$
						String tagValue = tagProp.getStringValue();
						switch (tagValue) {
							case "linkplain" :  //$NON-NLS-1$
								defaultTag= ""; //$NON-NLS-1$
								break;
							default:
								break;
						}
						break;
					}
				}
			}
		}
		return defaultTag;
	}

	private String getPropertyValue(String property, List<? extends ASTNode> tagProperties) {
		String defaultTag= null;
		if (tagProperties != null && property!= null) {
			for (ASTNode node : tagProperties) {
				if (node instanceof TagProperty) {
					TagProperty tagProp = (TagProperty) node;
					if (property.equals(tagProp.getName())) {
						defaultTag= tagProp.getStringValue();
						break;
					}
				}
			}
		}
		return defaultTag;
	}
	private ASTNode getPropertyNodeValue(String property, List<? extends ASTNode> tagProperties) {
		ASTNode defaultTag= null;
		if (tagProperties != null && property!= null) {
			for (ASTNode node : tagProperties) {
				if (node instanceof TagProperty) {
					TagProperty tagProp = (TagProperty) node;
					if (property.equals(tagProp.getName())) {
						defaultTag= tagProp.getNodeValue();
						break;
					}
				}
			}
		}
		return defaultTag;
	}

	private String getHighlightHtmlTag(List<? extends ASTNode> tagProperties) {
		String defaultTag= "b"; //$NON-NLS-1$
		if (tagProperties != null) {
			for (ASTNode node : tagProperties) {
				if (node instanceof TagProperty) {
					TagProperty tagProp = (TagProperty) node;
					if ("type".equals(tagProp.getName())) { //$NON-NLS-1$
						String tagValue = tagProp.getStringValue();
						switch (tagValue) {
							case "bold" :  //$NON-NLS-1$
								defaultTag= "b"; //$NON-NLS-1$
								break;
							case "italic" :  //$NON-NLS-1$
								defaultTag= "i"; //$NON-NLS-1$
								break;
							case "highlighted" :  //$NON-NLS-1$
								defaultTag= "mark"; //$NON-NLS-1$
								break;
							default :
								defaultTag= ""; //$NON-NLS-1$
								break;
						}
						break;
					}
				}
			}
		}
		return defaultTag;
	}

}
