/*******************************************************************************
* Copyright (c) 2007-2011 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.text.ext.hyperlink;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.jboss.tools.common.text.ext.ExtensionsPlugin;
import org.jboss.tools.common.text.ext.util.xpl.RegistryReader;
/**
* @author Igels
*/
public class HyperlinkPartitionerBuilder extends RegistryReader {
public static final String PL_HYPERLINK_PARTITIONER = "hyperlinkPartitioner"; //$NON-NLS-1$
public static final String PLUGIN_ID = ExtensionsPlugin.PLUGIN_ID;
public static final String TAG_HYPERLINK_PARTITIONER = "hyperlinkPartitioner"; //$NON-NLS-1$
public static final String TAG_CONTENT_TYPE_SYNONYM = "contentTypeSynonym"; //$NON-NLS-1$
public static final String TAG_CONTENT_TYPE = "contentType"; //$NON-NLS-1$
public static final String TAG_PARTITION_TYPE = "partitionType"; //$NON-NLS-1$
public static final String TAG_AXIS = "axis"; //$NON-NLS-1$
public static final String ATT_ID = "id"; //$NON-NLS-1$
public static final String ATT_TYPE = "type"; //$NON-NLS-1$
public static final String ATT_BASE = "base"; //$NON-NLS-1$
public static final String ATT_CLASS = "class"; //$NON-NLS-1$
public static final String ATT_PATH = "path"; //$NON-NLS-1$
public static final String ATT_IGNORE_CASE = "ignoreCase"; //$NON-NLS-1$
private static HyperlinkPartitionerBuilder fInstance;
private ArrayList fPartitionerDefs;
private HyperlinkPartitionerDefinition fCurrentHyperlinkPartitionerDefinition = null;
private String fCurrentContentType;
private String fCurrentPartitionType;
protected String targetContributionTag;
private Map<String, String> fContentTypeSynonyms =
new HashMap<String, String>();
/**
* returns singleton instance of HyperlinkPartitionerBuilder
*
* @return HyperlinkPartitionerBuilder
*/
public synchronized static HyperlinkPartitionerBuilder getInstance() {
if (fInstance == null) {
fInstance = new HyperlinkPartitionerBuilder();
}
return fInstance;
}
private HyperlinkPartitionerBuilder() {
super();
}
/* (non-Javadoc)
* @see com.ibm.sse.editor.internal.extension.RegistryReader#readElement(org.eclipse.core.runtime.IConfigurationElement)
*/
protected boolean readElement(IConfigurationElement element) {
String tag = element.getName();
if(tag.equals(targetContributionTag)) {
processHyperlinkPartitionerTag(element);
// make sure processing of current partition tag resulted in a current partition definition
// before continue reading the children
if (fCurrentHyperlinkPartitionerDefinition != null) {
readElementChildren(element);
}
return true;
} else if(tag.equals(TAG_CONTENT_TYPE_SYNONYM)) {
processContentTypeSynonymTag(element);
return true;
} else if(tag.equals(TAG_CONTENT_TYPE)) {
processContentTypeTag(element);
// make sure processing of current content type resulted in a valid content type
// before reading the children
if (fCurrentContentType != null) {
readElementChildren(element);
}
return true;
} else if(tag.equals(TAG_PARTITION_TYPE)) {
processPartitionTypeTag(element);
// make sure processing of current partition type resulted in a valid partition type
// before reading the children
if (fCurrentPartitionType != null) {
readElementChildren(element);
}
return true;
} else if(tag.equals(TAG_AXIS)) {
processAxisTag(element);
return true;
}
return false;
}
/**
* Processes element which should be a configuration element specifying an
* open on object. Creates a new open on partitioner definition object and
* adds it to the list of open on partitioner definition objects
*
* @param element hyperlink partitioner configuration element
*/
private void processHyperlinkPartitionerTag(IConfigurationElement element) {
String theId = getId(element);
String theClass = getHyperlinkPartitionerClass(element);
if(theId != null && theClass != null) {
// start building new HyperlinkPartitionerDefinition
fCurrentHyperlinkPartitionerDefinition = new HyperlinkPartitionerDefinition(theId, theClass, element);
// create a new list of open on partitioner definitions if it hasn't been created yet
if (fPartitionerDefs == null) {
fPartitionerDefs = new ArrayList();
}
fPartitionerDefs.add(fCurrentHyperlinkPartitionerDefinition);
} else {
fCurrentHyperlinkPartitionerDefinition = null;
}
}
/**
* Processes element which should be a configuration element specifying an
* open on object. Creates a new content type synonym object and
* adds it to the list of content type synonym objects
*
* @param element hyperlink partitioner configuration element
*/
private void processContentTypeSynonymTag(IConfigurationElement element) {
String theType = getType(element);
String theBase = getBase(element);
if(theType != null && theBase != null) {
// add new Content Type Synonym to the map
fContentTypeSynonyms.put(theType.trim(), theBase.trim());
}
}
/**
* Processes element which should be a configuration element specifying a content
* type for the current open on partitioner tag. Assumes that there is a valid current open
* on partitioner definition object.
*
* @param element contentType configuration element
*/
private void processContentTypeTag(IConfigurationElement element) {
// add to current hyperlinkDefinition
String theId = getId(element);
if (theId != null) {
fCurrentContentType = theId;
fCurrentHyperlinkPartitionerDefinition.addContentTypeId(fCurrentContentType);
} else {
fCurrentContentType = null;
}
}
/**
* Processes element which should be a configuration element specifying a partition
* type for the current open on partitioner/content type tag. Assumes that there is a valid
* current open on partitioner/content type tag.
*
* @param element partitionType configuration element
*/
private void processPartitionTypeTag(IConfigurationElement element) {
// add to current hyperlinkPartitionerDefinition/contentType
String theId = getId(element);
if (theId != null) {
fCurrentPartitionType = theId;
fCurrentHyperlinkPartitionerDefinition.addPartitionType(fCurrentContentType, theId);
} else {
fCurrentPartitionType = null;
}
}
/**
* Processes element which should be a configuration element specifying a axis
* for the current open on partitioner/partition type tag. Assumes that there is a valid
* current open on partitioner/partition type tag.
*
* @param element axis configuration element
*/
private void processAxisTag(IConfigurationElement element) {
// add to current hyperlinkPartitionerDefinition/contentType
String thePath = getPath(element);
boolean ignoreCase = isIgnoreCase(element);
if (thePath != null) {
fCurrentHyperlinkPartitionerDefinition.addAxis(fCurrentContentType, fCurrentPartitionType, thePath, ignoreCase);
}
}
/**
* Returns the name of the part ID attribute that is expected
* in the target extension.
*
* @param element
* @return String
*/
protected String getId(IConfigurationElement element) {
String value = element.getAttribute(ATT_ID);
return value;
}
/**
* Returns the name of the part PATH attribute that is expected
* in the target extension.
*
* @param element
* @return String
*/
protected String getPath(IConfigurationElement element) {
String value = element.getAttribute(ATT_PATH);
return value;
}
/**
* Returns the name of the part TYPE attribute that is expected
* in the target extension.
*
* @param element
* @return String
*/
protected String getType(IConfigurationElement element) {
String value = element.getAttribute(ATT_TYPE);
return value;
}
/**
* Returns the name of the part BASE attribute that is expected
* in the target extension.
*
* @param element
* @return String
*/
protected String getBase(IConfigurationElement element) {
String value = element.getAttribute(ATT_BASE);
return value;
}
protected boolean isIgnoreCase(IConfigurationElement element) {
String value = element.getAttribute(ATT_IGNORE_CASE);
if("true".equals(value)) { //$NON-NLS-1$
return true;
}
return false;
}
protected String getHyperlinkPartitionerClass(IConfigurationElement element) {
String value = element.getAttribute(ATT_CLASS);
return value;
}
private void initCache() {
if(fPartitionerDefs==null) {
readContributions(TAG_HYPERLINK_PARTITIONER, PL_HYPERLINK_PARTITIONER);
}
}
/**
* Reads the contributions from the registry for the provided workbench
* part and the provided extension point ID.
* @param tag
* @param extensionPoint
*/
protected void readContributions(String tag, String extensionPoint) {
targetContributionTag = tag;
IExtensionRegistry registry = Platform.getExtensionRegistry();
readRegistry(registry, PLUGIN_ID, extensionPoint);
}
/**
* Returns all the open on definition objects
* @return
*/
public HyperlinkPartitionerDefinition[] getHyperlinkPartitionerDefinitions() {
initCache();
if(fPartitionerDefs==null) {
return new HyperlinkPartitionerDefinition[0];
}
return (HyperlinkPartitionerDefinition[])fPartitionerDefs.toArray(new HyperlinkPartitionerDefinition[fPartitionerDefs.size()]);
}
public String getBaseContentType(String contentType) {
initCache();
if (contentType == null)
return null;
String baseContentType = contentType.trim();
while (fContentTypeSynonyms.get(baseContentType) != null && !baseContentType.equalsIgnoreCase(fContentTypeSynonyms.get(baseContentType))) {
baseContentType = fContentTypeSynonyms.get(baseContentType);
}
return baseContentType;
}
/**
* Returns all the open on partitioner definition objects valid for contentType/partitionType/axis
* @param contentType
* @param partitionType
* @param axis
* @return HyperlinkPartitionerDefinition[]
*/
public HyperlinkPartitionerDefinition[] getHyperlinkPartitionerDefinitions(String contentType, String partitionType, String axis) {
if (contentType == null || partitionType == null) {
// should not be able to define an hyperlink without a content type
return null;
}
String baseContentType = getBaseContentType(contentType);
// entire list of hyperlink definition objects
HyperlinkPartitionerDefinition[] allDefs = getHyperlinkPartitionerDefinitions();
// current list of open on definitions valid for contentType/partitionType/axis
List defs = new ArrayList();
for(int i=0; i<allDefs.length; i++) {
// for each one check if it contains contentType
List contentTypes = allDefs[i].getContentTypes();
for(int j=0; j<contentTypes.size(); j++) {
HyperlinkPartitionerDefinition.ContentType cType = (HyperlinkPartitionerDefinition.ContentType)contentTypes.get(j);
if(contentType.equals(cType.getId()) || baseContentType.equals(cType.getId())) {
HyperlinkPartitionerDefinition.PartitionType pType = cType.getPartitionType(partitionType);
if(pType!=null && pType.containtsAxis(axis)) {
defs.add(allDefs[i]);
}
}
}
}
// return the list
return (HyperlinkPartitionerDefinition[]) defs.toArray(new HyperlinkPartitionerDefinition[defs.size()]);
}
}