blob: 20cf68d732c5d44ec08ddab544a921fe8777715e [file] [log] [blame]
/*
* 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();
}
}