//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.I18nUtil;
import org.eclipse.epf.common.utils.NetUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.common.utils.XMLUtil;
import org.eclipse.epf.common.xml.XSLTProcessor;
import org.eclipse.epf.library.ILibraryManager;
import org.eclipse.epf.library.ILibraryResourceManager;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryResources;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.layout.BrowsingLayoutSettings;
import org.eclipse.epf.library.layout.DefaultContentValidator;
import org.eclipse.epf.library.layout.IContentValidator;
import org.eclipse.epf.library.layout.LayoutResources;
import org.eclipse.epf.library.layout.LinkInfo;
import org.eclipse.epf.library.layout.elements.ActivityLayout;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.layout.util.XmlHelper;
import org.eclipse.epf.persistence.MethodLibraryPersister;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.util.UmaUtil;

/**
 * @author Jinhua Xi
 * @since 1.0
 */
public class ResourceHelper {

	// public static final String BRACE_REPLACEMENT = "_BR_"; //$NON-NLS-1$
	// public static final String OPENBRACE_STRING = "\\{"; //$NON-NLS-1$

	public static final String URL_BOOKMARK_INDICATOR = "#"; //$NON-NLS-1$

	public static final String URL_PARAMETER_INDICATOR = "?"; //$NON-NLS-1$

	public static final String URL_PARAMETER_PROCESS = "proc"; //$NON-NLS-1$

	public static final String URL_STR_JAVASCRIPT = "javascript:"; //$NON-NLS-1$

	public static final String URL_STR_MAILTO = "mailto:"; //$NON-NLS-1$

	public static final String URL_PARAMETER_PATH = "path"; //$NON-NLS-1$

	public static final String TAG_ATTR_NAME = "name"; //$NON-NLS-1$

	public static final String TAG_ATTR_KEY = "key"; //$NON-NLS-1$

	public static final String TAG_ATTR_TEXT = "text"; //$NON-NLS-1$

	public static final String TAG_ATTR_CLASS = "class"; //$NON-NLS-1$

	public static final String TAG_ATTR_GUID = "guid"; //$NON-NLS-1$

	public static final String TAG_ATTR_HREF = "href"; //$NON-NLS-1$

	public static final String TAG_ATTR_VALUE_INDEX = "index"; //$NON-NLS-1$

	public static final String FILE_EXT_HTML = ".html"; //$NON-NLS-1$

	public static final String FILE_EXT_HTM = ".htm"; //$NON-NLS-1$

	public static final String FILE_EXT_JPEG = ".jpeg"; //$NON-NLS-1$

	public static final String MISSING_PAGES_FOLDER = "pages_not_installed/"; //$NON-NLS-1$

	public static final String ELEMENT_LINK_CLASS_elementLink = "elementLink"; //$NON-NLS-1$

	public static final String ELEMENT_LINK_CLASS_elementLinkWithType = "elementLinkWithType"; //$NON-NLS-1$

	public static final String ELEMENT_LINK_CLASS_elementLinkWithUserText = "elementLinkWithUserText"; //$NON-NLS-1$

	public static final String RESOURCE_FOLDER = MethodLibraryPersister.RESOURCE_FOLDER;

	public static final Pattern p_html_file_name = Pattern
			.compile("(.*),(.*)\\.html"); //$NON-NLS-1$

