001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.policy;
038:
039: import java.util.Collection;
040: import java.util.Iterator;
041: import java.util.Map;
042: import java.util.Set;
043: import javax.xml.namespace.QName;
044: import com.sun.xml.ws.policy.privateutil.PolicyUtils;
045: import com.sun.xml.ws.policy.sourcemodel.AssertionData;
046: import com.sun.xml.ws.policy.sourcemodel.ModelNode;
047:
048: /**
049: * Base class for any policy assertion implementations. It defines the common
050: * interface and provides some default implentation for common policy assertion
051: * functionality.
052: * <p/>
053: * NOTE: Assertion implementers should not extend this class directly. {@link SimpleAssertion}
054: * or {@link ComplexAssertion} should be used as a base class instead.
055: *
056: * @author Marek Potociar (marek.potociar at sun.com)
057: */
058: public abstract class PolicyAssertion {
059:
060: private final AssertionData data;
061: private AssertionSet parameters;
062: private NestedPolicy nestedPolicy; // TODO: remove
063:
064: protected PolicyAssertion() {
065: this .data = AssertionData.createAssertionData(null);
066: this .parameters = AssertionSet.createAssertionSet(null);
067: }
068:
069: /**
070: * Creates generic assertionand stores the data specified in input parameters
071: *
072: * @param assertionData assertion creation data specifying the details of newly created assertion. May be {@code null}.
073: * @param assertionParameters collection of assertions parameters of this policy assertion. May be {@code null}.
074: * @param nestedAlternative assertion set specifying nested policy alternative. May be {@code null}.
075: */
076: @Deprecated
077: protected PolicyAssertion(
078: final AssertionData assertionData,
079: final Collection<? extends PolicyAssertion> assertionParameters,
080: final AssertionSet nestedAlternative) {
081: this .data = assertionData;
082: if (nestedAlternative != null) {
083: this .nestedPolicy = NestedPolicy
084: .createNestedPolicy(nestedAlternative);
085: }
086:
087: this .parameters = AssertionSet
088: .createAssertionSet(assertionParameters);
089: }
090:
091: /**
092: * Creates generic assertionand stores the data specified in input parameters
093: *
094: * @param assertionData assertion creation data specifying the details of newly created assertion
095: * @param assertionParameters collection of assertions parameters of this policy assertion. May be {@code null}.
096: */
097: protected PolicyAssertion(
098: final AssertionData assertionData,
099: final Collection<? extends PolicyAssertion> assertionParameters) {
100: if (assertionData == null) {
101: this .data = AssertionData.createAssertionData(null);
102: } else {
103: this .data = assertionData;
104: }
105: this .parameters = AssertionSet
106: .createAssertionSet(assertionParameters);
107: }
108:
109: /**
110: * Returns the fully qualified name of the assertion.
111: *
112: * @return assertion's fully qualified name.
113: */
114: public final QName getName() {
115: return data.getName();
116: }
117:
118: /**
119: * Returns the value of the assertion - the character data content contained in the assertion element representation.
120: *
121: * @return assertion's value. May return {@code null} if there is no value set for the assertion.
122: */
123: public final String getValue() {
124: return data.getValue();
125: }
126:
127: /**
128: * Method specifies whether the assertion is otpional or not.
129: * <p/>
130: * This is a default implementation that may be overriden. The method returns {@code true} if the {@code wsp:optional} attribute
131: * is present on the assertion and its value is {@code 'true'}. Otherwise the method returns {@code false}.
132: *
133: * @return {@code 'true'} if the assertion is optional. Returns {@code false} otherwise.
134: */
135: public boolean isOptional() {
136: boolean result = false;
137: final String attributeValue = getAttributeValue(PolicyConstants.OPTIONAL);
138: if (attributeValue != null) {
139: result = Boolean.parseBoolean(attributeValue);
140: }
141:
142: return result;
143: }
144:
145: /**
146: * Method specifies whether the assertion is ignorable or not.
147: * <p/>
148: * This is a default implementation that may be overriden. The method returns {@code true} if the {@code wsp:Ignorable} attribute
149: * is present on the assertion and its value is {@code 'true'}. Otherwise the method returns {@code false}.
150: *
151: * @return {@code 'true'} if the assertion is ignorable. Returns {@code false} otherwise.
152: */
153: public boolean isIgnorable() {
154: boolean result = false;
155: final String attributeValue = getAttributeValue(PolicyConstants.IGNORABLE);
156: if (attributeValue != null) {
157: result = Boolean.parseBoolean(attributeValue);
158: }
159:
160: return result;
161: }
162:
163: /**
164: * Method specifies whether the assertion is private or not. This is specified by our proprietary visibility element.
165: *
166: * @return {@code 'true'} if the assertion is marked as private (i.e. should not be marshalled int generated WSDL documents). Returns {@code false} otherwise.
167: */
168: public final boolean isPrivate() {
169: return data.isPrivateAttributeSet();
170: }
171:
172: /**
173: * Returns the disconnected set of attributes attached to the assertion. Each attribute is represented as a single
174: * {@code Map.Entry<attributeName, attributeValue>} element.
175: * <p/>
176: * 'Disconnected' means, that the result of this method will not be synchronized with any consequent assertion's attribute modification. It is
177: * also important to notice that a manipulation with returned set of attributes will not have any effect on the actual assertion's
178: * attributes.
179: *
180: * @return disconected set of attributes attached to the assertion.
181: */
182: public final Set<Map.Entry<QName, String>> getAttributesSet() {
183: return data.getAttributesSet();
184: }
185:
186: /**
187: * Returns the disconnected map of attributes attached to the assertion.
188: * <p/>
189: * 'Disconnected' means, that the result of this method will not be synchronized with any consequent assertion's attribute modification. It is
190: * also important to notice that a manipulation with returned set of attributes will not have any effect on the actual assertion's
191: * attributes.
192: *
193: * @return disconnected map of attributes attached to the assertion.
194: */
195: public final Map<QName, String> getAttributes() {
196: return data.getAttributes();
197: }
198:
199: /**
200: * Returns the value of an attribute. Returns null if an attribute with the given name does not exist.
201: *
202: * @param name The fully qualified name of the attribute
203: * @return The value of the attribute. Returns {@code null} if there is no such attribute or if it's value is null.
204: */
205: public final String getAttributeValue(final QName name) {
206: return data.getAttributeValue(name);
207: }
208:
209: /**
210: * Returns the boolean information whether this assertion contains any parameters.
211: *
212: * @return {@code true} if the assertion contains parameters. Returns {@code false} otherwise.
213: *
214: * @deprecated Use hasParameters() instead
215: */
216: @Deprecated
217: public final boolean hasNestedAssertions() {
218: // TODO: remove
219: return !parameters.isEmpty();
220: }
221:
222: /**
223: * Returns the boolean information whether this assertion contains any parameters.
224: *
225: * @return {@code true} if the assertion contains parameters. Returns {@code false} otherwise.
226: */
227: public final boolean hasParameters() {
228: return !parameters.isEmpty();
229: }
230:
231: /**
232: * Returns the assertion's parameter collection iterator.
233: *
234: * @return the assertion's parameter collection iterator.
235: *
236: * @deprecated Use getNestedParametersIterator() instead
237: */
238: @Deprecated
239: public final Iterator<PolicyAssertion> getNestedAssertionsIterator() {
240: // TODO: remove
241: return parameters.iterator();
242: }
243:
244: /**
245: * Returns the assertion's parameter collection iterator.
246: *
247: * @return the assertion's parameter collection iterator.
248: */
249: public final Iterator<PolicyAssertion> getParametersIterator() {
250: return parameters.iterator();
251: }
252:
253: boolean isParameter() {
254: return data.getNodeType() == ModelNode.Type.ASSERTION_PARAMETER_NODE;
255: }
256:
257: /**
258: * Returns the boolean information whether this assertion contains nested policy.
259: *
260: * @return {@code true} if the assertion contains child (nested) policy. Returns {@code false} otherwise.
261: */
262: public boolean hasNestedPolicy() {
263: // TODO: make abstract
264: return getNestedPolicy() != null;
265: }
266:
267: /**
268: * Returns the nested policy if any.
269: *
270: * @return the nested policy if the assertion contains a nested policy. Returns {@code null} otherwise.
271: */
272: public NestedPolicy getNestedPolicy() {
273: // TODO: make abstract
274: return nestedPolicy;
275: }
276:
277: /**
278: * An {@code Object.toString()} method override.
279: */
280: @Override
281: public String toString() {
282: return toString(0, new StringBuffer()).toString();
283: }
284:
285: /**
286: * A helper method that appends indented string representation of this instance to the input string buffer.
287: *
288: * @param indentLevel indentation level to be used.
289: * @param buffer buffer to be used for appending string representation of this instance
290: * @return modified buffer containing new string representation of the instance
291: */
292: protected StringBuffer toString(final int indentLevel,
293: final StringBuffer buffer) {
294: final String indent = PolicyUtils.Text
295: .createIndent(indentLevel);
296: final String innerIndent = PolicyUtils.Text
297: .createIndent(indentLevel + 1);
298:
299: buffer.append(indent).append("Assertion[").append(
300: this .getClass().getName()).append("] {").append(
301: PolicyUtils.Text.NEW_LINE);
302: data.toString(indentLevel + 1, buffer);
303: buffer.append(PolicyUtils.Text.NEW_LINE);
304:
305: if (hasParameters()) {
306: buffer.append(innerIndent).append("parameters {").append(
307: PolicyUtils.Text.NEW_LINE);
308: for (PolicyAssertion parameter : parameters) {
309: parameter.toString(indentLevel + 2, buffer);
310: }
311: buffer.append(innerIndent).append('}').append(
312: PolicyUtils.Text.NEW_LINE);
313: } else {
314: buffer.append(innerIndent).append("no parameters").append(
315: PolicyUtils.Text.NEW_LINE);
316: }
317:
318: if (hasNestedPolicy()) {
319: getNestedPolicy().toString(indentLevel + 1, buffer).append(
320: PolicyUtils.Text.NEW_LINE);
321: } else {
322: buffer.append(innerIndent).append("no nested policy")
323: .append(PolicyUtils.Text.NEW_LINE);
324: }
325:
326: buffer.append(indent).append('}');
327:
328: return buffer;
329: }
330:
331: /**
332: * Checks whether this policy alternative is compatible with the provided policy alternative.
333: *
334: * @param assertion policy alternative used for compatibility test
335: * @param mode compatibility mode to be used
336: * @return {@code true} if the two policy alternatives are compatible, {@code false} otherwise
337: */
338: boolean isCompatibleWith(final PolicyAssertion assertion,
339: PolicyIntersector.CompatibilityMode mode) {
340: boolean result = this .data.getName().equals(
341: assertion.data.getName())
342: && (this .hasNestedPolicy() == assertion
343: .hasNestedPolicy());
344:
345: if (result && this .hasNestedPolicy()) {
346: result = this .getNestedPolicy().getAssertionSet()
347: .isCompatibleWith(
348: assertion.getNestedPolicy()
349: .getAssertionSet(), mode);
350: }
351:
352: return result;
353: }
354:
355: /**
356: * An {@code Object.equals(Object obj)} method override.
357: */
358: @Override
359: public boolean equals(final Object obj) {
360: if (this == obj) {
361: return true;
362: }
363:
364: if (!(obj instanceof PolicyAssertion)) {
365: return false;
366: }
367:
368: final PolicyAssertion that = (PolicyAssertion) obj;
369: boolean result = true;
370:
371: result = result && this .data.equals(that.data);
372: result = result && this .parameters.equals(that.parameters);
373: result = result
374: && ((this .getNestedPolicy() == null) ? ((that
375: .getNestedPolicy() == null) ? true : false)
376: : this .getNestedPolicy().equals(
377: that.getNestedPolicy()));
378:
379: return result;
380: }
381:
382: /**
383: * An {@code Object.hashCode()} method override.
384: */
385: @Override
386: public int hashCode() {
387: int result = 17;
388:
389: result = 37 * result + data.hashCode();
390: result = 37 * result + ((hasParameters()) ? 17 : 0);
391: result = 37 * result + ((hasNestedPolicy()) ? 17 : 0);
392:
393: return result;
394: }
395: }
|