/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.text.ext.hyperlink;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.custom.BusyIndicator;
import org.jboss.tools.common.text.ext.ExtensionsPlugin;
import org.osgi.framework.Bundle;
/**
* @author Igels
*/
public class HyperlinkPartitionerDefinition {
private String fId = null;
private String fClassName = null;
// a hash map of content type Ids (String) that points to lists of parition types (List of Strings)
// contentTypeId -> List(paritionType, paritionType, partitionType, ...)
// contentTypeId2 -> List(partitionType, partitionType, ...)
// ...
private ContentTypeMap fContentTypes = null;
private IConfigurationElement fConfigurationElement = null;
/**
* @param id
* @param className
* @param configurationElement
*/
public HyperlinkPartitionerDefinition(String id, String className, IConfigurationElement configurationElement) {
fId = id;
fClassName = className;
fConfigurationElement = configurationElement;
fContentTypes = new ContentTypeMap();
}
/**
* @return IHyperlinkPartitioner for this definition
*/
public IHyperlinkPartitioner createHyperlinkPartitioner() {
IHyperlinkPartitioner hyperlinkPartitioner = null;
if(getClassName()!=null) {
hyperlinkPartitioner = (IHyperlinkPartitioner)createExtension(HyperlinkPartitionerBuilder.ATT_CLASS);
}
return hyperlinkPartitioner;
}
public void addContentTypeId(String contentTypeId) {
fContentTypes.addType(new ContentType(contentTypeId));
}
public void addPartitionType(String contentTypeId, String partitionTypeId) {
addContentTypeId(contentTypeId);
ContentType contentType = fContentTypes.getContentType(contentTypeId);
contentType.addPartitionType(new PartitionType(partitionTypeId));
}
public void addAxis(String contentTypeId, String partitionTypeId, String axis, boolean ignoreCase) {
addPartitionType(contentTypeId, partitionTypeId);
PartitionType partitionType = fContentTypes.getContentType(contentTypeId).getPartitionType(partitionTypeId);
partitionType.addAxis(axis, ignoreCase);
}
/**
* @return Returns the fClass.
*/
public String getClassName() {
return fClassName;
}
/**
* @return Returns the fConfigurationElement.
*/
public IConfigurationElement getConfigurationElement() {
return fConfigurationElement;
}
/**
* @return Returns the fContentTypes.
*/
public List getContentTypes() {
return fContentTypes.getTypes();
}
/**
* @return Returns the fId.
*/
public String getId() {
return fId;
}
/**
* Creates an extension. If the extension plugin has not
* been loaded a busy cursor will be activated during the duration of
* the load.
* @param propertyName
* @return Object
*/
private Object createExtension(String propertyName) {
// If plugin has been loaded create extension.
// Otherwise, show busy cursor then create extension.
final IConfigurationElement element = getConfigurationElement();
final String name = propertyName;
final Object[] result = new Object[1];
Bundle bundle = Platform.getBundle(element.getDeclaringExtension().getNamespaceIdentifier());
if (bundle.getState() == org.osgi.framework.Bundle.ACTIVE) {
try {
return element.createExecutableExtension(name);
} catch (CoreException e) {
handleCreateExecutableException(result, e);
}
} else {
BusyIndicator.showWhile(null, new Runnable() {
public void run() {
try {
result[0] = element.createExecutableExtension(name);
} catch (CoreException e) {
handleCreateExecutableException(result, e);
}
}
});
}
return result[0];
}
/**
* @param result
* @param e
*/
private void handleCreateExecutableException(Object[] result, Exception x) {
ExtensionsPlugin.getPluginLog().logError("Error in creating extension", x); //$NON-NLS-1$
result[0] = null;
}
private static class TypeMap {
protected ArrayList<Object> fTypes = new ArrayList<Object>();
public List getTypes() {
return fTypes;
}
}
private static class ContentTypeMap extends TypeMap {
public void addType(ContentType type) {
if(!fTypes.contains(type)) {
fTypes.add(type);
}
}
public ContentType getContentType(String id) {
for(int i=0; i<fTypes.size(); i++) {
ContentType type = (ContentType)fTypes.get(i);
if(type.getId().equals(id)) {
return type;
}
}
return null;
}
}
private static class PartitionTypeMap extends TypeMap {
public void addType(PartitionType type) {
if(!fTypes.contains(type)) {
fTypes.add(type);
}
}
public PartitionType getPartitionType(String id) {
for(int i=0; i<fTypes.size(); i++) {
PartitionType type = (PartitionType)fTypes.get(i);
if(type.getId().equals(id)) {
return type;
}
}
return null;
}
}
public static class ContentType {
private PartitionTypeMap fPartitionTypeMap;
private String fId;
public ContentType(String id) {
fId = id;
fPartitionTypeMap = new PartitionTypeMap();
}
public ContentType(String id, PartitionTypeMap partitionTypeMap) {
fId = id;
fPartitionTypeMap = partitionTypeMap;
}
public void addPartitionType(PartitionType type) {
if(!containsPartitiontype(type.getId())) {
fPartitionTypeMap.addType(type);
}
}
public List getPartitionTypes() {
return fPartitionTypeMap.getTypes();
}
public String getId() {
return fId;
}
public boolean containsPartitiontype(String id) {
return fPartitionTypeMap.getTypes().contains(new PartitionType(id));
}
public PartitionType getPartitionType(String id) {
return fPartitionTypeMap.getPartitionType(id);
}
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof ContentType)) {
return false;
}
ContentType type = (ContentType)obj;
String objId = type.getId();
return fId==null?objId==null:fId.equals(objId);
}
}
public static class PartitionType {
private List<Axis> fAxises;
private String fId;
public PartitionType(String id) {
fId = id;
fAxises = new ArrayList<Axis>();
}
public void addAxis(String path, boolean ignoreCase) {
Axis axis = new Axis(path, ignoreCase);
for(int i=0; i<fAxises.size(); i++) {
if(axis.equals(fAxises.get(i))) {
return;
}
}
fAxises.add(axis);
}
public List getAxises() {
return fAxises;
}
public String getId() {
return fId;
}
public boolean containtsAxis(String path) {
if(fAxises.size()==0 || path==null) {
return true;
}
for(int i=0; i<fAxises.size(); i++) {
Axis axis = (Axis)fAxises.get(i);
if(axis.containtsPath(path)) {
return true;
}
}
return false;
}
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof PartitionType)) {
return false;
}
PartitionType type = (PartitionType)obj;
String objId = type.getId();
return fId==null?objId==null:fId.equals(objId);
}
}
public static class Axis {
private String fPath;
private boolean fIgnoreCase;
private String[] fDelimitedPathElements;
private boolean fStartDelim = false;
private boolean fEndDelim = false;
public Axis(String path, boolean ignoreCase) {
this.fIgnoreCase = ignoreCase;
setPath(path);
}
private String getCorrectPath(String path) {
path = path.trim();
if(fIgnoreCase) {
path = path.toLowerCase();
}
if(!path.startsWith(DELIM)) {
path = DELIM + path;
}
if(!path.endsWith(DELIM)) {
path = path + DELIM;
}
return path;
}
public boolean isIgnoreCase() {
return fIgnoreCase;
}
public String getPath() {
return fPath;
}
public void setIgnoreCase(boolean ignoreCase) {
this.fIgnoreCase = ignoreCase;
}
public void setPath(String path) {
this.fPath = getCorrectPath(path);
if(fPath.indexOf(ALL_TAGS)>-1) {
StringTokenizer st = new StringTokenizer(fPath, "*" , false); //$NON-NLS-1$
fStartDelim = fPath.startsWith(ALL_TAGS);
fEndDelim = fPath.endsWith(ALL_TAGS);
ArrayList<String> list = new ArrayList<String>();
while(st.hasMoreElements()) {
String element = (String)st.nextElement();
if(DELIM.equals(element)) {
continue;
}
list.add(element);
}
fDelimitedPathElements = (String[])list.toArray(new String[list.size()]);
} else {
fDelimitedPathElements = null;
}
}
private static String ALL_TAGS = "/*/"; //$NON-NLS-1$
private static String DELIM = "/"; //$NON-NLS-1$
private static String TAGLIB = "/["; //$NON-NLS-1$
public boolean containtsPath(String path) {
path = getCorrectPath(path);
if(ALL_TAGS.equals(fPath)) {
return true;
}
if(fDelimitedPathElements!=null) {
int lastIndex = -1;
int tagLib = -1;
for(int i=0; i<fDelimitedPathElements.length; i++) {
if(i==0 && !fStartDelim) {
if(path.startsWith(fDelimitedPathElements[i])) {
lastIndex = 0;
tagLib = 0;
continue;
} else {
return false;
}
} else {
int currentIndex = path.lastIndexOf(fDelimitedPathElements[i]);
if(currentIndex>-1 && currentIndex>lastIndex) {
lastIndex = currentIndex;
if(fDelimitedPathElements[i].startsWith(TAGLIB))
tagLib = lastIndex;
continue;
} else {
return false;
}
}
}
if(fEndDelim || path.endsWith(fDelimitedPathElements[fDelimitedPathElements.length-1])) {
int lastTaglib = path.lastIndexOf(TAGLIB);
if(tagLib == -1 || lastTaglib <= tagLib)
return true;
}
return false;
}
return fPath.equals(path);
}
public boolean equals(Object obj) {
if(obj == null || !(obj instanceof Axis)) {
return false;
}
Axis axis = (Axis)obj;
String path = axis.getPath();
boolean ignoreCase = axis.isIgnoreCase();
return ((ignoreCase == fIgnoreCase) && fPath.equals(path));
}
}
}