src/share/jaxws_classes/com/sun/xml/internal/ws/policy/sourcemodel/ModelNode.java

Thu, 12 Oct 2017 19:44:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 19:44:07 +0800
changeset 760
e530533619ec
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     1 /*
     2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.policy.sourcemodel;
    28 import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
    29 import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
    30 import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
    31 import com.sun.xml.internal.ws.policy.sourcemodel.wspolicy.XmlToken;
    33 import java.util.Collection;
    34 import java.util.Collections;
    35 import java.util.Iterator;
    36 import java.util.LinkedList;
    38 /**
    39  * The general representation of a single node within a {@link com.sun.xml.internal.ws.policy.sourcemodel.PolicySourceModel} instance.
    40  * The model node is created via factory methods of the {@link com.sun.xml.internal.ws.policy.sourcemodel.PolicySourceModel} instance.
    41  * It may also hold {@link com.sun.xml.internal.ws.policy.sourcemodel.AssertionData} instance in case its type is {@code ModelNode.Type.ASSERTION}.
    42  *
    43  * @author Marek Potociar
    44  */
    45 public final class ModelNode implements Iterable<ModelNode>, Cloneable {
    46     private static final PolicyLogger LOGGER = PolicyLogger.getLogger(ModelNode.class);
    48     /**
    49      * Policy source model node type enumeration
    50      */
    51     public static enum Type {
    52         POLICY(XmlToken.Policy),
    53         ALL(XmlToken.All),
    54         EXACTLY_ONE(XmlToken.ExactlyOne),
    55         POLICY_REFERENCE(XmlToken.PolicyReference),
    56         ASSERTION(XmlToken.UNKNOWN),
    57         ASSERTION_PARAMETER_NODE(XmlToken.UNKNOWN);
    59         private XmlToken token;
    61         Type(XmlToken token) {
    62             this.token = token;
    63         }
    65         public XmlToken getXmlToken() {
    66             return token;
    67         }
    69         /**
    70          * Method checks the PSM state machine if the creation of new child of given type is plausible for a node element
    71          * with type set to this type instance.
    72          *
    73          * @param childType The type.
    74          * @return True if the type is supported, false otherwise
    75          */
    76         private boolean isChildTypeSupported(final Type childType) {
    77             switch (this) {
    78                 case POLICY:
    79                 case ALL:
    80                 case EXACTLY_ONE:
    81                     switch (childType) {
    82                         case ASSERTION_PARAMETER_NODE:
    83                             return false;
    84                         default:
    85                             return true;
    86                     }
    87                 case POLICY_REFERENCE:
    88                     return false;
    89                 case ASSERTION:
    90                     switch (childType) {
    91                         case POLICY:
    92                         case POLICY_REFERENCE:
    93                         case ASSERTION_PARAMETER_NODE:
    94                             return true;
    95                         default:
    96                             return false;
    97                     }
    98                 case ASSERTION_PARAMETER_NODE:
    99                     switch (childType) {
   100                         case ASSERTION_PARAMETER_NODE:
   101                             return true;
   102                         default:
   103                             return false;
   104                     }
   105                 default:
   106                     throw LOGGER.logSevereException(new IllegalStateException(
   107                             LocalizationMessages.WSP_0060_POLICY_ELEMENT_TYPE_UNKNOWN(this)));
   108             }
   109         }
   110     }
   112     // comon model node attributes
   113     private LinkedList<ModelNode> children;
   114     private Collection<ModelNode> unmodifiableViewOnContent;
   115     private final ModelNode.Type type;
   116     private ModelNode parentNode;
   117     private PolicySourceModel parentModel;
   119     // attributes used only in 'POLICY_REFERENCE' model node
   120     private PolicyReferenceData referenceData;
   121     private PolicySourceModel referencedModel;
   123     // attibutes used only in 'ASSERTION' or 'ASSERTION_PARAMETER_NODE' model node
   124     private AssertionData nodeData;
   126     /**
   127      * The factory method creates and initializes the POLICY model node and sets it's parent model reference to point to
   128      * the model supplied as an input parameter. This method is intended to be used ONLY from {@link PolicySourceModel} during
   129      * the initialization of its own internal structures.
   130      *
   131      * @param model policy source model to be used as a parent model of the newly created {@link ModelNode}. Must not be {@code null}
   132      * @return POLICY model node with the parent model reference initialized to the model supplied as an input parameter
   133      * @throws IllegalArgumentException if the {@code model} input parameter is {@code null}
   134      */
   135     static ModelNode createRootPolicyNode(final PolicySourceModel model) throws IllegalArgumentException {
   136         if (model == null) {
   137             throw LOGGER.logSevereException(new IllegalArgumentException(LocalizationMessages.WSP_0039_POLICY_SRC_MODEL_INPUT_PARAMETER_MUST_NOT_BE_NULL()));
   138         }
   139         return new ModelNode(ModelNode.Type.POLICY, model);
   140     }
   142     private ModelNode(Type type, PolicySourceModel parentModel) {
   143         this.type = type;
   144         this.parentModel = parentModel;
   145         this.children = new LinkedList<ModelNode>();
   146         this.unmodifiableViewOnContent = Collections.unmodifiableCollection(this.children);
   147     }
   149     private ModelNode(Type type, PolicySourceModel parentModel, AssertionData data) {
   150         this(type, parentModel);
   152         this.nodeData = data;
   153     }
   155     private ModelNode(PolicySourceModel parentModel, PolicyReferenceData data) {
   156         this(Type.POLICY_REFERENCE, parentModel);
   158         this.referenceData = data;
   159     }
   161     private void checkCreateChildOperationSupportForType(final Type type) throws UnsupportedOperationException {
   162         if (!this.type.isChildTypeSupported(type)) {
   163             throw LOGGER.logSevereException(new UnsupportedOperationException(LocalizationMessages.WSP_0073_CREATE_CHILD_NODE_OPERATION_NOT_SUPPORTED(type, this.type)));
   164         }
   165     }
   167     /**
   168      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   169      * Each node is created with respect to its enclosing policy source model.
   170      *
   171      * @return A new Policy node.
   172      */
   173     public ModelNode createChildPolicyNode() {
   174         checkCreateChildOperationSupportForType(Type.POLICY);
   176         final ModelNode node = new ModelNode(ModelNode.Type.POLICY, parentModel);
   177         this.addChild(node);
   179         return node;
   180     }
   182     /**
   183      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   184      * Each node is created with respect to its enclosing policy source model.
   185      *
   186      * @return A new All node.
   187      */
   188     public ModelNode createChildAllNode() {
   189         checkCreateChildOperationSupportForType(Type.ALL);
   191         final ModelNode node = new ModelNode(ModelNode.Type.ALL, parentModel);
   192         this.addChild(node);
   194         return node;
   195     }
   197     /**
   198      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   199      * Each node is created with respect to its enclosing policy source model.
   200      *
   201      * @return A new ExactlyOne node.
   202      */
   203     public ModelNode createChildExactlyOneNode() {
   204         checkCreateChildOperationSupportForType(Type.EXACTLY_ONE);
   206         final ModelNode node = new ModelNode(ModelNode.Type.EXACTLY_ONE, parentModel);
   207         this.addChild(node);
   209         return node;
   210     }
   212     /**
   213      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   214      * Each node is created with respect to its enclosing policy source model.
   215      *
   216      * @return A new policy assertion node.
   217      */
   218     public ModelNode createChildAssertionNode() {
   219         checkCreateChildOperationSupportForType(Type.ASSERTION);
   221         final ModelNode node = new ModelNode(ModelNode.Type.ASSERTION, parentModel);
   222         this.addChild(node);
   224         return node;
   225     }
   227     /**
   228      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   229      * Each node is created with respect to its enclosing policy source model.
   230      *
   231      * @param nodeData The policy assertion data.
   232      * @return A new policy assertion node.
   233      */
   234     public ModelNode createChildAssertionNode(final AssertionData nodeData) {
   235         checkCreateChildOperationSupportForType(Type.ASSERTION);
   237         final ModelNode node = new ModelNode(Type.ASSERTION, parentModel, nodeData);
   238         this.addChild(node);
   240         return node;
   241     }
   243     /**
   244      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   245      * Each node is created with respect to its enclosing policy source model.
   246      *
   247      * @return A new assertion parameter node.
   248      */
   249     public ModelNode createChildAssertionParameterNode() {
   250         checkCreateChildOperationSupportForType(Type.ASSERTION_PARAMETER_NODE);
   252         final ModelNode node = new ModelNode(ModelNode.Type.ASSERTION_PARAMETER_NODE, parentModel);
   253         this.addChild(node);
   255         return node;
   256     }
   258     /**
   259      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   260      * Each node is created with respect to its enclosing policy source model.
   261      *
   262      * @param nodeData The assertion parameter data.
   263      * @return A new assertion parameter node.
   264      */
   265     ModelNode createChildAssertionParameterNode(final AssertionData nodeData) {
   266         checkCreateChildOperationSupportForType(Type.ASSERTION_PARAMETER_NODE);
   268         final ModelNode node = new ModelNode(Type.ASSERTION_PARAMETER_NODE, parentModel, nodeData);
   269         this.addChild(node);
   271         return node;
   272     }
   274     /**
   275      * Factory method that creates new policy source model node as specified by a factory method name and input parameters.
   276      * Each node is created with respect to its enclosing policy source model.
   277      *
   278      * @param referenceData The PolicyReference data.
   279      * @return A new PolicyReference node.
   280      */
   281     ModelNode createChildPolicyReferenceNode(final PolicyReferenceData referenceData) {
   282         checkCreateChildOperationSupportForType(Type.POLICY_REFERENCE);
   284         final ModelNode node = new ModelNode(parentModel, referenceData);
   285         this.parentModel.addNewPolicyReference(node);
   286         this.addChild(node);
   288         return node;
   289     }
   291     Collection<ModelNode> getChildren() {
   292         return unmodifiableViewOnContent;
   293     }
   295     /**
   296      * Sets the parent model reference on the node and its children. The method may be invoked only on the root node
   297      * of the policy source model (or - in general - on a model node that dose not reference a parent node). Otherwise an
   298      * exception is thrown.
   299      *
   300      * @param model new parent policy source model to be set.
   301      * @throws IllegalAccessException in case this node references a parent node (i.e. is not a root node of the model).
   302      */
   303     void setParentModel(final PolicySourceModel model) throws IllegalAccessException {
   304         if (parentNode != null) {
   305             throw LOGGER.logSevereException(new IllegalAccessException(LocalizationMessages.WSP_0049_PARENT_MODEL_CAN_NOT_BE_CHANGED()));
   306         }
   308         this.updateParentModelReference(model);
   309     }
   311     /**
   312      * The method updates the parentModel reference on current model node instance and all of it's children
   313      *
   314      * @param model new policy source model reference.
   315      */
   316     private void updateParentModelReference(final PolicySourceModel model) {
   317         this.parentModel = model;
   319         for (ModelNode child : children) {
   320             child.updateParentModelReference(model);
   321         }
   322     }
   324     /**
   325      * Returns the parent policy source model that contains this model node.
   326      *
   327      * @return the parent policy source model
   328      */
   329     public PolicySourceModel getParentModel() {
   330         return parentModel;
   331     }
   333     /**
   334      * Returns the type of this policy source model node.
   335      *
   336      * @return actual type of this policy source model node
   337      */
   338     public ModelNode.Type getType() {
   339         return type;
   340     }
   342     /**
   343      * Returns the parent referenced by this policy source model node.
   344      *
   345      * @return current parent of this policy source model node or {@code null} if the node does not have a parent currently.
   346      */
   347     public ModelNode getParentNode() {
   348         return parentNode;
   349     }
   351     /**
   352      * Returns the data for this policy source model node (if any). The model node data are expected to be not {@code null} only in
   353      * case the type of this node is ASSERTION or ASSERTION_PARAMETER_NODE.
   354      *
   355      * @return the data of this policy source model node or {@code null} if the node does not have any data associated to it
   356      * attached.
   357      */
   358     public AssertionData getNodeData() {
   359         return nodeData;
   360     }
   362     /**
   363      * Returns the policy reference data for this policy source model node. The policy reference data are expected to be not {@code null} only in
   364      * case the type of this node is POLICY_REFERENCE.
   365      *
   366      * @return the policy reference data for this policy source model node or {@code null} if the node does not have any policy reference data
   367      * attached.
   368      */
   369     PolicyReferenceData getPolicyReferenceData() {
   370         return referenceData;
   371     }
   373     /**
   374      * The method may be used to set or replace assertion data set for this node. If there are assertion data set already,
   375      * those are replaced by a new reference and eventualy returned from the method.
   376      * <p/>
   377      * This method is supported only in case this model node instance's type is {@code ASSERTION} or {@code ASSERTION_PARAMETER_NODE}.
   378      * If used from other node types, an exception is thrown.
   379      *
   380      * @param newData new assertion data to be set.
   381      * @return old and replaced assertion data if any or {@code null} otherwise.
   382      *
   383      * @throws UnsupportedOperationException in case this method is called on nodes of type other than {@code ASSERTION}
   384      * or {@code ASSERTION_PARAMETER_NODE}
   385      */
   386     public AssertionData setOrReplaceNodeData(final AssertionData newData) {
   387         if (!isDomainSpecific()) {
   388             throw LOGGER.logSevereException(new UnsupportedOperationException(LocalizationMessages.WSP_0051_OPERATION_NOT_SUPPORTED_FOR_THIS_BUT_ASSERTION_RELATED_NODE_TYPE(type)));
   389         }
   391         final AssertionData oldData = this.nodeData;
   392         this.nodeData = newData;
   394         return oldData;
   395     }
   397     /**
   398      * The method specifies whether the model node instance represents assertion related node, it means whether its type
   399      * is 'ASSERTION' or 'ASSERTION_PARAMETER_NODE'. This is, for example, the way to determine whether the node supports
   400      * setting a {@link AssertionData} object via {@link #setOrReplaceNodeData(AssertionData)} method or not.
   401      *
   402      * @return {@code true} or {@code false} according to whether the node instance represents assertion related node or not.
   403      */
   404     boolean isDomainSpecific() {
   405         return type == Type.ASSERTION || type == Type.ASSERTION_PARAMETER_NODE;
   406     }
   408     /**
   409      * Appends the specified child node to the end of the children list of this node and sets it's parent to reference
   410      * this node.
   411      *
   412      * @param child node to be appended to the children list of this node.
   413      * @return {@code true} (as per the general contract of the {@code Collection.add} method).
   414      *
   415      * @throws NullPointerException if the specified node is {@code null}.
   416      * @throws IllegalArgumentException if child has a parent node set already to point to some node
   417      */
   418     private boolean addChild(final ModelNode child) {
   419         children.add(child);
   420         child.parentNode = this;
   422         return true;
   423     }
   425     void setReferencedModel(final PolicySourceModel model) {
   426         if (this.type != Type.POLICY_REFERENCE) {
   427             throw LOGGER.logSevereException(new UnsupportedOperationException(LocalizationMessages.WSP_0050_OPERATION_NOT_SUPPORTED_FOR_THIS_BUT_POLICY_REFERENCE_NODE_TYPE(type)));
   428         }
   430         referencedModel = model;
   431     }
   433     PolicySourceModel getReferencedModel() {
   434         return referencedModel;
   435     }
   437     /**
   438      * Returns the number of child policy source model nodes. If this model node contains
   439      * more than {@code Integer.MAX_VALUE} children, returns {@code Integer.MAX_VALUE}.
   440      *
   441      * @return the number of children of this node.
   442      */
   443     public int childrenSize() {
   444         return children.size();
   445     }
   447     /**
   448      * Returns true if the node has at least one child node.
   449      *
   450      * @return true if the node has at least one child node, false otherwise.
   451      */
   452     public boolean hasChildren() {
   453         return !children.isEmpty();
   454     }
   456     /**
   457      * Iterates through all child nodes.
   458      *
   459      * @return An iterator for the child nodes
   460      */
   461     public Iterator<ModelNode> iterator() {
   462         return children.iterator();
   463     }
   465     /**
   466      * An {@code Object.equals(Object obj)} method override. Method ignores the parent source model. It means that two
   467      * model nodes may be the same even if they belong to different models.
   468      * <p/>
   469      * If parent model comparison is desired, it must be accomplished separately. To perform that, the reference equality
   470      * test is sufficient ({@code nodeA.getParentModel() == nodeB.getParentModel()}), since all model nodes are created
   471      * for specific model instances.
   472      */
   473     @Override
   474     public boolean equals(final Object obj) {
   475         if (this == obj) {
   476             return true;
   477         }
   479         if (!(obj instanceof ModelNode)) {
   480             return false;
   481         }
   483         boolean result = true;
   484         final ModelNode that = (ModelNode) obj;
   486         result = result && this.type.equals(that.type);
   487         // result = result && ((this.parentNode == null) ? that.parentNode == null : this.parentNode.equals(that.parentNode));
   488         result = result && ((this.nodeData == null) ? that.nodeData == null : this.nodeData.equals(that.nodeData));
   489         result = result && ((this.children == null) ? that.children == null : this.children.equals(that.children));
   491         return result;
   492     }
   494     /**
   495      * An {@code Object.hashCode()} method override.
   496      */
   497     @Override
   498     public int hashCode() {
   499         int result = 17;
   501         result = 37 * result + this.type.hashCode();
   502         result = 37 * result + ((this.parentNode == null) ? 0 : this.parentNode.hashCode());
   503         result = 37 * result + ((this.nodeData == null) ? 0 : this.nodeData.hashCode());
   504         result = 37 * result + this.children.hashCode();
   506         return result;
   507     }
   509     /**
   510      * Returns a string representation of the object. In general, the <code>toString</code> method
   511      * returns a string that "textually represents" this object.
   512      *
   513      * @return  a string representation of the object.
   514      */
   515     @Override
   516     public String toString() {
   517         return toString(0, new StringBuffer()).toString();
   518     }
   520     /**
   521      * A helper method that appends indented string representation of this instance to the input string buffer.
   522      *
   523      * @param indentLevel indentation level to be used.
   524      * @param buffer buffer to be used for appending string representation of this instance
   525      * @return modified buffer containing new string representation of the instance
   526      */
   527     public StringBuffer toString(final int indentLevel, final StringBuffer buffer) {
   528         final String indent = PolicyUtils.Text.createIndent(indentLevel);
   529         final String innerIndent = PolicyUtils.Text.createIndent(indentLevel + 1);
   531         buffer.append(indent).append(type).append(" {").append(PolicyUtils.Text.NEW_LINE);
   532         if (type == Type.ASSERTION) {
   533             if (nodeData == null) {
   534                 buffer.append(innerIndent).append("no assertion data set");
   535             } else {
   536                 nodeData.toString(indentLevel + 1, buffer);
   537             }
   538             buffer.append(PolicyUtils.Text.NEW_LINE);
   539         } else if (type == Type.POLICY_REFERENCE) {
   540             if (referenceData == null) {
   541                 buffer.append(innerIndent).append("no policy reference data set");
   542             } else {
   543                 referenceData.toString(indentLevel + 1, buffer);
   544             }
   545             buffer.append(PolicyUtils.Text.NEW_LINE);
   546         } else if (type == Type.ASSERTION_PARAMETER_NODE) {
   547             if (nodeData == null) {
   548                 buffer.append(innerIndent).append("no parameter data set");
   549             }
   550             else {
   551                 nodeData.toString(indentLevel + 1, buffer);
   552             }
   553             buffer.append(PolicyUtils.Text.NEW_LINE);
   554         }
   556         if (children.size() > 0) {
   557             for (ModelNode child : children) {
   558                 child.toString(indentLevel + 1, buffer).append(PolicyUtils.Text.NEW_LINE);
   559             }
   560         } else {
   561             buffer.append(innerIndent).append("no child nodes").append(PolicyUtils.Text.NEW_LINE);
   562         }
   564         buffer.append(indent).append('}');
   565         return buffer;
   566     }
   568     @Override
   569     protected ModelNode clone() throws CloneNotSupportedException {
   570         final ModelNode clone = (ModelNode) super.clone();
   572         if (this.nodeData != null) {
   573             clone.nodeData = this.nodeData.clone();
   574         }
   576         // no need to clone PolicyReferenceData, since those are immutable
   578         if (this.referencedModel != null) {
   579             clone.referencedModel = this.referencedModel.clone();
   580         }
   583         clone.children = new LinkedList<ModelNode>();
   584         clone.unmodifiableViewOnContent = Collections.unmodifiableCollection(clone.children);
   586         for (ModelNode thisChild : this.children) {
   587             clone.addChild(thisChild.clone());
   588         }
   590         return clone;
   591     }
   593     PolicyReferenceData getReferenceData() {
   594         return referenceData;
   595     }
   596 }

mercurial