/**
* This file is part of CloudML [ http://cloudml.org ]
*
* Copyright (C) 2012 - SINTEF ICT
* Contact: Franck Chauvel <franck.chauvel@sintef.no>
*
* Module: root
*
* CloudML is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* CloudML 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with CloudML. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.cloudml.core;
import java.util.Collection;
import org.cloudml.core.collections.ComponentInstanceGroup;
import org.cloudml.core.collections.InternalComponentInstanceGroup;
import org.cloudml.core.util.OwnedBy;
import org.cloudml.core.collections.ProvidedExecutionPlatformInstanceGroup;
import org.cloudml.core.collections.ProvidedPortInstanceGroup;
import org.cloudml.core.validation.Report;
public abstract class ComponentInstance<T extends Component> extends WithResources implements DeploymentElement, OwnedBy<Deployment> {
public static enum State {
/**
* The node is in transition.
*/
PENDING("PENDING"),
/**
* The node is visible, and in the process of being deleted. Available
* on jCLouds only.
*/
TERMINATED("TERMINATED"),
/**
* The node is deployed, but suspended or stopped.
*/
STOPPED("STOPPED"),
/**
* The node is available for requests
*/
RUNNING("RUNNING"),
/**
* There is an error on the node
*/
ERROR("ERROR"),
/**
* The state of the node is unrecognized.
*/
UNRECOGNIZED("UNRECOGNIZED"),
/**
* This status is available only on Flexiant
*/
RECOVERY("RECOVERY");
private String name = "PENDING";
private State(String s) {
this.name = s;
}
public boolean equalsName(String otherName) {
return (otherName == null) ? false : name.equals(otherName);
}
public String toString() {
return name;
}
}
private final OptionalOwner<Deployment> owner;
private T type;
private ProvidedPortInstanceGroup providedPorts;
private ProvidedExecutionPlatformInstanceGroup providedExecutionPlatforms;
public ComponentInstance(String name, T type) {
super(name);
this.owner = new OptionalOwner<Deployment>();
setType(type);
this.providedPorts = instantiateAllProvidedPorts(type);
this.providedExecutionPlatforms = instantiateAllExecutionPlatforms(type);
}
private ProvidedPortInstanceGroup instantiateAllProvidedPorts(T type) {
final ProvidedPortInstanceGroup instances = new ProvidedPortInstanceGroup();
for (ProvidedPort port: type.getProvidedPorts()) {
instances.add(port.instantiate());
}
return new LocalProvidedPortInstanceGroup(instances);
}
private LocalProvidedExecutionPlatformInstanceGroup instantiateAllExecutionPlatforms(T type) {
final ProvidedExecutionPlatformInstanceGroup group = new ProvidedExecutionPlatformInstanceGroup();
for (ProvidedExecutionPlatform platform: type.getProvidedExecutionPlatforms()) {
group.add(platform.instantiate());
}
return new LocalProvidedExecutionPlatformInstanceGroup(group);
}
/**
* @return true if this component instance can host other instance, (i.e.,
* if it provide at least one execution platform), false otherwise.
*/
public boolean canHost() {
return !getProvidedExecutionPlatforms().isEmpty();
}
/**
* @return true if this component instance can host the given component
* (i.e., if it provides a relevant execution platform), false otherwise
* @param componentType the component type that need an host
*/
public boolean canHost(InternalComponent componentType) {
return getProvidedExecutionPlatforms().firstMatchFor(componentType) != null;
}
public boolean isHosting(InternalComponentInstance component) {
return hostedComponents().contains(component);
}
public InternalComponentInstanceGroup clientComponents() {
if (getOwner().isUndefined()) {
return new InternalComponentInstanceGroup();
}
return getDeployment().getRelationshipInstances().clientsOf(this);
}
public InternalComponentInstanceGroup hostedComponents() {
if (getOwner().isUndefined()) {
return new InternalComponentInstanceGroup();
}
return getDeployment().getExecuteInstances().componentsHostedBy(this);
}
@Override
public void validate(Report report) {
if (owner.isUndefined()) {
final String error = String.format("Component instance '%s' has no owner", getQualifiedName());
report.addError(error);
}
}
public boolean canBeUninstalled() {
return !isUsed() && isInternal();
}
public boolean isUsed() {
return !hostedComponents().isEmpty() || !clientComponents().isEmpty();
}
public final boolean isInternal() {
return type.isInternal();
}
@SuppressWarnings("unchecked")
public final InternalComponentInstance asInternal() {
if (isExternal()) {
throw new IllegalStateException("Unable to convert an external component instance into an internal one");
}
return (InternalComponentInstance) this;
}
public final boolean isExternal() {
return !isInternal();
}
@SuppressWarnings("unchecked")
public final ExternalComponentInstance<ExternalComponent> asExternal() {
if (isInternal()) {
throw new IllegalStateException("Unable to convert an internal component instance into an external one");
}
return (ExternalComponentInstance<ExternalComponent>) this;
}
@Override
public Deployment getDeployment() {
return owner.get();
}
@Override
public String getQualifiedName() {
return getOwner().getName() + "::" + getName();
}
@Override
public OptionalOwner<Deployment> getOwner() {
return this.owner;
}
public ProvidedPortInstanceGroup getProvidedPorts() {
return this.providedPorts;
}
public void setProvidedPorts(ProvidedPortInstanceGroup ppig) {
this.providedPorts = ppig;
}
public T getType() {
return this.type;
}
public final void setType(T type) {
if (type == null) {
throw new IllegalArgumentException("'null' is not a valid type for a component instance");
}
this.type = type;
}
public ProvidedExecutionPlatformInstanceGroup getProvidedExecutionPlatforms() {
return providedExecutionPlatforms;
}
public void setProvidedExecutionPlatforms(ProvidedExecutionPlatformInstanceGroup pepig) {
this.providedExecutionPlatforms = pepig;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Instance " + getName() + " : " + getType().getName());
for(PortInstance p : this.getProvidedPorts())
builder.append("-Provided port:"+p.getName());
return builder.toString();
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (other instanceof ComponentInstance) {
ComponentInstance otherCompInst = (ComponentInstance) other;
Boolean match = getName().equals(otherCompInst.getName()) && type.equals(otherCompInst.getType());
return match;
} else {
return false;
}
}
private class LocalProvidedPortInstanceGroup extends ProvidedPortInstanceGroup {
public LocalProvidedPortInstanceGroup(Collection<ProvidedPortInstance> content) {
super();
for (ProvidedPortInstance port: content) {
super.add(port);
port.getOwner().set(ComponentInstance.this);
}
}
@Override
public boolean add(ProvidedPortInstance e) {
throw new UnsupportedOperationException("The provided ports of a component instance cannot be changed");
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("The provided ports of a component instance cannot be changed");
}
@Override
public void clear() {
throw new UnsupportedOperationException("The provided ports of a component instance cannot be changed");
}
}
private class LocalProvidedExecutionPlatformInstanceGroup extends ProvidedExecutionPlatformInstanceGroup {
public LocalProvidedExecutionPlatformInstanceGroup(Collection<ProvidedExecutionPlatformInstance> content) {
super();
for (ProvidedExecutionPlatformInstance platform: content) {
super.add(platform);
platform.getOwner().set(ComponentInstance.this);
}
}
@Override
public boolean add(ProvidedExecutionPlatformInstance e) {
throw new UnsupportedOperationException("The provided execution platforms of a component instance cannot be changed");
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException("The provided execution platforms of a component instance cannot be changed");
}
@Override
public void clear() {
throw new UnsupportedOperationException("The provided execution platforms of a component instance cannot be changed");
}
}
}