diff options
Diffstat (limited to 'bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java')
-rw-r--r-- | bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java | 601 |
1 files changed, 0 insertions, 601 deletions
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java deleted file mode 100644 index 5836285505..0000000000 --- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/validation/DelegatingSourceValidator.java +++ /dev/null @@ -1,601 +0,0 @@ -/******************************************************************************* - * 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 API and implementation - *******************************************************************************/ -package org.eclipse.wst.xml.ui.internal.validation; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.List; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.Path; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.wst.sse.core.StructuredModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IModelManager; -import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; -import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; -import org.eclipse.wst.validation.internal.core.IMessageAccess; -import org.eclipse.wst.validation.internal.core.ValidationException; -import org.eclipse.wst.validation.internal.provisional.core.IMessage; -import org.eclipse.wst.validation.internal.provisional.core.IProjectValidationContext; -import org.eclipse.wst.validation.internal.provisional.core.IReporter; -import org.eclipse.wst.validation.internal.provisional.core.IValidationContext; -import org.eclipse.wst.validation.internal.provisional.core.IValidator; -import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode; -import org.eclipse.wst.xml.core.internal.provisional.document.IDOMText; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * A DelegatingReconcileValidator calls its delegate validator to get a list - * of validation error IMessages. Using information in this IMessage the - * DelegatingReconcileValidator updates the IMessage with an offset and length - * to give a good range to be "squiggled" and adds the messages to the - * IReporter - * - * @author Mark Hutchinson - * - */ -public abstract class DelegatingSourceValidator implements IValidator { - // the selection strategies: - protected static final String ALL_ATTRIBUTES = "ALL_ATTRIBUTES"; //$NON-NLS-1$ - protected static final String ATTRIBUTE_NAME = "ATTRIBUTE_NAME"; //$NON-NLS-1$ - protected static final String ATTRIBUTE_VALUE = "ATTRIBUTE_VALUE"; //$NON-NLS-1$ - protected static final String START_TAG = "START_TAG"; //$NON-NLS-1$ - protected static final String TEXT = "TEXT"; //$NON-NLS-1$ - protected static final String FIRST_NON_WHITESPACE_TEXT = "FIRST_NON_WHITESPACE_TEXT"; //$NON-NLS-1$ - protected static final String TEXT_ENTITY_REFERENCE = "TEXT_ENTITY_REFERENCE"; //$NON-NLS-1$ - protected static final String VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE = "VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE"; //$NON-NLS-1$ - protected static final String END_TAG = "END_TAG"; //$NON-NLS-1$ - - /** - * This constant specifies the attribute name that specifies the side of - * the 'start tag' that the validator has used to report an error. A - * validator may choose to report a message at the left (the start of the - * start tag)or at the right (the end of the start tag). When this - * attribute is not specified error ERROR_SIDE_LEFT is the default. - */ - protected static final String ERROR_SIDE = "ERROR_SIDE"; //$NON-NLS-1$ - - /** - * When the ERROR_SIDE attribute specifies the ERROR_SIDE_LEFT value it is - * assumed that the message specifies a location to the left of the start - * tag - */ - protected static final String ERROR_SIDE_LEFT = "ERROR_SIDE_LEFT"; //$NON-NLS-1$ - - /** - * When the ERROR_SIDE attribute specifies the ERROR_SIDE_RIGHT value it - * is assumed that the message specifies a location to the right of the - * start tag - */ - protected static final String ERROR_SIDE_RIGHT = "ERROR_SIDE_RIGHT"; //$NON-NLS-1$ - - protected static final String COLUMN_NUMBER_ATTRIBUTE = "columnNumber"; //$NON-NLS-1$ - protected static final String SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE = "squiggleSelectionStrategy"; //$NON-NLS-1$ - protected static final String SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE = "squiggleNameOrValue"; //$NON-NLS-1$ - - public DelegatingSourceValidator() { - super(); // constructor - } - - public void cleanup(IReporter arg0) { // don't need to implement - } - - // My Implementation of IHelper - class MyHelper implements IProjectValidationContext { - InputStream inputStream; - - IFile file; - - public MyHelper(InputStream inputStream, IFile file) { - this.inputStream = inputStream; - this.file = file; - } - - public int getBuildKind() { - return 0; - } - - public Object loadModel(String symbolicName, Object[] parms) { - if (symbolicName.equals("getFile")) { //$NON-NLS-1$ - return file; - } - return null; - } - - public Object loadModel(String symbolicName) { - if (symbolicName.equals("inputStream")) { //$NON-NLS-1$ - return inputStream; - } - return null; - } - - public String[] getURIs() { - if (file != null) { - return new String[]{file.getFullPath().toString()}; - } - return new String[0]; - } - - public IProject getProject() { - if (file != null) { - return file.getProject(); - } - return null; - } - } - - // My Implementation of IReporter - class MyReporter implements IReporter { - List list = new ArrayList(); - - public MyReporter() { - super(); - } - - public void addMessage(IValidator origin, IMessage message) { - list.add(message); - } - - public void displaySubtask(IValidator validator, IMessage message) { - /* do not need to implement */ - } - - public IMessageAccess getMessageAccess() { - return null; - } - - public boolean isCancelled() { - return false; - } - - public void removeAllMessages(IValidator origin, Object object) { // do - /* do not need to implement */ - } - - public void removeAllMessages(IValidator origin) { - /* do not need to implement */ - } - - public void removeMessageSubset(IValidator validator, Object obj, String groupName) {// do - /* do not need to implement */ - } - - public List getMessages() { - return list; - } - } - - protected abstract IValidator getDelegateValidator(); - - /** - * Calls a delegate validator getting and updates it's list of - * ValidationMessages with a good squiggle offset and length. - * - * @param helper - * loads an object. - * @param reporter - * Is an instance of an IReporter interface, which is used for - * interaction with the user. - */ - public void validate(IValidationContext helper, IReporter reporter) throws ValidationException { - String[] delta = helper.getURIs(); - if (delta.length > 0) { - // get the file, model and document: - IFile file = getFile(delta[0]); - IDOMModel xmlModel = getModelForResource(file); - try { - IDOMDocument document = xmlModel.getDocument(); - - // store the text in a byte array; make a full copy to ease - // any threading problems - byte[] byteArray; - try { - byteArray = xmlModel.getStructuredDocument().get().getBytes("UTF-8"); - } - catch (UnsupportedEncodingException e) { - // Not likely to happen - byteArray = xmlModel.getStructuredDocument().get().getBytes(); - } - - if (isDelegateValidatorEnabled(file)) { - IValidator validator = getDelegateValidator(); - if (validator != null) { - // Validate the file: - IValidationContext vHelper = new MyHelper(new ByteArrayInputStream(byteArray), file); - MyReporter vReporter = new MyReporter(); - if (validator instanceof IValidatorJob) { - ((IValidatorJob) validator).validateInJob(vHelper, vReporter); - } - else { - validator.validate(vHelper, vReporter); - } - List messages = vReporter.list; - - // set the offset and length - updateValidationMessages(messages, document, reporter); - } - } - } - - - finally { - if (xmlModel != null) { - xmlModel.releaseFromRead(); - } - } - } - } - - /** - * iterates through the messages and calculates a "better" offset and - * length - * - * @param messages - - * a List of IMessages - * @param document - - * the document - * @param reporter - - * the reporter the messages are to be added to - */ - protected void updateValidationMessages(List messages, IDOMDocument document, IReporter reporter) { - for (int i = 0; i < messages.size(); i++) { - IMessage message = (IMessage) messages.get(i); - try { - if (message.getAttribute(COLUMN_NUMBER_ATTRIBUTE) != null) { - int column = ((Integer) message.getAttribute(COLUMN_NUMBER_ATTRIBUTE)).intValue(); - String selectionStrategy = (String) message.getAttribute(SQUIGGLE_SELECTION_STRATEGY_ATTRIBUTE); - String nameOrValue = (String) message.getAttribute(SQUIGGLE_NAME_OR_VALUE_ATTRIBUTE); - - // convert the line and Column numbers to an offset: - int start = document.getStructuredDocument().getLineOffset(message.getLineNumber() - 1) + column - 1; - - // calculate the "better" start and end offset: - int[] result = computeStartAndEndLocation(start, selectionStrategy, getErrorSide(message), nameOrValue, document); - if (result != null) { - message.setOffset(result[0]); - message.setLength(result[1] - result[0]); - reporter.addMessage(this, message); - } - } - } - catch (BadLocationException e) { // this exception should not - // occur - it is thrown if - // trying to convert an - // invalid line number to and - // offset - } - - } - } - - /** - * @param delta - * the IFileDelta containing the file name to get - * @return the IFile - */ - public IFile getFile(String delta) { - IResource res = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(delta)); - return res instanceof IFile ? (IFile) res : null; - } - - /** - * - * @param file - * the file to get the model for - * @return the file's XMLModel - */ - protected IDOMModel getModelForResource(IFile file) { - IStructuredModel model = null; - IModelManager manager = StructuredModelManager.getModelManager(); - - try { - model = manager.getModelForRead(file); - // TODO.. HTML validator tries again to get a model a 2nd way - } - catch (Exception e) { - // e.printStackTrace(); - } - - return model instanceof IDOMModel ? (IDOMModel) model : null; - } - - /** - * @deprecated use computeStartEndLocation(int startOffset, String - * errorMessage, String selectionStrategy, boolean leftError, - * String nameOrValue, IDOMDocument document) { - * - */ - protected int[] computeStartEndLocation(int startOffset, String errorMessage, String selectionStrategy, String nameOrValue, IDOMDocument document) { - return computeStartAndEndLocation(startOffset, selectionStrategy, ERROR_SIDE_RIGHT, nameOrValue, document); - } - - /** - * Calculates the "better" offsets. - * - * @param startOffset - - * the offset given by Xerces - * @param errorMessage - - * the Xerces error Message - * @param selectionStrategy - - * the selectionStrategy - * @param document - - * the document - * @return int[] - position 0 has the start offset of the squiggle range, - * position 1 has the endOffset - */ - /* - * The way the offsets is calculated is: - find the indexed region - * (element) closest to the given offset - if we are between two elements, - * choosing left or right element will depend on parameter 'errorSide' - - * based on the selectionStrategy choose the underlining strategy (eg - * START_TAG means underline the start tag of that element) - use - * information from nameOrValue and the DOM to get better offsets - * - */ - protected int[] computeStartAndEndLocation(int startOffset, String selectionStrategy, String errorSide, String nameOrValue, IDOMDocument document) { - try { - int startEndPositions[] = new int[2]; - - IndexedRegion region = document.getModel().getIndexedRegion(startOffset); - IndexedRegion prevRegion = document.getModel().getIndexedRegion(startOffset - 1); - - if (prevRegion != region) { - // if between two regions we use the 'errorSide' to understand - // which - // element is applicable. if we know the error has been - // reported to the - // right of the tag, then we can assume we need to step back - // to the previous - // region to land at the 'correct location. Otherwise assume - // we're - // exactly where we need to be. - if (ERROR_SIDE_LEFT.equals(errorSide)) { - region = prevRegion; - } - } - - // initialize start and end positions to be the start positions - // this means if the - // special case is not taken care of below the start and end - // offset are set to be - // the start of the region where the error was - if (region != null) { - startEndPositions[0] = region.getStartOffset(); - startEndPositions[1] = startEndPositions[0]; - } - else { // this will message will not get added to the IReporter - // since the length is 0 - startEndPositions[0] = 0; - startEndPositions[1] = 0; - } - if (region instanceof Node) { - Node node = (Node) region; - - if (START_TAG.equals(selectionStrategy)) {// then we want to - // underline the opening tag - if (node.getNodeType() == Node.ELEMENT_NODE) { - IDOMElement element = (IDOMElement) node; - startEndPositions[0] = element.getStartOffset() + 1; - startEndPositions[1] = startEndPositions[0] + element.getTagName().length(); - } - } - else if (END_TAG.equals(selectionStrategy)) {// then we want to - // underline the end tag - if (node.getNodeType() == Node.ELEMENT_NODE) { - IDOMElement element = (IDOMElement) node; - startEndPositions[0] = element.getEndStartOffset(); - startEndPositions[1] = element.getEndOffset(); - } - } - else if (ATTRIBUTE_NAME.equals(selectionStrategy)) { // in - // underline the attribute's name - if (node.getNodeType() == Node.ELEMENT_NODE) { - IDOMElement element = (IDOMElement) node; - IDOMNode attributeNode = (IDOMNode) (element.getAttributeNode(nameOrValue)); - if (attributeNode != null) { - startEndPositions[0] = attributeNode.getStartOffset(); - startEndPositions[1] = attributeNode.getStartOffset() + nameOrValue.length(); - } - } - } - else if (ATTRIBUTE_VALUE.equals(selectionStrategy)) { - // underline the attribute's value - if (node.getNodeType() == Node.ELEMENT_NODE) { - IDOMElement element = (IDOMElement) node; - IDOMAttr attributeNode = (IDOMAttr) (element.getAttributeNode(nameOrValue)); - if (attributeNode != null) { - startEndPositions[0] = attributeNode.getValueRegionStartOffset(); - startEndPositions[1] = startEndPositions[0] + attributeNode.getValueRegionText().length(); - } - } - } - else if (ALL_ATTRIBUTES.equals(selectionStrategy)) { - // underline all attributes - if (node.getNodeType() == Node.ELEMENT_NODE) { - IDOMElement element = (IDOMElement) node; - NamedNodeMap attributes = element.getAttributes(); - if (attributes != null) { - IDOMNode first = (IDOMNode) attributes.item(0); - IDOMNode last = (IDOMNode) attributes.item(attributes.getLength() - 1); - if ((first != null) && (last != null)) { - startEndPositions[0] = first.getStartOffset(); - startEndPositions[1] = last.getEndOffset(); - } - } - } - } - else if (TEXT.equals(selectionStrategy)) { - // underline the text between the tags - if (node.getNodeType() == Node.TEXT_NODE) { - IDOMText textNode = (IDOMText) node; - int start = textNode.getStartOffset(); - String value = textNode.getNodeValue(); - int index = 0; - char curChar = value.charAt(index); - // here we are finding start offset by skipping over - // whitespace: - while ((curChar == '\n') || (curChar == '\t') || (curChar == '\r') || (curChar == ' ')) { - curChar = value.charAt(index); - index++; - } - if (index > 0) { - index--; - - } - start = start + index; - startEndPositions[0] = start + index; - startEndPositions[1] = start + value.trim().length(); - } - else if (node.getNodeType() == Node.ELEMENT_NODE) { - IDOMElement element = (IDOMElement) node; - Node child = element.getFirstChild(); - if (child instanceof IDOMNode) { - IDOMNode xmlChild = ((IDOMNode) child); - startEndPositions[0] = xmlChild.getStartOffset(); - startEndPositions[1] = xmlChild.getEndOffset(); - } - } - } - else if (FIRST_NON_WHITESPACE_TEXT.equals(selectionStrategy)) { - // search through all child nodes and return range of - // first non-whitespace - // text node - if (node.getNodeType() == Node.ELEMENT_NODE) { - NodeList nodes = node.getChildNodes(); - for (int i = 0; i < nodes.getLength(); i++) { - Node currentNode = nodes.item(i); - if (currentNode.getNodeType() == Node.TEXT_NODE) { - // TODO (Trung) I don't think we should call - // getNodeValue(), trim(), length() - // repeatedly. - // This is inefficient, to improve use local - // variables to store values. - IDOMText textNode = (IDOMText) currentNode; - if (textNode.getNodeValue().trim().length() > 0) { - String value = textNode.getNodeValue(); - int index = 0; - int start = textNode.getStartOffset(); - char curChar = value.charAt(index); - // here we are finding start offset by - // skipping over whitespace: - while ((curChar == '\n') || (curChar == '\t') || (curChar == '\r') || (curChar == ' ')) { - curChar = value.charAt(index); - index++; - } - if (index > 0) { - index--; - - } - start = start + index; - startEndPositions[0] = start; - startEndPositions[1] = start + value.trim().length(); - break; - } - } - - } - } - } - - else if (TEXT_ENTITY_REFERENCE.equals(selectionStrategy)) { - if (node.getNodeType() == Node.ENTITY_REFERENCE_NODE) { - startEndPositions[0] = region.getStartOffset(); - startEndPositions[1] = region.getEndOffset(); - } - else if (node.getNodeType() == Node.ELEMENT_NODE) { - /* - * In this case the undeclared entity might be in one - * of the attribute values. Search through the - * attributes to find the range of the undeclared - * entity. - */ - String entity = "&" + nameOrValue + ";"; //$NON-NLS-1$ //$NON-NLS-2$ - NamedNodeMap attributes = node.getAttributes(); - for (int i = 0; i < attributes.getLength(); i++) { - IDOMAttr attr = (IDOMAttr) attributes.item(i); - String nodeValue = attr.getNodeValue(); - int index = nodeValue.indexOf(entity); - if (index != -1) { - startEndPositions[0] = attr.getValueRegionStartOffset() + index + 1; - startEndPositions[1] = startEndPositions[0] + entity.length(); - } - } - } - - } - else if (VALUE_OF_ATTRIBUTE_WITH_GIVEN_VALUE.equals(selectionStrategy)) { - // TODO (Trung) do we really need this strategy ? - // If we know the name of the name of the attribute, we - // can retrieve its value. - // Hence, we can incoperate this strategy with - // ATTRIBUTE_VALUE ? - if (node.getNodeType() == Node.ELEMENT_NODE) { - // here we will search through all attributes for the - // one with the - // with the value we want: - // TODO (Trung) I see a potential problem here. - // What happens when there is another attribute having - // the same value - // with this attribute's buggy value ? - // Need to solve when time permits. - NamedNodeMap attributes = node.getAttributes(); - for (int i = 0; i < attributes.getLength(); i++) { - IDOMAttr attr = (IDOMAttr) attributes.item(i); - String nodeValue = attr.getNodeValue().trim(); - if (nodeValue.equals(nameOrValue)) { - startEndPositions[0] = attr.getValueRegionStartOffset() + 1; - startEndPositions[1] = startEndPositions[0] + nodeValue.length(); - break; - } - } - } - } - } - return startEndPositions; - } - // catch (Exception e) { // e.printStackTrace(); - // } - finally { - } - // return null; - } - - /** - * Returns true if delegate validator is enabled based on Validation - * preferences - * - * @param file - * @return false if delegate validator is not enabled based on Validatoin - * preferences, true otherwise - */ - protected boolean isDelegateValidatorEnabled(IFile file) { - return true; - } - - protected String getErrorSide(IMessage message) { - // note that if the ERROR_SIDE is unspecified we return the default - // value ERROR_SIDE_LEFT - Object value = message.getAttribute(ERROR_SIDE); - return ERROR_SIDE_RIGHT.equals(value) ? ERROR_SIDE_RIGHT : ERROR_SIDE_LEFT; - } -} |