//------------------------------------------------------------------------------
// 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.VariabilityElement;
import org.eclipse.epf.uma.VariabilityType;
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, MethodConfiguration config) {
		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, config);
			} else if (ELEMENT_LINK_CLASS_elementLink.equalsIgnoreCase(linkType)) {
				linkedText = getElementLinkText(e, false, config);
			}
		}

		return linkedText;
	}
	
	public static String getLinkText(MethodElement e, String linkType) {
		return getLinkText(e, linkType, null);
	}

	/**
	 * 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) {
		return getElementLinkText(element, withType, null);
	}
	
	public static String getElementLinkText(MethodElement element,
			boolean withType, final MethodConfiguration config) {
		
		TngUtil.PresentationNameHelper pHelper = config == null ? null : 
								new TngUtil.PresentationNameHelper() {
			
			public String getPresentationName(MethodElement element) {
				if (element == null) {
					return null;
				}
				String str = super.getPresentationName(element);
				if (StrUtil.isBlank(str) && element instanceof VariabilityElement) {
					VariabilityElement ve = (VariabilityElement) element;
					if (ve.getVariabilityType() == VariabilityType.EXTENDS_REPLACES) {
						VariabilityElement base = ve.getVariabilityBasedOnElement();
						String baseStr = base == null ? null : base.getPresentationName();
						if (! StrUtil.isBlank(baseStr)) {
							return baseStr;
						}
					}					
				}
				return str;
			}
			
		};
		
		String text = TngUtil.getPresentationName(element, pHelper);
//		if (withType) {
		
//			return getElementTypeText(element) + LibraryResources.colon_with_space + text; 
//		}
//
//		return text;
		if (withType) {
			if (showSkinResource) {
				if ((LAYOUT_XSL_ROOT_PATH == null)
						|| (LAYOUT_XSL_ROOT_PATH.equals(""))) {//$NON-NLS-1$
					File xslPath = BrowsingLayoutSettings.INSTANCE.getXslPath();
					if (xslPath != null) 
						LAYOUT_XSL_ROOT_PATH = xslPath.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 elementName = element.eClass().getName();
				String key = elementName.substring(0, 1).toLowerCase()
						+ elementName.substring(1) + "Text";//$NON-NLS-1$
				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(newtext, '$');
		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);
	}
	

	
}
