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