| /** |
| * |
| */ |
| package org.apache.taverna.scufl2.api.configurations; |
| |
| /* |
| * 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. |
| */ |
| |
| |
| import java.io.IOException; |
| import java.net.URI; |
| |
| import org.apache.taverna.scufl2.api.activity.Activity; |
| import org.apache.taverna.scufl2.api.common.AbstractNamed; |
| import org.apache.taverna.scufl2.api.common.Child; |
| import org.apache.taverna.scufl2.api.common.Configurable; |
| import org.apache.taverna.scufl2.api.common.Typed; |
| import org.apache.taverna.scufl2.api.common.Visitor; |
| import org.apache.taverna.scufl2.api.common.WorkflowBean; |
| import org.apache.taverna.scufl2.api.core.Processor; |
| import org.apache.taverna.scufl2.api.core.Workflow; |
| import org.apache.taverna.scufl2.api.port.Port; |
| import org.apache.taverna.scufl2.api.profiles.Profile; |
| |
| |
| import com.fasterxml.jackson.core.JsonParser; |
| import com.fasterxml.jackson.databind.JsonNode; |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| import com.fasterxml.jackson.databind.node.ArrayNode; |
| import com.fasterxml.jackson.databind.node.JsonNodeFactory; |
| import com.fasterxml.jackson.databind.node.ObjectNode; |
| import com.fasterxml.jackson.databind.node.ValueNode; |
| |
| /** |
| * Configuration of a {@link Configurable} workflow bean. |
| * <p> |
| * A configuration is activated by a {@link Profile}, and provides a link to the |
| * {@link #getJson()} containing the properties to configure the bean, like an |
| * {@link Activity}. |
| * <p> |
| * A configuration is of a certain (RDF) <strong>type</strong>, as defined by |
| * {@link #getType()} - which determines which properties are required and |
| * optional. For instance, the type |
| * <code>http://ns.taverna.org.uk/2010/activity/wsdl/ConfigType</code> requires |
| * the property |
| * <code>http://ns.taverna.org.uk/2010/activity/wsdl/operation</code>. |
| * <p> |
| * These requirements are described in the {@link ConfigurationDefinition} that |
| * matches the getConfigurableType() of the {@link Configurable} found by |
| * {@link #getConfigures()}. Its |
| * {@link ConfigurationDefinition#getPropertyResourceDefinition()} should in |
| * {@link PropertyResourceDefinition#getTypeURI()} should match the |
| * {@link #getType()} of this {@link Configuration}. |
| * <p> |
| * Note: {@link #getType()} (and the potentially misleading {@link #getType()}) |
| * return the type of <b>this</b> Configuration, not the type of the |
| * {@link Configurable} bean that it happens to configure. For instance, a |
| * Configuration typed <code>http://example.com/WSDLConfiguration</code> might |
| * configure an activity typed <code>http://example.com/WSDLActivity</code>, but |
| * could also have configured an activity typed |
| * <code>http://example.com/GlobusWSDLActivity</code>. |
| * <p> |
| * <strong>TODO: Where are the ConfigurationDefinitions found?</strong> |
| * |
| * @author Alan R Williams |
| * @author Stian Soiland-Reyes |
| * |
| */ |
| public class Configuration extends AbstractNamed implements Child<Profile>, |
| Typed { |
| private static final JsonNodeFactory JSON_NODE_FACTORY = JsonNodeFactory.instance; |
| private Configurable configures; |
| private Profile parent; |
| private JsonNode json = JSON_NODE_FACTORY.objectNode(); |
| private JsonNode jsonSchema; |
| private URI type; |
| |
| /** |
| * Constructs a <code>Configuration</code> with a random UUID as the name. |
| */ |
| public Configuration() { |
| super(); |
| } |
| |
| /** |
| * Construct a <code>Configuration</code> with the specified name. |
| * |
| * @param name |
| * the name of the <code>Configuration</code>. <strong>Must |
| * not</strong> be <code>null</code> or an empty String. |
| */ |
| public Configuration(String name) { |
| super(name); |
| } |
| |
| @Override |
| public boolean accept(Visitor visitor) { |
| return visitor.visit(this); |
| } |
| |
| /** |
| * Return the {@link Configurable} workflow bean that is configured. |
| * Typically an {@link Activity} or {@link Processor}, {@link Workflow} and |
| * {@link Port} can be configured. |
| * |
| * @return the <code>Configurable</code> <code>WorkflowBean</code> that is |
| * configured |
| */ |
| public Configurable getConfigures() { |
| return configures; |
| } |
| |
| @Override |
| public Profile getParent() { |
| return parent; |
| } |
| |
| /** |
| * Return the underlying JSON {@link JsonNode} which contains the properties |
| * set by this configuration. |
| * <p> |
| * The JSON node is typically an {@link ObjectNode} or {@link ArrayNode}, |
| * but could also be a {@link ValueNode}. The default node for a freshly |
| * constructed Configuration is an {@link ObjectNode}. * @return the backing |
| * {@link ObjectNode}. |
| */ |
| public JsonNode getJson() { |
| return json; |
| } |
| |
| /** |
| * Return a string representation of the {@link #getJson()} configuration, |
| * the string is valid JSON. |
| * |
| * @return |
| */ |
| public String getJsonAsString() { |
| return json.toString(); |
| } |
| |
| /** |
| * Return the {@link #getJson()} configuration as an {@link ObjectNode}. |
| * This is the default type for a new {@link Configuration}. |
| * |
| * @throws IllegalStateException |
| * if the {@link #getJson()} is not an {@link ObjectNode} |
| * |
| * @return |
| */ |
| public ObjectNode getJsonAsObjectNode() { |
| if (!json.isObject()) |
| throw new IllegalStateException("JSON is not an ObjectNode, but " |
| + json); |
| return (ObjectNode) json; |
| } |
| |
| /** |
| * Return the type of the <code>Configuration</code>. |
| * <p> |
| * The URI will match the {@link PropertyResource#getTypeURI()}. |
| * |
| * @return the type of the <code>Configuration</code> |
| */ |
| @Override |
| public URI getType() { |
| return type; |
| } |
| |
| /** |
| * Set the {@link Configurable} {@link WorkflowBean} that is configured. |
| * |
| * @param configurable |
| * the <code>Configurable</code> <code>WorkflowBean</code> that |
| * is configured |
| */ |
| public void setConfigures(Configurable configurable) { |
| configures = configurable; |
| } |
| |
| @Override |
| public void setParent(Profile parent) { |
| if (this.parent != null && this.parent != parent) |
| this.parent.getConfigurations().remove(this); |
| this.parent = parent; |
| if (parent != null) |
| parent.getConfigurations().add(this); |
| } |
| |
| /** |
| * Set the underlying JSON {@link JsonNode} which contains the properties |
| * set by this configuration. The JSON node is typically an |
| * {@link ObjectNode} or {@link ArrayNode}, but could also be a |
| * {@link ValueNode}. |
| * <p> |
| * If the provided ObjectNode is <code>null</code>, a new, blank |
| * {@link ObjectNode} will be set. |
| * |
| * @param json |
| * the underlying <code>JsonNode</code> which contains the |
| * properties set by this configuration. |
| */ |
| public void setJson(JsonNode json) { |
| if (json == null) |
| this.json = JSON_NODE_FACTORY.objectNode(); |
| this.json = json; |
| } |
| |
| /** |
| * Set the type of the <code>Configuration</code>. |
| * <p> |
| * This will also set {@link PropertyResource#setTypeURI(URI)}. |
| * |
| * @param type |
| * the type of the <code>Configuration</code>. |
| */ |
| @Override |
| public void setType(URI type) { |
| this.type = type; |
| } |
| |
| @Override |
| protected void cloneInto(WorkflowBean clone, Cloning cloning) { |
| super.cloneInto(clone, cloning); |
| Configuration cloneConfig = (Configuration) clone; |
| cloneConfig.setConfigures(cloning.cloneOrOriginal(getConfigures())); |
| } |
| |
| public JsonNode getJsonSchema() { |
| return jsonSchema; |
| } |
| |
| public void setJsonSchema(JsonNode jsonSchema) { |
| this.jsonSchema = jsonSchema; |
| } |
| |
| public void setJsonSchema(String jsonString) { |
| setJsonSchema(parseJson(jsonString)); |
| } |
| |
| public void setJson(String jsonString) { |
| setJson(parseJson(jsonString)); |
| } |
| |
| protected JsonNode parseJson(String jsonString) { |
| ObjectMapper mapper = new ObjectMapper(); |
| try { |
| JsonParser parser = mapper.getFactory().createParser(jsonString); |
| return parser.readValueAs(JsonNode.class); |
| } catch (IOException e) { |
| throw new IllegalArgumentException("Not valid JSON string", e); |
| } |
| } |
| } |