/*
* The MIT License
*
* Copyright 2011 Sony Ericsson Mobile Communications. All rights reserved.
* Copyright 2012 Sony Mobile Communications AB. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.sonyericsson.hudson.plugins.metadata.model.values;
import com.sonyericsson.hudson.plugins.metadata.Constants;
import com.sonyericsson.hudson.plugins.metadata.model.JsonUtils;
import com.sonyericsson.hudson.plugins.metadata.model.MetadataContainer;
import com.sonyericsson.hudson.plugins.metadata.model.MetadataParent;
import com.sonyericsson.hudson.plugins.metadata.util.ExtensionUtils;
import hudson.EnvVars;
import hudson.model.Describable;
import hudson.model.Descriptor;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import java.io.Serializable;
import java.util.List;
/**
* A metadata value to be set in a job or node.
*/
@ExportedBean
public abstract class AbstractMetadataValue implements
Serializable, Describable<AbstractMetadataValue>, MetadataValue {
/**
* The name of this metadata value.
*/
protected String name;
private String description;
private MetadataParent<MetadataValue> parent;
private boolean generated = false;
private boolean exposedToEnvironment = false;
/**
* Constructor with name, description and exposedToEnvironment.
*
* @param name The name of the definitions.
* @param description The description of the definitions.
* @param exposedToEnvironment If this value should be exposed as an environment variable.
*/
protected AbstractMetadataValue(String name, String description, boolean exposedToEnvironment) {
this.name = name;
this.description = description;
this.exposedToEnvironment = exposedToEnvironment;
}
/**
* Constructor with name and description.
*
* @param name The name of the definitions.
* @param description The description of the definitions.
*/
protected AbstractMetadataValue(String name, String description) {
this(name, description, false);
}
/**
* Constructor with only a name.
*
* @param name The name of the definitions.
*/
protected AbstractMetadataValue(String name) {
this(name, null, false);
}
/**
* Get the description of this value.
*
* @return the description.
*/
@Exported
@Override
public synchronized String getDescription() {
return description;
}
/**
* Set the description of this value.
*
* @param description the description.
*/
public synchronized void setDescription(String description) {
this.description = description;
}
/**
* Get the name of this value.
*
* @return the name.
*/
@Exported
public final synchronized String getName() {
return name;
}
/**
* Set the name of this value.
* @param name the name.
*/
protected synchronized void setName(String name) {
this.name = name;
}
/**
* Get the value.
*
* @return the value.
*/
@Exported
@Override
public synchronized Object getValue() {
return null;
}
/**
* This value's parent.
*
* @return the parent.
*/
@Override
public MetadataParent<MetadataValue> getParent() {
return parent;
}
/**
* This value's parent.
*
* @param parent the parent.
*/
@Override
public void setParent(MetadataParent<MetadataValue> parent) {
this.parent = parent;
}
/**
* If this value is generated or user created.
*
* @return true if generated.
*/
@Override
public boolean isGenerated() {
return generated;
}
/**
* Set if this value is generated or user created.
*
* @param generated true if generated.
*/
@Override
public synchronized void setGenerated(boolean generated) {
this.generated = generated;
}
/**
* This function will generate the full name, using the chosen separator.
* @param separator the separator to use.
* @return the full name.
*/
@Exported
public String getFullName(String separator) {
MetadataParent<MetadataValue> myParent = getParent();
if (myParent == null) {
return getName();
}
String fullName = myParent.getFullName(separator);
if (fullName != null && !"".equals(fullName)) {
return fullName + separator + getName();
}
return getName();
}
/**
* This function will generate the full name.
* @return the full name.
*/
@Exported
public String getFullName() {
return getFullName(Constants.DISPLAY_NAME_SEPARATOR);
}
@Override
public synchronized String getFullNameFrom(MetadataParent<MetadataValue> base) {
MetadataParent<MetadataValue> myParent = getParent();
if (myParent == base || myParent == null) {
return name;
}
String fullNameFrom = myParent.getFullNameFrom(base);
if (fullNameFrom != null && !"".equals(fullNameFrom)) {
return fullNameFrom + Constants.DISPLAY_NAME_SEPARATOR + getName();
}
return name;
}
@Override
public String[] getFullPath() {
return getFullName().split("\\.");
}
@Override
public void replacementOf(MetadataValue old) {
//Nothing needs to be done as most types should be replaced directly.
}
@Override
public void addEnvironmentVariables(EnvVars variables, boolean exposeAll) {
if (exposedToEnvironment || exposeAll) {
variables.put(getEnvironmentName(), getValue().toString());
}
}
/**
* This function will generate the full environment variable name.
* The format will be MD_FULL_PATH_TO_CHILD
*
* @return the full environment variable name.
*/
@Exported
public String getEnvironmentName() {
String envName = (Constants.METADATA_ENV_PREFIX + getFullName(Constants.ENVIRONMENT_SEPARATOR));
envName = envName.toUpperCase();
return envName.replaceAll(Constants.METADATA_ENV_SPECIALS_REGEXP, Constants.ENVIRONMENT_SEPARATOR);
}
@Override
public boolean isExposedToEnvironment() {
return exposedToEnvironment;
}
@Override
public void setExposeToEnvironment(boolean expose) {
exposedToEnvironment = expose;
}
/**
* Converts this into a JSON Object <strong>without the value</strong>. Implementing classes can use this as a
* utility method for the name, type and description. And then just add the value.
*
* @return the half finished JSON Object.
*/
protected synchronized JSONObject toAbstractJson() {
JSONObject obj = new JSONObject();
obj.put(JsonUtils.NAME, name);
obj.put(JsonUtils.DESCRIPTION, description);
obj.put(JsonUtils.GENERATED, generated);
obj.put(JsonUtils.EXPOSED, exposedToEnvironment);
AbstractMetaDataValueDescriptor descriptor = (AbstractMetaDataValueDescriptor)getDescriptor();
obj.put(JsonUtils.METADATA_TYPE, descriptor.getJsonType());
return obj;
}
@Override
public AbstractMetadataValue clone() throws CloneNotSupportedException {
return (AbstractMetadataValue)super.clone();
}
/**
* The descriptor for the AbstractMetadataValue.
*/
public abstract static class AbstractMetaDataValueDescriptor extends Descriptor<AbstractMetadataValue> {
/**
* Tells if values of this descriptor can be added to the specified container type or not. Some value types
* might not apply to be added to a node and vice versa. The default implementation always returns true.
*
* @param containerDescriptor the descriptor for the container that the values of this type can be added to. Can
* be null.
* @return true if it applies.
*/
public boolean appliesTo(Descriptor containerDescriptor) {
return true;
}
/**
* Finds the descriptor for the given metadata-type.
* @param type the type to find.
* @return the Descriptor or null if non is found.
*/
public static AbstractMetaDataValueDescriptor findForJsonType(String type) {
List<AbstractMetaDataValueDescriptor> extensionList = ExtensionUtils.getMetadataValueDescriptors();
for (AbstractMetadataValue.AbstractMetaDataValueDescriptor d : extensionList) {
if (d.getJsonType().equals(type)) {
return d;
}
}
return null;
}
/**
* Gives the type to put into the JSON conversations.
*
* @return the JSON type field.
*/
public abstract String getJsonType();
/**
* Converts a JSON object into a MetadataValue of this descriptors describable.
*
* @param json the json data to use.
* @param container The container that the created object is intended to go into.
* Can be used to check for validity of attributes.
* @return the converted value.
*
* @throws JsonUtils.ParseException if something is for example missing.
*/
public abstract MetadataValue fromJson(JSONObject json, MetadataContainer<MetadataValue> container)
throws JsonUtils.ParseException;
}
}