[Yanel-commits] rev 24457 - in public/yanel/trunk/src:
core/java/org/wyona/yanel/core
core/java/org/wyona/yanel/core/workflow
core/java/org/wyona/yanel/core/workflow/impl
impl/java/org/wyona/yanel/impl
impl/java/org/wyona/yanel/impl/workflow
michi at wyona.com
michi at wyona.com
Mon May 14 22:57:08 CEST 2007
Author: michi
Date: 2007-05-14 22:57:06 +0200 (Mon, 14 May 2007)
New Revision: 24457
Added:
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Action.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Condition.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Transition.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Workflow.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowBuilder.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowException.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowHelper.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/TransitionImpl.java
public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/WorkflowImpl.java
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/DeactivateAction.java
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/PublishAction.java
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RemoveVariableAction.java
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionEqualsCondition.java
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionNotEqualsCondition.java
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RoleCondition.java
public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/SetRevisionAction.java
Log:
workflow api and impl added
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Action.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Action.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Action.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+
+public interface Action {
+
+ void execute(WorkflowableV1 workflowable, Workflow workflow,
+ String revision) throws WorkflowException;
+
+ void setExpression(String expression) throws WorkflowException;
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Condition.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Condition.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Condition.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+
+public interface Condition {
+
+ boolean isComplied(WorkflowableV1 workflowable, Workflow workflow,
+ String revision) throws WorkflowException;
+
+ void setExpression(String expression) throws WorkflowException;
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Transition.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Transition.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Transition.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow;
+
+public interface Transition {
+
+ String getID();
+
+ String getSourceState();
+
+ String getDestinationState();
+
+ Condition[] getConditions();
+
+ Action[] getActions();
+}
\ No newline at end of file
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Workflow.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Workflow.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/Workflow.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow;
+
+public interface Workflow {
+
+ String NAMESPACE = "http://www.wyona.org/yanel/workflow/1.0";
+
+ String getInitialState();
+
+// String[] getStates();
+
+// Transition[] getTransitions();
+
+ Transition[] getLeavingTransitions(String state);
+}
\ No newline at end of file
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowBuilder.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowBuilder.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowBuilder.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xml.resolver.tools.CatalogResolver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.wyona.yanel.core.workflow.impl.TransitionImpl;
+import org.wyona.yanel.core.workflow.impl.WorkflowImpl;
+
+public class WorkflowBuilder {
+
+ public Workflow buildWorkflow(InputStream stream) throws WorkflowException {
+ try {
+ Document document = readDocument(stream);
+ Workflow workflow = buildWorkflow(document);
+ return workflow;
+ } catch (Exception e) {
+ throw new WorkflowException(e);
+ }
+ }
+
+ private Document readDocument(InputStream stream) throws Exception {
+ DocumentBuilder builder = createBuilder();
+ return builder.parse(stream);
+ }
+
+ /**
+ * Creates a non-validating and namespace-aware DocumentBuilder.
+ * @return A new DocumentBuilder object.
+ * @throws ParserConfigurationException if an error occurs
+ */
+ protected DocumentBuilder createBuilder() throws ParserConfigurationException {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+
+ CatalogResolver cr = new CatalogResolver();
+ builder.setEntityResolver(cr);
+ return builder;
+ }
+
+ /**
+ * Builds a workflow object from an XML document.
+ * @param name The workflow name.
+ * @param document The XML document.
+ * @return A workflow implementation.
+ * @throws WorkflowException when something went wrong.
+ */
+ protected Workflow buildWorkflow(Document document) throws WorkflowException {
+
+ WorkflowImpl workflow = new WorkflowImpl();
+
+ Element root = document.getDocumentElement();
+ String initialState = null;
+
+ // load states
+ Element statesElement = (Element) root.getElementsByTagNameNS(Workflow.NAMESPACE, "states")
+ .item(0);
+ NodeList stateElements = statesElement.getElementsByTagNameNS(Workflow.NAMESPACE, "state");
+
+ ArrayList states = new ArrayList();
+ for (int i = 0; i < stateElements.getLength(); i++) {
+ Element element = (Element) stateElements.item(i);
+ String state = buildState(element);
+
+ if (isInitialStateElement(element)) {
+ initialState = state;
+ }
+ states.add(state);
+ }
+
+ workflow.setStates((String[]) states.toArray(new String[states.size()]));
+ workflow.setInitialState(initialState);
+
+ // load transitions
+ Element transitionsElement = (Element) root.getElementsByTagNameNS(Workflow.NAMESPACE,
+ "transitions").item(0);
+ NodeList transitionElements = transitionsElement.getElementsByTagNameNS(Workflow.NAMESPACE,
+ "transition");
+
+ ArrayList transitions = new ArrayList();
+ for (int i = 0; i < transitionElements.getLength(); i++) {
+ Transition transition = buildTransition((Element) transitionElements.item(i));
+ transitions.add(transition);
+ }
+
+ workflow.setTransitions((Transition[]) transitions.toArray(new Transition[transitions
+ .size()]));
+
+ return workflow;
+ }
+
+ /**
+ * Checks if a state element contains the initial state.
+ * @param element An XML element.
+ * @return A boolean value.
+ */
+ protected boolean isInitialStateElement(Element element) {
+ String initialAttribute = element.getAttribute("initial");
+
+ return (initialAttribute != null)
+ && (initialAttribute.equals("yes") || initialAttribute.equals("true"));
+ }
+
+ /**
+ * Builds a state from an XML element.
+ * @param element An XML element.
+ * @return A state.
+ */
+ protected String buildState(Element element) {
+ return element.getAttribute("id");
+ }
+
+ /**
+ * Builds a transition from an XML element.
+ * @param element An XML element.
+ * @return A transition.
+ * @throws WorkflowException when something went wrong.
+ */
+ protected Transition buildTransition(Element element) throws WorkflowException {
+
+ String id = element.getAttribute("id");
+ String source = element.getAttribute("from");
+ String destination = element.getAttribute("to");
+
+ TransitionImpl transition = new TransitionImpl(id, source, destination);
+
+ NodeList conditionElements = element.getElementsByTagNameNS(Workflow.NAMESPACE,
+ "condition");
+
+ Condition[] conditions = new Condition[conditionElements.getLength()];
+ for (int i = 0; i < conditionElements.getLength(); i++) {
+ conditions[i] = buildCondition((Element) conditionElements.item(i));
+ }
+
+ transition.setConditions(conditions);
+
+ NodeList actionElements = element.getElementsByTagNameNS(Workflow.NAMESPACE,
+ "action");
+
+ Action[] actions = new Action[actionElements.getLength()];
+ for (int i = 0; i < actionElements.getLength(); i++) {
+ actions[i] = buildAction((Element) actionElements.item(i));
+ }
+
+ transition.setActions(actions);
+
+ return transition;
+ }
+
+ protected Condition buildCondition(Element element) throws WorkflowException {
+ String className = element.getAttribute("class");
+ Class conditionClass;
+ Condition condition = null;
+ try {
+ conditionClass = Class.forName(className);
+ condition = (Condition)conditionClass.newInstance();
+ } catch (Exception e) {
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ Node node = element.getFirstChild();
+ String expression = null;
+ if (node != null) {
+ expression = node.getNodeValue();
+ }
+ condition.setExpression(expression);
+ return condition;
+ }
+
+ protected Action buildAction(Element element) throws WorkflowException {
+ String className = element.getAttribute("class");
+ Class actionClass;
+ Action action = null;
+ try {
+ actionClass = Class.forName(className);
+ action = (Action)actionClass.newInstance();
+ } catch (Exception e) {
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ Node node = element.getFirstChild();
+ String expression = null;
+ if (node != null) {
+ expression = node.getNodeValue();
+ }
+ action.setExpression(expression);
+ return action;
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowException.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowException.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowException.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,36 @@
+package org.wyona.yanel.core.workflow;
+
+/**
+ *
+ */
+public class WorkflowException extends Exception {
+
+ /**
+ *
+ */
+ public WorkflowException() {
+ super();
+ }
+
+ /**
+ *
+ */
+ public WorkflowException(Throwable t) {
+ super(t);
+ }
+
+ /**
+ *
+ */
+ public WorkflowException(String s) {
+ super(s);
+ }
+
+ /**
+ *
+ */
+ public WorkflowException(String s, Throwable t) {
+ super(s, t);
+ }
+
+}
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowHelper.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowHelper.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/WorkflowHelper.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow;
+
+import java.io.InputStream;
+import java.util.Date;
+
+import org.apache.log4j.Category;
+import org.wyona.yanel.core.Resource;
+import org.wyona.yanel.core.api.attributes.VersionableV2;
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.attributes.versionable.RevisionInformation;
+import org.wyona.yanel.core.util.DateUtil;
+import org.wyona.yarep.core.Node;
+import org.wyona.yarep.core.Property;
+import org.wyona.yarep.core.Revision;
+
+/**
+ * This class provides some helper methods related to workflow for resources
+ * which are WorkflowableV1 and VersionableV2 and which implement workflow
+ * according to the following conditions:
+ * - there is a resource config property 'workflow-schema' which points to the schema
+ * - the workflow information is stored as properties of a repository node in the repository
+ * of the resource with the path of the resource.
+ *
+ */
+public class WorkflowHelper {
+
+ private static Category log = Category.getInstance(WorkflowHelper.class);
+
+ protected static final String LIVE_REVISION_PROPERTY = "live-revision";
+ protected static final String WORKFLOW_DATE_PROPERTY = "workflow-date";
+ protected static final String WORKFLOW_STATE_PROPERTY = "workflow-state";
+
+ public static void doTransition(Resource resource, String transitionID, String revision)
+ throws WorkflowException {
+ boolean foundTransition = false;
+ String currentState = null;
+ WorkflowableV1 workflowable = (WorkflowableV1)resource;
+ Workflow workflow = getWorkflow(resource);
+ currentState = workflowable.getWorkflowState(revision);
+ if (currentState == null) {
+ currentState = workflow.getInitialState();
+ }
+ Transition[] transitions = workflow.getLeavingTransitions(currentState);
+
+ for (int i = 0; i < transitions.length; i++) {
+ if (transitions[i].getID().equals(transitionID)) {
+ Condition[] conditions = transitions[i].getConditions();
+ for (int j = 0; j < conditions.length; j++) {
+ if (!conditions[j].isComplied(workflowable, workflow, revision)) {
+ throw new WorkflowException("Workflow condition not complied for state " +
+ currentState + " and transition " + transitionID);
+ }
+ }
+ String newState = transitions[i].getDestinationState();
+
+ workflowable.setWorkflowState(newState, revision);
+
+ Action[] actions = transitions[i].getActions();
+ for (int j = 0; j < actions.length; j++) {
+ actions[j].execute(workflowable, workflow, revision);
+ }
+
+ foundTransition = true;
+ }
+ }
+ if (!foundTransition) {
+ throw new WorkflowException("Invalid workflow transition: " + transitionID +
+ " for state: " + currentState);
+ }
+ }
+
+ /*public static boolean canDoTransition(Resource resource, String transitionID, String revision)
+ throws WorkflowException {
+ WorkflowableV1 workflowable = (WorkflowableV1)resource;
+ Workflow workflow = getWorkflow(resource);
+ String currentState = workflowable.getWorkflowState(revision);
+ if (currentState == null) {
+ currentState = workflow.getInitialState();
+ }
+ Transition[] transitions = workflow.getLeavingTransitions(currentState);
+
+ for (int j = 0; j < transitions.length; j++) {
+ Condition[] conditions = transitions[j].getConditions();
+ for (int k = 0; k < conditions.length; k++) {
+ if (!conditions[k].isComplied(workflowable, workflow, revision)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }*/
+
+ public static String getLiveRevision(Resource resource) throws WorkflowException {
+ try {
+ WorkflowableV1 workflowable = (WorkflowableV1)resource;
+ return workflowable.getWorkflowVariable(LIVE_REVISION_PROPERTY);
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static boolean isLive(Resource resource) throws WorkflowException {
+ try {
+ WorkflowableV1 workflowable = (WorkflowableV1)resource;
+ if (workflowable.getWorkflowVariable(LIVE_REVISION_PROPERTY) != null) {
+ return true;
+ } else {
+ return false;
+ }
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static Workflow getWorkflow(Resource resource) throws WorkflowException {
+ try {
+ String workflowSchema = resource.getResourceConfigProperty("workflow-schema");
+ if (workflowSchema == null) {
+ return null;
+ } else {
+ WorkflowBuilder builder = new WorkflowBuilder();
+ InputStream stream;
+ stream = resource.getRealm().getRepository().getNode(workflowSchema).getInputStream();
+ // TODO: cache of workflow
+ return builder.buildWorkflow(stream);
+ }
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static String getWorkflowIntrospection(Resource resource) throws WorkflowException {
+ try {
+ StringBuffer sb = new StringBuffer();
+ RevisionInformation[] revisions = ((VersionableV2)resource).getRevisions();
+ WorkflowableV1 workflowable = (WorkflowableV1)resource;
+ String liveRevision = getLiveRevision(resource);
+ if (revisions != null && revisions.length > 0) {
+ sb.append("<versions>");
+ for (int i = revisions.length - 1; i >= 0; i--) {
+
+ Workflow workflow = getWorkflow(resource);
+ String state = workflowable.getWorkflowState(revisions[i].getName());
+ if (state == null) {
+ state = workflow.getInitialState();
+ }
+ Date workflowDate = workflowable.getWorkflowDate(revisions[i].getName());
+ String date = "";
+ if (workflowDate != null) {
+ date = DateUtil.format(workflowDate);
+ }
+
+ Transition[] transitions = workflow.getLeavingTransitions(state);
+
+ sb.append("<version url=\"?yanel.resource.revision=" + revisions[i].getName() + "\">");
+ sb.append("<comment>" + revisions[i].getComment() + "</comment>");
+ sb.append("<date>" + revisions[i].getDate() + "</date>");
+ sb.append("<user>" + revisions[i].getUser() + "</user>");
+ sb.append("<revision>" + revisions[i].getName() + "</revision>");
+
+ sb.append("<workflow>");
+
+ if (revisions[i].getName().equals(liveRevision)) {
+ state += "-LIVE"; // TODO: this is a hack
+ }
+ sb.append("<state date=\"" + date + "\">" + state + "</state>");
+
+ sb.append("<transitions>");
+transitions: for (int j = 0; j < transitions.length; j++) {
+ Condition[] conditions = transitions[j].getConditions();
+ for (int k = 0; k < conditions.length; k++) {
+ if (!conditions[k].isComplied(workflowable, workflow, revisions[i].getName())) {
+ continue transitions; // jump to next transition
+ }
+ }
+ sb.append("<transition id=\""+transitions[j].getID()+"\" to=\""+transitions[j].getDestinationState()+"\" url=\"?yanel.resource.workflow.transition="+transitions[j].getID()+"&yanel.resource.revision=" + revisions[i].getName() + "\" method=\"POST\">");
+ sb.append("<description>"+transitions[j].getID()+"</description>");
+ sb.append("</transition>");
+ }
+ sb.append("</transitions>");
+ sb.append("<history/>");
+ sb.append("</workflow>");
+
+ sb.append("</version>");
+ }
+ sb.append("</versions>");
+ return sb.toString();
+ } else {
+ return "";
+ }
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static String getWorkflowIntrospectionAnswer(Resource resource, String revision) throws WorkflowException {
+ try {
+ StringBuffer sb = new StringBuffer();
+ WorkflowableV1 workflowable = (WorkflowableV1)resource;
+
+ Workflow workflow = getWorkflow(resource);
+ String state = workflowable.getWorkflowState(revision);
+ if (state == null) {
+ state = workflow.getInitialState();
+ }
+ String date = "";
+
+ sb.append("<workflow xmlns=\"http://www.wyona.org/neutron/2.0\">");
+ sb.append(" <state date=\"" + date + "\">" + state + "</state>");
+
+ Transition[] transitions = workflow.getLeavingTransitions(state);
+
+ sb.append("<transitions>");
+transitions: for (int j = 0; j < transitions.length; j++) {
+ Condition[] conditions = transitions[j].getConditions();
+ for (int k = 0; k < conditions.length; k++) {
+ if (!conditions[k].isComplied(workflowable, workflow, revision)) {
+ continue transitions; // jump to next transition
+ }
+ }
+ sb.append("<transition id=\""+transitions[j].getID()+"\" to=\""+transitions[j].getDestinationState()+"\" url=\"?yanel.resource.workflow.transition="+transitions[j].getID()+"\" method=\"POST\">");
+ sb.append("<description>"+transitions[j].getID()+"</description>");
+ sb.append("</transition>");
+ }
+ sb.append("</transitions>");
+ sb.append("<history/>");
+ sb.append("</workflow>");
+
+ return sb.toString();
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static String getWorkflowVariable(Resource resource, String name) throws WorkflowException {
+ try {
+ Node node = resource.getRealm().getRepository().getNode(resource.getPath());
+ Property property = node.getProperty(name);
+ if (property != null) {
+ return property.getString();
+ } else {
+ return null;
+ }
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static void setWorkflowVariable(Resource resource, String name, String value) throws WorkflowException {
+ try {
+ Node node = resource.getRealm().getRepository().getNode(resource.getPath());
+ node.setProperty(name, value);
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static void removeWorkflowVariable(Resource resource, String name) throws WorkflowException {
+ try {
+ Node node = resource.getRealm().getRepository().getNode(resource.getPath());
+ node.removeProperty(name);
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static String getWorkflowState(Resource resource, String revision) throws WorkflowException {
+ try {
+ Node node = resource.getRealm().getRepository().getNode(resource.getPath());
+ Property stateProp = node.getRevision(revision).getProperty(WORKFLOW_STATE_PROPERTY);
+ if (stateProp != null) {
+ return stateProp.getString();
+ } else {
+ return null;
+ }
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static void setWorkflowState(Resource resource, String state, String revision) throws WorkflowException {
+ try {
+ Node node = resource.getRealm().getRepository().getNode(resource.getPath());
+ Revision rev = node.getRevision(revision);
+ rev.setProperty(WORKFLOW_STATE_PROPERTY, state);
+ rev.setProperty(WORKFLOW_DATE_PROPERTY, new Date());
+ // TODO: write workflow history
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+ public static Date getWorkflowDate(Resource resource, String revision) throws WorkflowException {
+ try {
+ Node node = resource.getRealm().getRepository().getNode(resource.getPath());
+ Property dateProp = node.getRevision(revision).getProperty(WORKFLOW_DATE_PROPERTY);
+ if (dateProp != null) {
+ return dateProp.getDate();
+ } else {
+ return null;
+ }
+ } catch (Exception e) {
+ log.error(e, e);
+ throw new WorkflowException(e.getMessage(), e);
+ }
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/TransitionImpl.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/TransitionImpl.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/TransitionImpl.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow.impl;
+
+import org.wyona.yanel.core.workflow.Action;
+import org.wyona.yanel.core.workflow.Condition;
+import org.wyona.yanel.core.workflow.Transition;
+
+public class TransitionImpl implements Transition {
+ private String id;
+ private String sourceState;
+ private String destinationState;
+ private Condition[] conditions;
+ private Action[] actions;
+
+ public TransitionImpl(String id, String from, String to) {
+ this.id = id;
+ this.sourceState = from;
+ this.destinationState = to;
+ }
+
+ public String getID() {
+ return id;
+ }
+
+ public void setID(String id) {
+ this.id = id;
+ }
+
+ public String getDestinationState() {
+ return destinationState;
+ }
+
+ public void setDestinationState(String destinationState) {
+ this.destinationState = destinationState;
+ }
+
+ public String getSourceState() {
+ return sourceState;
+ }
+
+ public void setSourceState(String sourceState) {
+ this.sourceState = sourceState;
+ }
+
+ public Action[] getActions() {
+ return actions;
+ }
+
+ public void setActions(Action[] actions) {
+ this.actions = actions;
+ }
+
+ public Condition[] getConditions() {
+ return conditions;
+ }
+
+ public void setConditions(Condition[] conditions) {
+ this.conditions = conditions;
+ }
+}
\ No newline at end of file
Added: public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/WorkflowImpl.java
===================================================================
--- public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/WorkflowImpl.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/core/java/org/wyona/yanel/core/workflow/impl/WorkflowImpl.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.core.workflow.impl;
+
+import java.util.ArrayList;
+
+import org.wyona.yanel.core.workflow.Transition;
+import org.wyona.yanel.core.workflow.Workflow;
+
+public class WorkflowImpl implements Workflow {
+
+ private String[] states;
+ private String initialState;
+ private Transition[] transitions;
+
+ public WorkflowImpl() {
+ }
+
+ public String getInitialState() {
+ return this.initialState;
+ }
+
+ public void setInitialState(String state) {
+ this.initialState = state;
+ }
+
+ public String[] getStates() {
+ return this.states;
+ }
+
+ public void setStates(String[] states) {
+ this.states = states;
+ }
+
+ public Transition[] getTransitions() {
+ return this.transitions;
+ }
+
+ public void setTransitions(Transition[] transitions) {
+ this.transitions = transitions;
+ }
+
+ public Transition[] getLeavingTransitions(String state) {
+ ArrayList leavingTransitions = new ArrayList();
+ for (int i = 0; i < transitions.length; i++) {
+ if (transitions[i].getSourceState().equals(state)) {
+ leavingTransitions.add(transitions[i]);
+ }
+ }
+ return (Transition[])leavingTransitions.toArray(new Transition[leavingTransitions.size()]);
+ }
+}
\ No newline at end of file
Added: public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/DeactivateAction.java
===================================================================
--- public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/DeactivateAction.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/DeactivateAction.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.impl.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.workflow.Action;
+import org.wyona.yanel.core.workflow.Workflow;
+import org.wyona.yanel.core.workflow.WorkflowException;
+
+public class DeactivateAction implements Action {
+
+ protected String variable;
+
+ public void setExpression(String expression) {
+ this.variable = expression;
+ }
+
+ public void execute(WorkflowableV1 workflowable, Workflow workflow, String revision)
+ throws WorkflowException {
+ // TODO
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/PublishAction.java
===================================================================
--- public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/PublishAction.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/PublishAction.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.impl.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.workflow.Action;
+import org.wyona.yanel.core.workflow.Workflow;
+import org.wyona.yanel.core.workflow.WorkflowException;
+
+public class PublishAction implements Action {
+
+ protected String variable;
+
+ public void setExpression(String expression) {
+ this.variable = expression;
+ }
+
+ public void execute(WorkflowableV1 workflowable, Workflow workflow, String revision)
+ throws WorkflowException {
+ // TODO
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RemoveVariableAction.java
===================================================================
--- public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RemoveVariableAction.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RemoveVariableAction.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.impl.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.workflow.Action;
+import org.wyona.yanel.core.workflow.Workflow;
+import org.wyona.yanel.core.workflow.WorkflowException;
+
+public class RemoveVariableAction implements Action {
+
+ protected String variable;
+
+ public void setExpression(String expression) {
+ this.variable = expression;
+ }
+
+ public void execute(WorkflowableV1 workflowable, Workflow workflow, String revision)
+ throws WorkflowException {
+ workflowable.removeWorkflowVariable(variable);
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionEqualsCondition.java
===================================================================
--- public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionEqualsCondition.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionEqualsCondition.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.impl.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.workflow.Condition;
+import org.wyona.yanel.core.workflow.Workflow;
+import org.wyona.yanel.core.workflow.WorkflowException;
+
+public class RevisionEqualsCondition implements Condition {
+
+ protected String variable;
+
+ public void setExpression(String expression) {
+ this.variable = expression;
+ }
+
+ public boolean isComplied(WorkflowableV1 workflowable, Workflow workflow, String revision)
+ throws WorkflowException {
+ String liveRevision = workflowable.getWorkflowVariable(variable);
+ boolean result = revision.equals(liveRevision);
+ return result;
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionNotEqualsCondition.java
===================================================================
--- public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionNotEqualsCondition.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RevisionNotEqualsCondition.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.impl.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.workflow.Condition;
+import org.wyona.yanel.core.workflow.Workflow;
+import org.wyona.yanel.core.workflow.WorkflowException;
+
+public class RevisionNotEqualsCondition implements Condition {
+
+ protected String variable;
+
+ public void setExpression(String expression) {
+ this.variable = expression;
+ }
+
+ public boolean isComplied(WorkflowableV1 workflowable, Workflow workflow, String revision)
+ throws WorkflowException {
+ String liveRevision = workflowable.getWorkflowVariable(variable);
+ boolean result = !revision.equals(liveRevision);
+ return result;
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RoleCondition.java
===================================================================
--- public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RoleCondition.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/RoleCondition.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.impl.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.workflow.Condition;
+import org.wyona.yanel.core.workflow.Workflow;
+import org.wyona.yanel.core.workflow.WorkflowException;
+
+public class RoleCondition implements Condition {
+
+ protected String role;
+
+ public void setExpression(String expression) {
+ this.role = expression;
+ }
+
+ public boolean isComplied(WorkflowableV1 workflowable, Workflow workflow, String revision)
+ throws WorkflowException {
+ // TODO
+ return true;
+ }
+
+}
\ No newline at end of file
Added: public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/SetRevisionAction.java
===================================================================
--- public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/SetRevisionAction.java 2007-05-14 20:54:57 UTC (rev 24456)
+++ public/yanel/trunk/src/impl/java/org/wyona/yanel/impl/workflow/SetRevisionAction.java 2007-05-14 20:57:06 UTC (rev 24457)
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2006 Wyona
+ *
+ * Licensed 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.wyona.org/licenses/APACHE-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 org.wyona.yanel.impl.workflow;
+
+import org.wyona.yanel.core.api.attributes.WorkflowableV1;
+import org.wyona.yanel.core.workflow.Action;
+import org.wyona.yanel.core.workflow.Workflow;
+import org.wyona.yanel.core.workflow.WorkflowException;
+
+public class SetRevisionAction implements Action {
+
+ protected String variable;
+
+ public void setExpression(String expression) {
+ this.variable = expression;
+ }
+
+ public void execute(WorkflowableV1 workflowable, Workflow workflow, String revision)
+ throws WorkflowException {
+ workflowable.setWorkflowVariable(variable, revision);
+ }
+
+}
\ No newline at end of file
More information about the Yanel-commits
mailing list