/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.wkf.ws;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.DeletableObject;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.NameChanged;
import org.openflexo.foundation.bindings.BindingValue;
import org.openflexo.foundation.bindings.BindingVariable;
import org.openflexo.foundation.wkf.DuplicateWKFObjectException;
import org.openflexo.foundation.wkf.FlexoLevel;
import org.openflexo.foundation.wkf.FlexoProcess;
import org.openflexo.foundation.wkf.LevelledObject;
import org.openflexo.foundation.wkf.WKFObject;
import org.openflexo.foundation.wkf.dm.ServiceInterfaceRemoved;
import org.openflexo.foundation.wkf.dm.ServiceOperationInserted;
import org.openflexo.foundation.wkf.dm.ServiceOperationRemoved;
import org.openflexo.foundation.ws.DuplicateWSObjectException;
import org.openflexo.foundation.ws.WSPortType;
import org.openflexo.foundation.ws.WSService;
import org.openflexo.foundation.xml.FlexoProcessBuilder;
import org.openflexo.inspector.InspectableObject;
/**
* A ServiceInteface is attached to a FlexoProcess and contains all the service operations used in the context of WebServices.
*
* @author Denis VANVYVE
*
*/
public class ServiceInterface extends WKFObject implements InspectableObject, LevelledObject, DeletableObject {
private static final Logger logger = Logger.getLogger(ServiceInterface.class.getPackage().getName());
// ==========================================================================
// ============================= Variables
// ==================================
// ==========================================================================
private String _name;
private Vector<ServiceOperation> _operations;
/**
* Constructor used during deserialization
*/
public ServiceInterface(FlexoProcessBuilder builder) {
this(builder.process);
initializeDeserialization(builder);
}
/**
* Default constructor
*/
public ServiceInterface(FlexoProcess process) {
super(process);
_operations = new Vector();
}
public ServiceInterface(FlexoProcess process, String name) throws DuplicateWKFObjectException, DuplicateWSObjectException {
this(process);
setName(name);
}
@Override
public String getName() {
return _name;
}
@Override
public void setName(String aName) throws DuplicateWSObjectException, DuplicateWKFObjectException {
if (!isDeserializing()) {
checkInterfaceName(getProcess(), aName, this);
}
// TODO: check that the serviceInterface is not used !
if (!isDeserializing() && isUsedInWebService() && _name != null && !_name.equals(aName)) {
WSPortType pt = getProject().getFlexoWSLibrary().getWSPortTypeNamed(getName());
while (pt != null) {
pt.setName(aName);
pt = null;
pt = getProject().getFlexoWSLibrary().getWSPortTypeNamed(getName());
}
}
_name = aName;
setChanged();
notifyObservers(new NameChanged(null, _name));
}
public static void checkInterfaceName(FlexoProcess process, String aName, ServiceInterface currentInt)
throws DuplicateWKFObjectException {
Vector allInterfaces = process.getServiceInterfaces();
for (Enumeration e = allInterfaces.elements(); e.hasMoreElements();) {
ServiceInterface p = (ServiceInterface) e.nextElement();
if (p != currentInt && p.getName().equals(aName)) {
throw new DuplicateWKFObjectException(p, "a_service_interface_with_the_same_name_already_exist");
}
}
}
@Override
public String getFullyQualifiedName() {
return getProcess().getFullyQualifiedName() + "." + getName() + ".SERVICE_INTERFACE";
}
/**
* Return a Vector of all embedded WKFObjects
*
* @return a Vector of WKFObject instances
*/
@Override
public Vector<WKFObject> getAllEmbeddedWKFObjects() {
Vector<WKFObject> returned = new Vector<WKFObject>();
returned.add(this);
returned.addAll(getOperations());
return returned;
}
public ServiceOperation addServiceOperation(String name, FlexoPort relatedPort) throws DuplicateWKFObjectException {
// will throw an exception
try {
ServiceOperation.checkOperationName(this, name, null);
} catch (DuplicateWKFObjectException e) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("An operation with the same name (" + name + ") already exist");
}
throw e;
}
ServiceOperation newOp = new ServiceOperation(this, name, relatedPort);
addToOperations(newOp);
return newOp;
}
public Vector<ServiceOperation> getOperations() {
return _operations;
}
public void setOperations(Vector<ServiceOperation> operations) {
_operations = operations;
}
public Enumeration<ServiceOperation> getSortedOperations() {
Vector<ServiceOperation> returned = new Vector<ServiceOperation>(getOperations());
Collections.sort(returned, new Comparator<ServiceOperation>() {
@Override
public int compare(ServiceOperation o1, ServiceOperation o2) {
return o1.getPort().getIndex() - o2.getPort().getIndex();
}
});
return returned.elements();
}
public void addToOperations(ServiceOperation anOp) {
if (!_operations.contains(anOp)) {
_operations.add(anOp);
anOp.setServiceInterface(this);
setChanged();
notifyObservers(new ServiceOperationInserted(anOp));
}
}
public void removeFromOperations(ServiceOperation anOp) {
if (_operations.contains(anOp)) {
_operations.remove(anOp);
setChanged();
notifyObservers(new ServiceOperationRemoved(anOp));
anOp.setServiceInterface(null);
}
}
public ServiceOperation operationWithName(String name) {
for (Enumeration e = getOperations().elements(); e.hasMoreElements();) {
ServiceOperation op = (ServiceOperation) e.nextElement();
if (op.getName().equals(name)) {
return op;
}
}
return null;
}
@Override
public String getInspectorName() {
return Inspectors.WKF.SERVICE_INTERFACE_INSPECTOR;
}
@Override
public FlexoLevel getLevel() {
return FlexoLevel.PROCESS;
}
@Override
public Vector<WKFObject> getAllEmbeddedDeleted() {
return getAllEmbeddedWKFObjects();
}
public boolean isUsedInWebService() {
WSPortType pt = getProject().getFlexoWSLibrary().getWSPortTypeNamed(getName());
if (pt != null && pt.getServiceInterface() != null && pt.getServiceInterface().equals(this)) {
return true;
}
return false;
}
/**
* uni-directional relationship between WSService and ServiceInterface. This method tries to implement the "implicit" inverse
* relationship. CAUTION: based on the assumption of a one-to-one relationship.
*
* @return
*/
public WSService getParentService() {
return getProject().getFlexoWSLibrary().getParentOfServiceInterface(this);
}
@Override
public void delete() {
// 1. remove from WS (while if there are many portTypes...)
while (isUsedInWebService()) {
WSPortType pt = getProject().getFlexoWSLibrary().getWSPortTypeNamed(getName());
if (pt != null) {
pt.delete();
}
}
// 2. delete
getProcess().removeFromServiceInterfaces(this);
Enumeration<ServiceOperation> en = new Vector<ServiceOperation>(getOperations()).elements();
while (en.hasMoreElements()) {
ServiceOperation op = en.nextElement();
removeFromOperations(op);
op.delete();
}
super.delete();
_name = null;
_operations.clear();
_operations = null;
notifyObservers(new ServiceInterfaceRemoved(this));
deleteObservers();
}
public static ServiceInterface copyPortsFromRegistry(ServiceInterface toInterface, PortRegistery fromReg) {
Enumeration<FlexoPort> en = fromReg.getAllPorts().elements();
while (en.hasMoreElements()) {
FlexoPort port = en.nextElement();
try {
ServiceOperation serviceOp = toInterface.addServiceOperation(port.getName(), port);
if (port instanceof AbstractInPort) {
MessageDefinition def = ((AbstractInPort) port).getInputMessageDefinition();
ServiceMessageDefinition serviceDef = serviceOp.getInputMessageDefinition();
Iterator it3 = def.getEntries().iterator();
serviceDef.setName(def.getName());
serviceDef.setDescription(def.getDescription());
while (it3.hasNext()) {
MessageEntry fromEntry = (MessageEntry) it3.next();
MessageEntry toEntry = new MessageEntry(toInterface.getProcess(), serviceDef);
toEntry.setVariableName(fromEntry.getVariableName());
toEntry.setType(fromEntry.getType());
serviceDef.addToEntries(toEntry);
ServiceMessageEntryBinding binding = serviceOp.getInputMessageBindings().getBinding(fromEntry);
BindingValue bvalue = new BindingValue(fromEntry, serviceOp.getInputMessageBindings());
// binding model based on variables of toEntry (operation's message)
// message def is from Port.
// a_pt=b_op
BindingVariable bvar = serviceOp.getInputMessageBindings().getBindingModel()
.bindingVariableNamed(toEntry.getVariableName());
bvalue.setBindingVariable(bvar);
binding.setBindingValue(bvalue);
}
}
if (port instanceof OutputPort) {
MessageDefinition def = ((OutputPort) port).getOutputMessageDefinition();
ServiceMessageDefinition serviceDef = serviceOp.getOutputMessageDefinition();
Iterator it3 = def.getEntries().iterator();
serviceDef.setName(def.getName());
serviceDef.setDescription(def.getDescription());
while (it3.hasNext()) {
MessageEntry fromEntry = (MessageEntry) it3.next();
MessageEntry toEntry = new MessageEntry(toInterface.getProcess(), serviceDef);
toEntry.setVariableName(fromEntry.getVariableName());
toEntry.setType(fromEntry.getType());
serviceDef.addToEntries(toEntry);
// binding model based on variables of fromEntry (port's message)
// message def is from operation.
// a_op=b_pt
ServiceMessageEntryBinding binding = serviceOp.getOutputMessageBindings().getBinding(toEntry);
BindingValue bvalue = new BindingValue(toEntry, serviceOp.getOutputMessageBindings());
BindingVariable bvar = serviceOp.getOutputMessageBindings().getBindingModel()
.bindingVariableNamed(fromEntry.getVariableName());
bvalue.setBindingVariable(bvar);
binding.setBindingValue(bvalue);
}
}
} catch (DuplicateWKFObjectException e) {
if (logger.isLoggable(Level.INFO)) {
logger.info("ServiceOperation already exist.");
}
}
}
return toInterface;
}
@Override
public String getClassNameKey() {
return "service_interface";
}
}