http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationPanel.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationPanel.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationPanel.java new file mode 100644 index 0000000..536a87d --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationPanel.java @@ -0,0 +1,271 @@ +/* +* 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 io.github.taverna_extras.component.ui.annotation; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.NORTH; +import static java.awt.Color.WHITE; +import static java.awt.Font.BOLD; +import static java.awt.GridBagConstraints.BOTH; +import static java.awt.GridBagConstraints.EAST; +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.SOUTHEAST; +import static java.lang.Integer.MIN_VALUE; +import static java.lang.String.format; +import static javax.swing.JOptionPane.ERROR_MESSAGE; +import static javax.swing.JOptionPane.OK_CANCEL_OPTION; +import static javax.swing.JOptionPane.OK_OPTION; +import static javax.swing.JOptionPane.showConfirmDialog; +import static javax.swing.JOptionPane.showMessageDialog; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.getDisplayName; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.getObjectName; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.Set; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.border.EmptyBorder; + +import io.github.taverna_extras.component.api.profile.SemanticAnnotationProfile; + +import org.apache.jena.ontology.OntProperty; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Statement; +import org.apache.taverna.lang.ui.DeselectingButton; + +public class SemanticAnnotationPanel extends JPanel { + private static final long serialVersionUID = -5949183295606132775L; + + private List<PropertyPanelFactorySPI> propertyPanelFactories; //FIXME beaninject + private final AbstractSemanticAnnotationContextualView semanticAnnotationContextualView; + private final SemanticAnnotationProfile semanticAnnotationProfile; + private final Set<Statement> statements; + private final boolean allowChange; + private final PropertyPanelFactorySPI bestFactory; + + public SemanticAnnotationPanel( + AbstractSemanticAnnotationContextualView semanticAnnotationContextualView, + SemanticAnnotationProfile semanticAnnotationProfile, + Set<Statement> statements, boolean allowChange) { + this.semanticAnnotationContextualView = semanticAnnotationContextualView; + this.semanticAnnotationProfile = semanticAnnotationProfile; + this.statements = statements; + this.allowChange = allowChange; + this.bestFactory = findBestPanelFactory(); + initialise(); + } + + private void initialise() { + setLayout(new GridBagLayout()); + // setBorder(new AbstractBorder() { + // @Override + // public void paintBorder(Component c, Graphics g, int x, int y, int + // width, int height) { + // g.setColor(Color.GRAY); + // g.drawLine(x, y+height-1, x+width-1, y+height-1); + // } + // }); + + GridBagConstraints c = new GridBagConstraints(); + c.anchor = SOUTHEAST; + c.fill = BOTH; + c.weightx = 1; + c.gridx = 0; + + OntProperty predicate = semanticAnnotationProfile.getPredicate(); + c.gridwidth = 3; + JLabel label = new JLabel(format("Annotation type : %s", + getDisplayName(predicate))); + label.setBorder(new EmptyBorder(5, 5, 5, 5)); + label.setBackground(WHITE); + label.setOpaque(true); + add(label, c); + + c.insets = new Insets(7, 0, 0, 0); + c.anchor = EAST; + c.fill = HORIZONTAL; + if (statements.isEmpty()) { + c.gridwidth = 2; + // c.weightx = 1; + // c.gridy++; + add(new JLabel("No semantic annotations"), c); + } else { + c.gridwidth = 1; + for (Statement statement : statements) { + c.gridx = 0; + c.weightx = 1; + if (bestFactory != null) { + add(bestFactory.getDisplayComponent( + semanticAnnotationProfile, statement), c); + } else { + JTextArea value = new JTextArea(getObjectName(statement)); + value.setLineWrap(true); + value.setWrapStyleWord(true); + value.setEditable(false); + value.setBackground(WHITE); + value.setOpaque(true); + value.setBorder(new EmptyBorder(2, 4, 2, 4)); + add(value, c); + } + if (allowChange) { + c.gridx = 1; + c.weightx = 0; + add(createChangeButton(statement), c); + + c.gridx = 2; + add(createDeleteButton(statement), c); + } + } + } + + if (allowChange + && !enoughAlready(statements, + semanticAnnotationProfile.getMaxOccurs())) { + c.gridx = 0; + c.gridwidth = 3; + c.anchor = SOUTHEAST; + c.fill = NONE; + add(createAddButton(), c); + } + } + + private boolean enoughAlready(Set<Statement> statements, Integer maxOccurs) { + return (maxOccurs != null) && (statements.size() >= maxOccurs); + } + + private JButton createChangeButton(final Statement statement) { + return new DeselectingButton("Change", new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + addOrChangeAnnotation(statement); + } + }); + } + + private JButton createDeleteButton(final Statement statement) { + return new DeselectingButton("Delete", new ActionListener() { + @Override + public void actionPerformed(ActionEvent arg0) { + semanticAnnotationContextualView.removeStatement(statement); + } + }); + } + + private JButton createAddButton() { + return new DeselectingButton("Add Annotation", new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + addOrChangeAnnotation(null); + } + }); + } + + private void addOrChangeAnnotation(Statement statement) { + JPanel annotationPanel = null; + JComponent inputComponent = null; + + if (bestFactory != null) { + inputComponent = bestFactory.getInputComponent( + semanticAnnotationProfile, statement); + annotationPanel = getPropertyPanel( + getDisplayName(semanticAnnotationProfile.getPredicate()), + inputComponent); + } + + if (annotationPanel == null) { + showMessageDialog(null, format("Unable to handle %s", + semanticAnnotationProfile.getPredicateString()), + "Annotation problem", ERROR_MESSAGE); + return; + } + + int answer = showConfirmDialog(null, annotationPanel, + "Add/change annotation", OK_CANCEL_OPTION); + if (answer == OK_OPTION) { + RDFNode response = bestFactory.getNewTargetNode(statement, + inputComponent); + if (response == null) + return; + if (statement != null) + semanticAnnotationContextualView.changeStatement(statement, + semanticAnnotationProfile.getPredicate(), response); + else + semanticAnnotationContextualView.addStatement( + semanticAnnotationProfile.getPredicate(), response); + } + } + + private PropertyPanelFactorySPI findBestPanelFactory() { + PropertyPanelFactorySPI result = null; + int currentRating = MIN_VALUE; + for (PropertyPanelFactorySPI factory : propertyPanelFactories) { + int ratingForSemanticAnnotation = factory + .getRatingForSemanticAnnotation(semanticAnnotationProfile); + if (ratingForSemanticAnnotation > currentRating) { + currentRating = ratingForSemanticAnnotation; + result = factory; + } + } + return result; + } + + public static JPanel getPropertyPanel(String displayName, + Component inputComponent) { + JPanel result = new JPanel(); + result.setLayout(new BorderLayout()); + JPanel messagePanel = new JPanel(new BorderLayout()); + messagePanel.setBorder(new EmptyBorder(5, 5, 0, 0)); + messagePanel.setBackground(WHITE); + result.add(messagePanel, NORTH); + + JLabel inputLabel = new JLabel("Enter a value for the annotation"); + inputLabel.setBackground(WHITE); + Font baseFont = inputLabel.getFont(); + inputLabel.setFont(baseFont.deriveFont(BOLD)); + messagePanel.add(inputLabel, NORTH); + + JTextArea messageText = new JTextArea(format( + "Enter a value for the annotation '%s'", displayName)); + messageText.setMargin(new Insets(5, 10, 10, 10)); + messageText.setMinimumSize(new Dimension(0, 30)); + messageText.setFont(baseFont.deriveFont(11f)); + messageText.setEditable(false); + messageText.setFocusable(false); + messagePanel.add(messageText, CENTER); + + result.add(new JScrollPane(inputComponent), CENTER); + return result; + } +}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationUtils.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationUtils.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationUtils.java new file mode 100644 index 0000000..68050c0 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/SemanticAnnotationUtils.java @@ -0,0 +1,190 @@ +/* +* 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 io.github.taverna_extras.component.ui.annotation; + +import static org.apache.jena.rdf.model.ModelFactory.createDefaultModel; +import static org.apache.log4j.Logger.getLogger; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.HashSet; +import java.util.Set; + +import org.apache.log4j.Logger; +import io.github.taverna_extras.component.api.ComponentException; +import io.github.taverna_extras.component.api.profile.Profile; +import io.github.taverna_extras.component.api.profile.SemanticAnnotationProfile; + +import org.apache.taverna.scufl2.api.annotation.Annotation; +import org.apache.taverna.scufl2.api.common.AbstractNamed; +import org.apache.taverna.scufl2.api.container.WorkflowBundle; + +import org.apache.jena.ontology.OntProperty; +import org.apache.jena.ontology.OntResource; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; + +/** + * @author David Withers + */ +public class SemanticAnnotationUtils { + protected static final String ENCODING = "TURTLE"; + /* Pretend-base for making relative URIs */ + private static String BASE = "widget://4aa8c93c-3212-487c-a505-3e337adf54a3/"; + private static Logger logger = getLogger(SemanticAnnotationUtils.class); + + public static String getObjectName(Statement statement) { + return getDisplayName(statement.getObject()); + } + + public static String getDisplayName(RDFNode node) { + if (node == null) + return "unknown"; + else if (node.isAnon()) + return "anon"; + else if (node.isLiteral()) + return node.asLiteral().getLexicalForm(); + else if (node.isResource()) { + Resource resource = node.asResource(); + if (resource instanceof OntResource) { + String label = ((OntResource) resource).getLabel(null); + if (label != null) + return label; + } + String localName = resource.getLocalName(); + if ((localName != null) && !localName.isEmpty()) + return localName; + return resource.toString(); + } else + return "unknown"; + } + + public static Annotation findSemanticAnnotation(AbstractNamed annotated) { + for (Annotation annotation : annotated.getAnnotations()) + return annotation; + return null; + } + + public static String getStrippedAnnotationContent(Annotation annotation) + throws IOException { + AbstractNamed target = (AbstractNamed) annotation.getTarget(); + return annotation.getRDFContent().replace( + target.getRelativeURI(annotation).toASCIIString(), BASE); + } + + public static Annotation createSemanticAnnotation(WorkflowBundle bundle, + AbstractNamed target, Model model) throws IOException { + Calendar now = new GregorianCalendar(); + Annotation annotation = new Annotation(); + annotation.setParent(bundle); + String path = annotation.getResourcePath(); + annotation.setTarget(target); + // annotation.setAnnotatedBy(annotatedBy); + annotation.setAnnotatedAt(now); + // annotation.setSerializedBy(serializedBy); + annotation.setSerializedAt(now); + bundle.getResources().addResource( + "@base<" + target.getRelativeURI(annotation).toASCIIString() + + "> .\n" + createTurtle(model), path, "text/rdf+n3"); + return annotation; + } + + /** + * @param model + * @return + */ + public static String createTurtle(Model model) { + StringWriter stringWriter = new StringWriter(); + model.write(stringWriter, ENCODING, BASE); + // Workaround for https://issues.apache.org/jira/browse/JENA-132 + return stringWriter.toString().replace(BASE, ""); + } + + public static Model populateModel(WorkflowBundle annotated) { + Model result = createDefaultModel(); + try { + for (Annotation a : annotated.getAnnotations()) + populateModelFromString(result, a.getRDFContent()); + } catch (Exception e) { + logger.error("failed to construct semantic annotation model", e); + } + return result; + } + + public static void populateModel(Model result, Annotation annotation) + throws IOException { + AbstractNamed target = (AbstractNamed) annotation.getTarget(); + String content = annotation.getRDFContent().replace( + target.getRelativeURI(annotation).toASCIIString(), BASE); + populateModelFromString(result, content); + } + + public static void populateModelFromString(Model result, String content) { + result.read(new StringReader(content), BASE, ENCODING); + } + + public static Resource createBaseResource(Model model) { + return model.createResource(BASE); + } + + /** + * Check if a profile is satisfied by a component. + * + * @param bundle + * The component definition. + * @param componentProfile + * The profile definition. + * @return The set of failed constraints. If empty, the profile is satisfied + * by the component. + */ + public static Set<SemanticAnnotationProfile> checkComponent( + WorkflowBundle bundle, Profile componentProfile) { + // TODO Check port presence by name + Set<SemanticAnnotationProfile> problemProfiles = new HashSet<>(); + Model model = populateModel(bundle); + Set<Statement> statements = model.listStatements().toSet(); + try { + for (SemanticAnnotationProfile saProfile : componentProfile + .getSemanticAnnotations()) { + OntProperty predicate = saProfile.getPredicate(); + if (predicate == null) + continue; + int count = 0; + for (Statement statement : statements) + if (statement.getPredicate().equals(predicate)) + count++; + if (count < saProfile.getMinOccurs()) + problemProfiles.add(saProfile); + if (saProfile.getMaxOccurs() != null + && count > saProfile.getMaxOccurs()) + // The UI should prevent this, but check anyway + problemProfiles.add(saProfile); + } + } catch (ComponentException e) { + logger.error("failed to look up profiles for semantic annotations", e); + } + return problemProfiles; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleContextualView.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleContextualView.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleContextualView.java new file mode 100644 index 0000000..8489fe6 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleContextualView.java @@ -0,0 +1,93 @@ +/* +* 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 io.github.taverna_extras.component.ui.annotation; + +import static java.awt.BorderLayout.CENTER; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.findSemanticAnnotation; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.getStrippedAnnotationContent; +import static org.slf4j.LoggerFactory.getLogger; + +import java.awt.BorderLayout; +import java.io.IOException; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +import org.slf4j.Logger; + +import org.apache.taverna.scufl2.api.annotation.Annotation; +import org.apache.taverna.scufl2.api.common.AbstractNamed; +import org.apache.taverna.scufl2.api.container.WorkflowBundle; +import org.apache.taverna.workbench.ui.views.contextualviews.ContextualView; + +/** + * @author alanrw + */ +public class TurtleContextualView extends ContextualView { + private static final long serialVersionUID = -3401885589263647202L; + private static final Logger log = getLogger(TurtleContextualView.class); + private JPanel panel; + private String annotationContent = ""; + + public TurtleContextualView(AbstractNamed selection, WorkflowBundle bundle) { + Annotation annotation = findSemanticAnnotation(selection); + try { + if (annotation != null) + annotationContent = getStrippedAnnotationContent(annotation); + } catch (IOException e) { + log.info("failed to read semantic annotation; using empty string", e); + } + initialise(); + initView(); + } + + @Override + public JComponent getMainFrame() { + return panel; + } + + @Override + public int getPreferredPosition() { + return 512; + } + + @Override + public String getViewTitle() { + return "Turtle representation"; + } + + @Override + public void refreshView() { + initialise(); + } + + protected final void initialise() { + if (panel == null) + panel = new JPanel(new BorderLayout()); + else + panel.removeAll(); + JTextArea textArea = new JTextArea(20, 80); + textArea.setEditable(false); + textArea.setText(annotationContent); + panel.add(textArea, CENTER); + revalidate(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleInputPanel.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleInputPanel.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleInputPanel.java new file mode 100644 index 0000000..7356cc9 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/TurtleInputPanel.java @@ -0,0 +1,105 @@ +/* +* 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 io.github.taverna_extras.component.ui.annotation; + +import static org.apache.jena.rdf.model.ModelFactory.createOntologyModel; +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.EAST; +import static java.awt.BorderLayout.SOUTH; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.populateModelFromString; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.apache.jena.ontology.Individual; +import org.apache.jena.ontology.OntClass; +import org.apache.jena.ontology.OntModel; +import org.apache.taverna.lang.ui.DeselectingButton; +import org.apache.taverna.lang.ui.ReadOnlyTextArea; + +/** + * @author alanrw + */ +@SuppressWarnings("serial") +public class TurtleInputPanel extends JPanel { + JTextArea turtleTextArea = new JTextArea(30, 80); + ReadOnlyTextArea errors = new ReadOnlyTextArea(1, 80); + private OntClass clazz; + + public TurtleInputPanel(OntClass clazz) { + super(new BorderLayout()); + this.clazz = clazz; + + add(new JScrollPane(turtleTextArea), CENTER); + + turtleTextArea.setText("<#changeme> a <" + clazz.getURI() + ">\n\n\n."); + + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new BorderLayout()); + JButton validateButton = new DeselectingButton(new AbstractAction( + "Validate") { + @Override + public void actionPerformed(ActionEvent arg0) { + getContentAsModel(); + } + }); + buttonPanel.add(errors, CENTER); + errors.setOpaque(false); + buttonPanel.add(validateButton, EAST); + add(buttonPanel, SOUTH); + } + + public OntModel getContentAsModel() { + OntModel result = createOntologyModel(); + try { + populateModelFromString(result, getContentAsString()); + + // Check it is not still called changeme + List<Individual> individuals = result.listIndividuals(clazz) + .toList(); + if (individuals.isEmpty()) { + errors.setText("No valid individuals"); + return null; + } + for (Individual i : individuals) + if (i.getURI().endsWith("changeme")) { + errors.setText("Name has not been changed"); + return null; + } + + errors.setText("No errors found"); + return result; + } catch (Throwable ex) { // syntax error? + errors.setText(ex.getMessage()); + return null; + } + } + + public String getContentAsString() { + return turtleTextArea.getText(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnrecognizedStatementPanel.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnrecognizedStatementPanel.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnrecognizedStatementPanel.java new file mode 100644 index 0000000..67d806d --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnrecognizedStatementPanel.java @@ -0,0 +1,43 @@ +/* +* 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 io.github.taverna_extras.component.ui.annotation; + +import static java.lang.String.format; + +import java.awt.BorderLayout; + +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.apache.jena.rdf.model.Statement; + +/** + * @author alanrw + * + */ +@SuppressWarnings("serial") +public class UnrecognizedStatementPanel extends JPanel { + public UnrecognizedStatementPanel(Statement statement) { + setLayout(new BorderLayout()); + setBorder(new GreyBorder()); + add(new JLabel(format("Unable to find %s in the profile", + statement.getPredicate()))); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnresolveablePredicatePanel.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnresolveablePredicatePanel.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnresolveablePredicatePanel.java new file mode 100644 index 0000000..a7e2c89 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/annotation/UnresolveablePredicatePanel.java @@ -0,0 +1,43 @@ +/* +* 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 io.github.taverna_extras.component.ui.annotation; + +import static java.lang.String.format; + +import java.awt.BorderLayout; + +import javax.swing.JLabel; +import javax.swing.JPanel; + +import io.github.taverna_extras.component.api.profile.SemanticAnnotationProfile; + +/** + * @author alanrw + */ +@SuppressWarnings("serial") +public class UnresolveablePredicatePanel extends JPanel { + public UnresolveablePredicatePanel( + SemanticAnnotationProfile semanticAnnotationProfile) { + setLayout(new BorderLayout()); + setBorder(new GreyBorder()); + add(new JLabel(format("Unable to resolve %s in the ontology", + semanticAnnotationProfile.getPredicateString()))); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigurationPanel.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigurationPanel.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigurationPanel.java new file mode 100644 index 0000000..712b861 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigurationPanel.java @@ -0,0 +1,171 @@ +/* +* 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 io.github.taverna_extras.component.ui.config; + +import static java.awt.event.ItemEvent.SELECTED; +import static org.apache.log4j.Logger.getLogger; +import static io.github.taverna_extras.component.api.config.ComponentPropertyNames.COMPONENT_NAME; +import static io.github.taverna_extras.component.api.config.ComponentPropertyNames.COMPONENT_VERSION; +import static io.github.taverna_extras.component.api.config.ComponentPropertyNames.FAMILY_NAME; +import static io.github.taverna_extras.component.api.config.ComponentPropertyNames.REGISTRY_BASE; +import static io.github.taverna_extras.component.ui.util.Utils.SHORT_STRING; + +import java.awt.GridBagConstraints; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.net.MalformedURLException; +import java.net.URI; +import java.util.SortedMap; + +import javax.swing.JComboBox; +import javax.swing.JLabel; + +import org.apache.log4j.Logger; +import io.github.taverna_extras.component.api.Component; +import io.github.taverna_extras.component.api.ComponentException; +import io.github.taverna_extras.component.api.ComponentFactory; +import io.github.taverna_extras.component.api.Version; +import io.github.taverna_extras.component.ui.panel.ComponentListCellRenderer; + +import org.apache.taverna.scufl2.api.activity.Activity; +import org.apache.taverna.services.ServiceRegistry; +import org.apache.taverna.workbench.ui.views.contextualviews.activity.ActivityConfigurationPanel; + +@SuppressWarnings("serial") +public class ComponentConfigurationPanel extends ActivityConfigurationPanel { + private static Logger logger = getLogger(ComponentConfigurationPanel.class); + + private ComponentFactory factory;//FIXME beaninject + private ServiceRegistry sr; + + private final JComboBox<Object> componentVersionChoice = new JComboBox<>(); + + public ComponentConfigurationPanel(Activity activity, + ComponentFactory factory, ServiceRegistry serviceRegistry) { + super(activity); + sr = serviceRegistry; + this.factory = factory; + componentVersionChoice.setPrototypeDisplayValue(SHORT_STRING); + initGui(); + } + + private Version getSelectedVersion() { + return (Version) componentVersionChoice.getSelectedItem(); + } + private URI getRegistryBase() { + return URI.create(getProperty(REGISTRY_BASE)); + } + private String getFamilyName() { + return getProperty(FAMILY_NAME); + } + private String getComponentName() { + return getProperty(COMPONENT_NAME); + } + private Integer getComponentVersion() { + return Integer.parseInt(getProperty(COMPONENT_VERSION)); + } + + protected void initGui() { + removeAll(); + setLayout(new GridLayout(0, 2)); + + componentVersionChoice.setRenderer(new ComponentListCellRenderer<>()); + componentVersionChoice.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent event) { + if (event.getStateChange() == SELECTED) + updateToolTipText(); + } + }); + updateComponentVersionChoice(); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(0, 5, 0, 5); + gbc.gridx = 0; + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridy = 2; + this.add(new JLabel("Component version:"), gbc); + gbc.gridx = 1; + gbc.weightx = 1; + this.add(componentVersionChoice, gbc); + + // Populate fields from activity configuration bean + refreshConfiguration(); + } + + /** + * Check that user values in UI are valid + */ + @Override + public boolean checkValues() { + return true; + } + + /** + * Check if the user has changed the configuration from the original + */ + @Override + public boolean isConfigurationChanged() { + return !getSelectedVersion().getVersionNumber().equals( + getComponentVersion()); + } + + /** + * Prepare a new configuration bean from the UI, to be returned with + * getConfiguration() + */ + @Override + public void noteConfiguration() { + setProperty(COMPONENT_VERSION, getSelectedVersion().getVersionNumber() + .toString()); + //FIXME is this right at all??? + configureInputPorts(sr); + configureOutputPorts(sr); + } + + private void updateComponentVersionChoice() { + Component component; + componentVersionChoice.removeAllItems(); + componentVersionChoice.setToolTipText(null); + try { + component = factory.getComponent(getRegistryBase().toURL(), + getFamilyName(), getComponentName()); + } catch (ComponentException | MalformedURLException e) { + logger.error("failed to get component", e); + return; + } + SortedMap<Integer, Version> componentVersionMap = component + .getComponentVersionMap(); + for (Version v : componentVersionMap.values()) + componentVersionChoice.addItem(v); + componentVersionChoice.setSelectedItem(componentVersionMap + .get(getComponentVersion())); + updateToolTipText(); + } + + private void updateToolTipText() { + Version selectedVersion = (Version) componentVersionChoice + .getSelectedItem(); + componentVersionChoice.setToolTipText(selectedVersion.getDescription()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigureAction.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigureAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigureAction.java new file mode 100644 index 0000000..81c9d2f --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/config/ComponentConfigureAction.java @@ -0,0 +1,69 @@ +/* +* 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 io.github.taverna_extras.component.ui.config; + +import java.awt.Frame; +import java.awt.event.ActionEvent; + +import io.github.taverna_extras.component.api.ComponentFactory; + +import org.apache.taverna.scufl2.api.activity.Activity; +import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry; +import org.apache.taverna.services.ServiceRegistry; +import org.apache.taverna.workbench.activityicons.ActivityIconManager; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.ui.actions.activity.ActivityConfigurationAction; +import org.apache.taverna.workbench.ui.views.contextualviews.activity.ActivityConfigurationDialog; + +@SuppressWarnings("serial") +public class ComponentConfigureAction extends ActivityConfigurationAction { + private EditManager editManager; + private FileManager fileManager; + private ServiceRegistry serviceRegistry; + private ComponentFactory factory; + + public ComponentConfigureAction(Activity activity, Frame owner, + ComponentFactory factory, ActivityIconManager activityIconManager, + ServiceDescriptionRegistry serviceDescriptionRegistry, + EditManager editManager, FileManager fileManager, + ServiceRegistry serviceRegistry) { + super(activity, activityIconManager, serviceDescriptionRegistry); + this.editManager = editManager; + this.fileManager = fileManager; + this.serviceRegistry = serviceRegistry; + this.factory = factory; + } + + @Override + public void actionPerformed(ActionEvent e) { + ActivityConfigurationDialog currentDialog = getDialog(getActivity()); + if (currentDialog != null) { + currentDialog.toFront(); + return; + } + + ComponentConfigurationPanel configView = new ComponentConfigurationPanel( + activity, factory, serviceRegistry); + ActivityConfigurationDialog dialog = new ActivityConfigurationDialog( + getActivity(), configView, editManager); + setDialog(getActivity(), dialog, fileManager); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthCheckExplainer.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthCheckExplainer.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthCheckExplainer.java new file mode 100644 index 0000000..7a2442f --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthCheckExplainer.java @@ -0,0 +1,91 @@ +/* +* 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 io.github.taverna_extras.component.ui.file; + +import static java.util.Collections.sort; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.getDisplayName; +import static io.github.taverna_extras.component.ui.util.ComponentHealthCheck.FAILS_PROFILE; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +import javax.swing.JComponent; +import javax.swing.JTextArea; + +import io.github.taverna_extras.component.api.profile.SemanticAnnotationProfile; +import io.github.taverna_extras.component.ui.util.ComponentHealthCheck; +import org.apache.taverna.visit.VisitKind; +import org.apache.taverna.visit.VisitReport; + +//import net.sf.taverna.t2.workbench.report.explainer.VisitExplainer; + +/** + * @author alanrw + */ +public class ComponentDataflowHealthCheckExplainer implements VisitExplainer { + private static final Comparator<SemanticAnnotationProfile> comparator = new Comparator<SemanticAnnotationProfile>() { + @Override + public int compare(SemanticAnnotationProfile a, + SemanticAnnotationProfile b) { + return getDisplayName(a.getPredicate()).compareTo( + getDisplayName(b.getPredicate())); + } + }; + + @Override + public boolean canExplain(VisitKind vk, int resultId) { + return vk instanceof ComponentHealthCheck + && resultId == FAILS_PROFILE; + } + + @Override + public JComponent getExplanation(VisitReport vr) { + @SuppressWarnings("unchecked") + Set<SemanticAnnotationProfile> problemProfiles = (Set<SemanticAnnotationProfile>) vr + .getProperty("problemProfiles"); + List<SemanticAnnotationProfile> sortedList = new ArrayList<>( + problemProfiles); + sort(sortedList, comparator); + StringBuilder text = new StringBuilder(); + for (SemanticAnnotationProfile profile : sortedList) + text.append(getSemanticProfileExplanation(profile)).append("\n"); + return new JTextArea(text.toString()); + } + + @Override + public JComponent getSolution(VisitReport vr) { + return new JTextArea("Correct the semantic annotation"); + } + + private static String getSemanticProfileExplanation( + SemanticAnnotationProfile p) { + Integer minOccurs = p.getMinOccurs(); + Integer maxOccurs = p.getMaxOccurs(); + String displayName = getDisplayName(p.getPredicate()); + if (maxOccurs == null) + return displayName + " must have at least " + minOccurs + " value"; + if (minOccurs.equals(maxOccurs)) + return displayName + " must have " + minOccurs + " value(s)"; + return displayName + " must have between " + minOccurs + " and " + + maxOccurs + " value(s)"; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthChecker.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthChecker.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthChecker.java new file mode 100644 index 0000000..7ce0c1b --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentDataflowHealthChecker.java @@ -0,0 +1,114 @@ +/* +* 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 io.github.taverna_extras.component.ui.file; + +import static org.apache.log4j.Logger.getLogger; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.checkComponent; +import static io.github.taverna_extras.component.ui.util.ComponentHealthCheck.FAILS_PROFILE; + +import java.util.List; +import java.util.Set; + +import org.apache.log4j.Logger; +import io.github.taverna_extras.component.api.ComponentException; +import io.github.taverna_extras.component.api.ComponentFactory; +import io.github.taverna_extras.component.api.Family; +import io.github.taverna_extras.component.api.Version; +import io.github.taverna_extras.component.api.profile.SemanticAnnotationProfile; +import io.github.taverna_extras.component.ui.util.ComponentHealthCheck; + +import org.apache.taverna.scufl2.api.container.WorkflowBundle; +import org.apache.taverna.visit.VisitReport; +import static org.apache.taverna.visit.VisitReport.Status.SEVERE; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workflowmodel.Dataflow; +import org.apache.taverna.workflowmodel.health.HealthChecker; + +/** + * @author alanrw + */ +public class ComponentDataflowHealthChecker implements HealthChecker<Dataflow> { + private static final String PROFILE_UNSATISFIED_MSG = "Workflow does not satisfy component profile"; + private static Logger logger = getLogger(ComponentDataflowHealthChecker.class); + + private FileManager fm; + private ComponentHealthCheck visitType = ComponentHealthCheck.getInstance(); //FIXME beaninject? + private ComponentFactory factory; + + public void setComponentFactory(ComponentFactory factory) { + this.factory = factory; + } + + public void setFileManager(FileManager fm) { + this.fm = fm; + } + + private Version.ID getSource(Object o) { + return (Version.ID) fm.getDataflowSource((WorkflowBundle) o); + } + + public void checkProfileSatisfied(WorkflowBundle bundle) { + //FIXME + } + @Override + public boolean canVisit(Object o) { + try { + return getSource(o) != null; + } catch (IllegalArgumentException e) { + // Not open? + } catch (ClassCastException e) { + // Not dataflow? Not component? + } + return false; + } + + @Override + public VisitReport visit(WorkflowBundle dataflow, List<Object> ancestry) { + try { + Version.ID ident = getSource(dataflow); + Family family = factory.getFamily(ident.getRegistryBase(), + ident.getFamilyName()); + + Set<SemanticAnnotationProfile> problemProfiles = checkComponent( + dataflow, family.getComponentProfile()); + if (problemProfiles.isEmpty()) + return null; + + VisitReport visitReport = new VisitReport(visitType, dataflow, + PROFILE_UNSATISFIED_MSG, FAILS_PROFILE, SEVERE); + visitReport.setProperty("problemProfiles", problemProfiles); + return visitReport; + } catch (ComponentException e) { + logger.error( + "failed to comprehend profile while checking for match", e); + return null; + } + } +// +// @Override +// public VisitReport visit(Dataflow o, List<Object> ancestry) { +// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. +// } +// +// @Override +// public boolean isTimeConsuming() { +// throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. +// } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentOpener.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentOpener.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentOpener.java new file mode 100644 index 0000000..f2e16e6 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentOpener.java @@ -0,0 +1,88 @@ +/* +* 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 io.github.taverna_extras.component.ui.file; + +import static org.apache.log4j.Logger.getLogger; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; +import io.github.taverna_extras.component.api.ComponentException; +import io.github.taverna_extras.component.api.ComponentFactory; +import io.github.taverna_extras.component.api.Version; +import io.github.taverna_extras.component.api.Version.ID; + +import org.apache.taverna.scufl2.api.container.WorkflowBundle; +import org.apache.taverna.workbench.file.AbstractDataflowPersistenceHandler; +import org.apache.taverna.workbench.file.DataflowInfo; +import org.apache.taverna.workbench.file.DataflowPersistenceHandler; +import org.apache.taverna.workbench.file.FileType; +import org.apache.taverna.workbench.file.exceptions.OpenException; + +/** + * @author alanrw + */ +public class ComponentOpener extends AbstractDataflowPersistenceHandler + implements DataflowPersistenceHandler { + private static Logger logger = getLogger(ComponentOpener.class); + + private ComponentFactory factory; + private FileType fileType; + + public void setComponentFactory(ComponentFactory factory) { + this.factory = factory; + } + + public void setFileType(FileType fileType) { + this.fileType = fileType; + } + + @Override + public DataflowInfo openDataflow(FileType fileType, Object source) + throws OpenException { + if (!getOpenFileTypes().contains(fileType)) + throw new IllegalArgumentException("Unsupported file type " + + fileType); + if (!(source instanceof Version.ID)) + throw new IllegalArgumentException("Unsupported source type " + + source.getClass().getName()); + + WorkflowBundle d; + try { + d = factory.getVersion((ID) source).getImplementation(); + } catch (ComponentException e) { + logger.error("Unable to read dataflow", e); + throw new OpenException("Unable to read dataflow", e); + } + return new DataflowInfo(fileType, source, d, new Date()); + } + + @Override + public List<FileType> getOpenFileTypes() { + return Arrays.<FileType> asList(fileType); + } + + @Override + public List<Class<?>> getOpenSourceTypes() { + return Arrays.<Class<?>> asList(Version.ID.class); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentSaver.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentSaver.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentSaver.java new file mode 100644 index 0000000..19b52d9 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/ComponentSaver.java @@ -0,0 +1,185 @@ +/* +* 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 io.github.taverna_extras.component.ui.file; + +import static javax.swing.JOptionPane.OK_CANCEL_OPTION; +import static javax.swing.JOptionPane.OK_OPTION; +import static javax.swing.JOptionPane.showConfirmDialog; +import static org.apache.log4j.Logger.getLogger; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.checkComponent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.apache.log4j.Logger; +import io.github.taverna_extras.component.api.Component; +import io.github.taverna_extras.component.api.ComponentException; +import io.github.taverna_extras.component.api.ComponentFactory; +import io.github.taverna_extras.component.api.Family; +import io.github.taverna_extras.component.api.Registry; +import io.github.taverna_extras.component.api.Version; +import io.github.taverna_extras.component.api.profile.SemanticAnnotationProfile; +import io.github.taverna_extras.component.ui.serviceprovider.ComponentServiceProvider; + +import org.apache.taverna.scufl2.api.container.WorkflowBundle; +import org.apache.taverna.scufl2.validation.ValidationReport; +import org.apache.taverna.scufl2.validation.structural.StructuralValidator; +import org.apache.taverna.workbench.file.AbstractDataflowPersistenceHandler; +import org.apache.taverna.workbench.file.DataflowInfo; +import org.apache.taverna.workbench.file.DataflowPersistenceHandler; +import org.apache.taverna.workbench.file.FileType; +import org.apache.taverna.workbench.file.exceptions.SaveException; + +/** + * @author alanrw + */ +public class ComponentSaver extends AbstractDataflowPersistenceHandler + implements DataflowPersistenceHandler { + private static final String UNSATISFIED_PROFILE_WARNING = "The component does not satisfy the profile.\n" + + "See validation report.\nDo you still want to save?"; + private static final Logger logger = getLogger(ComponentSaver.class); + + private ComponentFactory factory; + private ComponentServiceProvider provider; + private FileType cft; + + public void setComponentFactory(ComponentFactory factory) { + this.factory = factory; + } + + public void setFileType(FileType fileType) { + this.cft = fileType; + } + + public void setServiceProvider(ComponentServiceProvider provider) { + this.provider = provider; + } + + @Override + public DataflowInfo saveDataflow(WorkflowBundle bundle, FileType fileType, + Object destination) throws SaveException { + if (!getSaveFileTypes().contains(fileType)) + throw new IllegalArgumentException("Unsupported file type " + + fileType); + if (!(destination instanceof Version.ID)) + throw new IllegalArgumentException("Unsupported destination type " + + destination.getClass().getName()); + + ValidationReport structuralValidity = new StructuralValidator() + .validate(bundle); + if (structuralValidity.detectedProblems()) + throw new SaveException( + "Cannot save a structurally invalid workflow as a component", + structuralValidity.getException()); + + /* + * Saving an invalid dataflow is OK. Validity check is done to get + * predicted depth for output (if possible) + */ + + Version.ID ident = (Version.ID) destination; + + if (ident.getComponentVersion() == -1) { + Version.ID newIdent = new Version.Identifier( + ident.getRegistryBase(), ident.getFamilyName(), + ident.getComponentName(), 0); + return new DataflowInfo(cft, newIdent, bundle); + } + + Family family; + try { + Registry registry = factory.getRegistry(ident.getRegistryBase()); + family = registry.getComponentFamily(ident.getFamilyName()); + } catch (ComponentException e) { + throw new SaveException("Unable to read component", e); + } + + Version newVersion = null; + try { + List<SemanticAnnotationProfile> problemProfiles = new ArrayList<>( + checkComponent(bundle, family.getComponentProfile())); + + if (!problemProfiles.isEmpty()) { + int answer = showConfirmDialog(null, + UNSATISFIED_PROFILE_WARNING, "Profile problem", + OK_CANCEL_OPTION); + if (answer != OK_OPTION) + throw new SaveException("Saving cancelled"); + } + + JTextArea descriptionArea = new JTextArea(10, 60); + descriptionArea.setLineWrap(true); + descriptionArea.setWrapStyleWord(true); + final JScrollPane descriptionScrollPane = new JScrollPane( + descriptionArea); + if (ident.getComponentVersion() == 0) { + int answer = showConfirmDialog(null, descriptionScrollPane, + "Component description", OK_CANCEL_OPTION); + if (answer != OK_OPTION) + throw new SaveException("Saving cancelled"); + newVersion = family.createComponentBasedOn( + ident.getComponentName(), descriptionArea.getText(), + bundle); + } else { + Component component = family.getComponent(ident + .getComponentName()); + int answer = showConfirmDialog(null, descriptionScrollPane, + "Version description", OK_CANCEL_OPTION); + if (answer != OK_OPTION) + throw new SaveException("Saving cancelled"); + newVersion = component.addVersionBasedOn(bundle, + descriptionArea.getText()); + } + } catch (ComponentException e) { + logger.error("Unable to save new version of component", e); + throw new SaveException("Unable to save new version of component", + e); + } + + Version.ID newIdent = new Version.Identifier(ident.getRegistryBase(), + ident.getFamilyName(), ident.getComponentName(), + newVersion.getVersionNumber()); + provider.refreshProvidedComponent(ident); + return new DataflowInfo(cft, newIdent, bundle); + } + + @Override + public List<FileType> getSaveFileTypes() { + return Arrays.<FileType> asList(cft); + } + + @Override + public List<Class<?>> getSaveDestinationTypes() { + return Arrays.<Class<?>> asList(Version.ID.class); + } + + @Override + public boolean wouldOverwriteDataflow(WorkflowBundle dataflow, + FileType fileType, Object destination, DataflowInfo lastDataflowInfo) { + if (!getSaveFileTypes().contains(fileType)) + throw new IllegalArgumentException("Unsupported file type " + + fileType); + return false; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/FileManagerObserver.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/FileManagerObserver.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/FileManagerObserver.java new file mode 100644 index 0000000..8ee99b9 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/file/FileManagerObserver.java @@ -0,0 +1,146 @@ +/* +* 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 io.github.taverna_extras.component.ui.file; + +import static java.awt.Color.WHITE; +import static java.awt.Font.BOLD; +import static javax.swing.SwingUtilities.invokeLater; +import static javax.swing.SwingUtilities.isEventDispatchThread; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Insets; + +import javax.swing.border.Border; + +import org.apache.batik.swing.JSVGCanvas; +import io.github.taverna_extras.component.api.Version; +import io.github.taverna_extras.component.ui.util.Utils; +import org.apache.taverna.lang.observer.Observable; +import org.apache.taverna.lang.observer.Observer; + +import org.apache.taverna.scufl2.api.container.WorkflowBundle; +import org.apache.taverna.workbench.StartupSPI; +import org.apache.taverna.workbench.configuration.colour.ColourManager; +import org.apache.taverna.workbench.file.FileManager; +import org.apache.taverna.workbench.file.events.FileManagerEvent; +import org.apache.taverna.workbench.models.graph.svg.SVGGraphController; +import org.apache.taverna.workbench.views.graph.GraphViewComponent; + +public class FileManagerObserver implements StartupSPI { + private static final Color COLOR = new Color(230, 147, 210); + + private FileManager fileManager; + private ColourManager colours; + private GraphViewComponent graphView; + private Utils utils; + + public void setFileManager(FileManager fileManager) { + this.fileManager = fileManager; + } + + public void setColourManager(ColourManager colours) { + this.colours = colours; + } + + public void setGraphView(GraphViewComponent graphView) { + this.graphView = graphView; + } + + public void setUtils(Utils utils) { + this.utils = utils; + } + + @Override + public boolean startup() { + colours.setPreferredColour( + "io.github.taverna_extras.component.registry.Component", COLOR); + colours.setPreferredColour( + "io.github.taverna_extras.component.ComponentActivity", COLOR); + fileManager.addObserver(new Observer<FileManagerEvent>() { + @Override + public void notify(Observable<FileManagerEvent> observable, + FileManagerEvent event) throws Exception { + FileManagerObserverRunnable runnable = new FileManagerObserverRunnable(); + if (isEventDispatchThread()) + runnable.run(); + else + invokeLater(runnable); + } + }); + return true; + } + + @Override + public int positionHint() { + return 200; + } + + public class FileManagerObserverRunnable implements Runnable { + @Override + public void run() { + WorkflowBundle currentDataflow = fileManager.getCurrentDataflow(); + if (currentDataflow == null) + return; + SVGGraphController graphController = (SVGGraphController) graphView + .getGraphController(currentDataflow.getMainWorkflow()); + if (graphController == null) + return; + JSVGCanvas svgCanvas = graphController.getSVGCanvas(); + Object dataflowSource = fileManager + .getDataflowSource(currentDataflow); + if (utils.currentDataflowIsComponent()) + svgCanvas.setBorder(new ComponentBorder( + (Version.ID) dataflowSource)); + else + svgCanvas.setBorder(null); + svgCanvas.repaint(); + } + } + + static class ComponentBorder implements Border { + private final Insets insets = new Insets(25, 0, 0, 0); + private final String text; + + public ComponentBorder(Version.ID identification) { + text = "Component : " + identification.getComponentName(); + } + + @Override + public Insets getBorderInsets(java.awt.Component c) { + return insets; + } + + @Override + public boolean isBorderOpaque() { + return true; + } + + @Override + public void paintBorder(java.awt.Component c, Graphics g, int x, int y, + int width, int height) { + g.setColor(COLOR); + g.fillRect(x, y, width, 20); + g.setFont(g.getFont().deriveFont(BOLD)); + g.setColor(WHITE); + g.drawString(text, x + 5, y + 15); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/localworld/LocalWorld.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/localworld/LocalWorld.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/localworld/LocalWorld.java new file mode 100644 index 0000000..a35ab61 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/localworld/LocalWorld.java @@ -0,0 +1,107 @@ +/* +* 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 io.github.taverna_extras.component.ui.localworld; + +import static org.apache.jena.rdf.model.ModelFactory.createOntologyModel; +import static org.apache.log4j.Logger.getLogger; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.createTurtle; +import static io.github.taverna_extras.component.ui.annotation.SemanticAnnotationUtils.populateModelFromString; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.util.List; + +import org.apache.log4j.Logger; + +import org.apache.jena.ontology.Individual; +import org.apache.jena.ontology.OntClass; +import org.apache.jena.ontology.OntModel; +import org.apache.jena.rdf.model.Resource; +import org.apache.taverna.configuration.app.ApplicationConfiguration; + +/** + * @author alanrw + */ +public class LocalWorld { + private static final String FILENAME = "localWorld.ttl"; + private static final Logger logger = getLogger(LocalWorld.class); + protected static final String ENCODING = "TURTLE"; + private static LocalWorld instance = null; + + private OntModel model; + + public synchronized static LocalWorld getInstance() { + if (instance == null) + instance = new LocalWorld(); + return instance; + } + + private LocalWorld() { + File modelFile = new File(calculateComponentsDirectory(), FILENAME); + model = createOntologyModel(); + if (modelFile.exists()) + try (Reader in = new InputStreamReader(new FileInputStream( + modelFile), "UTF-8")) { + model.read(in, null, ENCODING); + } catch (IOException e) { + logger.error("failed to construct local annotation world", e); + } + } + + ApplicationConfiguration config;//FIXME beaninject + + public File calculateComponentsDirectory() { + return new File(config.getApplicationHomeDir(), "components"); + } + + public Individual createIndividual(String urlString, OntClass rangeClass) { + try { + return model.createIndividual(urlString, rangeClass); + } finally { + saveModel(); + } + } + + private void saveModel() { + File modelFile = new File(calculateComponentsDirectory(), FILENAME); + try (OutputStream out = new FileOutputStream(modelFile)) { + out.write(createTurtle(model).getBytes("UTF-8")); + } catch (IOException e) { + logger.error("failed to save local annotation world", e); + } + } + + public List<Individual> getIndividualsOfClass(Resource clazz) { + return model.listIndividuals(clazz).toList(); + } + + public void addModelFromString(String addedModel) { + try { + populateModelFromString(model, addedModel); + } finally { + saveModel(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/AbstractContextComponentMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/AbstractContextComponentMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/AbstractContextComponentMenuAction.java new file mode 100644 index 0000000..0911a66 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/AbstractContextComponentMenuAction.java @@ -0,0 +1,58 @@ +/* +* 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 io.github.taverna_extras.component.ui.menu; + +import java.net.URI; + +import io.github.taverna_extras.component.api.config.ComponentConfig; + +import org.apache.taverna.scufl2.api.activity.Activity; +import org.apache.taverna.scufl2.api.core.Processor; +import org.apache.taverna.ui.menu.AbstractContextualMenuAction; + +public abstract class AbstractContextComponentMenuAction extends AbstractContextualMenuAction { + public AbstractContextComponentMenuAction(URI parentId, int positionHint) { + super(parentId, positionHint); + } + + public AbstractContextComponentMenuAction(URI parentId, int positionHint, URI id) { + super(parentId, positionHint, id); + } + + protected boolean isComponentActivity(Activity act) { + if (act == null) + return false; + return act.getType().equals(ComponentConfig.URI); + } + + protected Activity findActivity() { + if (getContextualSelection() == null) + return null; + Object selection = getContextualSelection().getSelection(); + if (selection instanceof Processor) { + Processor processor = (Processor) selection; + return processor.getParent().getParent().getMainProfile() + .getProcessorBindings().getByName(processor.getName()) + .getBoundActivity(); + } else if (selection instanceof Activity) + return (Activity) selection; + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentConfigureMenuAction.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentConfigureMenuAction.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentConfigureMenuAction.java new file mode 100644 index 0000000..0feb63e --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentConfigureMenuAction.java @@ -0,0 +1,81 @@ +/* +* 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 io.github.taverna_extras.component.ui.menu; + +import static javax.swing.Action.NAME; +import static io.github.taverna_extras.component.ui.ComponentConstants.ACTIVITY_URI; + +import javax.swing.Action; + +import io.github.taverna_extras.component.api.ComponentFactory; +import io.github.taverna_extras.component.ui.config.ComponentConfigureAction; +import org.apache.taverna.servicedescriptions.ServiceDescriptionRegistry; +import org.apache.taverna.services.ServiceRegistry; +import org.apache.taverna.workbench.activityicons.ActivityIconManager; +import org.apache.taverna.workbench.activitytools.AbstractConfigureActivityMenuAction; +import org.apache.taverna.workbench.edits.EditManager; +import org.apache.taverna.workbench.file.FileManager; + +public class ComponentConfigureMenuAction extends + AbstractConfigureActivityMenuAction { + public ComponentConfigureMenuAction() { + super(ACTIVITY_URI); + } + + private ActivityIconManager aim; + private ServiceDescriptionRegistry sdr; + private EditManager em; + private FileManager fm; + private ServiceRegistry str; + private ComponentFactory factory; + + public void setActivityIconManager(ActivityIconManager aim) { + this.aim = aim; + } + + public void setServiceDescriptionRegistry(ServiceDescriptionRegistry sdr) { + this.sdr = sdr; + } + + public void setEditManager(EditManager em) { + this.em = em; + } + + public void setFileManager(FileManager fm) { + this.fm = fm; + } + + public void setServiceTypeRegistry(ServiceRegistry str) { + this.str = str; + } + + public void setComponentFactory(ComponentFactory factory) { + this.factory = factory; + } + + @Override + protected Action createAction() { + Action result = new ComponentConfigureAction(findActivity(), + getParentFrame(), factory, aim, sdr, em, fm, str); + result.putValue(NAME, "Configure component"); + addMenuDots(result); + return result; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentMenu.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentMenu.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentMenu.java new file mode 100644 index 0000000..99cec65 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentMenu.java @@ -0,0 +1,41 @@ +/* +* 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 io.github.taverna_extras.component.ui.menu; + +import java.net.URI; +import org.apache.taverna.ui.menu.AbstractMenu; +import static org.apache.taverna.ui.menu.DefaultMenuBar.DEFAULT_MENU_BAR; + +/** + * @author alanrw + */ +public class ComponentMenu extends AbstractMenu { + public static final URI COMPONENT = URI + .create("http://taverna.sf.net/2008/t2workbench/menu#component"); + public static final String TITLE = "Components"; + + public ComponentMenu() { + super(DEFAULT_MENU_BAR, 950, COMPONENT, makeAction()); + } + + public static DummyAction makeAction() { + return new DummyAction(TITLE); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-plugin-component/blob/b7b61e71/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentSection.java ---------------------------------------------------------------------- diff --git a/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentSection.java b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentSection.java new file mode 100644 index 0000000..337ee73 --- /dev/null +++ b/taverna-component-activity-ui/src/main/java/io/github/taverna_extras/component/ui/menu/ComponentSection.java @@ -0,0 +1,44 @@ +/* +* 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 io.github.taverna_extras.component.ui.menu; + +import java.net.URI; +import org.apache.taverna.ui.menu.AbstractMenuSection; + +/** + * @author alanrw + * + */ +public class ComponentSection extends AbstractMenuSection { + public static final String COMPONENT_SECTION = "Components"; + public static final URI componentSection = URI + .create("http://taverna.sf.net/2009/contextMenu/components"); + public static final URI editSection = URI + .create("http://taverna.sf.net/2009/contextMenu/edit"); + + public ComponentSection() { + super(editSection, 100, componentSection); + } + + @Override + public boolean isEnabled() { + return super.isEnabled(); + } +}
