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