aoqi@0: /*
aoqi@0: * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0: *
aoqi@0: * This code is free software; you can redistribute it and/or modify it
aoqi@0: * under the terms of the GNU General Public License version 2 only, as
aoqi@0: * published by the Free Software Foundation. Oracle designates this
aoqi@0: * particular file as subject to the "Classpath" exception as provided
aoqi@0: * by Oracle in the LICENSE file that accompanied this code.
aoqi@0: *
aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0: * accompanied this code).
aoqi@0: *
aoqi@0: * You should have received a copy of the GNU General Public License version
aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0: *
aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0: * or visit www.oracle.com if you need additional information or have any
aoqi@0: * questions.
aoqi@0: */
aoqi@0:
aoqi@0: package com.sun.xml.internal.ws.policy.sourcemodel;
aoqi@0:
aoqi@0: import com.sun.xml.internal.ws.policy.PolicyConstants;
aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.LocalizationMessages;
aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.PolicyLogger;
aoqi@0: import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
aoqi@0:
aoqi@0: import java.io.Serializable;
aoqi@0: import java.util.HashMap;
aoqi@0: import java.util.HashSet;
aoqi@0: import java.util.Map;
aoqi@0: import java.util.Set;
aoqi@0: import javax.xml.namespace.QName;
aoqi@0:
aoqi@0: /**
aoqi@0: * Wrapper class for possible data that each "assertion" and "assertion parameter content" policy source model node may
aoqi@0: * have attached.
aoqi@0: *
aoqi@0: * This data, when stored in an 'assertion' model node, is intended to be used as input parameter when creating
aoqi@0: * {@link com.sun.xml.internal.ws.policy.PolicyAssertion} objects via {@link com.sun.xml.internal.ws.policy.spi.PolicyAssertionCreator}
aoqi@0: * implementations.
aoqi@0: *
aoqi@0: * @author Marek Potociar (marek.potociar@sun.com)
aoqi@0: * @author Fabian Ritzmann
aoqi@0: */
aoqi@0: public final class AssertionData implements Cloneable, Serializable {
aoqi@0: private static final long serialVersionUID = 4416256070795526315L;
aoqi@0: private static final PolicyLogger LOGGER = PolicyLogger.getLogger(AssertionData.class);
aoqi@0:
aoqi@0: private final QName name;
aoqi@0: private final String value;
aoqi@0: private final Map attributes;
aoqi@0: private ModelNode.Type type;
aoqi@0:
aoqi@0: private boolean optional;
aoqi@0: private boolean ignorable;
aoqi@0:
aoqi@0: /**
aoqi@0: * Constructs assertion data wrapper instance for an assertion that does not
aoqi@0: * contain any value nor any attributes.
aoqi@0: *
aoqi@0: * @param name the FQN of the assertion
aoqi@0: *
aoqi@0: * @throws IllegalArgumentException in case the {@code type} parameter is not
aoqi@0: * {@link ModelNode.Type#ASSERTION ASSERTION} or
aoqi@0: * {@link ModelNode.Type#ASSERTION_PARAMETER_NODE ASSERTION_PARAMETER_NODE}
aoqi@0: */
aoqi@0: public static AssertionData createAssertionData(final QName name) throws IllegalArgumentException {
aoqi@0: return new AssertionData(name, null, null, ModelNode.Type.ASSERTION, false, false);
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Constructs assertion data wrapper instance for an assertion parameter that
aoqi@0: * does not contain any value nor any attributes.
aoqi@0: *
aoqi@0: * @param name the FQN of the assertion parameter
aoqi@0: *
aoqi@0: * @throws IllegalArgumentException in case the {@code type} parameter is not
aoqi@0: * {@link ModelNode.Type#ASSERTION ASSERTION} or
aoqi@0: * {@link ModelNode.Type#ASSERTION_PARAMETER_NODE ASSERTION_PARAMETER_NODE}
aoqi@0: */
aoqi@0: public static AssertionData createAssertionParameterData(final QName name) throws IllegalArgumentException {
aoqi@0: return new AssertionData(name, null, null, ModelNode.Type.ASSERTION_PARAMETER_NODE, false, false);
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Constructs assertion data wrapper instance for an assertion that does
aoqi@0: * contain a value or attributes.
aoqi@0: *
aoqi@0: * @param name the FQN of the assertion
aoqi@0: * @param value a {@link String} representation of model node value
aoqi@0: * @param attributes map of model node's <attribute name, attribute value> pairs
aoqi@0: * @param optional flag indicating whether the assertion is optional or not
aoqi@0: * @param ignorable flag indicating whether the assertion is ignorable or not
aoqi@0: *
aoqi@0: * @throws IllegalArgumentException in case the {@code type} parameter is not
aoqi@0: * {@link ModelNode.Type#ASSERTION ASSERTION} or
aoqi@0: * {@link ModelNode.Type#ASSERTION_PARAMETER_NODE ASSERTION_PARAMETER_NODE}
aoqi@0: */
aoqi@0: public static AssertionData createAssertionData(final QName name, final String value, final Map attributes, boolean optional, boolean ignorable) throws IllegalArgumentException {
aoqi@0: return new AssertionData(name, value, attributes, ModelNode.Type.ASSERTION, optional, ignorable);
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Constructs assertion data wrapper instance for an assertion parameter that
aoqi@0: * contains a value or attributes
aoqi@0: *
aoqi@0: * @param name the FQN of the assertion parameter
aoqi@0: * @param value a {@link String} representation of model node value
aoqi@0: * @param attributes map of model node's <attribute name, attribute value> pairs
aoqi@0: *
aoqi@0: * @throws IllegalArgumentException in case the {@code type} parameter is not
aoqi@0: * {@link ModelNode.Type#ASSERTION ASSERTION} or
aoqi@0: * {@link ModelNode.Type#ASSERTION_PARAMETER_NODE ASSERTION_PARAMETER_NODE}
aoqi@0: */
aoqi@0: public static AssertionData createAssertionParameterData(final QName name, final String value, final Map attributes) throws IllegalArgumentException {
aoqi@0: return new AssertionData(name, value, attributes, ModelNode.Type.ASSERTION_PARAMETER_NODE, false, false);
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Constructs assertion data wrapper instance for an assertion or assertion parameter that contains a value or
aoqi@0: * some attributes. Whether the data wrapper is constructed for assertion or assertion parameter node is distinguished by
aoqi@0: * the supplied {@code type} parameter.
aoqi@0: *
aoqi@0: * @param name the FQN of the assertion or assertion parameter
aoqi@0: * @param value a {@link String} representation of model node value
aoqi@0: * @param attributes map of model node's <attribute name, attribute value> pairs
aoqi@0: * @param type specifies whether the data will belong to the assertion or assertion parameter node. This is
aoqi@0: * a workaround solution that allows us to transfer this information about the owner node to
aoqi@0: * a policy assertion instance factory without actualy having to touch the {@link PolicyAssertionCreator}
aoqi@0: * interface and protected {@link PolicyAssertion} constructors.
aoqi@0: *
aoqi@0: * @throws IllegalArgumentException in case the {@code type} parameter is not
aoqi@0: * {@link ModelNode.Type#ASSERTION ASSERTION} or
aoqi@0: * {@link ModelNode.Type#ASSERTION_PARAMETER_NODE ASSERTION_PARAMETER_NODE}
aoqi@0: */
aoqi@0: AssertionData(QName name, String value, Map attributes, ModelNode.Type type, boolean optional, boolean ignorable) throws IllegalArgumentException {
aoqi@0: this.name = name;
aoqi@0: this.value = value;
aoqi@0: this.optional = optional;
aoqi@0: this.ignorable = ignorable;
aoqi@0:
aoqi@0: this.attributes = new HashMap();
aoqi@0: if (attributes != null && !attributes.isEmpty()) {
aoqi@0: this.attributes.putAll(attributes);
aoqi@0: }
aoqi@0: setModelNodeType(type);
aoqi@0: }
aoqi@0:
aoqi@0: private void setModelNodeType(final ModelNode.Type type) throws IllegalArgumentException {
aoqi@0: if (type == ModelNode.Type.ASSERTION || type == ModelNode.Type.ASSERTION_PARAMETER_NODE) {
aoqi@0: this.type = type;
aoqi@0: } else {
aoqi@0: throw LOGGER.logSevereException(new IllegalArgumentException(
aoqi@0: LocalizationMessages.WSP_0074_CANNOT_CREATE_ASSERTION_BAD_TYPE(type, ModelNode.Type.ASSERTION, ModelNode.Type.ASSERTION_PARAMETER_NODE)));
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Copy constructor.
aoqi@0: *
aoqi@0: * @param data The instance that is to be copied.
aoqi@0: */
aoqi@0: AssertionData(final AssertionData data) {
aoqi@0: this.name = data.name;
aoqi@0: this.value = data.value;
aoqi@0: this.attributes = new HashMap();
aoqi@0: if (!data.attributes.isEmpty()) {
aoqi@0: this.attributes.putAll(data.attributes);
aoqi@0: }
aoqi@0: this.type = data.type;
aoqi@0: }
aoqi@0:
aoqi@0: @Override
aoqi@0: protected AssertionData clone() throws CloneNotSupportedException {
aoqi@0: return (AssertionData) super.clone();
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Returns true if the given attribute exists, false otherwise.
aoqi@0: *
aoqi@0: * @param name The name of the attribute. Must not be null.
aoqi@0: * @return True if the given attribute exists, false otherwise.
aoqi@0: */
aoqi@0: public boolean containsAttribute(final QName name) {
aoqi@0: synchronized (attributes) {
aoqi@0: return attributes.containsKey(name);
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: @Override
aoqi@0: public boolean equals(final Object obj) {
aoqi@0: if (this == obj) {
aoqi@0: return true;
aoqi@0: }
aoqi@0:
aoqi@0: if (!(obj instanceof AssertionData)) {
aoqi@0: return false;
aoqi@0: }
aoqi@0:
aoqi@0: boolean result = true;
aoqi@0: final AssertionData that = (AssertionData) obj;
aoqi@0:
aoqi@0: result = result && this.name.equals(that.name);
aoqi@0: result = result && ((this.value == null) ? that.value == null : this.value.equals(that.value));
aoqi@0: synchronized (attributes) {
aoqi@0: result = result && this.attributes.equals(that.attributes);
aoqi@0: }
aoqi@0:
aoqi@0: return result;
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: /**
aoqi@0: * Returns the value of the given attribute. Returns null if the attribute
aoqi@0: * does not exist.
aoqi@0: *
aoqi@0: * @param name The name of the attribute. Must not be null.
aoqi@0: * @return The value of the given attribute. Returns null if the attribute
aoqi@0: * does not exist.
aoqi@0: */
aoqi@0: public String getAttributeValue(final QName name) {
aoqi@0: synchronized (attributes) {
aoqi@0: return attributes.get(name);
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: /**
aoqi@0: * Returns the disconnected map of attributes attached to the assertion.
aoqi@0: *
aoqi@0: * 'Disconnected' means, that the result of this method will not be synchronized with any consequent assertion's attribute modification. It is
aoqi@0: * also important to notice that a manipulation with returned set of attributes will not have any effect on the actual assertion's
aoqi@0: * attributes.
aoqi@0: *
aoqi@0: * @return disconnected map of attributes attached to the assertion.
aoqi@0: */
aoqi@0: public Map getAttributes() {
aoqi@0: synchronized (attributes) {
aoqi@0: return new HashMap(attributes);
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: /**
aoqi@0: * Returns the disconnected set of attributes attached to the assertion. Each attribute is represented as a single
aoqi@0: * {@code Map.Entry} element.
aoqi@0: *
aoqi@0: * 'Disconnected' means, that the result of this method will not be synchronized with any consequent assertion's attribute modification. It is
aoqi@0: * also important to notice that a manipulation with returned set of attributes will not have any effect on the actual assertion's
aoqi@0: * attributes.
aoqi@0: *
aoqi@0: * @return disconnected set of attributes attached to the assertion.
aoqi@0: */
aoqi@0: public Set> getAttributesSet() {
aoqi@0: synchronized (attributes) {
aoqi@0: return new HashSet>(attributes.entrySet());
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: /**
aoqi@0: * Returns the name of the assertion.
aoqi@0: *
aoqi@0: * @return assertion's name
aoqi@0: */
aoqi@0: public QName getName() {
aoqi@0: return name;
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: /**
aoqi@0: * Returns the value of the assertion.
aoqi@0: *
aoqi@0: * @return assertion's value
aoqi@0: */
aoqi@0: public String getValue() {
aoqi@0: return value;
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: /**
aoqi@0: * An {@code Object.hashCode()} method override.
aoqi@0: */
aoqi@0: @Override
aoqi@0: public int hashCode() {
aoqi@0: int result = 17;
aoqi@0:
aoqi@0: result = 37 * result + this.name.hashCode();
aoqi@0: result = 37 * result + ((this.value == null) ? 0 : this.value.hashCode());
aoqi@0: synchronized (attributes) {
aoqi@0: result = 37 * result + this.attributes.hashCode();
aoqi@0: }
aoqi@0: return result;
aoqi@0: }
aoqi@0:
aoqi@0:
aoqi@0: /**
aoqi@0: * Method specifies whether the assertion data contain proprietary visibility element set to "private" value.
aoqi@0: *
aoqi@0: * @return {@code 'true'} if the attribute is present and set properly (i.e. the node containing this assertion data instance should
aoqi@0: * not be marshaled into generated WSDL documents). Returns {@code false} otherwise.
aoqi@0: */
aoqi@0: public boolean isPrivateAttributeSet() {
aoqi@0: return PolicyConstants.VISIBILITY_VALUE_PRIVATE.equals(getAttributeValue(PolicyConstants.VISIBILITY_ATTRIBUTE));
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Removes the given attribute from the assertion data.
aoqi@0: *
aoqi@0: * @param name The name of the attribute. Must not be null
aoqi@0: * @return The value of the removed attribute.
aoqi@0: */
aoqi@0: public String removeAttribute(final QName name) {
aoqi@0: synchronized (attributes) {
aoqi@0: return attributes.remove(name);
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Adds or overwrites an attribute.
aoqi@0: *
aoqi@0: * @param name The name of the attribute.
aoqi@0: * @param value The value of the attribute.
aoqi@0: */
aoqi@0: public void setAttribute(final QName name, final String value) {
aoqi@0: synchronized (attributes) {
aoqi@0: attributes.put(name, value);
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Sets the optional attribute.
aoqi@0: *
aoqi@0: * @param value The value of the optional attribute.
aoqi@0: */
aoqi@0: public void setOptionalAttribute(final boolean value) {
aoqi@0: optional = value;
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Tests if the optional attribute is set.
aoqi@0: *
aoqi@0: * @return True if optional is set and is true. False otherwise.
aoqi@0: */
aoqi@0: public boolean isOptionalAttributeSet() {
aoqi@0: return optional;
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Sets the ignorable attribute.
aoqi@0: *
aoqi@0: * @param value The value of the ignorable attribute.
aoqi@0: */
aoqi@0: public void setIgnorableAttribute(final boolean value) {
aoqi@0: ignorable = value;
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * Tests if the ignorable attribute is set.
aoqi@0: *
aoqi@0: * @return True if ignorable is set and is true. False otherwise.
aoqi@0: */
aoqi@0: public boolean isIgnorableAttributeSet() {
aoqi@0: return ignorable;
aoqi@0: }
aoqi@0:
aoqi@0: @Override
aoqi@0: public String toString() {
aoqi@0: return toString(0, new StringBuffer()).toString();
aoqi@0: }
aoqi@0:
aoqi@0: /**
aoqi@0: * A helper method that appends indented string representation of this instance to the input string buffer.
aoqi@0: *
aoqi@0: * @param indentLevel indentation level to be used.
aoqi@0: * @param buffer buffer to be used for appending string representation of this instance
aoqi@0: * @return modified buffer containing new string representation of the instance
aoqi@0: */
aoqi@0: public StringBuffer toString(final int indentLevel, final StringBuffer buffer) {
aoqi@0: final String indent = PolicyUtils.Text.createIndent(indentLevel);
aoqi@0: final String innerIndent = PolicyUtils.Text.createIndent(indentLevel + 1);
aoqi@0: final String innerDoubleIndent = PolicyUtils.Text.createIndent(indentLevel + 2);
aoqi@0:
aoqi@0: buffer.append(indent);
aoqi@0: if (type == ModelNode.Type.ASSERTION) {
aoqi@0: buffer.append("assertion data {");
aoqi@0: } else {
aoqi@0: buffer.append("assertion parameter data {");
aoqi@0: }
aoqi@0: buffer.append(PolicyUtils.Text.NEW_LINE);
aoqi@0:
aoqi@0: buffer.append(innerIndent).append("namespace = '").append(name.getNamespaceURI()).append('\'').append(PolicyUtils.Text.NEW_LINE);
aoqi@0: buffer.append(innerIndent).append("prefix = '").append(name.getPrefix()).append('\'').append(PolicyUtils.Text.NEW_LINE);
aoqi@0: buffer.append(innerIndent).append("local name = '").append(name.getLocalPart()).append('\'').append(PolicyUtils.Text.NEW_LINE);
aoqi@0: buffer.append(innerIndent).append("value = '").append(value).append('\'').append(PolicyUtils.Text.NEW_LINE);
aoqi@0: buffer.append(innerIndent).append("optional = '").append(optional).append('\'').append(PolicyUtils.Text.NEW_LINE);
aoqi@0: buffer.append(innerIndent).append("ignorable = '").append(ignorable).append('\'').append(PolicyUtils.Text.NEW_LINE);
aoqi@0: synchronized (attributes) {
aoqi@0: if (attributes.isEmpty()) {
aoqi@0: buffer.append(innerIndent).append("no attributes");
aoqi@0: } else {
aoqi@0:
aoqi@0: buffer.append(innerIndent).append("attributes {").append(PolicyUtils.Text.NEW_LINE);
aoqi@0: for(Map.Entry entry : attributes.entrySet()) {
aoqi@0: final QName aName = entry.getKey();
aoqi@0: buffer.append(innerDoubleIndent).append("name = '").append(aName.getNamespaceURI()).append(':').append(aName.getLocalPart());
aoqi@0: buffer.append("', value = '").append(entry.getValue()).append('\'').append(PolicyUtils.Text.NEW_LINE);
aoqi@0: }
aoqi@0: buffer.append(innerIndent).append('}');
aoqi@0: }
aoqi@0: }
aoqi@0:
aoqi@0: buffer.append(PolicyUtils.Text.NEW_LINE).append(indent).append('}');
aoqi@0:
aoqi@0: return buffer;
aoqi@0: }
aoqi@0:
aoqi@0: public ModelNode.Type getNodeType() {
aoqi@0: return type;
aoqi@0: }
aoqi@0:
aoqi@0: }