| /* |
| * 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 org.apache.lenya.cms.workflow; |
| |
| import java.text.ParsePosition; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.SortedMap; |
| import java.util.TreeMap; |
| |
| import org.apache.avalon.framework.container.ContainerUtil; |
| import org.apache.avalon.framework.logger.AbstractLogEnabled; |
| import org.apache.avalon.framework.logger.Logger; |
| import org.apache.avalon.framework.service.ServiceManager; |
| import org.apache.lenya.ac.Identity; |
| import org.apache.lenya.ac.User; |
| import org.apache.lenya.cms.metadata.MetaData; |
| import org.apache.lenya.cms.observation.RepositoryEvent; |
| import org.apache.lenya.cms.observation.RepositoryEventFactory; |
| import org.apache.lenya.cms.publication.Document; |
| import org.apache.lenya.cms.publication.ResourceType; |
| import org.apache.lenya.cms.repository.Session; |
| import org.apache.lenya.workflow.Version; |
| import org.apache.lenya.workflow.Workflow; |
| import org.apache.lenya.workflow.Workflowable; |
| |
| /** |
| * Workflowable around a CMS document. |
| * |
| * @version $Id: DocumentWorkflowable.java 416648 2006-06-23 09:15:28Z andreas $ |
| */ |
| class DocumentWorkflowable extends AbstractLogEnabled implements Workflowable { |
| |
| /** |
| * Ctor. |
| * @param manager The service manager. |
| * @param session The repository session. |
| * @param document The document. |
| * @param logger The logger. |
| */ |
| public DocumentWorkflowable(ServiceManager manager, Session session, Document document, |
| Logger logger) { |
| this.document = document; |
| this.session = session; |
| this.manager = manager; |
| ContainerUtil.enableLogging(this, logger); |
| } |
| |
| private Session session; |
| |
| private ServiceManager manager; |
| |
| /** |
| * @return The service manager. |
| */ |
| public ServiceManager getServiceManager() { |
| return this.manager; |
| } |
| |
| /** |
| * @return The repository session. |
| */ |
| public Session getSession() { |
| return session; |
| } |
| |
| private Document document; |
| |
| protected Document getDocument() { |
| return this.document; |
| } |
| |
| /** |
| * @return The name of the workflow schema. |
| */ |
| protected String getWorkflowSchema() { |
| String workflowName = null; |
| try { |
| ResourceType doctype = document.getResourceType(); |
| if (doctype != null) { |
| workflowName = document.getPublication().getWorkflowSchema(doctype); |
| } |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| return workflowName; |
| } |
| |
| private Version[] versions = null; |
| |
| private long lastModified = 0; |
| |
| protected static final String METADATA_NAMESPACE = "http://apache.org/lenya/metadata/workflow/1.0"; |
| protected static final String METADATA_VERSION = "workflowVersion"; |
| |
| /** |
| * @see org.apache.lenya.workflow.Workflowable#getVersions() |
| */ |
| public Version[] getVersions() { |
| try { |
| MetaData meta = this.document.getMetaData(METADATA_NAMESPACE); |
| if (this.versions == null || meta.getLastModified() > this.lastModified) { |
| String[] versionStrings = meta.getValues(METADATA_VERSION); |
| this.versions = new Version[versionStrings.length]; |
| |
| SortedMap number2version = new TreeMap(); |
| |
| for (int i = 0; i < versionStrings.length; i++) { |
| String string = versionStrings[i]; |
| int spaceIndex = string.indexOf(" "); |
| String numberString = string.substring(0, spaceIndex); |
| int number = Integer.parseInt(numberString); |
| String versionString = string.substring(spaceIndex + 1); |
| Version version = decodeVersion(versionString); |
| number2version.put(new Integer(number), version); |
| } |
| |
| int number = 0; |
| for (Iterator i = number2version.keySet().iterator(); i.hasNext(); ) { |
| Version version = (Version) number2version.get(i.next()); |
| this.versions[number] = version; |
| number++; |
| } |
| |
| this.lastModified = meta.getLastModified(); |
| } |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| return this.versions; |
| } |
| |
| /** |
| * @see org.apache.lenya.workflow.Workflowable#getLatestVersion() |
| */ |
| public Version getLatestVersion() { |
| Version version = null; |
| Version[] versions = getVersions(); |
| if (versions.length > 0) { |
| version = versions[versions.length - 1]; |
| } |
| return version; |
| } |
| |
| /** |
| * @see org.apache.lenya.workflow.Workflowable#newVersion(org.apache.lenya.workflow.Workflow, |
| * org.apache.lenya.workflow.Version) |
| */ |
| public void newVersion(Workflow workflow, Version version) { |
| Version[] newVersions = new Version[getVersions().length + 1]; |
| for (int i = 0; i < getVersions().length; i++) { |
| newVersions[i] = getVersions()[i]; |
| } |
| |
| int number = newVersions.length - 1; |
| newVersions[number] = version; |
| |
| String string = number + " " + encodeVersion(workflow, version); |
| addToMetaData(string); |
| |
| WorkflowEventDescriptor descriptor = new WorkflowEventDescriptor(version); |
| RepositoryEvent event = RepositoryEventFactory.createEvent( |
| this.manager, getDocument(), getLogger(), descriptor); |
| getDocument().getRepositoryNode().getSession().enqueueEvent(event); |
| } |
| |
| protected void addToMetaData(String versionString) { |
| try { |
| String[] areas = getDocument().getPublication().getAreaNames(); |
| for (int i = 0; i < areas.length; i++) { |
| if (getDocument().existsAreaVersion(areas[i])) { |
| Document doc = getDocument().getAreaVersion(areas[i]); |
| MetaData meta = doc.getMetaData(METADATA_NAMESPACE); |
| meta.addValue(METADATA_VERSION, versionString); |
| } |
| } |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| protected String encodeVersion(Workflow workflow, Version version) { |
| |
| StringBuffer stringBuf = new StringBuffer("event:").append(version.getEvent()); |
| stringBuf.append(" state:").append(version.getState()); |
| |
| Identity identity = getSession().getIdentity(); |
| User user = identity.getUser(); |
| if (user != null) { |
| stringBuf.append(" user:").append(identity.getUser().getId()); |
| } |
| stringBuf.append(" machine:").append(identity.getMachine().getIp()); |
| |
| SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss"); |
| stringBuf.append(" date:").append(format.format(new Date())); |
| |
| String names[] = workflow.getVariableNames(); |
| for (int i = 0; i < names.length; i++) { |
| String value = Boolean.toString(version.getValue(names[i])); |
| stringBuf.append(" var:").append(names[i]); |
| stringBuf.append("=").append(value); |
| } |
| return stringBuf.toString(); |
| } |
| |
| protected Version decodeVersion(String string) { |
| |
| String event = null; |
| String state = null; |
| String user = null; |
| String machine = null; |
| Date date = null; |
| Map variables = new HashMap(); |
| |
| String[] parts = string.split(" "); |
| for (int i = 0; i < parts.length; i++) { |
| String[] steps = parts[i].split(":", 2); |
| if (steps[0].equals("event")) { |
| event = steps[1]; |
| } else if (steps[0].equals("state")) { |
| state = steps[1]; |
| } else if (steps[0].equals("user")) { |
| user = steps[1]; |
| } else if (steps[0].equals("date")) { |
| SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss", Locale.US); |
| date = sdf.parse(steps[1], new ParsePosition(0)); |
| } else if (steps[0].equals("machine")) { |
| machine = steps[1]; |
| } else if (steps[0].equals("var")) { |
| String[] nameValue = steps[1].split("="); |
| variables.put(nameValue[0], nameValue[1]); |
| } |
| } |
| |
| Version version = new LenyaVersion(event, state); |
| for (Iterator i = variables.keySet().iterator(); i.hasNext();) { |
| String name = (String) i.next(); |
| String value = (String) variables.get(name); |
| version.setUserId(user); |
| version.setDate(date); |
| version.setIPAddress(machine); |
| version.setValue(name, Boolean.valueOf(value).booleanValue()); |
| } |
| return version; |
| } |
| |
| /** |
| * @see org.apache.lenya.workflow.Workflowable#getWorkflowSchemaURI() |
| */ |
| public String getWorkflowSchemaURI() { |
| String uri = null; |
| String schema = getWorkflowSchema(); |
| if (schema != null) { |
| |
| if (schema.indexOf("://") != -1) { |
| return schema; |
| } else { |
| uri = this.document.getPublication().getSourceURI() + "/config/workflow/" + schema; |
| uri = uri.substring("lenya://".length()); |
| uri = "context://" + uri; |
| } |
| } |
| return uri; |
| } |
| |
| public String toString() { |
| return this.document.toString(); |
| } |
| |
| } |