001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Julien Anguenot 011 * Florent Guillaume 012 */ 013 014package org.nuxeo.ecm.core.lifecycle.impl; 015 016import java.util.Collection; 017import java.util.List; 018import java.util.Map; 019 020import org.apache.commons.logging.Log; 021import org.apache.commons.logging.LogFactory; 022import org.nuxeo.ecm.core.api.LifeCycleException; 023import org.nuxeo.ecm.core.lifecycle.LifeCycle; 024import org.nuxeo.ecm.core.lifecycle.LifeCycleService; 025import org.nuxeo.ecm.core.lifecycle.LifeCycleState; 026import org.nuxeo.ecm.core.lifecycle.extensions.LifeCycleDescriptor; 027import org.nuxeo.ecm.core.lifecycle.extensions.LifeCycleTypesDescriptor; 028import org.nuxeo.ecm.core.model.Document; 029import org.nuxeo.runtime.model.ComponentName; 030import org.nuxeo.runtime.model.DefaultComponent; 031import org.nuxeo.runtime.model.Extension; 032 033/** 034 * Life cycle service implementation. 035 * 036 * @see org.nuxeo.ecm.core.lifecycle.LifeCycleService 037 * @author Julien Anguenot 038 * @author Florent Guillaume 039 */ 040public class LifeCycleServiceImpl extends DefaultComponent implements LifeCycleService { 041 042 public static final ComponentName NAME = new ComponentName("org.nuxeo.ecm.core.lifecycle.LifeCycleService"); 043 044 private static final Log log = LogFactory.getLog(LifeCycleServiceImpl.class); 045 046 protected LifeCycleRegistry lifeCycles = new LifeCycleRegistry(); 047 048 protected LifeCycleTypeRegistry lifeCycleTypes = new LifeCycleTypeRegistry(); 049 050 public LifeCycleServiceImpl() { 051 } 052 053 @Override 054 public LifeCycle getLifeCycleByName(String name) { 055 return lifeCycles.getLifeCycle(name); 056 } 057 058 @Override 059 public LifeCycle getLifeCycleFor(Document doc) { 060 String lifeCycleName = getLifeCycleNameFor(doc.getType().getName()); 061 return getLifeCycleByName(lifeCycleName); 062 } 063 064 @Override 065 public String getLifeCycleNameFor(String typeName) { 066 return lifeCycleTypes.getLifeCycleNameForType(typeName); 067 } 068 069 @Override 070 public Collection<LifeCycle> getLifeCycles() { 071 return lifeCycles.getLifeCycles(); 072 } 073 074 @Override 075 public Collection<String> getTypesFor(String lifeCycleName) { 076 return lifeCycleTypes.getTypesFor(lifeCycleName); 077 } 078 079 @Override 080 public Map<String, String> getTypesMapping() { 081 return lifeCycleTypes.getTypesMapping(); 082 } 083 084 @Override 085 public void initialize(Document doc) throws LifeCycleException { 086 initialize(doc, null); 087 } 088 089 @Override 090 public void initialize(Document doc, String initialStateName) throws LifeCycleException { 091 String lifeCycleName; 092 LifeCycle documentLifeCycle = getLifeCycleFor(doc); 093 if (documentLifeCycle == null) { 094 lifeCycleName = "undefined"; 095 if (initialStateName == null) { 096 initialStateName = "undefined"; 097 } 098 } else { 099 lifeCycleName = documentLifeCycle.getName(); 100 // set initial life cycle state 101 if (initialStateName == null) { 102 initialStateName = documentLifeCycle.getDefaultInitialStateName(); 103 } else { 104 // check it's a valid state 105 LifeCycleState state = documentLifeCycle.getStateByName(initialStateName); 106 if (state == null) { 107 throw new LifeCycleException(String.format("State '%s' is not a valid state " + "for lifecycle %s", 108 initialStateName, lifeCycleName)); 109 } 110 } 111 } 112 doc.setCurrentLifeCycleState(initialStateName); 113 doc.setLifeCyclePolicy(lifeCycleName); 114 } 115 116 @Override 117 public void followTransition(Document doc, String transitionName) throws LifeCycleException { 118 String lifeCycleState = doc.getLifeCycleState(); 119 LifeCycle lifeCycle = getLifeCycleFor(doc); 120 if (lifeCycle.getAllowedStateTransitionsFrom(lifeCycleState).contains(transitionName)) { 121 String destinationStateName = lifeCycle.getTransitionByName(transitionName).getDestinationStateName(); 122 doc.setCurrentLifeCycleState(destinationStateName); 123 } else { 124 throw new LifeCycleException("Not allowed to follow transition <" + transitionName + "> from state <" 125 + lifeCycleState + '>'); 126 } 127 } 128 129 @Override 130 public void reinitLifeCycle(Document doc) throws LifeCycleException { 131 LifeCycle documentLifeCycle = getLifeCycleFor(doc); 132 if (documentLifeCycle == null) { 133 log.debug("No lifecycle policy for this document. Nothing to do !"); 134 return; 135 } 136 doc.setCurrentLifeCycleState(documentLifeCycle.getDefaultInitialStateName()); 137 } 138 139 /** 140 * Register extensions. 141 */ 142 @Override 143 public void registerExtension(Extension extension) { 144 Object[] contributions = extension.getContributions(); 145 if (contributions != null) { 146 String point = extension.getExtensionPoint(); 147 if (point.equals("lifecycle")) { 148 for (Object contribution : contributions) { 149 LifeCycleDescriptor desc = (LifeCycleDescriptor) contribution; 150 lifeCycles.addContribution(desc); 151 } 152 } else if (point.equals("lifecyclemanager")) { 153 log.warn("Ignoring deprecated lifecyclemanager extension point"); 154 } else if (point.equals("types")) { 155 for (Object mapping : contributions) { 156 LifeCycleTypesDescriptor desc = (LifeCycleTypesDescriptor) mapping; 157 lifeCycleTypes.addContribution(desc); 158 } 159 } 160 } 161 } 162 163 /** 164 * Unregisters an extension. 165 */ 166 @Override 167 public void unregisterExtension(Extension extension) { 168 super.unregisterExtension(extension); 169 Object[] contributions = extension.getContributions(); 170 if (contributions != null) { 171 String point = extension.getExtensionPoint(); 172 if (point.equals("lifecycle")) { 173 for (Object lifeCycle : contributions) { 174 LifeCycleDescriptor lifeCycleDescriptor = (LifeCycleDescriptor) lifeCycle; 175 lifeCycles.removeContribution(lifeCycleDescriptor); 176 } 177 } else if (point.equals("types")) { 178 for (Object contrib : contributions) { 179 LifeCycleTypesDescriptor desc = (LifeCycleTypesDescriptor) contrib; 180 lifeCycleTypes.removeContribution(desc); 181 } 182 183 } 184 } 185 } 186 187 @Override 188 public List<String> getNonRecursiveTransitionForDocType(String docTypeName) { 189 return lifeCycleTypes.getNonRecursiveTransitionForDocType(docTypeName); 190 } 191 192}