//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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.layout;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import org.eclipse.epf.common.utils.NetUtil;
import org.eclipse.epf.common.xml.XSLTProcessor;
import org.eclipse.epf.library.ILibraryManager;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.configuration.ConfigurationHelper;
import org.eclipse.epf.library.edit.util.MethodElementPropUtil;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.layout.util.XmlHelper;
import org.eclipse.epf.library.persistence.ILibraryResourceSet;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.publish.layout.LayoutPlugin;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodLibrary;
import org.eclipse.epf.uma.MethodPackage;
import org.eclipse.epf.uma.ProcessComponent;
/**
* class to process an element link in the content
*
* @author Jinhua Xi
* @since 1.0
*/
public class LinkInfo {
public static final String LINK_ATTR_CLASS = "class"; //$NON-NLS-1$
public static final String LINK_ATTR_GUID = "guid"; //$NON-NLS-1$
public static final String LINK_ATTR_HREF = "href"; //$NON-NLS-1$
public static final String LINK_ATTR_KEY = "key"; //$NON-NLS-1$
public static final String LINK_ATTR_TEXT = "text"; //$NON-NLS-1$
public static final String LINK_ATTR_NAME = "name"; //$NON-NLS-1$
private String linkedText = ""; //$NON-NLS-1$
private MethodElement linkElement = null;
private MethodElement ownerElement = null;
private boolean isMissingReference = false;
private Map<String, String> attributeMap = new LinkedHashMap<String, String>();
private IContentValidator validator;
private String pubDir;
private String tag;
//Temp solution for getting around without having a libMgr during migration
//Should be removed when lib loaded during migration is registed with Lib service.
private static MethodLibrary library;
/**
* constructor
*
* @param owner
* @param validator
* @param pubDir
*/
public LinkInfo(MethodElement owner, IContentValidator validator,
String pubDir, String tag) {
this.ownerElement = owner;
this.validator = validator;
this.pubDir = pubDir;
this.tag = tag;
}
/**
* is this an element link?
* @return boolean
*/
public boolean isElementLink() {
return ResourceHelper.isElementLink(getElementLinkType());
}
/**
* get the element link type
* @return String
*/
public String getElementLinkType() {
return getAttribute(LINK_ATTR_CLASS);
}
/**
* get the guid of the element link
* @return String
*/
public String getGuid() {
return getAttribute(LINK_ATTR_GUID);
}
/**
* get the url of the link
* @return String
*/
public String getUrl() {
return getAttribute(LINK_ATTR_HREF);
}
/**
* get the linked text
* @return String
*/
public String getLinkedText() {
return linkedText;
}
/**
* get the linked element
* @return MethodElement
*/
public MethodElement getLinkedElement() {
return linkElement;
}
/**
* get the html for the link.
*
* @param showBrokenLinks boolean true to show the broken link mark. false to show text only
* @return StringBuffer
*/
public StringBuffer getHtml(boolean showBrokenLinks) {
StringBuffer buffer = new StringBuffer();
if (isMissingReference && (pubDir != null)) {
String url = ""; //$NON-NLS-1$
if (!showBrokenLinks) {
buffer.append(linkedText);
return buffer;
}
url = getMissingElementUrl();
buffer
.append("<img alt=\"\" src=\"" + ResourceHelper.getBackPath(ownerElement) + "images/no_rup.gif\"> "); //$NON-NLS-1$ //$NON-NLS-2$
setUrl(url);
}
buffer.append("<" + tag); //$NON-NLS-1$
for (Iterator<Map.Entry<String, String>> it = attributeMap.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, String> entry = it.next();
String key = entry.getKey();
String value = entry.getValue();
if (LINK_ATTR_HREF.equals(key)
&& (value == null || value.length() == 0)) {
continue;
}
buffer.append(" ") //$NON-NLS-1$
.append(entry.getKey()).append("=") //$NON-NLS-1$
.append("\"").append(entry.getValue()).append("\""); //$NON-NLS-1$ //$NON-NLS-2$
}
buffer.append(">").append(linkedText).append("</" + tag + ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return buffer;
}
/**
* validate the link attributes
* @param attributes String the link attributes
* @param text String the linked text
* @param config MethodConfiguration
*/
public void validateLink(String attributes, String text,
MethodConfiguration config) {
this.linkedText = text;
Matcher m2 = ResourceHelper.p_tag_attributes.matcher(attributes);
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();
}
/*
* if (attrValue.startsWith("\"")) { attrValue =
* attrValue.substring(1); } if (attrValue.endsWith("\"")) {
* attrValue = attrValue.substring(0, attrValue.length() - 1); }
*/
// GVT: 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(LINK_ATTR_HREF)) {
try {
attrValue = decode(attrValue);
} catch (Exception e) {
e.printStackTrace();
}
}
attributeMap.put(attrName, attrValue);
}
String guid = getGuid();
if (guid == null) {
// check if the file contains guid, if yes, need to get the element
String url = getUrl();
guid = ResourceHelper.getGuidFromFileName(url);
if (guid != null) {
setGuid(guid);
}
}
validateElementUrl(config);
}
protected String decode(String str) throws UnsupportedEncodingException {
if (NetUtil.isRawUrl(str)) {
return str;
}
return URLDecoder.decode(str, "UTF-8"); //$NON-NLS-1$
}
/**
* get attribute
* @param name
* @return String
*/
private String getAttribute(String name) {
return (String) attributeMap.get(name);
}
/**
* set guid
* @param guid String
*/
private void setGuid(String guid) {
attributeMap.put(LINK_ATTR_GUID, guid);
}
public void setUrl(String url) {
attributeMap.put(LINK_ATTR_HREF, url);
}
private void validateElementUrl(MethodConfiguration config) {
String guid = getGuid();
if (guid != null) {
MethodElement e = null;
e = getMethodElement(guid);
// if process component, get show the process
if (e instanceof ProcessComponent) {
e = ((ProcessComponent) e).getProcess();
}
// 156474 - Process Package (either CP package or DP package) can
// not be linked in RTE
// don't show link for packages.
if (e instanceof MethodPackage || e instanceof MethodConfiguration
|| e instanceof MethodLibrary) {
e = null;
// remove the link atytribute
setUrl(null);
return;
}
if (e != null) {
if (config != null) {
MethodElement e1 = ConfigurationHelper
.getCalculatedElement(e, config);
if (e1 != null) {
if (! validator.showBrokenLinks() && validator.isDiscarded(ownerElement, null, e1)) {
isMissingReference = true;
validator.logMissingReference(ownerElement, e1);
} else {
e = e1;
}
} else {
isMissingReference = true;
validator.logMissingReference(ownerElement, e);
}
}
} else {
boolean toLog = true;
if (ownerElement instanceof CustomCategory) {
if (MethodElementPropUtil.getMethodElementPropUtil().isTransientElement(ownerElement)) {
toLog = false;
}
}
if (toLog) {
isMissingReference = true;
validator.logMissingReference(ownerElement, guid, linkedText);
}
}
if (e != null) {
guid = e.getGuid();
setGuid(guid);
String url = getUrl();
// url can be null, for example, an element link for
// presentation name, such as
// <a class="PresentationName"
// guid="{EE97A8CD-66CA-4A9B-9871-E3B94CCED528}">Project
// Manager</a>
// we only need to get the element from the guid
if (url != null) {
url = url.trim();
if (!url.toLowerCase().startsWith(
ResourceHelper.URL_STR_JAVASCRIPT)) {
url = ResourceHelper.getUrl(e, ownerElement,
ResourceHelper.FILE_EXT_HTML, url);
setUrl(url);
}
}
if (isElementLink() && !tag.equals("area")) { //$NON-NLS-1$
String text = ResourceHelper.getLinkText(e,
getElementLinkType(), config);
if (text != null) {
// if null, can be used text, don't reset it
this.linkedText = text;
}
}
if (validator.isDiscarded(ownerElement, IContentValidator.elementUrlFeature, e, config)) {
isMissingReference = true;
validator.logMissingReference(ownerElement, e);
e = null; // ignore the element since it's discarded
}
}
this.linkElement = e;
}
}
public static MethodElement getMethodElement(String guid) {
MethodElement e;
ILibraryManager manager = LibraryService.getInstance()
.getCurrentLibraryManager();
if (manager != null && getLibrary() == null) {
e = manager.getMethodElement(guid);
} else {
e = getMethodElement_(guid);
if (e == null && manager != null) {
e = manager.getMethodElement(guid);
}
}
return e;
}
// private static final String MISSING_PAGES_XSL = "pages_not_installed/";
// //$NON-NLS-1$
private String getMissingElementUrl() {
if (!isMissingReference) {
return ""; //$NON-NLS-1$
}
String url = null;
// if (linkElement == null) {
// // this is an invalid element, maybe deleted from the library
// // already
// url = ResourceHelper.MISSING_PAGES_FOLDER + getGuid()
// + ResourceHelper.FILE_EXT_HTML;
// } else {
// url = ResourceHelper.MISSING_PAGES_FOLDER
// + ResourceHelper.getFileName(linkElement,
// ResourceHelper.FILE_EXT_HTML);
// }
url = ResourceHelper.MISSING_PAGES_FOLDER + "pages_not_installed" //$NON-NLS-1$
+ ResourceHelper.FILE_EXT_HTML;
File f = new File(pubDir, url);
File dir = f.getParentFile();
if (!dir.exists()) {
dir.mkdirs();
}
// if ( !f.exists() )
{
// generate the html file
XmlElement xml = new XmlElement("Element"); //$NON-NLS-1$
Locale locale = Locale.getDefault();
String lang = locale.getLanguage();
xml.setAttribute("lang", lang); //$NON-NLS-1$
if (linkElement == null) {
xml.setAttribute("invalidLink", "true") //$NON-NLS-1$ //$NON-NLS-2$
.setAttribute("guid", getGuid()) //$NON-NLS-1$
.setAttribute("name", linkedText); //$NON-NLS-1$
} else {
xml
.setAttribute("guid", getGuid()) //$NON-NLS-1$
.setAttribute("type", linkElement.getType().getName()) //$NON-NLS-1$
.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$
saveHtml(xml, xslPath, f);
}
return ResourceHelper.getBackPath(ownerElement).replace(
File.separatorChar, '/')
+ url;
}
/**
* save a html file
* @param xmlElement
* @param xsl_uri
* @param outputFile
* @deprecated this method id not used any more
*/
public void saveHtml(XmlElement xmlElement, String xsl_uri, File outputFile) {
try {
StringBuffer xml = new StringBuffer();
xml.append(XmlHelper.XML_HEADER).append(xmlElement.toXml());
OutputStreamWriter output = new OutputStreamWriter(
new FileOutputStream(outputFile), "utf-8"); //$NON-NLS-1$
Properties xslParams = LayoutPlugin.getDefault().getProperties(
"/layout/xsl/resources.properties"); //$NON-NLS-1$
XSLTProcessor.transform(xsl_uri, xml.toString(), xslParams, output);
output.flush();
output.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static MethodElement getMethodElement_(String guid) {
try {
if (getLibrary() == null) {
return null;
}
ILibraryResourceSet resourceSet = (ILibraryResourceSet) getLibrary()
.eResource().getResourceSet();
if (resourceSet != null) {
return (MethodElement) resourceSet.getEObject(guid);
}
} catch (Throwable th) {
// Log error here
th.printStackTrace();
}
return null;
}
public static MethodLibrary getLibrary() {
return library;
}
public static void setLibrary(MethodLibrary library) {
LinkInfo.library = library;
}
}