	// this one does not work when containing non-english characters, use the
	// more general one
	// public static final Pattern p_link_ref =
	// Pattern.compile("<a\\s+?([^>]*)>(.*?)</a>", Pattern.CASE_INSENSITIVE |
	// Pattern.DOTALL); //$NON-NLS-1$
	public static final Pattern p_link_ref = Pattern
			.compile(
					"<a\\s+?(.*?)>(.*?)</a>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_template_attachment_url = Pattern
			.compile(
					"<a\\s+?href\\s*?=\\s*?\"(.*?)\"\\s*?>(.*?)</a>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

//	public static final Pattern p_area_ref = Pattern
//			.compile(
//					"<area.*?(href\\s*=\\s*\"(.*?)\")", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$
	public static final Pattern p_area_ref = Pattern
	.compile(
			"<area\\s+?(.*?)/?>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_link_ref_gen = Pattern
			.compile(
					"<(a|area)\\s+?([^>]*)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_link_type_picker = Pattern
			.compile(
					"\\s*class\\s*?=\\s*?(.*?)\\s+", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_link_guid_picker = Pattern
			.compile(
					"\\s*guid\\s*?=\\s*?(.*?)\\s+", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_link_href_picker = Pattern
			.compile(
					"\\s*href\\s*?=\\s*?\"(.*?)\"\\s+", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_tag_ref = Pattern
			.compile(
					"<([^>!]*)(\\n|\\r)([^>]*)>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_image_ref = Pattern
			.compile(
					"(<(img|iframe).*?src\\s*=\\s*\")(.*?)(\")", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_url_decoder = Pattern
			.compile(
					"(<[^>]*?(src|href)\\s*=\\s*\")(.*?)(\"[^>]*?>)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_tag_attributes = Pattern
	.compile(
			"([\\S&&[^=]]+)\\s*=\\s*([\\S&&[^\"]]+|\"([\\S &&[^\"]]+)\")", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	public static final Pattern p_css_ref = Pattern.compile(
			" url\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$

	// define constants for diagram type.
	// This will be used when linking diagrams into published contents
	// Activity diagram
	public static final String DIAGRAM_TYPE_WORKFLOW = "Activity"; //$NON-NLS-1$

	// activity detail diagram
	public static final String DIAGRAM_TYPE_ACTIVITY_DETAIL = "ActivityDetail"; //$NON-NLS-1$

	// WPDependency diagram
	public static final String DIAGRAM_TYPE_WP_DEPENDENCY = "WPDependency"; //$NON-NLS-1$

	private static ILibraryResourceManager defaultResourceMgr;
		
	private static boolean showSkinResource = false;
	
	public static String LAYOUT_XSL_ROOT_PATH = null;
	
	public ResourceHelper() {
	}

	public static synchronized void setDefaultResourceMgr(ILibraryResourceManager mgr) {
		defaultResourceMgr = mgr;
	}
	
	public static synchronized ILibraryResourceManager getDefaultResourceMgr() {
		return defaultResourceMgr;
	}
	
	public static ILibraryResourceManager getResourceMgr(MethodElement element) {
		MethodLibrary lib = UmaUtil.getMethodLibrary(element);
		if ( lib != null ) {
			ILibraryManager libMgr = LibraryService.getInstance().getLibraryManager(lib);
			if (libMgr == null) {
				lib = LibraryService.getInstance().getCurrentMethodLibrary();
				libMgr = LibraryService.getInstance().getLibraryManager(lib);
			}
			if (libMgr == null) {
				return getDefaultResourceMgr();
			}
			return libMgr.getResourceManager();
		}
		
		return null;
	}
	
	/**
	 * the relative path of the resource folder of the plugin in the library,
	 * relative to the library root
	 * 
	 * @param element
	 * @return String
	 */
	public static String getPluginResourcePath(MethodElement element) {
		ILibraryResourceManager resMgr = getResourceMgr(element);
		if ( resMgr != null ) {
			MethodPlugin plugin = UmaUtil.getMethodPlugin(element);
			if (plugin == null) {
				return resMgr.getLogicalResourcePath(element);
			} else {
				return resMgr.getLogicalResourcePath(plugin);
			}
		}
		
		return null;
	}

	/**
	 * get the relative path of the resource folder of the element in the
	 * library, relative to the library root
	 * 
	 * @param element MethodElement
	 * @return String
	 */
	public static String getElementResourcePath(MethodElement element) {
		ILibraryResourceManager resMgr = getResourceMgr(element);
		if ( resMgr != null ) {
			return resMgr.getLogicalResourcePath(element);
		}
		
		return null;
	}
	
	/**
	 * Gets the absolute path of the resource folder of the element in the library.
	 * 
	 * @param e
	 * @return absolute path of the element's resource folder
	 */
	public static String getAbsoluteElementResourcePath(MethodElement element) {
		ILibraryResourceManager resMgr = getResourceMgr(element);
		if ( resMgr != null ) {
			return resMgr.getPhysicalResourcePath(element);
		}
		
		return null;
	}

	/**
	 * get the relative path of the folder of the element in the library,
	 * relative to the library root
	 * 
	 * @param element MethodElement
	 * @return String
	 */
	public static String getElementPath(MethodElement element) {
//		try {
//			String path = MethodLibraryPersister.INSTANCE.getRelativeElementPath(element);
//			if (path == null || path.equals("")) //$NON-NLS-1$
//			{
//				System.out
//						.println("Warning! No Path for Element [" + element.getType().getName() + ": " + element.getName() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
//				return ""; //$NON-NLS-1$
//			}
//			return fixPath(path);
//		} catch (RuntimeException e) {
//			e.printStackTrace();
//		}
//
//		return ""; //$NON-NLS-1$
		ILibraryResourceManager resMgr = getResourceMgr(element);
		if ( resMgr != null ) {
			return resMgr.getLogicalPath(element);
		}
		
		return null;
	}
	
//	private static IFileBasedLibraryPersister getFileBasedLibraryPersister(MethodElement element) {
//		Resource resource = element.eResource();
//		if(resource != null) {
//			ILibraryPersister persister = LibraryServiceUtil.getPersisterFor(resource);
//			if(persister instanceof IFileBasedLibraryPersister) {
//				return ((IFileBasedLibraryPersister)persister);
//			}
//		}
//		return null;
//	}
//	
//	/**
//	 * Gets the path of a method element's folder relative to its plug-in.
//	 * 
//	 * @param element
//	 * @return
//	 * @deplicated 
//	 */
//	private static String getFolderRelativePath(MethodElement element) {
//		IFileBasedLibraryPersister persister = getFileBasedLibraryPersister(element);
//		return persister != null ? persister.getFolderRelativePath(element) : null;
//	}
	
	/**
	 * Gets the absolute path of a method element's folder.
	 * 
	 * @param element
	 * @return the absolute path
	 */
	public static String getFolderAbsolutePath(MethodElement element) {
//		if ( element == null ) {
//			return null;
//		}
//		
//		IFileBasedLibraryPersister persister = getFileBasedLibraryPersister(element);
//		return persister != null ? persister.getFolderAbsolutePath(element) : null;
		ILibraryResourceManager resMgr = getResourceMgr(element);
		if ( resMgr != null ) {
			return resMgr.getPhysicalPath(element);
		}
		
		return null;
	}

//	/**
//	 * return the parent folder of the plugin or configuration of the element.
//	 * or the library root if the element is the MethodLibrary.
//	 * 
//	 * @param element MethodElement
//	 * @return String
//	 */
//	public static String getVirtualLibraryRoot(MethodElement element) {
//		if ( element instanceof MethodLibrary ) {
//			// default, return the current library path
//			return LibraryService.getInstance().getCurrentMethodLibraryLocation();					
//		} 
//		
//		String path = null;
//		if (element instanceof MethodConfiguration ) {
//			path = getFolderAbsolutePath(element);
//		} else {
//			path = getPluginPath(element);
//		}
//		
//		if ( path != null ) {
//			File f = new File(path);
//			return f.getParentFile().getAbsolutePath();
//		}
//		
//		return null;
//	}
	
//	/**
//	 * fix the path by appending a File.seperator to the end of it
//	 * @param path String
//	 * @return String
//	 */
//	public static String fixPath(String path) {
//		if (path == null || path.equals("")) //$NON-NLS-1$
//		{
//			return ""; //$NON-NLS-1$
//		} else if (!path.endsWith(File.separator)) {
//			return path + File.separator;
//		} else {
//			return path;
//		}
//	}

	
	/**
	 * get the element's back path relative to the library root. For example,
	 * "OpenUP\guidance\concept\c1.xml", the back path is "./../../../"
	 * 
	 * @param element MethodElement
	 * @return String
	 */
	public static String getBackPath(MethodElement element) {
//		// Linux: Browsing and preview shows only plain text.
//		// There are no images/sections
//		// element path should check File.separatorChar instead of "\"
//		String backPath = ""; //$NON-NLS-1$
//		String path = getElementPath(element);
//		if (path != null && path.length() > 0) {
//			backPath = path.replace(File.separatorChar, '/').replaceAll(
//					".*?/", "\\.\\./"); //$NON-NLS-1$ //$NON-NLS-2$
//		}
//		return "./" + backPath; //$NON-NLS-1$
		
		ILibraryResourceManager resMgr = getResourceMgr(element);
		if ( resMgr != null ) {
			return resMgr.getBackPath(element);
		}
		
		return ""; //$NON-NLS-1$
	}

	/**
	 * get the file name with the given extension
	 * 
	 * @param element MethodElement
	 * @param ext String the file extenasion, for example, ".html"
	 * @return String
	 */
	public static String getFileName(MethodElement element, String ext) {
		return getFileName(element, null, null, ext);
	}

	/**
	 * get the file name with the given prefix and extension
	 * @param element MethodElement
	 * @param namePrefix String prefix for the name
	 * @param nameSuffix String suffix for the name
	 * @param ext String file extension, for example, ".html"
	 * @return String
	 */	 
	public static String getFileName(MethodElement element, String namePrefix,
			String nameSuffix, String ext) {		
		return FileNameGenerator.INSTANCE.getFileName(element, namePrefix, nameSuffix, ext);
	}

	/**
	 * get the guid from the file name, assuming the file name is generated from an element, 
	 * return null if not found.
	 * @param fileName String
	 * @return String
	 */
	public static String getGuidFromFileName(String fileName) {
		return FileNameGenerator.INSTANCE.getGuidFromFileName(fileName);
	}

	/**
	 * get the element from the file name, assuming the file name is generated from an element,
	 * return null if not.
	 * @param fileName String
	 * @return MethodElement
	 */
	public static MethodElement getElementFromFileName(String fileName) {
		String guid = getGuidFromFileName(fileName);
		if (guid != null) {
			ILibraryManager manager = LibraryService.getInstance()
					.getCurrentLibraryManager();
			if (manager != null) {
				return manager.getMethodElement(guid);
			}
		}

		return null;
	}

	/**
	 * get the element url relative to the refElement
	 * 
	 * @param element MethodElement
	 * @param refElement MethodElement
	 * @param fileExt String file extension
	 * @param old_url String the old url of the element. If the old url is not null, 
	 * any bookmark or url parameters are passed to the new url
	 * @return String String the new element
	 */
	public static String getUrl(MethodElement element,
			MethodElement refElement, String fileExt, String old_url) {
		String url = getUrl(element, refElement, fileExt);

		// if the old url has bookmark in it, keep it
		if (old_url != null) {
			int indx = old_url.indexOf(URL_BOOKMARK_INDICATOR);
			if (indx < 0) {
				// keep url query string as well
				indx = old_url.indexOf(URL_PARAMETER_INDICATOR);
			}

			if (indx >= 0) {
				url = url + old_url.substring(indx);
			}
		}

		return url;
	}

	/**
	 * get the element url relative to the refElement
	 * 
	 * @param element MethodElement
	 * @param refElement MethodElement
	 * @param fileExt String file extension
	 * @return String the url
	 */
	public static String getUrl(MethodElement element,
			MethodElement refElement, String fileExt) {
		if (element == null) {
			return ""; //$NON-NLS-1$
		}

		if (refElement == null) {
			return getElementPath(element).replace(File.separatorChar, '/')
					+ getFileName(element, fileExt);
		} else {
			return (getBackPath(refElement) + getElementPath(element)).replace(
					File.separatorChar, '/')
					+ getFileName(element, fileExt);
		}
	}

	/**
	 * get the link text for an element
	 * @param e MethodElement
	 * @param linkType String
	 * @return String
	 */
	public static String getLinkText(MethodElement e, String linkType) {
		String linkedText = null;
		
		// RTE may change the case of attributes.
		if ((linkType != null)
				&& !ELEMENT_LINK_CLASS_elementLinkWithUserText.equalsIgnoreCase(linkType)) {
			if (ELEMENT_LINK_CLASS_elementLinkWithType.equalsIgnoreCase(linkType)) {
				linkedText = getElementLinkText(e, true);
			} else if (ELEMENT_LINK_CLASS_elementLink.equalsIgnoreCase(linkType)) {
				linkedText = getElementLinkText(e, false);
			}
		}

		return linkedText;
	}

	/**
	 * get the element link text for the given element
	 * @param element MethodElement
	 * @param withType boolean if true the element type string will be included
	 * @return String
	 */
	public static String getElementLinkText(MethodElement element,
			boolean withType) {
		String text = TngUtil.getPresentationName(element);
//		if (withType) {
//			return getElementTypeText(element) + LibraryResources.colon_with_space + text; 
//		}
//
//		return text;
		if (withType) {
			if (showSkinResource) {
				String xslPath = null;

				if ((LAYOUT_XSL_ROOT_PATH == null)
						|| (LAYOUT_XSL_ROOT_PATH.equals(""))) {
					LAYOUT_XSL_ROOT_PATH = BrowsingLayoutSettings.INSTANCE.getXslPath()
							.getAbsolutePath();
				}
				Properties browsingResource = new Properties();
				File file = new File(LAYOUT_XSL_ROOT_PATH, "resources.properties"); //$NON-NLS-1$
				Locale locale = Locale.getDefault();
				String localFileName = I18nUtil.getLocalizedFile(file
						.getAbsolutePath(), locale);
				if (localFileName != null) {
					file = new File(localFileName);
				}
				if (file.exists()) {
					try {
						browsingResource.load(new FileInputStream(file));
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

				String type = getElementTypeText(element);
				String key = type.substring(0, 1).toLowerCase()
						+ type.substring(1) + "Text";
				String value = browsingResource.getProperty(key);
				if (value != null) {
					return value + LibraryResources.colon_with_space + text;
				} else {
					return type + LibraryResources.colon_with_space + text;
				}
			}
			else
			{
				return getElementTypeText(element) + LibraryResources.colon_with_space + text;
			}
			
		}
		
		return text;
	}

	/**
	 * gte the element type string
	 * @param element MethodElement
	 * @return String
	 */
	public static String getElementTypeText(MethodElement element) {
		if (element == null) {
			return ""; //$NON-NLS-1$
		}

		return TngUtil.getTypeText(element);
	}

	/**
	 * auto generated element link <a class="elementLink" href="element_url"
	 * guid="element_guid">element_type: element_presentation_name</a>
	 * 
	 * @param element
	 *            MethodElement
	 * @param withType
	 *            boolean
	 * @param url
	 *            String
	 * @return String
	 */
	public static String getElementLink(MethodElement element,
			boolean withType, String url) {
		String text = getElementLinkText(element, withType);
		String linkClass = ELEMENT_LINK_CLASS_elementLink;
		if (withType)
			linkClass = ELEMENT_LINK_CLASS_elementLinkWithType;
		return getElementLink(element, text, url, linkClass);
	}

	/**
	 * element link with user specified link text
	 * 
	 * @param element
	 * @param text
	 * @param url
	 * @return String
	 */
	public static String getElementLink(MethodElement element, String text,
			String url) {
		return getElementLink(element, text, url,
				ELEMENT_LINK_CLASS_elementLinkWithUserText);
	}

	/**
	 * element link with user specified link text
	 * 
	 * @param element
	 * @param text
	 * @param url
	 * @return String
	 */
	public static String getElementLink(MethodElement element, String text,
			String url, String linkClass) {
		return "<a class=\"" + linkClass + "\" " + getUrlText(url) + " guid=\"" + element.getGuid() + "\" >" + text + "</a>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
	}

	/**
	 * the passed in url might contain the href attribute with it, or even other
	 * attributes, so check if this is a pure url or not. return the url href
	 * term string
	 * 
	 * @param url
	 * @return
	 */
	private static String getUrlText(String url) {
		if (url == null) {
			url = ""; //$NON-NLS-1$
		} else {
			url = url.trim();
		}

		// starts with href, or contains an href term in it
		if (url.toLowerCase().startsWith("href") || url.toLowerCase().indexOf(" href") > 0) //$NON-NLS-1$ //$NON-NLS-2$
		{
			return url;
		}

		return "href=\"" + url + "\""; //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * validate the content by checking element links and images
	 * 
	 * @param element
	 * @param source
	 * @return String
	 */
	public static String validateContent(MethodElement element, String source) {
		return validateContent(element, source, new DefaultContentValidator(),
				null, null);
	}

	/**
	 * check if the link type is element link or not
	 * @param linkType String
	 * @return boolean
	 */
	public static boolean isElementLink(String linkType) {
		if (linkType == null || linkType.length() == 0) {
			return false;
		}

		// RTE may change the case of attributes.
		return linkType.equalsIgnoreCase(ELEMENT_LINK_CLASS_elementLink)
				|| linkType.equalsIgnoreCase(ELEMENT_LINK_CLASS_elementLinkWithType)
				|| linkType.equalsIgnoreCase(ELEMENT_LINK_CLASS_elementLinkWithUserText);
	}

	/**
	 * validate the content by checking element links and images, for the
	 * specified element owner
	 * 
	 * @param element
	 *            MethodElement, the element that owns the content
	 * @param content
	 * @param config
	 *            MethodConfiguration the configuration to which the content is
	 *            validated
	 * @param linkedElements
	 *            List a passed in list to collect the linked elements in this
	 *            content, if null, no linked elements are collected.
	 * @return String the validated content
	 */
	public static String validateContent(MethodElement element, String source,
			IContentValidator validator, MethodConfiguration config, String layoutXslRootPath) {
		
		try {
			ResourceHelper.LAYOUT_XSL_ROOT_PATH = layoutXslRootPath;
			showSkinResource = true;
			// first validate the tags, remove any CF/LF from the tag text
			source = validateTag(source);

			StringBuffer sb = new StringBuffer();
			Matcher m = p_link_ref.matcher(source);

			while (m.find()) {
				String text = m.group();

				// Problems parsing <a href> tags
				// need to remove all LF, CR within the <a ..> tag
				String urltext = m.group(1);
				String linkedText = m.group(2);
				LinkInfo info = validator.validateLink(element, urltext,
						linkedText, config, "a"); //$NON-NLS-1$
				if (info != null) {
					text = info.getHtml(validator.showBrokenLinks()).toString();
					MethodElement e = info.getLinkedElement();
					if (e != null) {
						validator.addReferencedElement(element, e);
					}
				}

				String replacement = text.replaceAll("file:///", ""); //$NON-NLS-1$ //$NON-NLS-2$
				replacement = replacement.replaceAll("file://", ""); //$NON-NLS-1$ //$NON-NLS-2$				
				m.appendReplacement(sb, regExpEscape(replacement));
			}

			m.appendTail(sb);

			if (element == null) {
				return sb.toString();
			}

			// also fix the area map
			source = sb.toString();
			m = p_area_ref.matcher(source);
			sb.setLength(0);
			while (m.find()) {
				String text = m.group();

				String urltext = m.group(1);
				LinkInfo info = validator.validateLink(element, urltext,
						"", config, "area");  //$NON-NLS-1$ //$NON-NLS-2$
				if (info != null) {
					
					// don't show broken links in area map. Show plan text instead
					text = info.getHtml(false/*validator.showBrokenLinks()*/).toString();
					MethodElement e = info.getLinkedElement();
					if (e != null) {
						validator.addReferencedElement(element, e);
					}
				}

				String replacement = text.replaceAll("file:///", ""); //$NON-NLS-1$ //$NON-NLS-2$
				replacement = replacement.replaceAll("file://", ""); //$NON-NLS-1$ //$NON-NLS-2$				
				m.appendReplacement(sb, regExpEscape(replacement));
			}

			m.appendTail(sb);

			// Shape icon broken in preview and browsing
			// // need to decode the image path unless we can disable the url
			// encoding in xslt
			// source = sb.toString();
			// sb.setLength(0);
			// m = ResourceHelper.p_image_ref.matcher(source);
			// while ( m.find() )
			// {
			// String url = m.group(3);
			// url = URLDecoder.decode(url, "UTF-8");
			// m.appendReplacement(sb, m.group(1) + url + m.group(4));
			// }
			// m.appendTail(sb);
			// return sb.toString();

			// decode the urls
			return decodeUrlsInContent(sb.toString());

		} catch (Exception ex) {
			ex.printStackTrace();
		}
		finally
		{
			ResourceHelper.LAYOUT_XSL_ROOT_PATH = null;
			showSkinResource = false;
		}

		return source;
	}

	/**
	 * decode the urls in the content. Content from xslt output are encoded. We
	 * don't want this to be encoded since the browser may decode it in a wrong
	 * encoding.
	 * 
	 * @param content
	 * @return String
	 */
	public static String decodeUrlsInContent(String content) {
		try {
			// Shape icon broken in preview and browsing
			// need to decode the image path unless we can disable the url
			// encoding in xslt
			StringBuffer sb = new StringBuffer();
			Matcher m = ResourceHelper.p_url_decoder.matcher(content);
			while (m.find()) {
				String url = m.group(3);
				url = URLDecoder.decode(url, "UTF-8"); //$NON-NLS-1$
				String text = m.group(1) + url + m.group(4);
				m.appendReplacement(sb, regExpEscape(text)); 	
			}
			m.appendTail(sb);

			return sb.toString();

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		return content;
	}

	/**
	 * escape the regexp reserved words, such as $
	 * @param text String
	 * @return String
	 */
	public static String regExpEscape(String text) {
		// escape the regExp reserved words,
		// the $ sign is reserved for group matching 
		String newtext = StrUtil.escapeChar(text, '$');
		newtext = StrUtil.escapeChar(text, '\\');
		return newtext;
	}
	
	/**
	 * fix the element url in the urltext. the text is the part from the
	 * p_link_ref pattern match
	 * 
	 * @param urltext
	 * @param config
	 *            MethodConfiguration the configuration to which the content is
	 *            validated
	 * @return String the fixed text
	 */
	public static String fixElementUrl(MethodElement element, String urltext,
			MethodConfiguration config) {
		Matcher m = p_link_href_picker.matcher(" " + urltext + " "); //$NON-NLS-1$ //$NON-NLS-2$
		StringBuffer sb = new StringBuffer();
		if (m.find()) {
			String url = m.group(1);
			String newurl = null;
			if (element != null) {
				String guid = getGuidFromUrl(urltext);
				if (guid != null) {
					ILibraryManager manager = LibraryService.getInstance()
							.getCurrentLibraryManager();
					MethodElement e = manager != null ? manager
							.getMethodElement(guid) : null;
					if (e != null) {
						if (config != null) {
							e = ConfigurationHelper.getCalculatedElement(e,
									config);
						}
						newurl = getUrl(e, element, FILE_EXT_HTML, url);
					}

					// if the element is null, we should remove the url link and
					// log an error
					// TODO
				}
			}

			if (newurl != null && !newurl.equals(url)) {
				String replacement = " href=\"" + newurl + "\" "; //$NON-NLS-1$ //$NON-NLS-2$
				m.appendReplacement(sb, regExpEscape(replacement));
				m.appendTail(sb);
				return sb.toString();

			}
		}

		return urltext;
	}

	/**
	 * get the element link type for the url
	 * @param source String the link
	 * @return String the type string
	 */
	public static String getElementLinkType(String source) {
		Matcher m = p_link_type_picker.matcher(" " + source + " "); //$NON-NLS-1$ //$NON-NLS-2$
		if (m.find()) {
			return m.group(1).trim().replaceAll("\"", ""); //$NON-NLS-1$ //$NON-NLS-2$
		}

		return null;
	}

	/**
	 * get the guid from the url
	 * @param source String the url
	 * @return Strign the guid
	 */
	public static String getGuidFromUrl(String source) {
		Matcher m = p_link_guid_picker.matcher(" " + source + " "); //$NON-NLS-1$ //$NON-NLS-2$
		if (m.find()) {
			return m.group(1).trim().replaceAll("\"", ""); //$NON-NLS-1$ //$NON-NLS-2$
		}

		m = p_link_href_picker.matcher(" " + source + " "); //$NON-NLS-1$ //$NON-NLS-2$
		if (m.find()) {
			String href = m.group(1).trim().replaceAll("\"", ""); //$NON-NLS-1$ //$NON-NLS-2$
			return getGuidFromFileName(href);
		}

		return null;
	}

	/**
	 * handle a bug in IE. anchor tag can't have CR LF, like <A \r\n
	 * href="www.yahoo.com" \r\n> scan the string source, find all anchor tags
	 * and replace with space.
	 * 
	 * @param source
	 * @return String the fixed source
	 */
	public static String validateTag(String source) {
		// Pattern p_anchor_ref = Pattern.compile("(*+?)=(*.?)",
		// Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

		StringBuffer sb = new StringBuffer();
		Matcher m = p_tag_ref.matcher(source);
		// StringBuffer tempSb = new StringBuffer();

		while (m.find()) {
			String text = m.group();
			String replacement = fixTagAttribute(text);
			m.appendReplacement(sb, regExpEscape(replacement));
		}

		m.appendTail(sb);

		return sb.toString();
	}

	/**
	 * fix tag attribute
	 * @param source
	 * @return String
	 */
	public static String fixTagAttribute(String source) {
		// simply replace all CR LF with ' ', fine tune later
		return source
				.replaceAll("\\\r\\\n", " ").replaceAll("\\\r", " ").replaceAll("\\\n", " "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
	}

//	/**
//	 * get the resource file url relative to the library root
//	 * 
//	 * @param e
//	 *            MethodElement the element that references this resource
//	 * @param file
//	 *            File the resource's physical path
//	 * @return String the url to this resource from the element
//	 * @deplicated this method is not valid for distributed library
//	 */
//	private static String getResourceFileUrl(MethodElement e, File file) {
//		String fileUrl = getFileUrl(file);
//		// String elementPath =
//		// ResourceHelper.getElementResourcePath(e).replace(File.separatorChar,
//		// '/');
//
//		fileUrl = ResourceHelper.getBackPath(e) + fileUrl;
//
//		return fileUrl;
//
//	}
//
//	/**
//	 * return the file's relative path to the plugin root
//	 * 
//	 * @param f
//	 * @return String
//	 * @deplicated this method is not valid for distributed library
//	 */
//	private static String getFileUrl(File f) {
//		String path = getFileRelPath(f);
//		path = path.replace(File.separatorChar, '/');
//		return path;
//	}

//	/**
//	 * get the URI relative to the specified base
//	 * 
//	 * @param uri
//	 * @return java.net.URI
//	 */
//	public static URI getRelativeURI(URI uri, String rootPath) {
//		return getRelativeURI(uri, new File(rootPath).toURI());
//	}

	/**
	 * get the URI relative to the specified base
	 * 
	 * @param uri
	 * @return java.net.URI
	 * @deplicated
	 */
	public static URI getRelativeURI(URI uri, URI relativeTo) {
		URI relUri = relativeTo.relativize(uri);
		return relUri;
	}

//	/**
//	 * resolve the relative path to the library root
//	 * 
//	 * @param f
//	 * @return String the raltive path
//	 * @deplicated this method is not valid for distributed library
//	 */
//	private static String getFileRelPath(File f) {
//		File libraryRootPath = new File(LibraryService.getInstance()
//				.getCurrentMethodLibraryLocation());
//		String root = libraryRootPath.getAbsolutePath();
//		String path = f.getAbsolutePath();
//		if (path.startsWith(root)) {
//			path = path.substring(root.length());
//		}
//
//		if (path.startsWith(File.separator)) {
//			path = path.substring(1);
//		}
//
//		return path;
//	}

//	/**
//	 * get the URI relative to the library root
//	 * 
//	 * @param f
//	 * @return java.net.URI
//	 * @deplicated this method is not valid for distributed library
//	 */
//	private static java.net.URI getFileRelativeURI(File f) {
//		File libraryRootPath = new File(LibraryService.getInstance()
//				.getCurrentMethodLibraryLocation());
//		java.net.URI libURI = libraryRootPath.toURI();
//		java.net.URI fileURI = f.toURI();
//		java.net.URI relUri = libURI.relativize(fileURI);
//
//		return relUri;
//	}



	/**
	 * 
	 * @param element
	 * @param attachment
	 * @return String
	 */
	public static String getRelativePathToFileFromElement(
			MethodElement element, File attachment) {
		String elementLoc = getFolderAbsolutePath(element);	
		return FileUtil.getRelativePath(attachment, new File(elementLoc));
	}

	/**
	 * get the file path name of the type of diagram for the specified element
	 * 
	 * @param e
	 * @param diagramType
	 *            String diagram type defined in one of the diagram type
	 *            constants
	 * @return String the file path relative to the library root
	 */
	public static String getDiagramFilePathName(MethodElement e,
			String diagramType) {
		// Instances of the same activity/CP share the
		// same diagram in a Delivery Process
		// need to make the name unique
//		return getElementResourcePath(e)
//				+ StrUtil.removeSpecialCharacters(e.getName())
//				+ "_" + e.getGuid() + "_" + diagramType + FILE_EXT_JPEG; //$NON-NLS-1$ //$NON-NLS-2$
		
		return getElementResourcePath(e)
		+ FileNameGenerator.INSTANCE.getFileName(e, "", "_" + diagramType, FILE_EXT_JPEG); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public static String getXmlExportedDiagramImageFileName(MethodElement e, String diagramType, String format) {
		String str = e.getName() + " " + e.getGuid() + "_" + diagramType + format; //$NON-NLS-1$ //$NON-NLS-2$
		return str;
	}
	
	public static boolean isAbsolutepath(String path) {
		
		if ( path == null ) {
			return false;
		}
		
		if ( 	path.startsWith("/")  //$NON-NLS-1$
				|| path.startsWith(File.separator) 
				|| path.indexOf(":") > 0 ) { //$NON-NLS-1$
			return true;
		}
		
		return false;
	}
	
	/**
	 * get the relative path of the file based on the url
	 * 
	 * @param url
	 *            String the url
	 * @param contentPath
	 *            String the path of the content that contains this url
	 * @return String the file path relative to the content publishing root
	 */
	public static String getFilePathFromUrl(String url, String contentPath) {

		String filePath = url;
		if (isExternalLink(filePath)
				|| filePath.startsWith("mailto:") || filePath.startsWith(URL_BOOKMARK_INDICATOR)) //$NON-NLS-1$ 
		{
			return null;
		}

		int index = filePath.indexOf(NetUtil.FILE_PREFIX_3);
		if (index == 0) {
			filePath = filePath.substring(NetUtil.FILE_PREFIX_3.length());
		}

		index = filePath.indexOf(NetUtil.FILE_PREFIX_2);
		if (index == 0) {
			filePath = filePath.substring(NetUtil.FILE_PREFIX_2.length());
		}
		
		if ( isAbsolutepath(filePath) ) {
			// assume this is an absolute path
			return XMLUtil.unescape(NetUtil.decodedFileUrl(filePath));
//			return url;
		}

		File f = new File(contentPath);
		
		int start = 0;
		index = 0;
		while ((f != null) && (index = filePath.indexOf("../", start)) >= 0) //$NON-NLS-1$
		{
			f = f.getParentFile();
			start = index + 3;
		}
		
		String rootFolder = ""; //$NON-NLS-1$
		if (f != null) {
			rootFolder = f.getPath();
		}

		if (rootFolder.length() > 0 && !rootFolder.endsWith(File.separator)) {
			rootFolder += File.separator;
		}

		// the file path is
		String path = rootFolder
				+ filePath.substring(start).replace('/', File.separatorChar);

		return XMLUtil.unescape(NetUtil.decodedFileUrl(path));
	}

	/**
	 * for the given content with url based on the oldContentPath, resolve to
	 * the path relative to the root of the contentPath. If backpath is
	 * specified, add the backPath. return the updated content. A typical
	 * scenario is the content is from a contributing element, which has urls
	 * relative to the contributing element's contentPath. This method will fix
	 * the url to based on the base element's contentPath.
	 * 
	 * So call fixContentUrlPath(contributor_text, contributor_elementPath,
	 * baseElement_backPath)
	 * 
	 * @param content
	 * @param contentPath
	 * @param oldContentPath
	 * @return String the updated content with fixed path.
	 */
	public static String fixContentUrlPath(String content, String contentPath,
			String backPath) {
		
		if ( contentPath == null || backPath == null ) {
			return content;
		}
		
		StringBuffer sb = new StringBuffer();
		try {
			// process images
			Matcher m = ResourceHelper.p_image_ref.matcher(content);
			while (m.find()) {
				String url = m.group(3);
				url = resolveUrl(url, contentPath, backPath);
				if (url != null) {
					m.appendReplacement(sb, regExpEscape(m.group(1) + url + m.group(4)));
				}
			}
			m.appendTail(sb);

			content = sb.toString();
			sb = new StringBuffer();
			
			// process attachments
			m = ResourceHelper.p_link_ref_gen.matcher(content);
			while (m.find()) {
				StringBuffer sbLink = new StringBuffer();
				// String tag = m.group(1);
				String urltext = " " + m.group(2) + " "; //$NON-NLS-1$ //$NON-NLS-2$
				
				if (ResourceHelper.getGuidFromUrl(urltext) == null) {
					Matcher m2 = ResourceHelper.p_link_href_picker
							.matcher(urltext);
					if (m2.find()) {
						String url = m2.group(1).trim().replaceAll("\"", ""); //$NON-NLS-1$ //$NON-NLS-2$

						if ( isExternalLink(url) ) {
							// decode for external link 
							url = XMLUtil.unescape(NetUtil.decodedFileUrl(url));
						} else {
							url = resolveUrl(url, contentPath, backPath);
						}
						if (url != null) {
							String replacement = urltext.substring(m2.start(), m2.start(1))
									+ url
									+ urltext.substring(m2.end(1), m2.end());
							
							m2.appendReplacement(sbLink, regExpEscape(replacement));
							m2.appendTail(sbLink);
							
							replacement = content.substring(m.start(), m.start(2))
									+ sbLink.toString() + content.substring(m.end(2), m.end());
							m.appendReplacement(sb, regExpEscape(replacement));
						}
					}
				}

			}
			m.appendTail(sb);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return sb.toString();
	}

	/**
	 * 
	 * @param url
	 * @param contentPath
	 * @param backPath
	 * @return String
	 */
	public static String resolveUrl(String url, String contentPath,
			String backPath) {
		String new_url = getFilePathFromUrl(url, contentPath);
		if (isAbsolutepath(new_url))
			return new_url;
		if (new_url != null && !new_url.equals(url) ) {
			if (backPath != null) {
				new_url = backPath + new_url;
			}

			return new_url.replace(File.separatorChar, '/');
		}

		return null;
	}

	private static final String EXTERNAL_URL_START_WITH = LayoutResources
			.getString("externalUrl_startWith"); //$NON-NLS-1$

	public static final Pattern p_external_url_startWith = Pattern
			.compile(
					"(" + EXTERNAL_URL_START_WITH + ")", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); //$NON-NLS-1$ //$NON-NLS-2$

	/**
	 * check if this is an external url or not
	 * @param url
	 * @return boolean
	 */
	public static boolean isExternalLink(String url) {
		// 162969 - Refine external link's regular exp in epf.library/layout/LayoutResources.properties
		// file:// should be excluded
		if ( url == null ) {
			return false;
		}
		
		url = url.toLowerCase();
		if ( url.startsWith("file://") ) {  //$NON-NLS-1$
			return false;
		}
		
		if ( url.startsWith("http://") 	//$NON-NLS-1$
				|| url.startsWith("https://") //$NON-NLS-1$
				|| url.startsWith("ftp://")  //$NON-NLS-1$
				|| url.startsWith("www.") ) { //$NON-NLS-1$
			return true;
		}
		
		Matcher m = p_external_url_startWith.matcher(url);
		if (m.find()) {
			return (m.start(1) == 0);
		}

		return false;
	}

	/**
	 * 
	 * @param url
	 * @return boolean
	 */
	public static boolean isJavascriptUrl(String url) {
		if (url == null ) {
			return false;
		}
		return url.startsWith(URL_STR_MAILTO)
				|| url.toLowerCase().startsWith(URL_STR_JAVASCRIPT);
	}
	
	/**
	 * find the resource file based on the url, copy the file to the destination
	 * folder. if the file is an html attachment, scan the file recursively and
	 * copy contained images, resources.
	 * 
	 * @param owner
	 *            MethodElement, the owner element
	 * @param resourceFile
	 *            File, the resource file
	 * @param url
	 *            String the url to be processed
	 * @param contentPath
	 *            String the content path of the url owner, relative to the
	 *            source root path
	 * @param sourceRootPath
	 *            File the source root path, usually it's the library root path
	 * @param targetRootPath
	 *            File the target root path, usually it's the publishing root
	 *            path
	 * @param rootContentPath String the content path of the root
	 * @param processedItems
	 *            List, a list to hold all processed urls, to avoid duplicate
	 *            processing
	 * @param validator
	 *            IContentValidator
	 * @return String the fixed url, not used.
	 */
	public static String processResourceUrl(MethodElement owner,
			File resourceFile, String url, String contentPath,
			File sourceRootPath, File targetRootPath, String rootContentPath, List processedItems,
			IContentValidator validator) {
		if (url == null || isExternalLink(url) || isJavascriptUrl(url)
				|| url.startsWith(URL_BOOKMARK_INDICATOR)) {
			return url;
		}
		
		// if the url contains the guid, it might be some kind of element link,
		// for example, activity can have model than one element link
		String guid = ""; //$NON-NLS-1$
		if (owner != null) {
			guid = owner.getGuid();
			if (url.indexOf(guid) >= 0 || isActivityTabUrl(url) ) {				
				return url;
			}			
		}
		
		// Publishing report lists missing resource files that
		// are present
		// bookmarks should be stripped out when checking resource
		int index = url.indexOf(URL_BOOKMARK_INDICATOR);
		if (index < 0) {
			index = url.indexOf(URL_PARAMETER_INDICATOR);
		}

		String url_tail = ""; //$NON-NLS-1$
		if (index > 0) {
			url_tail = url.substring(index);
			url = url.substring(0, index);
		}

		String imageFile = ResourceHelper.getFilePathFromUrl(url, contentPath);
		if (imageFile == null) {
			if (validator != null) {
				validator.logMissingResource(owner, resourceFile, url);
			}
			return null;
		}
			
		// index.htm is the default index file, always ignore it
		if (imageFile.equalsIgnoreCase("index.htm") || imageFile.equalsIgnoreCase("index.html")) //$NON-NLS-1$ //$NON-NLS-2$
		{
			return url + url_tail;
		}

		String newUrl = url;

		File source;
		File dest;
		
		// if the url is a local file in an absolute path, we don't copy the file, leave as is
		source = new File(imageFile);
		if ( source.exists() ) {
			return url + url_tail;
		}

		// if root Content path is set, remove from the file path
		boolean usePubRoot = true;
		String filePath = imageFile;
		if ( rootContentPath != null && rootContentPath.length() > 0 ) {
			if ( filePath.startsWith(rootContentPath) ) {
				filePath = filePath.substring(rootContentPath.length());
				usePubRoot = false;
			}
		}
		// check if this is a real file, if not, it is a reference to a base
		// plugin
		source = new File(sourceRootPath, filePath);
		
		// if the source does not exist, might be a reference to a resource in another plugin?
		// for example, if the content is contributed from another element in another plugin, this will happen
		if (!source.exists()) {
			ILibraryResourceManager mgr = getResourceMgr(owner);
			if ( mgr != null ) {
				String tmpPath = mgr.resolve(owner, filePath);
				if ( tmpPath != null ) {
					source = new File(tmpPath);
				}
			}
		}
		
		// if the file is not in the library, check the plugin layout folder
		if (!source.exists()) {
			source = new File(LibraryPlugin.getDefault().getLayoutPath(),
					filePath);
		}

		// if the filePath is relative to the pub root, fix the target path
		if ( usePubRoot && rootContentPath != null && rootContentPath.length() > 0 ) {
			File tmpf =  new File(rootContentPath);
			while ( tmpf != null ) {
				tmpf = tmpf.getParentFile();
				targetRootPath = targetRootPath.getParentFile();
			}
		}
		
		dest = new File(targetRootPath, filePath);

		if (source.exists()) {
			FileUtil.copyFile(source, dest);

			// if the file is an html attachment, need to scan the file and copy
			// the referenced file in it, recursively
			if (imageFile.endsWith(ResourceHelper.FILE_EXT_HTM)
					|| imageFile.endsWith(ResourceHelper.FILE_EXT_HTML)) {
				File f = new File(imageFile);
				try {
					resolveResources(owner, f, FileUtil.readFile(source,
							FileUtil.ENCODING_UTF_8).toString(), f.getParent(),
							sourceRootPath, targetRootPath, rootContentPath, processedItems,
							validator);
				} catch (Exception ex) {
					ex.printStackTrace();
				}
			}
		}
		// if the destination file is there, might be generated dynamically, so
		// don't log it
		else if (!dest.exists() && isValidFileUrl(url) && (validator != null)) {
			validator.logMissingResource(owner, resourceFile, url);
		}

		return newUrl + url_tail;

	}

	private static boolean isActivityTabUrl(String url) {
		return ActivityLayout.isActivityTabUrl(url);
	}
	
	private static boolean isValidFileUrl(String url) {
		// just a temp solution here to get rid of the wrong reporting of mssing
		// resource
		if (url == null || url.equals("' + diagram_img + '")) { //$NON-NLS-1$
			return false;
		}

		return true;
	}

	/**
	 * resolve the images in the text. copy the image to destination if needed
	 * This is used for copying resources from a library to another destination
	 * 
	 * @param owner
	 *            MethodElement, the owner element
	 * @param resourceFile
	 *            File, the resource file
	 * @param content
	 *            String the content string to be processed
	 * @param contentPath
	 *            String the content path of the source text, relative to the
	 *            source root path
	 * @param sourceRootPath
	 *            File the source root path, usually it's the library root path
	 * @param targetRootPath
	 *            File the target root path, usually it's the publishing root
	 *            path
	 * @param rootContentPath String the content path of the root
	 * @param processedItems
	 *            List, a list to hold all processed urls, to avoid duplicate
	 *            processing
	 * @param validator
	 *            IContentValidator
	 */
	public static void resolveResources(MethodElement owner, File resourceFile,
			String content, String contentPath, File sourceRootPath,
			File targetRootPath, String rootContentPath, List processedItems,
			IContentValidator validator) {
		try {
			// process images
			Matcher m = ResourceHelper.p_image_ref.matcher(content);
			while (m.find()) {
				String url = m.group(3);
				if (!processedItems.contains(url)) {
					// note: add the url into the processedItems list first,
					// otherwise may get deadlock if the url content has
					// reference back to the owner
					processedItems.add(url);
					ResourceHelper.processResourceUrl(owner, resourceFile, url,
							contentPath, sourceRootPath, targetRootPath, rootContentPath, 
							processedItems, validator);
				}
			}

			m = ResourceHelper.p_css_ref.matcher(content);
			while (m.find()) {
				String cssURL = m.group(1);

				// it's hard to tell if this is a right match or not
				// since we can't tell if the matched one is actually from a css
				// or just a html text
				// for example, text can have something like url(xxx) which is
				// matched here
				// we don't want to report missing resource for this
				// so don't set the validator
				// Publishing warnings: inappropriate warnings
				// coming from required copyrite.htm

				if (!processedItems.contains(cssURL)) {
					// note: add the url into the processedItems list first,
					// otherwise may get deadlock if the url content has
					// reference back to the owner
					processedItems.add(cssURL);
					ResourceHelper
							.processResourceUrl(owner, resourceFile, cssURL,
									contentPath, sourceRootPath,
									targetRootPath, rootContentPath, processedItems, null/* validator */);
				}
			}

			// process attachments
			m = ResourceHelper.p_link_ref_gen.matcher(content);
			while (m.find()) {
				// String tag = m.group(1);
				String urltext = m.group(2);
				if (ResourceHelper.getGuidFromUrl(urltext) == null) {
					Matcher m2 = ResourceHelper.p_link_href_picker
							.matcher(" " + urltext + " "); //$NON-NLS-1$ //$NON-NLS-2$
					if (m2.find()) {
						String url = m2.group(1).trim().replaceAll("\"", ""); //$NON-NLS-1$ //$NON-NLS-2$
						if (!processedItems.contains(url)) {
							// note: add the url into the processedItems list
							// first, otherwise may get deadlock if the url
							// content has reference back to the owner
							processedItems.add(url);
							ResourceHelper.processResourceUrl(owner,
									resourceFile, url, contentPath,
									sourceRootPath, targetRootPath, rootContentPath, 
									processedItems, validator);
						}
					}
				}
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * take the tag attributes string as input and returns the attribute
	 * name-value map
	 * 
	 * @param attributesStr
	 * @return Map the attribute name-value map
	 */
	public static Map getTagAttributes(String attributesStr) {
		try {
			// use LinkedHashMap to reserve the order of the attributes
			Map attributeMap = new LinkedHashMap(3);
			Matcher m2 = p_tag_attributes.matcher(attributesStr);

			while (m2.find()) {
				String attrName = m2.group(1).trim().toLowerCase();
				String attrValue = ""; //$NON-NLS-1$
				if (m2.group(3) != null) {
					attrValue = m2.group(3).trim();
				} else if (m2.group(2) != null) {
					attrValue = m2.group(2).trim();
				}				
		
				// Cannot Preview/Browse Description Tab when
				// the CP contains chinese characters
				// generated html from xslt got the href urls encoded. we don't want
				// that make sure decode the url using "UTF-8" encoding
				if (attrName.equals(TAG_ATTR_HREF)) {
					try {
						attrValue = URLDecoder.decode(attrValue, "UTF-8"); //$NON-NLS-1$
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}					
				}
				attributeMap.put(attrName, attrValue);
			}
			return attributeMap;
		} catch (Exception e) {			
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * returns the attribute name-value map for an HTML link
	 * 
	 * @param link
	 * @return Map
	 */
	public static Map getAttributesFromLink(String link) {
		Matcher m = p_link_ref.matcher(link);
		if (m.find()) {
			String attributes = m.group(1);
			return getTagAttributes(attributes);
		}
		return null;
	}

	/**
	 * returns the attribute name-value map for an HTML link
	 * 
	 * @param link
	 * @return Map
	 */
	public static Map getAttributesFromLink(Pattern pattern, String link) {
		Matcher m = pattern.matcher(link);
		if (m.find()) {
			String attributes = m.group(1);
			return getTagAttributes(attributes);
		}
		return null;
	}
	
	/**
	 * takes an attributeMap (ie, from #getTagAttributes) and returns the String
	 * representation
	 * 
	 * @param attributeMap
	 * @return String
	 */
	public static String getAttributesAsString(Map attributeMap) {
		StringBuffer buf = new StringBuffer();
		for (Iterator iter = attributeMap.keySet().iterator(); iter.hasNext();) {
			String key = (String) iter.next();
			String value = (String) attributeMap.get(key);
			if (buf.length() > 0)
				buf.append(" "); //$NON-NLS-1$
			buf.append(key + "=\"" + value + "\""); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return buf.toString();
	}

	/**
	 * Bad link from Welcome page hump chart
	 * 
	 */
	private static String getDiscardedElementURL(MethodElement ownerElement,
			MethodElement linkElement, String guid, String pubDir) {
		StringBuffer discardedElementURL = new StringBuffer();

		discardedElementURL.append(MISSING_PAGES_FOLDER).append(
				"pages_not_installed").append(FILE_EXT_HTML); //$NON-NLS-1$

		File outputFile = new File(pubDir, discardedElementURL.toString());
		File dir = outputFile.getParentFile();
		if (!dir.exists()) {
			dir.mkdirs();
		}

		// generate the html file
		XmlElement xml = new XmlElement("Element"); //$NON-NLS-1$

		xml
				.setAttribute("guid", guid).setAttribute("type", linkElement.getType().getName()) //$NON-NLS-1$ //$NON-NLS-2$
				.setAttribute("name", linkElement.getName()) //$NON-NLS-1$
				.setAttribute(
						"pluginName", LibraryUtil.getMethodPlugin(linkElement).getName()); //$NON-NLS-1$								
		String xslPath = LayoutResources.getDefaultXslPath("page_not_installed", null); //$NON-NLS-1$

		try {
			StringBuffer xml2 = new StringBuffer();
			xml2.append(XmlHelper.XML_HEADER).append(xml.toXml());

			OutputStreamWriter output = new OutputStreamWriter(
					new FileOutputStream(outputFile), "utf-8"); //$NON-NLS-1$
			Properties xslParams = LibraryPlugin.getDefault().getProperties(
					"/layout/xsl/resources.properties"); //$NON-NLS-1$

			XSLTProcessor
					.transform(xslPath, xml2.toString(), xslParams, output);
			output.flush();
			output.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return getBackPath(ownerElement).replace(File.separatorChar, '/')
				+ discardedElementURL.toString();
	}
	
	
	
	/**
	 * FOR USE WITH RICH TEXT EDITOR
	 * validate the content by checking element links and images, for the
	 * specified element owner
	 * 
	 * This is identical to the validateContent method, except it does not decode the results
	 * via URLDecoder.decode()
	 * 
	 *  this will do the following to the HTML:
	 *  1.  update Element Links
	 *  2.  change <A ..> to <a ..>
	 *  3.  change </A> to </a>
	 *  4.  add double-quotes (") around all attribute values if they are missing
	 * 
	 * @param element
	 *            MethodElement, the element that owns the content
	 * @param content
	 * @param config
	 *            MethodConfiguration the configuration to which the content is
	 *            validated
	 * @param linkedElements
	 *            List a passed in list to collect the linked elements in this
	 *            content, if null, no linked elements are collected.
	 * @return String the validated content
	 */
	public static String validateRichTextContent(MethodElement element, String source, IContentValidator validator) {
 		try {
			MethodConfiguration config = null;
			
			// first validate the tags, remove any CF/LF from the tag text
			source = validateTag(source);

			StringBuffer sb = new StringBuffer();
			Matcher m = p_link_ref.matcher(source);

			while (m.find()) {
				String text = m.group();

				// Problems parsing <a href> tags
				// need to remove all LF, CR within the <a ..> tag
				String urltext = m.group(1);
				String linkedText = m.group(2);
				LinkInfo info = validator.validateLink(element, urltext,
						linkedText, config, "a"); //$NON-NLS-1$
				if (info != null) {
					text = info.getHtml(validator.showBrokenLinks()).toString();
					MethodElement e = info.getLinkedElement();
					if (e != null) {
						validator.addReferencedElement(element, e);
					}
				}

				String replacement = text.replaceAll("file:///", ""); //$NON-NLS-1$ //$NON-NLS-2$
				replacement = replacement.replaceAll("file://", ""); //$NON-NLS-1$ //$NON-NLS-2$
				m.appendReplacement(sb, regExpEscape(replacement));
			}

			m.appendTail(sb);

			if (element == null) {
				return sb.toString();
			}

			// also fix the area map
			source = sb.toString();
			m = p_area_ref.matcher(source);
			sb.setLength(0);

			while (m.find()) {
				String text = m.group();

				// Problems parsing <a href> tags
				// need to remove all LF, CR within the <a ..> tag
				String urltext = m.group(1);
				LinkInfo info = validator.validateLink(element, urltext,
						"", config, "area"); //$NON-NLS-1$ //$NON-NLS-2$
				if (info != null) {
					text = info.getHtml(validator.showBrokenLinks()).toString();
					MethodElement e = info.getLinkedElement();
					if (e != null) {
						validator.addReferencedElement(element, e);
					}
				}

				String replacement = text.replaceAll("file:///", ""); //$NON-NLS-1$ //$NON-NLS-2$
				replacement = replacement.replaceAll("file://", ""); //$NON-NLS-1$ //$NON-NLS-2$
				m.appendReplacement(sb, regExpEscape(replacement));
			}

			m.appendTail(sb);

			return sb.toString();

		} catch (Exception ex) {
			LibraryPlugin.getDefault().getLogger().logError(ex);
		}

		return source;
	}

//	/**
//	 * copy all resource files associated with the element to the target location.
//	 * recursive all it's contained elements if recursive is true.
//	 * 
//	 * @param element
//	 * @param from
//	 * @param to
//	 */
//	public static void copyAllResources(MethodElement element, File from, File to, boolean recursive) {
//		
//		ContentResourceScanner scanner = new ContentResourceScanner(from, to, );
//		scanner.setTargetRootPath(to);
//		scanner.copyResources(element);
//		
//		if ( recursive ) {
//			for ( Iterator it = element.eAllContents(); it.hasNext(); ) {
//				Object obj = it.next();
//				if ( obj instanceof MethodElement ) {
//					scanner.copyResources((MethodElement)obj);
//				}
//			}
//		}
//	}
	
	public static String getPluginPath(MethodElement e) {		
		MethodPlugin plugin = UmaUtil.getMethodPlugin(e);
		return getFolderAbsolutePath(plugin);
	}

	public static String getPluginPath(MethodPlugin plugin) {
		return getFolderAbsolutePath(plugin);
	}
	

	
}
