/*
* Copyright 2008 the original author or authors.
* Copyright 2005 Sun Microsystems, Inc.
*
* 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.rioproject.impl.opstring;
import org.rioproject.opstring.OperationalString;
import org.rioproject.opstring.ServiceElement;
import org.rioproject.opstring.UndeployOption;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* An implementation of an {@link org.rioproject.opstring.OperationalString}
*
* @author Dennis Reedy
*/
public class OpString implements OperationalString, Serializable {
private static final long serialVersionUID = 1L;
/** Name of the OperationalString */
private String name;
/** Collection of services within the OperationalString */
private final List<ServiceElement> services = new ArrayList<ServiceElement>();
/** Collection of nested OperationalString */
private final List<OperationalString> nestedOpStrings = new ArrayList<OperationalString>();
/** The deployed state of the OperationalString */
private int deployedStatus = OperationalString.UNDEPLOYED;
/** The URL OperationalString was loaded from */
private URL loadedFrom;
private UndeployOption undeployOption;
/**
* Create an OpString
*
* @param name The name of the OperationalString, must not be null
* @param loadedFrom The URL where the OperationalString was loaded
* from. May be null
*/
public OpString(String name, URL loadedFrom) {
if (name == null)
throw new IllegalArgumentException("OpString name is null");
this.name = name;
this.loadedFrom = loadedFrom;
}
/**
* @see OperationalString#setDeployed
*/
public void setDeployed(int deployed) {
if(deployed < OperationalString.UNDEPLOYED &&
deployed > OperationalString.DEPLOYED)
throw new IllegalArgumentException("bad deployment status "+
"["+deployed+"]");
synchronized(this) {
deployedStatus = deployed;
}
}
/**
* @see OperationalString#getStatus()
*/
public int getStatus() {
int myStatus;
synchronized(this) {
if(deployedStatus<OperationalString.DEPLOYED) {
myStatus = deployedStatus;
} else {
myStatus = OperationalString.INTACT;
ServiceElement[] sElems = getServices();
for (ServiceElement sElem : sElems) {
int actual = sElem.getActual();
int planned = sElem.getPlanned();
if (actual == 0) {
myStatus = OperationalString.BROKEN;
break;
}
if (actual < planned) {
myStatus = OperationalString.COMPROMISED;
break;
}
}
OperationalString[] nested = getNestedOperationalStrings();
for (OperationalString aNested : nested) {
int nestedStatus = aNested.getStatus();
if (nestedStatus < myStatus)
myStatus = nestedStatus;
}
}
}
return(myStatus);
}
/**
* Set the name of the OperationalString
*
* @param name The name of the OperationalString, must not be null. This
* will additionally set all ServiceElement instance OperationalString
* names as well
*/
public void setName(String name) {
if(name==null)
throw new IllegalArgumentException("name is null");
this.name = name;
ServiceElement[] services = getServices();
for (ServiceElement service : services)
service.setOperationalStringName(name);
}
/**
* @see OperationalString#getName
*/
public String getName() {
return(name);
}
/**
* @see OperationalString#getServices
*/
public ServiceElement[] getServices() {
ServiceElement[] sams;
synchronized(services) {
sams = new ServiceElement[services.size()];
for(int i=0; i<sams.length; i++) {
sams[i] = services.get(i);
}
}
return(sams);
}
/**
* @see OperationalString#addService
*/
public void addService(ServiceElement sElem) {
if(sElem==null)
throw new IllegalArgumentException("ServiceElement is null");
synchronized(services) {
if(!services.contains(sElem))
services.add(sElem);
}
}
/**
* @see OperationalString#removeService
*/
public void removeService(ServiceElement sElem) {
if(sElem==null)
throw new IllegalArgumentException("ServiceElement is null");
synchronized(services) {
services.remove(sElem);
}
}
/**
* Add included OperationalString objects to the OperationalString
*
* @param opStrings Array of OperationalString objects to add
*/
public void addOperationalString(OperationalString[] opStrings) {
if(opStrings==null)
throw new IllegalArgumentException("OperationalString is null");
for (OperationalString opString : opStrings) {
addOperationalString(opString);
}
}
/**
* Add included OperationalString to the OperationalString
*
* @param opString OperationalString to add
*/
public void addOperationalString(OperationalString opString) {
if(opString==null)
throw new IllegalArgumentException("OperationalString is null");
synchronized(nestedOpStrings) {
nestedOpStrings.add(opString);
}
}
/**
* @see OperationalString#getNestedOperationalStrings()
*/
public OperationalString[] getNestedOperationalStrings() {
OperationalString[] ops;
synchronized(nestedOpStrings) {
ops = new OperationalString[nestedOpStrings.size()];
for(int i=0; i<ops.length; i++) {
ops[i] = nestedOpStrings.get(i);
}
}
return(ops);
}
/**
* Override hashCode to return the hashCode of the name attribute
*/
public int hashCode() {
int hc = 17;
hc = 37*hc+name.hashCode();
hc = 37*hc+services.hashCode();
return(hc);
}
/**
* An OperationalString is equal to another OperationalString if their
* names are the same and they have they same ServiceElements
*/
public boolean equals(Object obj) {
if(this == obj)
return(true);
if(!(obj instanceof OpString)) {
return(false);
}
OpString that = (OpString)obj;
if(this.name.equals(that.name)) {
ServiceElement[] thisServices = this.getServices();
ServiceElement[] thatServices = that.getServices();
if(thisServices.length == thatServices.length) {
/* Go through the services in both opstrings. They may contain
* the same services, but be in different order */
for (ServiceElement thisService : thisServices) {
boolean matched = false;
for (ServiceElement thatService : thatServices) {
if (thisService.equals(thatService)) {
matched = true;
break;
}
}
if (!matched)
return (false);
}
return(true);
}
}
return(false);
}
/**
* Check if a service with the provided name is included in the
* OperationalString
*
* @param serviceName The name of the service to check
*
* @return Return true if the serviceName is part of this
* OperationalString, false otherwise
*/
public boolean containsNamedService(String serviceName) {
boolean found=false;
synchronized(services) {
for (ServiceElement sElem : services) {
if (sElem.getName().equals(serviceName)) {
found = true;
break;
}
}
}
return(found);
}
/**
* Get the service with the provided name
*
* @param serviceName The name of the service to check
*
* @return Return the ServiceElement for the serviceName or null if not
* found
*/
public ServiceElement getNamedService(String serviceName) {
ServiceElement foundService=null;
synchronized(services) {
for (ServiceElement sElem : services) {
if (sElem.getName().equals(serviceName)) {
foundService = sElem;
break;
}
}
}
return(foundService);
}
/**
* Check if an OperationalString with the provided name is included in the
* OperationalString
*
* @param opStringName The name of the OperationalString to check
*
* @return Return true if the OperationalString is part of this
* OperationalString, false otherwise
*/
public boolean containsOperationalString(String opStringName) {
boolean found=false;
synchronized(nestedOpStrings) {
for (OperationalString nestedOpString : nestedOpStrings) {
if (nestedOpString.getName().equals(opStringName)) {
found = true;
break;
}
}
}
return(found);
}
/**
* Get the nested OperationalString with the provided name
*
* @param opStringName The name of the OperationalString to check
*
* @return Return the OperationalString if found, otherwise return null
*/
public OperationalString getNestedOperationalString(String opStringName) {
OperationalString nested=null;
synchronized(nestedOpStrings) {
for (OperationalString nestedOpString : nestedOpStrings) {
if (nestedOpString.getName().equals(opStringName)) {
nested = nestedOpString;
break;
}
}
}
return(nested);
}
/**
* @see OperationalString#loadedFrom
*/
public URL loadedFrom() {
return(loadedFrom);
}
/**
* Set the loaded from property
*
* @param loadedFrom The URL the OperationalString was loaded from
*/
public void setLoadedFrom(URL loadedFrom) {
this.loadedFrom = loadedFrom;
}
public UndeployOption getUndeployOption() {
return undeployOption;
}
public void setUndeployOption(UndeployOption undeployOption) {
this.undeployOption = undeployOption;
}
}