blob: faf7b6e73f0624979e936bc5a3bb0be205017ded [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2012 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 API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.ui.editor.text;
import java.util.*;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jdt.core.JavaConventions;
import org.eclipse.pde.core.plugin.*;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.ischema.*;
import org.eclipse.pde.internal.core.text.*;
import org.eclipse.pde.internal.core.util.PDEJavaHelper;
import org.eclipse.pde.internal.ui.PDEPlugin;
/**
* Utility class for XML operations and editors.
*/
public abstract class XMLUtil {
/**
* Scans up the node's parents till it reaches
* a IPluginExtension or IPluginExtensionPoint (or null)
* and returns the result.
*
* @param node
* @return the IPluginExtension or IPluginExtensionPoint that contains <code>node</code>
*/
public static IPluginObject getTopLevelParent(IDocumentRange range) {
IDocumentElementNode node = null;
if (range instanceof IDocumentAttributeNode)
node = ((IDocumentAttributeNode) range).getEnclosingElement();
else if (range instanceof IDocumentTextNode)
node = ((IDocumentTextNode) range).getEnclosingElement();
else if (range instanceof IPluginElement)
node = (IDocumentElementNode) range;
else if (range instanceof IPluginObject)
// not an attribute/text node/element -> return direct node
return (IPluginObject) range;
while (node != null && !(node instanceof IPluginExtension) && !(node instanceof IPluginExtensionPoint))
node = node.getParentNode();
return node != null ? (IPluginObject) node : null;
}
private static boolean withinRange(int start, int len, int offset) {
return start <= offset && offset <= start + len;
}
public static boolean withinRange(IDocumentRange range, int offset) {
if (range instanceof IDocumentAttributeNode)
return withinRange(((IDocumentAttributeNode) range).getValueOffset(), ((IDocumentAttributeNode) range).getValueLength(), offset);
if (range instanceof IDocumentElementNode)
return withinRange(((IDocumentElementNode) range).getOffset(), ((IDocumentElementNode) range).getLength(), offset);
if (range instanceof IDocumentTextNode)
return withinRange(((IDocumentTextNode) range).getOffset(), ((IDocumentTextNode) range).getLength(), offset);
return false;
}
/**
* Get the ISchemaElement corresponding to this IDocumentElementNode
* @param node
* @param extensionPoint the extension point of the schema, if <code>null</code> it will be deduced
* @return the ISchemaElement for <code>node</code>
*/
public static ISchemaElement getSchemaElement(IDocumentElementNode node, String extensionPoint) {
if (extensionPoint == null) {
IPluginObject obj = getTopLevelParent(node);
if (!(obj instanceof IPluginExtension))
return null;
extensionPoint = ((IPluginExtension) obj).getPoint();
}
ISchema schema = PDECore.getDefault().getSchemaRegistry().getSchema(extensionPoint);
if (schema == null)
return null;
// Bug 213457 - look up elements based on the schema in which the parent is found
if (schema.getIncludes().length == 0 || "extension".equals(node.getXMLTagName())) //$NON-NLS-1$
return schema.findElement(node.getXMLTagName());
// if element is not "extension" & has multiple sub-schemas,
// Then search for the element in the same schema in which the parent element if found.
Stack<String> stack = new Stack<>();
while (node != null) {
String tagName = node.getXMLTagName();
if ("extension".equals(tagName)) //$NON-NLS-1$
break;
stack.push(node.getXMLTagName());
node = node.getParentNode();
}
ISchemaElement element = null;
while (!stack.isEmpty()) {
element = schema.findElement(stack.pop());
if (element == null)
return null;
schema = element.getSchema();
}
return element;
}
/**
* Get the ISchemaAttribute corresponding to this IDocumentAttributeNode
* @param attr
* @param extensionPoint the extension point of the schema, if <code>null</code> it will be deduced
* @return the ISchemaAttribute for <code>attr</code>
*/
public static ISchemaAttribute getSchemaAttribute(IDocumentAttributeNode attr, String extensionPoint) {
ISchemaElement ele = getSchemaElement(attr.getEnclosingElement(), extensionPoint);
if (ele == null)
return null;
return ele.getAttribute(attr.getAttributeName());
}
/**
* Creates a default class name including package prefix. Uses the schema attribute
* to determine a default name, prepends a default package name based on the project
* and appends the counter if more than one such class exists.
* @param project project that the class name is being generated for
* @param attInfo the schema attribute describing the new class
* @param counter used to make each generated name unique
*/
public static String createDefaultClassName(IProject project, ISchemaAttribute attInfo, int counter) {
String tag = attInfo.getParent().getName();
String expectedType = attInfo.getBasedOn();
String className = ""; //$NON-NLS-1$
if (expectedType == null) {
StringBuffer buf = new StringBuffer(tag);
buf.setCharAt(0, Character.toUpperCase(tag.charAt(0)));
className = buf.toString();
} else {
className = expectedType;
int dotLoc = className.lastIndexOf('.');
if (dotLoc != -1)
className = className.substring(dotLoc + 1);
if (className.length() > 2 && className.charAt(0) == 'I' && Character.isUpperCase(className.charAt(1)))
className = className.substring(1);
}
String packageName = createDefaultPackageName(project, className);
className += counter;
return packageName + "." + className; //$NON-NLS-1$
}
/**
* Creates a default package name based on the name of the project. If the project name is
* not a valid java identifier, this method will return the given class name converted to lower
* case.
*
* @param project the project to generate the package name from
* @param className class name to use as package name if project name fails
*/
public static String createDefaultPackageName(IProject project, String className) {
String id = project.getName().toLowerCase(Locale.ENGLISH);
IStatus status = JavaConventions.validatePackageName(id, PDEJavaHelper.getJavaSourceLevel(project), PDEJavaHelper.getJavaComplianceLevel(project));
if (status.getSeverity() == IStatus.ERROR)
return className.toLowerCase(Locale.ENGLISH);
return id;
}
/**
* @param project
* @param attInfo
* @param counter
*/
public static String createDefaultName(IProject project, ISchemaAttribute attInfo, int counter) {
if (attInfo.getType().getName().equals("boolean")) //$NON-NLS-1$
return "true"; //$NON-NLS-1$
String tag = attInfo.getParent().getName();
return project.getName() + "." + tag + counter; //$NON-NLS-1$
}
/**
* @param elementInfo
*/
public static int getCounterValue(ISchemaElement elementInfo) {
Hashtable<String, Integer> counters = PDEPlugin.getDefault().getDefaultNameCounters();
String counterKey = getCounterKey(elementInfo);
Integer counter = counters.get(counterKey);
if (counter == null) {
counter = new Integer(1);
} else
counter = new Integer(counter.intValue() + 1);
counters.put(counterKey, counter);
return counter.intValue();
}
public static String getCounterKey(ISchemaElement elementInfo) {
return elementInfo.getSchema().getQualifiedPointId() + "." + elementInfo.getName(); //$NON-NLS-1$
}
}