package cz.cuni.mff.d3s.been.web.pages.task; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.tapestry5.annotations.Component; import org.apache.tapestry5.annotations.Property; import org.apache.tapestry5.annotations.SessionState; import org.apache.tapestry5.corelib.components.Form; import cz.cuni.mff.d3s.been.api.BeenApiException; import cz.cuni.mff.d3s.been.bpk.BpkIdentifier; import cz.cuni.mff.d3s.been.core.task.ModeEnum; import cz.cuni.mff.d3s.been.core.task.TaskDescriptor; import cz.cuni.mff.d3s.been.web.components.Layout; import cz.cuni.mff.d3s.been.web.model.ConversationHolder; import cz.cuni.mff.d3s.been.web.model.KeyValuePair; import cz.cuni.mff.d3s.been.web.model.TaskDescriptorInitializer; import cz.cuni.mff.d3s.been.web.pages.Index; import cz.cuni.mff.d3s.been.web.pages.Overview; import cz.cuni.mff.d3s.been.web.pages.Page; /** * This component is used to edit task descriptor properties and submit task * defined by this task descriptor. * * @author Kuba Brecka * @author Tadeas Palusga */ @Page.Navigation(section = Layout.Section.TASK_SUBMIT) @SuppressWarnings("unused") public class SubmitTaskDescriptor extends Page { // ----------------------------- // KEYS USED IN CONVERSATION HOLDER // ----------------------------- private static final String KEY_TASK_DESCRIPTOR = "task_descriptor"; private static final String KEY_ARGS = "args"; private static final String KEY_OPTS = "opts"; // ----------------------------- // CONVERSATION POLICY // ----------------------------- @SessionState(create = true) private ConversationHolder<Map<String, Object>> conversationHolder; @Property boolean save; @Property String saveName; /** * Task descriptor loaded in onActivate() method */ @Property TaskDescriptor taskDescriptor; /** * Argument list transformed from list of string on taskDescriptor to list of * keyValuePairs. We have to assign temporary IDs (keys) to arguments (values) * specified in task descriptor to tie them conclusively from JAVA to * JAVASCRIPT and vice versa. (Arguments in task descriptor has no unique ID) */ @Property List<KeyValuePair> args; /** * Java option list transformed from list of string on taskDescriptor to list * of keyValuePairs. We have to assign temporary IDs (keys) to options * (values) specified in task descriptor to tie them conclusively from JAVA to * JAVASCRIPT and vice versa. (Java Options in task descriptor has no unique * ID) */ @Property List<KeyValuePair> opts; // ----------------------------- // TAPESTRY TEMPLATE FIELDS // ----------------------------- /** * Identifier of current conversation */ private String conversationId; /** * Injected form component for task submitting. */ @Component @SuppressWarnings("unused") private Form submitTaskForm; // ----------------------------- // ACTIVATION AND PASSIVATION // ----------------------------- /** * Is set to true if page has been already activated */ private boolean activated; /** * Activate page with context of conversation with given identifier. * * @param conversationId * @return null if page has been already activated or page has been correctly * activated. Redirect to {@link Index} page otherwise. */ Object onActivate(String conversationId) { // we have to check if page has been already activated, because we don't want // to override context of already activated pages if (activated) { return null; } if (!conversationHolder.contains(conversationId)) { return Index.class; } else { taskDescriptor = (TaskDescriptor) conversationHolder.get(conversationId).get(KEY_TASK_DESCRIPTOR); args = (List<KeyValuePair>) conversationHolder.get(conversationId).get(KEY_ARGS); opts = (List<KeyValuePair>) conversationHolder.get(conversationId).get(KEY_OPTS); this.conversationId = conversationId; activated = true; return null; } } /** * Setup method. Loads task descriptor (corresponding to given parameters) * using been api and sets this descriptor as editable property for this * component. * * @param groupId * group id of {@link BpkIdentifier} to which the underlying * {@link TaskDescriptor} belows * @param bpkId * bpk id of {@link BpkIdentifier} to which the underlying * {@link TaskDescriptor} belows * @param version * version id of {@link BpkIdentifier} to which the underlying * {@link TaskDescriptor} belows * @param descriptorName * name of concrete {@link TaskDescriptor} for {@link BpkIdentifier} * identified by previous parameters * @return null (see tapestry page documentation about return values from * onActivate and onPassivate methods) */ @SuppressWarnings("unused") Object onActivate(String groupId, String bpkId, String version, String descriptorName) throws BeenApiException { // load correct task descriptor BpkIdentifier bpkIdentifier = new BpkIdentifier().withGroupId(groupId).withBpkId(bpkId).withVersion(version); this.taskDescriptor = getApi().getTaskDescriptor(bpkIdentifier, descriptorName); if (this.taskDescriptor == null) { this.taskDescriptor = getApi().getNamedTaskDescriptorsForBpk(bpkIdentifier).get(descriptorName); } args = new ArrayList<>(); opts = new ArrayList<>(); TaskDescriptorInitializer.initialize(taskDescriptor, args, opts); HashMap<String, Object> conversationArgs = new HashMap<String, Object>(); conversationArgs.put(KEY_OPTS, opts); conversationArgs.put(KEY_ARGS, args); conversationArgs.put(KEY_TASK_DESCRIPTOR, taskDescriptor); this.conversationId = conversationHolder.set(conversationArgs); activated = true; return null; } /** * @return conversationId as passivate parameter (used on next onActivate * parameter). See tapestry documentation to get more information * about expected return values from onActivate and onPassivate * methods */ Object onPassivate() { return conversationId; } // ----------------------------- // FORM HANDLING // ----------------------------- /** * This handler is called when users click on form SUBMIT button. Submits task * to BEEN cluster using {@link cz.cuni.mff.d3s.been.api.BeenApi} * * @return redirect to {@link Overview} page */ Object onSubmitFromSubmitTaskForm() throws BeenApiException { prepareTaskBeforeSubmit(taskDescriptor, args, opts); if (save) { saveTaskDescriptor(taskDescriptor, saveName); } submitTaskDescriptor(taskDescriptor); return Overview.class; } private void prepareTaskBeforeSubmit(TaskDescriptor taskDescriptor, List<KeyValuePair> args, List<KeyValuePair> opts) { args.remove(null); taskDescriptor.getArguments().getArgument().clear(); taskDescriptor.getJava().getJavaOptions().getJavaOption().clear(); for (KeyValuePair arg : args) { if (arg.value != null) { taskDescriptor.getArguments().getArgument().add(arg.value); } } for (KeyValuePair opt : opts) { if (opt.value != null) { taskDescriptor.getJava().getJavaOptions().getJavaOption().add(opt.value); } } if (taskDescriptor.getDebug().getMode() == ModeEnum.NONE) { taskDescriptor.getDebug().setSuspend(false); } } private void saveTaskDescriptor(TaskDescriptor taskDescriptor, String saveName) throws BeenApiException { BpkIdentifier bpkIdentifier = new BpkIdentifier().withGroupId(taskDescriptor.getGroupId()).withBpkId( taskDescriptor.getBpkId()).withVersion(taskDescriptor.getVersion()); getApi().saveNamedTaskDescriptor(taskDescriptor, saveName, bpkIdentifier); } protected void submitTaskDescriptor(TaskDescriptor taskDescriptor) throws BeenApiException { // try to execute the filter to see if it is syntactically correct String xpath = taskDescriptor.getHostRuntimes().getXpath(); if (xpath != null && !xpath.isEmpty()) { getApi().getRuntimes(taskDescriptor.getHostRuntimes().getXpath()); } getApi().submitTask(taskDescriptor); } }