/*=============================================================================*
* Copyright 2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*=============================================================================*/
package org.apache.muse.ws.dm.muws.impl;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.apache.muse.core.ResourceManager;
import org.apache.muse.core.routing.MessageHandler;
import org.apache.muse.util.ReflectUtils;
import org.apache.muse.util.messages.Messages;
import org.apache.muse.util.messages.MessagesFactory;
import org.apache.muse.util.xml.XmlUtils;
import org.apache.muse.ws.addressing.soap.SoapFault;
import org.apache.muse.ws.dm.muws.MuwsConstants;
import org.apache.muse.ws.dm.muws.Participant;
import org.apache.muse.ws.dm.muws.RelationshipResource;
import org.apache.muse.ws.dm.muws.RelationshipType;
import org.apache.muse.ws.dm.muws.Relationships;
import org.apache.muse.ws.dm.muws.ext.faults.RelationshipCreationFailedFault;
import org.apache.muse.ws.resource.WsResource;
import org.apache.muse.ws.resource.basefaults.BaseFault;
/**
*
* SimpleRelationships is Muse's default implementation of the MUWS (Part 2)
* Relationships capability. It performs the following tasks:
* <ul>
* <li>Ensures that the application has a resource type with the
* {@linkplain RelationshipResource RelationshipResource capability} so that
* there will be SOAP-level access to the relationships resources,
* </li>
* <li>Provides lifecycle management for the relationship resources, and
* </li>
* <li>Implements the muws2:Relationship property and QueryRelationshipsByType
* operation.
* </li>
*
* @author Dan Jemiolo (danj)
*
*/
public class SimpleRelationships
extends AbstractManageabilityCapability implements Relationships
{
//
// Used to look up all exception messages
//
private static Messages _MESSAGES = MessagesFactory.get(SimpleRelationships.class);
//
// The context path of the resource type that represents
// relationship resources
//
private String _relationshipPath = null;
private Set _relationships = new HashSet();
public WsResource addRelationship(String name,
RelationshipType type,
Participant[] participants)
throws BaseFault
{
WsResource relationship = createRelationship(name, type, participants);
_relationships.add(relationship);
return relationship;
}
protected MessageHandler createQueryHandler()
{
MessageHandler handler = new QueryRelationshipsHandler();
Method method = ReflectUtils.getFirstMethod(getClass(), "queryRelationshipsByType");
handler.setMethod(method);
return handler;
}
/**
*
* This method reads the relationship fields from the XML and forwards them
* to createRelationship(String, RelationshipType, Participant[]).
*
*/
protected WsResource createRelationship(Element xml)
throws BaseFault
{
String name = XmlUtils.getElementText(xml, MuwsConstants.NAME_QNAME);
Element typeXML = XmlUtils.getElement(xml, MuwsConstants.TYPE_QNAME);
RelationshipType type = new SimpleRelationshipType(typeXML);
Element[] participantsXML = XmlUtils.getElements(xml, MuwsConstants.PARTICIPANT_QNAME);
Participant[] participants = new SimpleParticipant[participantsXML.length];
for (int n = 0; n < participantsXML.length; ++n)
participants[n] = new SimpleParticipant(participantsXML[n]);
return createRelationship(name, type, participants);
}
/**
*
* Creates a new relationship resource with the given fields, initializes
* it, and adds it to the ResourceManager before returning it.
*
*/
protected WsResource createRelationship(String name,
RelationshipType type,
Participant[] participants)
throws BaseFault
{
ResourceManager manager = getWsResource().getResourceManager();
String endpoint = getRelationshipContextPath();
//
// first create an empty instance of the relationship type
//
WsResource resource = null;
try
{
resource = (WsResource)manager.createResource(endpoint);
}
catch (SoapFault error)
{
throw new RelationshipCreationFailedFault(error);
}
//
// use the relationship capability to set the fields before initializing
//
RelationshipResource relationship =
(RelationshipResource)resource.getCapability(MuwsConstants.RELATIONSHIP_RESOURCE_URI);
relationship.setName(name);
relationship.setType(type);
relationship.setParticipant(participants);
try
{
resource.initialize();
manager.addResource(resource.getEndpointReference(), resource);
}
catch (SoapFault error)
{
throw new RelationshipCreationFailedFault(error);
}
return resource;
}
public Element[] getProperty(QName propertyName)
throws BaseFault
{
//
// special case - relationship is returned as a WsResource[], we
// want to turn that into muws2:Relationship XML
//
if (propertyName.equals(MuwsConstants.RELATIONSHIP_QNAME))
return getRelationshipElements();
return super.getProperty(propertyName);
}
public QName[] getPropertyNames()
{
return PROPERTIES;
}
public WsResource[] getRelationship()
{
WsResource[] array = new WsResource[_relationships.size()];
return (WsResource[])_relationships.toArray(array);
}
protected String getRelationshipContextPath()
{
return _relationshipPath;
}
/**
*
* This method converts the WsResource[] returned by getRelationship()
* into an Element[] with muws2:Relationship XML that is compliant with
* the MUWS Part 2 spec.
*
*/
protected Element[] getRelationshipElements()
{
WsResource[] relationships = getRelationship();
Element[] relationshipXML = new Element[relationships.length];
for (int n = 0; n < relationships.length; ++n)
{
RelationshipResource capability =
(RelationshipResource)relationships[n].getCapability(MuwsConstants.RELATIONSHIP_RESOURCE_URI);
relationshipXML[n] = capability.toXML();
}
return relationshipXML;
}
public void initialize()
throws SoapFault
{
super.initialize();
//
// make sure the RelationshipResource endpoint is exposed, since our
// relationships are all first-class resources
//
WsResource resource = getWsResource();
ResourceManager manager = resource.getResourceManager();
_relationshipPath = manager.getResourceContextPath(RelationshipResource.class);
if (_relationshipPath == null)
throw new RuntimeException(_MESSAGES.get("NoRelationshipEndpoint"));
setMessageHandler(createQueryHandler());
}
public WsResource[] queryRelationshipsByType(QName[] types)
throws BaseFault
{
if (types == null)
throw new NullPointerException(_MESSAGES.get("NullQueryTypes"));
if (types.length == 0)
throw new IllegalArgumentException(_MESSAGES.get("EmptyQueryTypes"));
//
// add types to a hashtable so we can quickly determine if a
// relationship has one of the requested types
//
Set typesSet = new HashSet();
for (int n = 0; n < types.length; ++n)
typesSet.add(types[n]);
WsResource[] relationships = getRelationship();
Collection results = new ArrayList();
for (int n = 0; n < relationships.length; ++n)
{
RelationshipResource capability =
(RelationshipResource)relationships[n].getCapability(MuwsConstants.RELATIONSHIP_RESOURCE_URI);
QName[] typeValues = capability.getType().getValues();
//
// we only check the first (top-level) name in the type array,
// because this operation doesn't provide a way to specify
// more complex types or paths - we have to ignore the rest
//
if (typesSet.contains(typeValues[0]))
results.add(relationships[n]);
}
WsResource[] asArray = new WsResource[results.size()];
return (WsResource[])results.toArray(asArray);
}
public void removeRelationship(WsResource relationship)
{
if (relationship == null)
throw new NullPointerException(_MESSAGES.get("NullRelationship"));
if (!_relationships.remove(relationship))
throw new RuntimeException(_MESSAGES.get("RelationshipNotFound"));
}
}