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

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 }

mercurial