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