001/* 002 * Copyright 2013 Anyware Services 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 */ 016package org.ametys.plugins.cart.generators; 017 018import java.io.IOException; 019import java.util.Collections; 020import java.util.Comparator; 021import java.util.Date; 022import java.util.List; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.ProcessingException; 027import org.apache.cocoon.environment.ObjectModelHelper; 028import org.apache.cocoon.environment.Request; 029import org.apache.cocoon.generation.ServiceableGenerator; 030import org.apache.cocoon.xml.AttributesImpl; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.commons.lang.ArrayUtils; 033import org.xml.sax.SAXException; 034 035import org.ametys.cms.repository.Content; 036import org.ametys.cms.repository.WorkflowAwareContent; 037import org.ametys.core.user.CurrentUserProvider; 038import org.ametys.core.user.User; 039import org.ametys.core.user.UserIdentity; 040import org.ametys.core.user.UserManager; 041import org.ametys.plugins.cart.Cart; 042import org.ametys.plugins.cart.CartElement; 043import org.ametys.plugins.cart.ContentElement; 044import org.ametys.plugins.repository.AmetysObjectResolver; 045import org.ametys.plugins.repository.AmetysRepositoryException; 046import org.ametys.plugins.repository.version.VersionAwareAmetysObject; 047import org.ametys.plugins.workflow.store.AmetysStep; 048import org.ametys.plugins.workflow.support.WorkflowHelper; 049import org.ametys.plugins.workflow.support.WorkflowProvider; 050import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow; 051import org.ametys.runtime.i18n.I18nizableText; 052import org.ametys.runtime.parameter.ParameterHelper; 053 054import com.opensymphony.workflow.WorkflowException; 055import com.opensymphony.workflow.spi.Step; 056 057/** 058 * SAX a {@link Cart} 059 * 060 */ 061public class CartElementsGenerator extends ServiceableGenerator 062{ 063 /** The Ametys object resolver */ 064 protected AmetysObjectResolver _resolver; 065 /** The workflow provider */ 066 protected WorkflowProvider _workflowProvider; 067 /** The workflow helper */ 068 protected WorkflowHelper _workflowHelper; 069 /** The current user provider */ 070 protected CurrentUserProvider _userProvider; 071 /** The user manager */ 072 protected UserManager _userManager; 073 074 @Override 075 public void service(ServiceManager smanager) throws ServiceException 076 { 077 super.service(smanager); 078 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 079 _workflowProvider = (WorkflowProvider) smanager.lookup(WorkflowProvider.ROLE); 080 _workflowHelper = (WorkflowHelper) smanager.lookup(WorkflowHelper.ROLE); 081 _userManager = (UserManager) smanager.lookup(UserManager.ROLE); 082 _userProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 083 } 084 085 @Override 086 public void generate() throws IOException, SAXException, ProcessingException 087 { 088 Request request = ObjectModelHelper.getRequest(objectModel); 089 String id = request.getParameter("cartId"); 090 091 Cart cart = _resolver.resolveById(id); 092 093 contentHandler.startDocument(); 094 095 UserIdentity user = _userProvider.getUser(); 096 if (cart.canRead(user)) 097 { 098 AttributesImpl attrs = new AttributesImpl(); 099 attrs.addCDATAAttribute("id", cart.getId()); 100 101 XMLUtils.startElement(contentHandler, "cart", attrs); 102 103 XMLUtils.createElement(contentHandler, "label", cart.getTitle()); 104 XMLUtils.createElement(contentHandler, "description", cart.getDescription()); 105 XMLUtils.createElement(contentHandler, "visibility", cart.getVisibility().toString()); 106 107 List<CartElement> elements = cart.getElements(); 108 for (CartElement elmt : elements) 109 { 110 _saxElement(elmt); 111 } 112 113 XMLUtils.createElement(contentHandler, "total", String.valueOf(elements.size())); 114 115 XMLUtils.endElement(contentHandler, "cart"); 116 } 117 else 118 { 119 XMLUtils.createElement(contentHandler, "not-allowed"); 120 } 121 122 contentHandler.endDocument(); 123 } 124 125 /** 126 * SAX an element of the cart 127 * @param elmt The element to SAX 128 * @throws SAXException if something goes wrong when saxing the element 129 */ 130 protected void _saxElement (CartElement elmt) throws SAXException 131 { 132 List<I18nizableText> groups = elmt.getGroups(); 133 134 for (I18nizableText group : groups) 135 { 136 AttributesImpl attrs = new AttributesImpl(); 137 attrs.addCDATAAttribute("id", elmt.getId()); 138 139 XMLUtils.startElement(contentHandler, "cartElement", attrs); 140 141 elmt.getTitle().toSAX(contentHandler, "title"); 142 elmt.getDescription().toSAX(contentHandler, "description"); 143 group.toSAX(contentHandler, "group"); 144 145 XMLUtils.createElement(contentHandler, "lastModification", ParameterHelper.valueToString(elmt.getLastModified())); 146 147 UserIdentity lastContributor = elmt.getLastContributor(); 148 User user = _userManager.getUser(lastContributor.getPopulationId(), lastContributor.getLogin()); 149 XMLUtils.createElement(contentHandler, "lastContributor", user.getFullName()); 150 151 String glyphIcon = elmt.getGlyphIcon(); 152 if (glyphIcon != null) 153 { 154 XMLUtils.createElement(contentHandler, "glyphIcon", glyphIcon); 155 } 156 157 String smallIcon = elmt.getSmallIcon(); 158 if (smallIcon != null) 159 { 160 XMLUtils.createElement(contentHandler, "smallIcon", smallIcon); 161 } 162 String mediumIcon = elmt.getSmallIcon(); 163 if (mediumIcon != null) 164 { 165 XMLUtils.createElement(contentHandler, "mediumIcon", mediumIcon); 166 } 167 168 XMLUtils.createElement(contentHandler, "type", elmt.getType()); 169 170 if (elmt instanceof ContentElement) 171 { 172 Content content = _resolver.resolveById(elmt.getId()); 173 _saxWorkflowStep(content); 174 } 175 176 XMLUtils.endElement(contentHandler, "cartElement"); 177 } 178 } 179 180 /** 181 * SAX the workflow step if the content is a <code>WorkflowAwareContent</code> 182 * @param content The content 183 * @throws SAXException if an error occurs while SAXing. 184 */ 185 protected void _saxWorkflowStep (Content content) throws SAXException 186 { 187 if (content instanceof WorkflowAwareContent) 188 { 189 WorkflowAwareContent waContent = (WorkflowAwareContent) content; 190 191 try 192 { 193 AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(waContent); 194 long workflowId = waContent.getWorkflowId(); 195 String workflowName = workflow.getWorkflowName(workflowId); 196 197 Step currentStep = _getCurrentStep(waContent, workflow); 198 199 int currentStepId = currentStep.getStepId(); 200 201 I18nizableText workflowStepName = new I18nizableText("application", _workflowHelper.getStepName(workflowName, currentStepId)); 202 203 AttributesImpl atts = new AttributesImpl(); 204 atts.addAttribute("", "id", "id", "CDATA", String.valueOf(currentStepId)); 205 if ("application".equals(workflowStepName.getCatalogue())) 206 { 207 atts.addAttribute("", "icon-small", "icon-small", "CDATA", "/plugins/cms/resources_workflow/" + workflowStepName.getKey() + "-small.png"); 208 atts.addAttribute("", "icon-medium", "icon-medium", "CDATA", "/plugins/cms/resources_workflow/" + workflowStepName.getKey() + "-medium.png"); 209 atts.addAttribute("", "icon-large", "icon-large", "CDATA", "/plugins/cms/resources_workflow/" + workflowStepName.getKey() + "-large.png"); 210 } 211 else 212 { 213 String pluginName = workflowStepName.getCatalogue().substring("plugin.".length()); 214 atts.addAttribute("", "icon-small", "icon-small", "CDATA", "/plugins/" + pluginName + "/resources/img/workflow/" + workflowStepName.getKey() + "-small.png"); 215 atts.addAttribute("", "icon-medium", "icon-medium", "CDATA", "/plugins/" + pluginName + "/resources/img/workflow/" + workflowStepName.getKey() + "-medium.png"); 216 atts.addAttribute("", "icon-large", "icon-large", "CDATA", "/plugins/" + pluginName + "/resources/img/workflow/" + workflowStepName.getKey() + "-large.png"); 217 } 218 219 XMLUtils.startElement(contentHandler, "workflow-step", atts); 220 workflowStepName.toSAX(contentHandler); 221 XMLUtils.endElement(contentHandler, "workflow-step"); 222 } 223 catch (AmetysRepositoryException e) 224 { 225 // Current step id was not positioned 226 } 227 catch (WorkflowException e) 228 { 229 // Ignore, just don't SAX the workflow step. 230 } 231 } 232 } 233 234 /** 235 * Get a content's step, wherever it works on the base version or not. 236 * @param content the content. 237 * @param workflow the workflow instance bound to this content 238 * @return the content's workflow step. 239 * @throws WorkflowException if an error occurs. 240 */ 241 protected Step _getCurrentStep(WorkflowAwareContent content, AmetysObjectWorkflow workflow) throws WorkflowException 242 { 243 long workflowId = content.getWorkflowId(); 244 Step currentStep = (Step) workflow.getCurrentSteps(workflowId).get(0); 245 246 if (content instanceof VersionAwareAmetysObject) 247 { 248 VersionAwareAmetysObject vaContent = (VersionAwareAmetysObject) content; 249 String currentRevision = vaContent.getRevision(); 250 251 if (currentRevision != null) 252 { 253 254 String[] allRevisions = vaContent.getAllRevisions(); 255 int currentRevIndex = ArrayUtils.indexOf(allRevisions, currentRevision); 256 257 if (currentRevIndex > -1 && currentRevIndex < (allRevisions.length - 1)) 258 { 259 String nextRevision = allRevisions[currentRevIndex + 1]; 260 261 Date currentRevTimestamp = vaContent.getRevisionTimestamp(); 262 Date nextRevTimestamp = vaContent.getRevisionTimestamp(nextRevision); 263 264 // Get all steps between the two revisions. 265 List<Step> steps = _workflowHelper.getStepsBetween(workflow, workflowId, currentRevTimestamp, nextRevTimestamp); 266 267 // In the old workflow structure 268 // We take the second, which is current revision's last step. 269 if (steps.size() > 0 && steps.get(0) instanceof AmetysStep) 270 { 271 AmetysStep amStep = (AmetysStep) steps.get(0); 272 if (amStep.getProperty("actionFinishDate") != null) 273 { 274 // New workflow structure detected: cut the first workflow step 275 // in the list, as it belongs to the next version. 276 steps = steps.subList(1, steps.size()); 277 } 278 } 279 280 // Order by step descendant. 281 Collections.sort(steps, new Comparator<Step>() 282 { 283 public int compare(Step step1, Step step2) 284 { 285 return -new Long(step1.getId()).compareTo(step2.getId()); 286 } 287 }); 288 289 // The first step in the list is the current version's last workflow step. 290 if (steps.size() > 0) 291 { 292 currentStep = steps.get(0); 293 } 294 } 295 } 296 } 297 return currentStep; 298 } 299}