/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.brooklyn.location.jclouds.templates;
import java.util.ArrayList;
import java.util.List;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.TemplateOptions;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
public abstract class AbstractPortableTemplateBuilder<T extends AbstractPortableTemplateBuilder<?>> implements TemplateBuilder {
/** list of commands supplied by user, excluding options */
protected List<Function<TemplateBuilder,TemplateBuilder>> commands = new ArrayList<Function<TemplateBuilder,TemplateBuilder>>();
private Hardware hardware;
private Image image;
private Template template;
private String locationId;
private String imageId;
private String hardwareId;
private OsFamily os;
private String osNameRegex;
private String osDescriptionRegex;
private String osVersionRegex;
private String osArchitectureRegex;
private String hypervisorRegex;
private Boolean is64bit;
private String imageNameRegex;
private String imageDescriptionRegex;
private String imageVersionRegex;
private Double minCores;
private Integer minRam;
private Double minDisk;
private Predicate<Image> imageCondition;
private Function<Iterable<? extends Image>, Image> imageChooserFunction;
/** this is the last options instance set by a call to options(TemplateOptions) */
private TemplateOptions options;
/** these are extra options that we want _added_, in order, on top of the last options set */
private List<TemplateOptions> additionalOptions = new ArrayList<TemplateOptions>();
@Override
public T any() {
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.any(); }});
return (T)this;
}
@Override
public T fromHardware(final Hardware hardware) {
this.hardware = hardware;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.fromHardware(hardware); }});
return (T)this;
}
public Hardware getHardware() {
return hardware;
}
@Override
public T fromImage(final Image image) {
this.image = image;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.fromImage(image); }});
return (T)this;
}
public Image getImage() {
return image;
}
@Override
public T fromTemplate(final Template template) {
this.template = template;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.fromTemplate(template); }});
return (T)this;
}
public Template getTemplate() {
return template;
}
@Override
public T smallest() {
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.smallest(); }});
return (T)this;
}
@Override
public T fastest() {
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.fastest(); }});
return (T)this;
}
@Override
public T biggest() {
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.biggest(); }});
return (T)this;
}
@Override
public T locationId(final String locationId) {
this.locationId = locationId;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.locationId(locationId); }});
return (T)this;
}
public String getLocationId() {
return locationId;
}
@Override
public T imageId(final String imageId) {
this.imageId = imageId;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.imageId(imageId); }});
return (T)this;
}
public String getImageId() {
return imageId;
}
@Override
public T hardwareId(final String hardwareId) {
this.hardwareId = hardwareId;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.hardwareId(hardwareId); }});
return (T)this;
}
public String getHardwareId() {
return hardwareId;
}
@Override
public T osNameMatches(final String osNameRegex) {
this.osNameRegex = osNameRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.osNameMatches(osNameRegex); }});
return (T)this;
}
public String getOsNameMatchesRegex() {
return osNameRegex;
}
@Override
public T osDescriptionMatches(final String osDescriptionRegex) {
this.osDescriptionRegex = osDescriptionRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.osDescriptionMatches(osDescriptionRegex); }});
return (T)this;
}
public String getOsDescriptionMatchesRegex() {
return osDescriptionRegex;
}
@Override
public T osVersionMatches(final String osVersionRegex) {
this.osVersionRegex = osVersionRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.osVersionMatches(osVersionRegex); }});
return (T)this;
}
public String getOsVersionMatchesRegex() {
return osVersionRegex;
}
@Override
public T osArchMatches(final String osArchitectureRegex) {
this.osArchitectureRegex = osArchitectureRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.osArchMatches(osArchitectureRegex); }});
return (T)this;
}
public String getOsArchitectureMatchesRegex() {
return osArchitectureRegex;
}
@Override
public T os64Bit(final boolean is64bit) {
this.is64bit = is64bit;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.os64Bit(is64bit); }});
return (T)this;
}
public Boolean getIs64bit() {
return is64bit;
}
@Override
public T osFamily(final OsFamily os) {
this.os = os;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.osFamily(os); }});
return (T)this;
}
public OsFamily getOsFamily() {
return os;
}
@Override
public T hypervisorMatches(final String hypervisorRegex) {
this.hypervisorRegex = hypervisorRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.hypervisorMatches(hypervisorRegex); }});
return (T)this;
}
public String getHypervisorMatchesRegex() {
return hypervisorRegex;
}
@Override
public T imageNameMatches(final String imageNameRegex) {
this.imageNameRegex = imageNameRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.imageNameMatches(imageNameRegex); }});
return (T)this;
}
public String getImageNameMatchesRegex() {
return imageNameRegex;
}
@Override
public T imageDescriptionMatches(final String imageDescriptionRegex) {
this.imageDescriptionRegex = imageDescriptionRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.imageDescriptionMatches(imageDescriptionRegex); }});
return (T)this;
}
public String getImageDescriptionMatchesRegex() {
return imageDescriptionRegex;
}
@Override
public T imageVersionMatches(final String imageVersionRegex) {
this.imageVersionRegex = imageVersionRegex;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.imageVersionMatches(imageVersionRegex); }});
return (T)this;
}
public String getImageVersionMatchesRegex() {
return imageVersionRegex;
}
@Override
public T imageMatches(final Predicate<Image> condition) {
this.imageCondition = condition;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.imageMatches(condition); }});
return (T)this;
}
public Predicate<Image> getImageMatchesCondition() {
return imageCondition;
}
@Override
public T minCores(final double minCores) {
this.minCores = minCores;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.minCores(minCores); }});
return (T)this;
}
public Double getMinCores() {
return minCores;
}
@Override
public T minRam(final int megabytes) {
this.minRam = megabytes;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.minRam(megabytes); }});
return (T)this;
}
/** megabytes */
public Integer getMinRam() {
return minRam;
}
@Override
public T minDisk(final double gigabytes) {
this.minDisk = gigabytes;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.minDisk(gigabytes); }});
return (T)this;
}
/** megabytes */
public Double getMinDisk() {
return minDisk;
}
public T imageChooser(final Function<Iterable<? extends Image>, Image> imageChooserFunction) {
this.imageChooserFunction = imageChooserFunction;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.imageChooser(imageChooserFunction); }});
return (T)this;
}
public Function<Iterable<? extends Image>, Image> imageChooser() {
return imageChooserFunction;
}
/** clears everything set in this template, including any default from the compute service */
// not sure this is that useful, as the default is only applied if there are no changes
public T blank() {
hardware = null;
image = null;
template = null;
hypervisorRegex = null;
os = null;
locationId = null;
imageId = null;
hardwareId = null;
osNameRegex = null;
osDescriptionRegex = null;
osVersionRegex = null;
osArchitectureRegex = null;
is64bit = null;
imageNameRegex = null;
imageDescriptionRegex = null;
imageVersionRegex = null;
imageCondition = null;
minCores = null;
minRam = null;
options = null;
additionalOptions.clear();
// clear all fields, and commands
commands.clear();
// then add a command to clear osName + Version + 64bit
osFamily(null);
osVersionMatches(null);
// no way to turn off 64-bitness, but it won't usually be turned on
// os64bit(null);
// set _something_ to prevent the default from applying
minRam(1);
return (T)this;
}
/** true if the templateBuilder spec is blank (ignoring customization options e.g. tags for the resulting instance) */
public boolean isBlank() {
if (commands.isEmpty()) return true;
//also "blank" if we've blanked it
if (commands.size()==1 && (minRam!=null && minRam==1)) return true;
return false;
}
@Override
public T options(final TemplateOptions options) {
this.options = options;
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.options(options); }});
return (T)this;
}
/** sets customization options; may be null if not set. use addOptions(new TemplateOptions()) to set new ones. */
public TemplateOptions getOptions() {
return options;
}
/** adds customization options; if options have already been set, this will additively set selected options
* (but not all, see addTemplateOptions for more info)
*/
public T addOptions(final TemplateOptions options) {
this.additionalOptions.add(options);
commands.add(new Function<TemplateBuilder,TemplateBuilder>() {
public TemplateBuilder apply(TemplateBuilder b) { return b.options(options); }});
return (T)this;
}
public List<TemplateOptions> getAdditionalOptions() {
return ImmutableList.copyOf(additionalOptions);
}
@Override
public int hashCode() {
return Objects.hashCode(
hypervisorRegex,
os,
locationId,
hardwareId,
imageId,
imageDescriptionRegex,
imageNameRegex,
imageVersionRegex,
// might not be implement hashCode, so ignore
// imageCondition,
// imageChooserFunction,
is64bit,
locationId,
osArchitectureRegex,
osDescriptionRegex,
osNameRegex,
osVersionRegex,
minCores,
minRam,
minDisk,
options,
additionalOptions,
// might not implement hashCode, so ignore
// template,
0);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
AbstractPortableTemplateBuilder other = (AbstractPortableTemplateBuilder) obj;
if (!Objects.equal(additionalOptions, other.additionalOptions)) return false;
if (!Objects.equal(commands, other.commands)) return false;
if (!Objects.equal(locationId, other.locationId)) return false;
if (!Objects.equal(hardware, other.hardware)) return false;
if (!Objects.equal(hardwareId, other.hardwareId)) return false;
if (!Objects.equal(image, other.image)) return false;
if (!Objects.equal(imageId, other.imageId)) return false;
if (!Objects.equal(imageDescriptionRegex, other.imageDescriptionRegex)) return false;
if (!Objects.equal(imageNameRegex, other.imageNameRegex)) return false;
if (!Objects.equal(imageVersionRegex, other.imageVersionRegex)) return false;
if (!Objects.equal(imageCondition, other.imageCondition)) return false;
if (!Objects.equal(imageChooserFunction, other.imageChooserFunction)) return false;
if (!Objects.equal(os, other.os)) return false;
if (!Objects.equal(osArchitectureRegex, other.osArchitectureRegex)) return false;
if (!Objects.equal(osDescriptionRegex, other.osDescriptionRegex)) return false;
if (!Objects.equal(osNameRegex, other.osNameRegex)) return false;
if (!Objects.equal(osVersionRegex, other.osVersionRegex)) return false;
if (!Objects.equal(is64bit, other.is64bit)) return false;
if (!Objects.equal(hypervisorRegex, other.hypervisorRegex)) return false;
if (!Objects.equal(minCores, other.minCores)) return false;
if (!Objects.equal(minRam, other.minRam)) return false;
if (!Objects.equal(minDisk, other.minDisk)) return false;
if (!Objects.equal(options, other.options)) return false;
if (!Objects.equal(template, other.template)) return false;
return true;
}
@Override
public String toString() {
return getClass().getSimpleName()+"["+makeNonTrivialArgumentsString()+"]";
}
protected String makeNonTrivialArgumentsString() {
String s =
(hardware != null ? "hardware=" + hardware + ", " : "")
+ (image != null ? "image=" + image + ", " : "")
+ (template != null ? "template=" + template + ", " : "")
+ (hypervisorRegex != null ? "hypervisorRegex="
+ hypervisorRegex + ", " : "")
+ (os != null ? "os=" + os + ", " : "")
+ (locationId != null ? "locationId=" + locationId + ", " : "")
+ (imageId != null ? "imageId=" + imageId + ", " : "")
+ (hardwareId != null ? "hardwareId=" + hardwareId + ", " : "")
+ (osNameRegex != null ? "osNameRegex=" + osNameRegex + ", "
: "")
+ (osDescriptionRegex != null ? "osDescriptionRegex="
+ osDescriptionRegex + ", " : "")
+ (osVersionRegex != null ? "osVersionRegex=" + osVersionRegex
+ ", " : "")
+ (osArchitectureRegex != null ? "osArchictectureRegex="
+ osArchitectureRegex + ", " : "")
+ (is64bit != null ? "is64bit=" + is64bit + ", " : "")
+ (imageNameRegex != null ? "imageNameRegex=" + imageNameRegex
+ ", " : "")
+ (imageDescriptionRegex != null ? "imageDescriptionRegex="
+ imageDescriptionRegex + ", " : "")
+ (imageVersionRegex != null ? "imageVersionRegex="
+ imageVersionRegex + ", " : "")
+ (imageCondition != null ? "imageCondition=" + imageCondition
+ ", " : "")
+ (imageChooserFunction != null ? "imageChooserFunction=" + imageChooserFunction
+ ", " : "")
+ (minCores != null ? "minCores=" + minCores + ", " : "")
+ (minRam != null ? "minRam=" + minRam + ", " : "")
+ (minDisk != null ? "minDisk=" + minDisk + ", " : "");
if (s.endsWith(", ")) s = s.substring(0, s.length()-2);
return s;
}
}