/**
* 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 org.cloudml.core.collections.*;
import org.cloudml.core.util.ModelUtils;
import org.cloudml.core.validation.CanBeValidated;
import org.cloudml.core.validation.Report;
import org.cloudml.core.visitors.Visitable;
import org.cloudml.core.visitors.Visitor;
import java.util.Random;
public class Deployment extends WithProperties implements Visitable, CanBeValidated {
private final ProviderGroup providers;
private final ComponentGroup components;
private final ComponentInstanceGroup<ComponentInstance<? extends Component>> componentInstances;
private final RelationshipGroup relationships;
private final RelationshipInstanceGroup relationshipInstances;
private final ExecuteInstanceGroup executeInstances;
private final ResourcePoolGroup resourcePoolInstances;
private final CloudGroup clouds;
public Deployment() {
this(DEFAULT_NAME);
}
public Deployment(String name) {
super(name);
this.providers = new LocalProviderGroup();
this.components = new LocalComponentGroup();
this.componentInstances = new LocalComponentInstanceGroup<ComponentInstance<? extends Component>>();
this.relationships = new LocalRelationshipGroup();
this.relationshipInstances = new LocalRelationshipInstanceGroup();
this.executeInstances = new LocalExecuteInstanceGroup();
this.clouds = new LocalCloudGroup();
this.resourcePoolInstances=new LocalResourcePoolGroup();
}
public Deployment clone(){
Deployment tmp=new Deployment();
tmp.getComponents().addAll(this.getComponents());
tmp.getComponentInstances().addAll(this.getComponentInstances());
tmp.getExecuteInstances().addAll(this.getExecuteInstances());
tmp.getProviders().addAll(this.getProviders());
tmp.getRelationshipInstances().addAll(this.getRelationshipInstances());
tmp.getClouds().addAll(this.getClouds());
tmp.getRelationships().addAll(this.getRelationships());
tmp.setName(this.getName());
return tmp;
}
@Override
public void accept(Visitor visitor) {
visitor.visitDeployment(this);
}
@Override
public void validate(Report report) {
if (providers.isEmpty()
&& components.isEmpty()
&& componentInstances.isEmpty()
&& relationships.isEmpty()
&& relationshipInstances.isEmpty()) {
report.addWarning("empty deployment model");
}
}
public ProviderGroup getProviders() {
return this.providers;
}
public ComponentGroup getComponents() {
return components;
}
public InternalComponentGroup internalComponents() {
return components.onlyInternals();
}
public ComponentInstanceGroup<ComponentInstance<? extends Component>> getComponentInstances() {
return componentInstances;
}
public ExecuteInstanceGroup getExecuteInstances() {
return this.executeInstances;
}
public RelationshipGroup getRelationships() {
return relationships;
}
public RelationshipInstanceGroup getRelationshipInstances() {
return relationshipInstances;
}
public CloudGroup getClouds() {
return clouds;
}
public void deploy(InternalComponentInstance component, ComponentInstance<? extends Component> host) {
final ProvidedExecutionPlatformInstance platform = host.getProvidedExecutionPlatforms().firstMatchFor(component);
if (platform == null) {
final String error = String.format(
"Unable to deploy! '%s' does not provide any execution platform that suits '%s' (candidates are: %s)",
host.getQualifiedName(),
component.getRequiredExecutionPlatform().getQualifiedName(),
host.getProvidedExecutionPlatforms().onlyNames().toString());
throw new IllegalArgumentException(error);
}
final ExecuteInstance execute = new ExecuteInstance(ModelUtils.generateUniqueName("runOn"),component, platform);
executeInstances.add(execute);
}
@Override
public boolean equals(Object other) {
if (other instanceof Deployment) {
Deployment otherDepModel = (Deployment) other;
return components.equals(otherDepModel.components) && componentInstances.equals(otherDepModel.componentInstances)
&& relationships.equals(otherDepModel.relationships) && relationshipInstances.equals(otherDepModel.relationshipInstances);
}
else {
return false;
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Deployment model " + getName() + "{\n");
builder.append("- Component types: {\n");
for (Component t : components) {
builder.append(" - " + t + "\n");
}
builder.append("}\n");
builder.append("- Relationship types: {\n");
for (Relationship b : relationships) {
builder.append(" - " + b + "\n");
}
builder.append("}\n");
builder.append("- Component instances: {\n");
for (ComponentInstance i : componentInstances) {
builder.append(" - " + i.toString() + "\n");
}
builder.append("}\n");
builder.append("- Relationship instances: {\n");
for (RelationshipInstance b : relationshipInstances) {
builder.append(" - " + b + "\n");
}
builder.append("}\n");
return builder.toString();
}
public ResourcePoolGroup getResourcePoolInstances() {
return resourcePoolInstances;
}
private class LocalProviderGroup extends ProviderGroup {
@Override
public boolean add(Provider e) {
if (firstNamed(e.getName()) != null) {
final String error = String.format("Provider name must be unique! There is already a provider named '%s'", e.getName());
throw new IllegalStateException(error);
}
e.getOwner().set(Deployment.this);
return super.add(e);
}
@Override
public boolean remove(Object o) {
if (o instanceof Provider) {
final Provider provider = (Provider) o;
if (provider.isUsed()) {
final String error = String.format("Unable to remove provider '5s' as it is still in use", provider.getName());
throw new IllegalStateException(error);
}
provider.getOwner().discard();
}
return super.remove(o);
}
}
private class LocalComponentGroup extends ComponentGroup {
public boolean replace(Component component){
if (firstNamed(component.getName()) != null) {
super.remove(component);
}
component.getOwner().set(Deployment.this);
return super.add(component);
}
@Override
public boolean add(Component component) {
if (firstNamed(component.getName()) != null) {
//final String error = String.format("Component name must be unique! There is already a component named '%s'.", component.getName());
//throw new IllegalStateException(error);
return false;
}
component.getOwner().set(Deployment.this);
return super.add(component);
}
@Override
public boolean remove(Object o) {
if (o instanceof Component) {
final Component component = (Component) o;
if (component.isUsed()) {
final String error = String.format("Unable to remove the component '%s' as it is still in use!", component.getQualifiedName());
throw new IllegalStateException(error);
}
component.getOwner().discard();
}
return super.remove(o);
}
}
private class LocalComponentInstanceGroup<T extends ComponentInstance<? extends Component>> extends ComponentInstanceGroup<T> {
public boolean replace(T element){
if (firstNamed(element.getName()) != null) {
super.remove(element);
}
element.getOwner().set(Deployment.this);
return super.add(element);
}
@Override
public boolean add(T element) {
element.getOwner().set(Deployment.this);
if (firstNamed(element.getName()) != null) {
//final String error = String.format("Component instance name must be unique! There is already a component instance named '%s'.", element.getName());
//throw new IllegalStateException(error);
return false;
}
return super.add(element);
}
@Override
public boolean remove(Object o) {
Boolean b=super.remove(o);
if (b && o instanceof ComponentInstance) {
final ComponentInstance<? extends Component> instance = (ComponentInstance<? extends Component>) o;
instance.getOwner().discard();
}
return b;
}
}
private class LocalRelationshipGroup extends RelationshipGroup {
public boolean replace(Relationship relationship){
if (firstNamed(relationship.getName()) != null) {
super.remove(relationship);
}
relationship.getOwner().set(Deployment.this);
return super.add(relationship);
}
@Override
public boolean add(Relationship relationship) {
relationship.getOwner().set(Deployment.this);
if (firstNamed(relationship.getName()) != null) {
//final String error = String.format("Relationship name must be unique! There is already a relationhip named '%s'.", relationship.getName());
//throw new IllegalStateException(error);
return false;
}
return super.add(relationship);
}
@Override
public boolean remove(Object o) {
if (o instanceof Relationship) {
((Relationship) o).getOwner().discard();
}
return super.remove(o);
}
}
private class LocalRelationshipInstanceGroup extends RelationshipInstanceGroup {
public boolean replace(RelationshipInstance relationship){
if (firstNamed(relationship.getName()) != null) {
super.remove(relationship);
}
relationship.getOwner().set(Deployment.this);
return super.add(relationship);
}
@Override
public boolean add(RelationshipInstance instance) {
if (firstNamed(instance.getName()) != null) {
//final String error = String.format("Relationship instance name must be unique! There is already a relationhip instance named '%s'.", instance.getName());
//throw new IllegalStateException(error);
return false;
}
instance.getOwner().set(Deployment.this);
return super.add(instance);
}
@Override
public boolean remove(Object o) {
if (o instanceof RelationshipInstance) {
((RelationshipInstance) o).getOwner().discard();
}
return super.remove(o);
}
}
private class LocalExecuteInstanceGroup extends ExecuteInstanceGroup {
public boolean replace(ExecuteInstance e){
if (firstNamed(e.getName()) != null) {
super.remove(e);
}
e.getOwner().set(Deployment.this);
return super.add(e);
}
@Override
public boolean add(ExecuteInstance e) {
e.getOwner().set(Deployment.this);
return super.add(e);
}
@Override
public boolean remove(Object o) {
if (o instanceof ExecuteInstance) {
((ExecuteInstance) o).getOwner().discard();
}
return super.remove(o);
}
}
private class LocalResourcePoolGroup extends ResourcePoolGroup{
@Override
public boolean add(ResourcePoolInstance e) {
e.getOwner().set(Deployment.this);
return super.add(e);
}
@Override
public boolean remove(Object o) {
if (o instanceof ResourcePoolInstance) {
((ResourcePoolInstance) o).getOwner().discard();
}
return super.remove(o);
}
}
private class LocalCloudGroup extends CloudGroup {
@Override
public boolean add(Cloud e) {
e.getOwner().set(Deployment.this);
return super.add(e);
}
@Override
public boolean remove(Object o) {
if (o instanceof Cloud) {
((Cloud) o).getOwner().discard();
}
return super.remove(o);
}
}
}