Package org.dozer.eclipse.plugin.sourcepage.validation

Source Code of org.dozer.eclipse.plugin.sourcepage.validation.Validator$LocationTrackingDOMParser

/**
* Copyright 2005-2013 Dozer Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dozer.eclipse.plugin.sourcepage.validation;

import org.apache.xerces.dom.NodeImpl;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XNIException;
import org.dozer.eclipse.plugin.sourcepage.util.DozerPluginUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.wst.xml.core.internal.validation.core.AbstractNestedValidator;
import org.eclipse.wst.xml.core.internal.validation.core.NestedValidatorContext;
import org.eclipse.wst.xml.core.internal.validation.core.ValidationInfo;
import org.eclipse.wst.xml.core.internal.validation.core.ValidationReport;
import org.springframework.ide.eclipse.core.java.JdtUtils;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.UserDataHandler;
import org.xml.sax.InputSource;

import java.io.InputStream;
import java.net.URI;

@SuppressWarnings("restriction")
public class Validator extends AbstractNestedValidator {

  @Override
  public ValidationReport validate(String uri, InputStream inputstream,
      NestedValidatorContext context) {   

    ValidationInfo validationReport = new ValidationInfo(uri);
    try {
      //Get IFile from URI
      IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(new URI(uri.replace(" ", "%20")));
     
      //hmm, could be multiple? Lets just take the first
      IFile file = files[0];
     
//      FIXME this is sick.
//      To get the line/column-numbers for the broken custom-converter properties, we need to
//      extend the DOMParser class to get the location information.
//      No idea whether this will work everywhere. I bet there is a a better solution somewhere...     
      LocationTrackingDOMParser parser = new LocationTrackingDOMParser();
      parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false)//must disable that feature to get location
      parser.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
      parser.parse(new InputSource(uri));
      Document doc = parser.getDocument()//Parse the Doc (every node gets UserData-Info for location info, see below)
     
      //DocumentType docType = doc.getDoctype();
      //String sysId = null;
      //if (docType != null)
      //  sysId = docType.getSystemId();
     
      //if (sysId != null && "http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd".equals(sysId)) {
      if ("mapping".equals(doc.getDocumentElement().getNodeName()))
        //classes exist?
        checkClassNodes(doc.getElementsByTagName("class-a"), file, validationReport);
        checkClassNodes(doc.getElementsByTagName("class-b"), file, validationReport);
       
        //field correct?
        checkFieldNodes(doc.getElementsByTagName("field"), file, validationReport);
        checkFieldNodes(doc.getElementsByTagName("field-exclude"), file, validationReport);
      //}
    } catch (Throwable e) {
      e.printStackTrace();
    }
   
    return validationReport;
  }
 
  @SuppressWarnings("restriction")
  private void checkClassNodes(NodeList nodeList, IFile file, ValidationInfo validationReport) throws JavaModelException, DOMException {
    int len = nodeList.getLength();
    for (int i = 0; i < len; i++) {
      Node node = nodeList.item(i);
      Node textNode = node.getFirstChild();
     
      if (textNode.getNodeType() == Node.TEXT_NODE) {
        String className = textNode.getNodeValue();
       
        IType javaType = JdtUtils.getJavaType(file.getProject(), className);
        //class not found
        if (javaType == null) {
          Integer[] location = (Integer[])node.getUserData("location");
          validationReport.addError("Class "+className+" not found.", location[0], location[1], validationReport.getFileURI());
        }
      }
     
    }
  }
 
  @SuppressWarnings("restriction")
  private void checkFieldNodes(NodeList nodeList, IFile file, ValidationInfo validationReport) throws JavaModelException, DOMException {
    int len = nodeList.getLength();
    //check all field-nodes...
    for (int i = 0; i < len; i++) {
      Node node = nodeList.item(i)//field
     
      //..have custom-converter attributes
      Node attrNode = node.getAttributes().getNamedItem("custom-converter");
      if (attrNode != null) {
        //...doesnt implement the CustomConverter Interface
        if (!checkClassImplementsCustomConverter(file.getProject(), attrNode.getNodeValue())) {
          //this class doesnt implement the interface and is worth an error
          Integer[] location = (Integer[])node.getUserData("location");
          validationReport.addError("Class does not implement interface CustomConverter", location[0], location[1], validationReport.getFileURI());
        }
      //...have custom-converter-id attributes
      } else {
        attrNode = node.getAttributes().getNamedItem("custom-converter-id");
        if (attrNode != null) {
          String className = DozerPluginUtils.getClassNameForCCI(file, attrNode.getNodeValue());
          if (className != null && !checkClassImplementsCustomConverter(file.getProject(), className)) {
            //this class doesnt implement the interface and is worth an error
            Integer[] location = (Integer[])node.getUserData("location");
            validationReport.addError("Bean does not implement interface CustomConverter", location[0], location[1], validationReport.getFileURI());
          }
        }
      }
     
      NodeList abList = node.getChildNodes();
      int abLen = abList.getLength();
      for (int a = 0; a < abLen; a++) {
        Node abNode = abList.item(a)//a or b
        if ("a".equals(abNode.getNodeName()) || "b".equals(abNode.getNodeName())) {
          Node textNode = abNode.getFirstChild();
          //...no value set between <a></a> or <b></b>?
          if(textNode == null){
            Integer[] location = (Integer[])node.getUserData("location");
            String className = DozerPluginUtils.getMappingClassName(abNode);
            String nodeName = abNode.getNodeName();           
           
            validationReport.addError("Unsetted property value in node "+nodeName+" for class " + className, location[0], location[1], validationReport.getFileURI());
          }
          //...is fieldname correct?
          else if (textNode.getNodeType() == Node.TEXT_NODE) {         
            String property = textNode.getNodeValue();
            String className = DozerPluginUtils.getMappingClassName(abNode);
           
            attrNode = DozerPluginUtils.getMappingNode(abNode).getAttributes().getNamedItem("type");
            boolean bIsBiDirectional = true;
            if (attrNode != null) {
              bIsBiDirectional = "bi-directional".equals(attrNode.getNodeValue());
            }
           
            if (!"this".equals(property)) {
              Node isAccessibleNode = abNode.getAttributes().getNamedItem("is-accessible");
              boolean isAccessible = isAccessibleNode != null && "true".equals(isAccessibleNode.getNodeValue());
             
              if ((bIsBiDirectional || "a".equals(abNode.getNodeName())) &&
                  DozerPluginUtils.hasReadProperty(property, className, file.getProject(), isAccessible) == null) {
                Integer[] location = (Integer[])abNode.getUserData("location");
                validationReport.addError("Property "+property+" for class "+className+" cannot be read from.", location[0], location[1], validationReport.getFileURI());
              } else if ((bIsBiDirectional || "b".equals(abNode.getNodeName())) &&
                  DozerPluginUtils.hasWriteProperty(property, className, file.getProject()) == null) {
                Integer[] location = (Integer[])abNode.getUserData("location");
                validationReport.addError("Property "+property+" for class "+className+" cannot be written to.", location[0], location[1], validationReport.getFileURI());
              }
            }
          }     
        }       
      }
    }
  }
 
  private boolean checkClassImplementsCustomConverter(IProject project, String className) throws JavaModelException {
    IType javaType = JdtUtils.getJavaType(project, className);
   
    if (javaType == null)
      return false;
   
    ITypeHierarchy hierarchy = javaType.newSupertypeHierarchy(new NullProgressMonitor());
    IType[] interfaces = hierarchy.getAllSuperInterfaces(javaType);
   
    for (IType type : interfaces) {
      if (type.getElementName().equals("CustomConverter")) {
        return true;
      }
    }
   
    return false;
  }
 
  /**
   * Borrowed and enhanced from Cocoon Woody DOMHelper Class
   */
  public static class LocationTrackingDOMParser extends DOMParser {
        XMLLocator locator;

        @Override
    public void startDocument(XMLLocator xmlLocator,
        String arg1, org.apache.xerces.xni.NamespaceContext arg2,
        Augmentations arg3) throws org.apache.xerces.xni.XNIException {
      super.startDocument(xmlLocator, arg1, arg2, arg3);
            this.locator = xmlLocator;
            setLocation();
    }

    @Override
    public void startElement(QName qName, XMLAttributes xmlAttributes,
                Augmentations augmentations) throws XNIException {
            super.startElement(qName, xmlAttributes, augmentations);
            setLocation();
        }

        private final void setLocation() {
          if (this.locator == null) {
                throw new RuntimeException(
                        "Error: locator is null. Check that you have the" +
                        " correct version of Xerces (such as the one that" +
                        " comes with Cocoon) in your endorsed library path.");
            }
            NodeImpl node = null;
            try {
                node = (NodeImpl)this.getProperty(
                        "http://apache.org/xml/properties/dom/current-element-node");
            } catch (org.xml.sax.SAXException ex) {
                System.err.println("except" + ex);
            }
            if (node != null) {
                Integer[] location = new Integer[] {locator.getLineNumber(), locator.getColumnNumber()};
                node.setUserData("location", location, (UserDataHandler)null);
            }
        }
  }

}
TOP

Related Classes of org.dozer.eclipse.plugin.sourcepage.validation.Validator$LocationTrackingDOMParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.