001/* 002 * Copyright 2018 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.odf.services; 017 018import java.io.IOException; 019import java.io.UnsupportedEncodingException; 020import java.util.HashSet; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.cocoon.ProcessingException; 025import org.apache.cocoon.environment.ObjectModelHelper; 026import org.apache.cocoon.environment.Request; 027import org.apache.cocoon.generation.ServiceableGenerator; 028import org.apache.cocoon.xml.XMLUtils; 029import org.apache.commons.lang.ArrayUtils; 030import org.apache.commons.lang3.StringUtils; 031import org.xml.sax.SAXException; 032 033import org.ametys.cms.contenttype.ContentTypesHelper; 034import org.ametys.cms.contenttype.MetadataDefinition; 035import org.ametys.cms.contenttype.MetadataDefinitionReference; 036import org.ametys.cms.contenttype.MetadataManager; 037import org.ametys.cms.contenttype.MetadataSet; 038import org.ametys.cms.repository.DefaultContent; 039import org.ametys.odf.workflow.ValidateODFContentFunction; 040import org.ametys.plugins.repository.AmetysObjectResolver; 041import org.ametys.plugins.repository.AmetysRepositoryException; 042import org.ametys.plugins.repository.metadata.CompositeMetadata; 043import org.ametys.runtime.i18n.I18nizableText; 044 045/** 046 * Class to parse a metadata from an ODF content in Live version. 047 */ 048public class ODFContentFieldGenerator extends ServiceableGenerator 049{ 050 /** The source resolver */ 051 protected AmetysObjectResolver _resolver; 052 053 /** Metadata manager */ 054 protected MetadataManager _metadataManager; 055 056 /** Content type helper */ 057 protected ContentTypesHelper _contentTypesHelper; 058 059 @Override 060 public void service(ServiceManager serviceManager) throws ServiceException 061 { 062 super.service(serviceManager); 063 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 064 _metadataManager = (MetadataManager) serviceManager.lookup(MetadataManager.ROLE); 065 _contentTypesHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 066 } 067 068 @Override 069 public void generate() throws ProcessingException 070 { 071 Request request = ObjectModelHelper.getRequest(objectModel); 072 String contentId = request.getParameter("contentId"); 073 if (StringUtils.isEmpty(contentId)) 074 { 075 throw new ProcessingException("The content ID is empty."); 076 } 077 078 try 079 { 080 DefaultContent content = _resolver.resolveById(contentId); 081 082 // Is this an ODF content ? 083 if (!_contentTypesHelper.isInstanceOf(content, "org.ametys.plugins.odf.Content.odfContent")) 084 { 085 throw new ProcessingException(String.format("The content with the ID '%s' is not an ODF content.", contentId)); 086 } 087 088 // The content Have a Live version ? 089 String[] labels = content.getAllLabels(); 090 if (!ArrayUtils.contains(labels, ValidateODFContentFunction.VALID_LABEL)) 091 { 092 throw new ProcessingException(String.format("The content with the ID '%s' hasn't a Live version.", contentId)); 093 } 094 095 // Get the Live version to the content 096 content.switchToLabel(ValidateODFContentFunction.VALID_LABEL); 097 098 // Do we have a metadata name ? 099 String metadataName = request.getParameter("metadata"); 100 if (StringUtils.isEmpty(metadataName)) 101 { 102 throw new ProcessingException(String.format("No metadata has been transmitted for the content '%s'.", contentId)); 103 } 104 105 // The metadata exists ? 106 MetadataDefinition definition = _contentTypesHelper.getMetadataDefinitionByMetadataValuePath(metadataName, content); 107 if (definition == null) 108 { 109 throw new ProcessingException(String.format("There is no metadata named '%s' for the content '%s'.", metadataName, contentId)); 110 } 111 112 113 // Sax the metadata 114 contentHandler.startDocument(); 115 XMLUtils.startElement(contentHandler, "metadata"); 116 if (metadataName.contains("/")) 117 { 118 MetadataDefinition cmDefinition = _contentTypesHelper.getMetadataDefinitionByMetadataValuePath(StringUtils.substringBeforeLast(metadataName, "/"), content); 119 120 CompositeMetadata holder = content.getMetadataHolder(); 121 while (holder != null && metadataName.contains("/")) 122 { 123 String currentMetadataName = StringUtils.substringBefore(metadataName, "/"); 124 String entryName = _getEntryName(currentMetadataName); 125 currentMetadataName = StringUtils.substringBefore(currentMetadataName, "["); 126 holder = _getHolder(holder, currentMetadataName, entryName); 127 metadataName = StringUtils.substringAfter(metadataName, "/"); 128 } 129 130 MetadataSet metadataSet = new MetadataSet(); 131 metadataSet.setName("__generated__"); 132 metadataSet.setLabel(new I18nizableText("Metadataset for export")); 133 metadataSet.setDescription(new I18nizableText("Metadataset for export")); 134 metadataSet.setEdition(false); 135 metadataSet.setInternal(true); 136 metadataSet.addElement(new MetadataDefinitionReference(metadataName, "main")); 137 _metadataManager.saxMetadata(contentHandler, content, holder, metadataSet, cmDefinition, null, new HashSet<>()); 138 } 139 else 140 { 141 _metadataManager.saxMetadata(contentHandler, content, metadataName, null); 142 } 143 144 XMLUtils.endElement(contentHandler, "metadata"); 145 contentHandler.endDocument(); 146 } 147 catch (UnsupportedEncodingException e) 148 { 149 // Shouldn't happen 150 throw new ProcessingException("Impossible to decode the parameter.", e); 151 } 152 catch (AmetysRepositoryException e) 153 { 154 throw new ProcessingException(String.format("Unable to get the content with the ID '%s'.", contentId), e); 155 } 156 catch (SAXException e) 157 { 158 throw new ProcessingException("Error while saxing the document.", e); 159 } 160 catch (IOException e) 161 { 162 throw new ProcessingException(String.format("Error while saxing the content '%s' on the 'export' metadata set.", contentId), e); 163 } 164 } 165 166 private CompositeMetadata _getHolder(CompositeMetadata holder, String metadataName, String entryName) 167 { 168 if (!holder.hasMetadata(metadataName)) 169 { 170 return null; 171 } 172 173 CompositeMetadata cm = holder.getCompositeMetadata(metadataName); 174 175 if (StringUtils.isNotEmpty(entryName)) 176 { 177 if (!cm.hasMetadata(entryName)) 178 { 179 return null; 180 } 181 182 cm = cm.getCompositeMetadata(entryName); 183 } 184 185 return cm; 186 } 187 188 private String _getEntryName(String metadataName) 189 { 190 return StringUtils.substringBefore(StringUtils.substringAfter(metadataName, "["), "]"); 191 } 192}