/*******************************************************************************
* Copyright (c) 2009 MATERNA Information & Communications. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html. For further
* project-related information visit http://www.ws4d.org. The most recent
* version of the JMEDS framework can be obtained from
* http://sourceforge.net/projects/ws4d-javame.
******************************************************************************/
package org.ws4d.java.service;
import org.ws4d.java.schema.Element;
import org.ws4d.java.service.parameter.ParameterValue;
import org.ws4d.java.structures.DataStructure;
import org.ws4d.java.types.AttributableSupport;
import org.ws4d.java.util.WS4DIllegalStateException;
import org.ws4d.java.wsdl.IOType;
import org.ws4d.java.wsdl.WSDLMessagePart;
/**
* Faults are the web-services correspondents to exceptions from the Java world.
* They can be declared on {@link Operation}s or {@link DefaultEventSource}s
* just like exceptions may be declared on Java methods. A fault has a
* {@link #getName() name}, which must not be <code>null</code> and unique
* within the scope of the surrounding operation/event, and an
* {@link #getAction() action URI} corresponding to the <em>wsa:Action</em>
* property of the fault message within which the fault is sent . The action URI
* must also not be <code>null</code> and must be unique within the operation.
* However, when creating a user-defined <code>Fault</code>, it is possible to
* omit specifying the action URI explicitly as the DPWS framework will provide
* an auto-generated one in case it was not set prior to adding the fault to an
* operation/event.
* <p>
* A <code>Fault</code> can also carry user-defined data, just like exceptions
* can be designed to encapsulate additional state within their instance
* variables. Within the <code>Fault</code>, this state is described by means of
* its associated {@link #getElement() element}.
* </p>
* <p>
* It is important to notice that modifications to a fault are not possible
* after it has been added to an operation. Calling any of the setter methods at
* this time will result in <code>IllegalStateException</code>s being thrown.
* </p>
*/
public class Fault extends AttributableSupport {
boolean attached = false;
private final String name;
private String action;
private Element element;
/**
* Creates a fault with the given <code>name</code>, which must be unique
* within the scope of the surrounding operation. The fault will be assigned
* an auto-generated {@link #getAction() action} when it is
* {@link OperationCommons#addFault(Fault) added} to an operation or event.
*
* @param name the name of this fault; unique within the scope of the
* surrounding operation
*/
public Fault(String name) {
this(name, null);
}
/**
* Creates a fault with the given <code>name</code> (must be unique within
* the scope of the surrounding operation). The <code>action</code> argument
* should be a URI representing the <em>wsa:Action</em> associated to this
* fault.
*
* @param name the name of the fault; unique within the scope of the
* surrounding operation
* @param action the wsa:Action URI of this fault
*/
public Fault(String name, String action) {
super();
this.name = name;
this.action = action;
}
Fault(IOType fault) {
this(fault.getName(), fault.getAction());
DataStructure parts = fault.getParts();
int size = parts.size();
if (size > 1) {
// TODO throw exception: unsupported WSDL feature
throw new IllegalArgumentException("Unsupported WSDL feature (fault message with more than one parts ): " + fault.getMessage());
} else if (size == 1) {
WSDLMessagePart part = (WSDLMessagePart) parts.iterator().next();
if (part.isElement()) {
setElement(part.getElement());
} else {
// TODO throw exception: unsupported WSDL feature
throw new IllegalArgumentException("Unsupported WSDL feature (message part referring to a type): " + part);
}
}
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("Fault [ name=").append(getName());
sb.append(", action=").append(getAction());
sb.append(", element=").append(getElement());
sb.append(" ]");
return sb.toString();
}
/**
* Returns the <em>wsa:Action</em> associated to this fault.
* <p>
* As <code>Faults</code> are always required to have an action URI
* associated to them, one will be automatically generated when adding this
* <code>Fault</code> to an {@link Operation operation} or
* {@link DefaultEventSource event}, if it was not specified explicitly.
*
* @return the action of this fault
*/
public String getAction() {
return action;
}
/**
* Sets the <em>wsa:Action</em> of this fault. This method may be called
* only <strong>before</strong> this <code>Fault</code> is added to an
* {@link Operation operation} or {@link DefaultEventSource event}.
*
* @param action the action to set
* @throws WS4DIllegalStateException if the fault is currently attached to
* an operation or an event
*/
public void setAction(String action) {
if (attached) {
throw new WS4DIllegalStateException("unable to modify after being added to operation or event");
}
this.action = action;
}
/**
* Returns the element of this fault, which defines the type and structure
* of any user-defined data the fault may contain. It can be used to
* {@link #createValue() create} a suitable {@link ParameterValue} container
* for the actual values when sending messages containing this fault.
*
* @return this fault's element
* @see #setElement(Element)
*/
public Element getElement() {
return element;
}
/**
* Sets the element of this <code>Fault</code>. The element describes the
* type and contents of a user-defined data structure providing additional
* information about the fault. Calling this method after having already
* added this <code>Fault</code> to an {@link Operation operation} or
* {@link DefaultEventSource event} will result in an
* <code>IllegalStateException</code> being thrown.
*
* @param element the element to set
* @throws WS4DIllegalStateException if the fault is currently attached to
* an operation or an event
*/
public void setElement(Element element) {
if (attached) {
throw new WS4DIllegalStateException("unable to modify after being added to operation or event");
}
this.element = element;
}
/**
* Returns the name of this <code>Fault</code>. This name must be unique
* within the scope of its surrounding operation or event.
*
* @return this fault's name
*/
public String getName() {
return name;
}
/**
* A shorthand method for creating a suitable data container for this
* fault's element. Technically equivalent to
* <code>ParameterValue.createElementValue(getElement())</code>.
*
* @return a data container suitable for this fault's element
* @see #getElement()
*/
public ParameterValue createValue() {
return ParameterValue.createElementValue(getElement());
}
}