package cz.cuni.mff.d3s.been.benchmarkapi; import static cz.cuni.mff.d3s.been.core.jaxb.XSD.TASK_CONTEXT_DESCRIPTOR; import java.io.InputStream; import cz.cuni.mff.d3s.been.core.jaxb.BindingParser; import cz.cuni.mff.d3s.been.core.task.*; /** * Builder of {@link cz.cuni.mff.d3s.been.core.task.TaskContextDescriptor} * * @author Martin Sixta */ public final class ContextBuilder { /** * The descriptor we are building */ private TaskContextDescriptor descriptor; /** * Private constructor. * * @param contextDescriptor * the context descriptor to use */ private ContextBuilder(TaskContextDescriptor contextDescriptor) { this.descriptor = contextDescriptor; } /** * Sets name of the context. * * @param name * Name of the context which will be visible to a user. */ public void setName(final String name) { descriptor.setName(name); } /** * Sets description of the context * * @param contextDescription * Description of the context which will be visible to a user. */ public void setDescription(final String contextDescription) { descriptor.setContextDescription(contextDescription); } /** * Sets a context-wide property. * <p/> * Previous value corresponding to the name will be overwritten. * * @param name * name of the property which will be available to the whole context * @param value * value corresponding to the given property with {@code name} * available to the whole context */ public void setProperty(final String name, final String value) { if (!descriptor.isSetProperties()) { descriptor.setProperties(new Properties()); } for (Property property : descriptor.getProperties().getProperty()) { if (property.isSetName() && name.equals(property.getName())) { property.setValue(value); return; } } descriptor.getProperties().getProperty().add(new Property().withName(name).withValue(value)); } /** * Clears all tasks from the descriptor. */ public void clearTasks() { descriptor.getTask().clear(); } /** * Adds a {@link Task} to the context. * <p/> * The Task will be properly initialized and added to the context. The task * can be further customized by setting its properties. \ * * @param name * user visible name of the task * @return task initialized and linked task for further customization */ public Task addTask(String name) { Task task = newEmptyTask().withName(name); addTask(task); return task; } /** * Adds a {@link Task} to the context with a link to a {@link Template}. * <p/> * The template must already exist. * <p/> * The Task will be properly initialized and added to the context. The task * can be further customized by setting its properties , but the * {@link TaskDescriptor} of the template will be used. * * @param name * user visible name of the task * @param templateName * name of the template the task should use as its base * @return initialized and linked task for further customization * @throws BenchmarkException * when no template with {@code templateName} exists */ public Task addTask(final String name, final String templateName) throws BenchmarkException { Task task = newEmptyTask().withName(name); task.getDescriptor().setFromTemplate(templateName); addTask(task); return task; } /** * Adds named {@link Template} to the context. * * @param templateName * name of the template * @throws BenchmarkException * when template with the same name already exits */ public void addTemplate(String templateName) throws BenchmarkException { for (Template template : descriptor.getTemplates().getTemplate()) { if (template.isSetName() && template.getName().equals(templateName)) { String msg = String.format("Template with name '%s' already exists", templateName); throw new BenchmarkException(msg); } } Template template = new Template().withName(templateName).withTaskDescriptor(new TaskDescriptor()); descriptor.getTemplates().getTemplate().add(template); } /** * Returns template with {@code templateName}. * * @param templateName * name of the template to look for * @return the template with {@code templateName} * @throws BenchmarkException * when no template with {@code templateName} exits */ public Template getTemplate(String templateName) throws BenchmarkException { for (Template template : descriptor.getTemplates().getTemplate()) { if (template.isSetName() && template.getName().equals(templateName)) { if (!template.isSetTaskDescriptor()) { template.setTaskDescriptor(new TaskDescriptor()); } return template; } } String msg = String.format("No such with name '%s' exists", templateName); throw new BenchmarkException(msg); } /** * Sets selector on a template. * * @param templateName * name of the template to set the selector on * @param selector * expression which selects Host Runtimes the task can run on * * @throws BenchmarkException * when no template with {@code templateName} exits */ public void setSelector(final String templateName, final String selector) throws BenchmarkException { Template template = getTemplate(templateName); if (selector == null || selector.isEmpty()) { return; } if (!template.getTaskDescriptor().isSetHostRuntimes()) { template.getTaskDescriptor().setHostRuntimes(new HostRuntimes()); } template.getTaskDescriptor().getHostRuntimes().setXpath(selector); } /** * Sets tasks exclusivity for a template. * * @param templateName * name of the template to set the {@code exclusivity} on * @param exclusivity * exclusivity of all tasks created from the template * @throws BenchmarkException * when no template with {@code templateName} exits */ public void setExclusivity(final String templateName, final TaskExclusivity exclusivity) throws BenchmarkException { Template template = getTemplate(templateName); template.getTaskDescriptor().setExclusive(exclusivity); } /** * Returns the TaskContextDescriptor this class was used to build. * * @return the resulting context descriptor */ public TaskContextDescriptor build() { return descriptor; } /** * Creates a builder with empty {@link TaskContextDescriptor} * * @param name * name of the context * @return a builder which can be used to build a context descriptor */ public static ContextBuilder create(String name) { return new ContextBuilder(new TaskContextDescriptor().withName(name)); } /** * Creates the builder from a resource with TaskContextDescriptor xml. * * @param classResourceBase * from where to look for the resource * @param resourceName * name of the resource with xml representation of a * TaskContextDescriptor * @return builder which is initialized from the resource * @throws BenchmarkException * when an error has occurred during the creation of the descriptor */ public static ContextBuilder createFromResource(Class<?> classResourceBase, String resourceName) throws BenchmarkException { InputStream inputStream = classResourceBase.getResourceAsStream(resourceName); if (inputStream == null) { String msg = String.format("Cannot locate resource '%s'", resourceName); throw new BenchmarkException(msg); } try { TaskContextDescriptor contextDescriptor; BindingParser<TaskContextDescriptor> bindingComposer = TASK_CONTEXT_DESCRIPTOR.createParser(TaskContextDescriptor.class); contextDescriptor = bindingComposer.parse(inputStream); return new ContextBuilder(contextDescriptor); } catch (Exception e) { throw new BenchmarkException("Cannot parse input xml", e); } } /** * Adds a task into the current context descriptor. * * @param task * the task to add * @return true if the task was successfully added */ private boolean addTask(Task task) { return descriptor.getTask().contains(task) || descriptor.getTask().add(task); } /** * Creates a new empty task that can be added into the context. * * @return a new empty task */ private Task newEmptyTask() { return new Task().withDescriptor(new Descriptor()).withProperties(new Properties()); } }