001/* 002 * Copyright 2010 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.cms.content; 017 018import java.io.IOException; 019import java.text.DateFormat; 020import java.text.SimpleDateFormat; 021import java.util.Locale; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.cocoon.ProcessingException; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.generation.Generator; 029import org.apache.cocoon.generation.ServiceableGenerator; 030import org.apache.cocoon.i18n.I18nUtils; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.commons.lang.ArrayUtils; 033import org.apache.commons.lang3.StringUtils; 034import org.xml.sax.SAXException; 035 036import org.ametys.cms.contenttype.ContentType; 037import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 038import org.ametys.cms.contenttype.ContentTypesHelper; 039import org.ametys.cms.repository.Content; 040import org.ametys.runtime.model.View; 041import org.ametys.runtime.model.ViewHelper; 042 043/** 044 * {@link Generator} for rendering raw content data. 045 */ 046public class ContentGenerator extends ServiceableGenerator 047{ 048 /** The display date format. */ 049 protected static final DateFormat _DC_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); 050 051 /** Content type extension point. */ 052 protected ContentTypeExtensionPoint _contentTypeExtensionPoint; 053 /** Helper for content types */ 054 protected ContentTypesHelper _cTypesHelper; 055 /** The content saxer */ 056 protected ContentSaxer _contentSaxer; 057 058 @Override 059 public void service(ServiceManager serviceManager) throws ServiceException 060 { 061 super.service(serviceManager); 062 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 063 _cTypesHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 064 _contentSaxer = (ContentSaxer) serviceManager.lookup(ContentSaxer.CMS_CONTENT_SAXER_ROLE); 065 } 066 067 public void generate() throws IOException, SAXException, ProcessingException 068 { 069 contentHandler.startDocument(); 070 _generateContent(); 071 contentHandler.endDocument(); 072 } 073 074 /** 075 * Generate the content (with the start/end document) 076 * @throws SAXException if an error occurs while SAXing 077 * @throws IOException if an error occurs 078 * @throws ProcessingException if an error occurs 079 */ 080 protected void _generateContent() throws SAXException, IOException, ProcessingException 081 { 082 Request request = ObjectModelHelper.getRequest(objectModel); 083 Content content = (Content) request.getAttribute(Content.class.getName()); 084 085 // SAX the content 086 _saxContent(content, getDefaultLocale(request)); 087 } 088 089 /** 090 * Get the default locale to use to sax localized values 091 * @param request the request 092 * @return the default locale 093 */ 094 protected Locale getDefaultLocale(Request request) 095 { 096 String lang = parameters.getParameter("lang", request.getParameter("lang")); 097 return StringUtils.isNotEmpty(lang) ? new Locale(lang) : I18nUtils.findLocale(objectModel, "locale", null, Locale.getDefault(), true); 098 } 099 100 /** 101 * SAX the content 102 * @param content The content to SAX 103 * @param defaultLocale The default locale to use to sax localized values if the content's language is null. 104 * @throws SAXException if an error occurs while SAXing 105 * @throws IOException if an error occurs 106 * @throws ProcessingException if an error occurs 107 */ 108 protected void _saxContent (Content content, Locale defaultLocale) throws SAXException, IOException, ProcessingException 109 { 110 _contentSaxer.saxRootTag(content, contentHandler, defaultLocale, "content"); 111 112 boolean isEdition = parameters.getParameterAsBoolean("isEdition", false); 113 boolean showDisableValues = parameters.getParameterAsBoolean("showDisableValues", false); 114 115 View view = _getView(content, isEdition); 116 Locale locale = content.getLanguage() != null ? new Locale(content.getLanguage()) : defaultLocale; 117 118 // FIXME CMS-3057 119 Request request = ObjectModelHelper.getRequest(objectModel); 120 boolean displayWorkflow = !"true".equals(request.getParameter("ignore-workflow")); 121 122 _contentSaxer.saxContent(content, contentHandler, locale, view, null, displayWorkflow, displayWorkflow, true, "metadata", isEdition, showDisableValues); 123 124 if (isEdition) 125 { 126 XMLUtils.startElement(contentHandler, "comments"); 127 _saxAttributesComments(content, view); 128 XMLUtils.endElement(contentHandler, "comments"); 129 } 130 131 String[] cTypes = (String[]) ArrayUtils.addAll(content.getTypes(), content.getMixinTypes()); 132 for (String cTypeId : cTypes) 133 { 134 ContentType cType = _contentTypeExtensionPoint.getExtension(cTypeId); 135 cType.saxContentTypeAdditionalData(contentHandler, content); 136 } 137 138 _saxOtherData(content, defaultLocale); 139 140 XMLUtils.endElement(contentHandler, "content"); 141 } 142 143 /** 144 * SAX content attributes comments. 145 * @param content the content. 146 * @param view the view containing the attributes. 147 * @throws SAXException if an error occurs while SAXing. 148 */ 149 protected void _saxAttributesComments(Content content, View view) throws SAXException 150 { 151 content.commentsToSAX(contentHandler, view); 152 } 153 154 /** 155 * SAX any other data needed by the view.<p> 156 * Default implementation does nothing. 157 * @param content the content. 158 * @throws SAXException if an error occurs while SAXing. 159 * @throws ProcessingException if an error occurs. 160 * @deprecated Use and/or override {@link #_saxOtherData(Content, Locale)} instead 161 */ 162 @Deprecated 163 protected void _saxOtherData(Content content) throws SAXException, ProcessingException 164 { 165 // No other data to SAX 166 } 167 168 /** 169 * SAX any other data needed by the view.<p> 170 * Default implementation does nothing. 171 * @param content the content. 172 * @param defaultLocale The default locale 173 * @throws SAXException if an error occurs while SAXing. 174 * @throws ProcessingException if an error occurs. 175 * @throws IOException if an error occurs. 176 */ 177 protected void _saxOtherData(Content content, Locale defaultLocale) throws SAXException, ProcessingException, IOException 178 { 179 // For legacy purposes 180 _saxOtherData(content); 181 } 182 183 /** 184 * Retrieves the view to be used when SAX'ing attributes and attribute comments. 185 * @param content The content to consider. Cannot be null. 186 * @param isEdition <code>true</code> if the view is to use for edition, <code>false</code> otherwise 187 * @return The retrieved view 188 * @throws ProcessingException If the view could not be retrieved 189 */ 190 protected View _getView(Content content, boolean isEdition) throws ProcessingException 191 { 192 String fallbackViewName = parameters.getParameter("fallbackViewName", StringUtils.EMPTY); 193 String viewName = parameters.getParameter("viewName", StringUtils.EMPTY); 194 195 View view = _cTypesHelper.getViewWithFallback(viewName, fallbackViewName, content); 196 if (view == null) 197 { 198 String errorMsg = String.format("Unknown view '%s' nor fallback view '%s' for content '%s'", viewName, fallbackViewName, content.getId()); 199 getLogger().error(errorMsg); 200 throw new IllegalArgumentException(errorMsg); 201 } 202 203 return isEdition ? ViewHelper.getTruncatedView(view) : view; 204 } 205}