| /******************************************************************************* |
| * Copyright (c) 2006 Oracle 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: |
| * Oracle Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.bpel.validator.rules; |
| |
| import java.lang.reflect.Field; |
| import java.util.List; |
| |
| import javax.xml.namespace.QName; |
| |
| import org.eclipse.bpel.validator.model.ARule; |
| import org.eclipse.bpel.validator.model.Filters; |
| import org.eclipse.bpel.validator.model.IConstants; |
| import org.eclipse.bpel.validator.model.IFilter; |
| import org.eclipse.bpel.validator.model.IModelQueryLookups; |
| import org.eclipse.bpel.validator.model.INode; |
| import org.eclipse.bpel.validator.model.IProblem; |
| import org.eclipse.bpel.validator.model.NodeNameFilter; |
| import org.eclipse.bpel.validator.model.RuleFactory; |
| import org.eclipse.bpel.validator.model.Validator; |
| |
| |
| /** |
| * @author Michal Chmielewski (michal.chmielewski@oracle.com) |
| * @date Oct 12, 2006 |
| * |
| */ |
| |
| @SuppressWarnings("nls") |
| public class CValidator extends Validator { |
| |
| /** The parent node */ |
| protected INode fParentNode; |
| |
| /** Children nodes */ |
| protected List<INode> fChildren; |
| |
| List<INode> fTypeToCheckList; |
| |
| |
| @Override |
| protected void start () { |
| |
| super.start(); |
| |
| fParentNode = mNode.parentNode(); |
| |
| // get the children, as we will be checking them |
| fChildren = mNode.children() ; |
| } |
| /** |
| * Check to make sure that parent node |
| * of my node is within the set of nodes |
| * that is allowed. |
| */ |
| |
| @ARule( |
| sa = 2001, |
| desc = "Check to make sure that my parent node is within a set of allowed nodes", |
| author = "michal.chmielewski@oracle.com", |
| date = "02/15/2007", |
| errors="BPELC__WRONG_PARENT" |
| ) |
| public void rule_CheckParentNode_1 () { |
| |
| checkParentNode (); |
| } |
| |
| |
| /** |
| * Check the parent Node |
| */ |
| public void checkParentNode () { |
| IFilter<INode> filter = parentNodeNames(); |
| |
| if (fParentNode == null) { |
| return ; |
| } |
| |
| if (filter.select(fParentNode) ) { |
| return ; |
| } |
| |
| // Otherwise, we have a problem ... |
| |
| IProblem problem; |
| problem = createError(); |
| problem.fill("BPELC__WRONG_PARENT", //$NON-NLS-1$ |
| toString(mNode.nodeName()), |
| toString(fParentNode.nodeName()), |
| filter.toString() ); |
| |
| // Disable all the rules from being run, if we get here. |
| disableRules(); |
| |
| } |
| |
| |
| /** |
| * Check the children nodes, to make sure that they are present |
| */ |
| |
| @ARule( |
| sa = 2002, |
| desc = "Check my children nodes (types and occurances)", |
| author = "michal.chmielewski@oracle.com", |
| date = "02/15/2007", |
| errors="BPELC__MIN_IN_PARENT,BPELC__MAX_IN_PARENT" |
| ) |
| public void rule_CheckChildrenNodes_0 () { |
| checkChildren(); |
| } |
| |
| |
| |
| /** |
| * Check the children nodes |
| * |
| */ |
| |
| public void checkChildren () { |
| |
| } |
| |
| |
| /** |
| * Check to make sure that the node nodeName appears in the |
| * children as specified by he min/max parameters. |
| * @param node |
| * @param min |
| * @param max |
| * @return the number of occurrences of this child. |
| */ |
| |
| public int checkChild (QName node, int min, int max) { |
| return checkChild ( new NodeNameFilter(node),min,max) ; |
| } |
| |
| /** |
| * @param filter |
| * @param min |
| * @param max |
| * @return the # of occurrences of this child |
| */ |
| |
| |
| @SuppressWarnings("boxing") |
| public int checkChild ( IFilter<INode> filter, int min, int max) { |
| int count = 0; |
| for(INode n : fChildren) { |
| if (filter.select(n)) { |
| count += 1; |
| } |
| } |
| |
| IProblem problem; |
| |
| if (count < min) { |
| problem = createError(); |
| problem.fill("BPELC__MIN_IN_PARENT", |
| toString(mNode.nodeName()), |
| getNodeKind ( mNode ), |
| IConstants.KIND_NODE, |
| filter.toString(), |
| count, |
| min |
| ); |
| |
| } else if (count > max) { |
| problem = createError(); |
| problem.fill("BPELC__MAX_IN_PARENT", |
| toString(mNode.nodeName()), |
| getNodeKind ( mNode ), |
| IConstants.KIND_NODE, |
| filter.toString(), |
| count, |
| max |
| ); |
| } |
| |
| return count; |
| } |
| |
| |
| |
| /** |
| * Answer with my parent nodes. Subclasses must override this |
| * because most nodes can only be children of certain nodes. |
| * |
| * @return an array of valid parent nodes. |
| */ |
| |
| |
| @SuppressWarnings("unchecked") |
| public IFilter<INode> parentNodeNames () { |
| try { |
| Field f = getClass().getField("PARENTS"); |
| return (IFilter) f.get(null); |
| } catch (java.lang.NoSuchFieldException nsfe) { |
| // do nothing. |
| } catch (Throwable t) { |
| t.printStackTrace(); |
| } |
| return Filters.EMPTY ; |
| } |
| |
| |
| /** |
| * Return the value of getExitOnStandardFault |
| * |
| * @param node |
| * @return either yes or no, depending on the setting in the scopes. |
| */ |
| |
| public String getExitOnStandardFault ( INode node ) { |
| |
| INode nn = mSelector.selectParent(node, new IFilter<INode>() { |
| |
| public boolean select(INode n) { |
| QName name = n.nodeName(); |
| if (name.equals(ND_SCOPE) == false && name.equals(ND_PROCESS) == false) { |
| return false; |
| } |
| String value = n.getAttribute(AT_EXIT_ON_STANDARD_FAULT); |
| if (isEmpty(value) == false) { |
| return true; |
| } |
| return false; |
| } |
| }); |
| |
| if (nn != null) { |
| return nn.getAttribute(AT_EXIT_ON_STANDARD_FAULT); |
| } |
| return NO; |
| } |
| |
| |
| /** |
| * Register a type to check. |
| * @param node |
| */ |
| |
| public void registerTypeToCheck (INode node) { |
| |
| if (isUndefined(node)) { |
| return; |
| } |
| |
| if ( fTypeToCheckList == null) { |
| |
| INode process = mNode.rootNode(); |
| fTypeToCheckList = getValue(process, "types.to.check", null); |
| } |
| |
| if (fTypeToCheckList == null) { |
| return ; |
| } |
| |
| if ( fTypeToCheckList.contains ( node ) == false ) { |
| fTypeToCheckList.add ( node ); |
| } |
| |
| } |
| |
| |
| |
| /** |
| * Check if the copy is compatible |
| * |
| * @param fromNode |
| * @param toNode |
| */ |
| public void compatibleCopyCheck ( INode fromNode, INode toNode ) { |
| |
| INode fromTypeNode = getValue(fromNode,"type",null); |
| INode toTypeNode = getValue(toNode,"type",null); |
| |
| if (hasProblems(fromNode) || hasProblems(toNode)) { |
| return ; |
| } |
| |
| if (fromTypeNode == null && toTypeNode == null) { |
| return ; |
| } |
| |
| /** Compatible assign */ |
| IProblem problem ; |
| if (fromTypeNode == null || toTypeNode == null) { |
| |
| problem = createInfo(); |
| problem.fill("BPELC_COPY__NOT_CHECKED", |
| toString(mNode.nodeName()), |
| "text.term.from", |
| fromTypeNode == null ? "text.term.unspecified" : fromTypeNode , |
| "text.term.to", |
| toTypeNode == null ? "text.term.unspecified" : toTypeNode ); |
| return ; |
| } |
| // fix Bug 323945 |
| String fHeaderName = getValue(fromNode, "header", null); |
| //if there is a header defined in from, it should ODE ws-bpel extension, so ignore |
| //the compatibleCopyCheck |
| if(!isEmpty(fHeaderName)){ |
| return ; |
| } |
| |
| // source -> destination |
| boolean bCompatible = mModelQuery.check(IModelQueryLookups.TEST_COMPATIBLE_TYPE, fromTypeNode, toTypeNode); |
| |
| // if these are simple types, warn if incompatibility found as engines may perform implicit conversion |
| // much like XPath does. |
| |
| if (mModelQuery.check(IModelQueryLookups.TEST_IS_SIMPLE_TYPE,fromTypeNode,null) && |
| mModelQuery.check(IModelQueryLookups.TEST_IS_SIMPLE_TYPE,toTypeNode,null)) { |
| |
| if (bCompatible == false) { |
| |
| problem = createWarning(); |
| problem.fill("BPELC_COPY__INCOMPATIBLE_SIMPLE", |
| toString(mNode.nodeName()), |
| "text.term.from", |
| fromTypeNode, |
| "text.term.to", |
| toTypeNode |
| ); |
| |
| } |
| |
| // Temporary workaround for 3369 - disable check if from/to has a part attr |
| String fromPart = fromNode.getAttribute(AT_PART); |
| String toPart = toNode.getAttribute(AT_PART); |
| if (fromPart != null || toPart != null){ |
| return; |
| } |
| |
| |
| } else if (bCompatible == false) { |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=330813 |
| // https://jira.jboss.org/browse/JBIDE-7351 |
| // added diagnostic message for easier location of the incompatibility |
| problem = createError(); |
| problem.fill("BPELC_COPY__INCOMPATIBLE", |
| toString(mNode.nodeName()), |
| "text.term.from", |
| fromTypeNode, |
| "text.term.to", |
| toTypeNode, |
| mModelQuery.getDiagnostic(0) |
| ); |
| |
| } |
| |
| } |
| |
| |
| /** |
| * A generic check against attributes |
| * |
| * @param node the context node. |
| * @param name name of the attribute |
| * @param kind 1 for activity node, 0 for generic node |
| * @param filter the filter that checks the allowed values |
| * @param bMandatory true for mandatory, false otherwise. |
| * @return the attribute value or null if the value does not exist or is not allowed. |
| */ |
| |
| @SuppressWarnings("boxing") |
| public String getAttribute ( INode node, QName name, int kind, IFilter<String> filter, boolean bMandatory ) { |
| |
| IProblem problem; |
| |
| String value = node.getAttribute(name); |
| |
| if (bMandatory) { |
| if (isEmpty(value)) { |
| problem = createError(node); |
| problem.setAttribute(IProblem.CONTEXT, name.getLocalPart() ); |
| problem.fill("BPELC__UNSET_ATTRIBUTE", //$NON-NLS-1$ |
| toString(node.nodeName()) , |
| toString(name), kind ); |
| return null; |
| } |
| } |
| |
| |
| if (filter == null || isEmpty(value) ) { |
| return value; |
| } |
| |
| if (filter.select(value)) { |
| return value; |
| } |
| |
| problem = createError(node); |
| problem.setAttribute(IProblem.CONTEXT, name.getLocalPart()); |
| problem.fill("BPELC__INVALID_ATTRIBUTE_VALUE", //$NON-NLS-1$ |
| toString(node.nodeName()), |
| toString(name), |
| value, |
| filter.toString() , |
| kind); |
| |
| return null ; |
| } |
| |
| |
| /** |
| * A generic check against all attributes that are pointers to other |
| * objects. For example, portType on invoke, partnerLink, etc. are |
| * represented as attributes but in fact refer to larger objects in the |
| * models. |
| * |
| * @param node |
| * @param ref the referenced node |
| * @param name the name of the attribute that references the node |
| * @param kind 1 for activity node, 0 for generic node |
| * @return true if the attribute pointer can be resolved, false otherwise |
| */ |
| |
| @SuppressWarnings("boxing") |
| public boolean checkAttributeNode ( INode node, INode ref, QName name, int kind ) { |
| |
| IProblem problem; |
| |
| if (ref == null) { |
| problem = createError(node); |
| problem.setAttribute(IProblem.CONTEXT, name); |
| problem.fill("BPELC__UNSET_ATTRIBUTE", //$NON-NLS-1$ |
| toString(node.nodeName()) , |
| toString(name), kind ); |
| return false; |
| } |
| |
| if (ref.isResolved() == false) { |
| String atValue = node.getAttribute( name ); |
| |
| problem = createError(node); |
| problem.setAttribute(IProblem.CONTEXT, name); |
| problem.fill("BPELC__UNRESOLVED_ATTRIBUTE", //$NON-NLS-1$ |
| toString(node.nodeName()), |
| toString(name), kind , atValue ); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| |
| /** |
| * Check if NCName is valid. |
| * |
| * @param node the node on which we are checking. |
| * @param ncName the ncName |
| * @param atName the attribute name from where the ncName came from. |
| * @return return true if checkName succeeds, false otherwise. |
| */ |
| |
| |
| @SuppressWarnings("boxing") |
| public boolean checkNCName ( INode node, String ncName, QName atName ) { |
| |
| if (ncName == null || ncName.length() == 0) { |
| |
| IProblem problem = createError( node ); |
| problem.setAttribute(IProblem.CONTEXT, atName.getLocalPart() ); |
| problem.fill("BPELC__UNSET_ATTRIBUTE", |
| toString(node.nodeName()) , |
| atName, |
| IConstants.KIND_NODE); |
| return false ; |
| } |
| |
| if (Filters.NC_NAME.select(ncName) == false) { |
| |
| IProblem problem = createError( node ); |
| problem.setAttribute(IProblem.CONTEXT, atName.getLocalPart() ); |
| problem.fill("General.NCName_Bad", //$NON-NLS-1$ |
| toString(atName), |
| toString(node.nodeName()) , ncName ); |
| return false; |
| } |
| |
| // Check for uniqueness of name within a scope or process ? |
| return true; |
| } |
| |
| |
| /** |
| * Check the node's validator to see if there are any problems reported on the |
| * node. |
| * |
| * @param node the context node |
| * @param ref the referenced node that comes from the node via an attribute |
| * @param name the name of the attribute reference |
| * @param kind 0 for node, 1 for activity |
| * @return true if there are any problems, false otherwise. |
| */ |
| |
| @SuppressWarnings("boxing") |
| public boolean checkValidator ( INode node, INode ref, QName name, int kind ) { |
| |
| if (ref == null) { |
| return false; |
| } |
| |
| Validator validator = ref.nodeValidator(); |
| if (validator == null) { |
| return true; |
| } |
| |
| IProblem problem; |
| if (validator.hasProblems()) { |
| problem = createWarning(node); |
| problem.setAttribute(IProblem.CONTEXT, name.getLocalPart() ); |
| problem.fill("BPELC_REF_NODE_PROBLEMS", //$NON-NLS-1$ |
| toString(node.nodeName()), |
| toString(ref.nodeName()), |
| name, |
| kind); |
| |
| return false; |
| } |
| |
| return true; |
| } |
| |
| |
| /** |
| * |
| * Return the language (expression or query) from the node. |
| * |
| * @param node |
| * @param atName the attribute name |
| * @return the default language. |
| */ |
| |
| public String getLanguage (INode node, QName atName) { |
| |
| // get the expression language |
| String lang = node.getAttribute (atName); |
| if (lang == null) { |
| INode process = node.rootNode (); |
| lang = process.getAttribute(atName); |
| } |
| |
| // the default language |
| |
| if (lang == null) { |
| return IConstants.XMLNS_XPATH_EXPRESSION_LANGUAGE; |
| } |
| return lang; |
| } |
| |
| |
| protected int getNodeKind ( INode node ) { |
| if (Filters.ACTIVITIES.select(node)) { |
| return IConstants.KIND_ACTIVITY; |
| } |
| return IConstants.KIND_NODE; |
| } |
| |
| |
| protected Validator createExpressionValidator ( QName qname ) { |
| |
| Validator object = RuleFactory.INSTANCE.createValidator ( qname ); |
| |
| IProblem problem; |
| |
| if (object == null) { |
| |
| problem = createWarning(); |
| problem.fill("BPELC__NO_EXPRESSION_VALIDATOR", //$NON-NLS-1$ |
| toString(mNode.nodeName()), |
| qname.getNamespaceURI() |
| ); |
| return null; |
| } |
| return object; |
| } |
| |
| |
| |
| } |