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.cms.contenttype; 017 018import java.io.IOException; 019import java.util.Map; 020 021import org.apache.avalon.framework.parameters.Parameters; 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.avalon.framework.service.Serviceable; 025import org.apache.cocoon.ProcessingException; 026import org.apache.cocoon.environment.ObjectModelHelper; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.environment.SourceResolver; 029import org.apache.cocoon.generation.AbstractGenerator; 030import org.apache.cocoon.xml.AttributesImpl; 031import org.apache.cocoon.xml.XMLUtils; 032import org.apache.commons.lang3.ArrayUtils; 033import org.xml.sax.SAXException; 034 035import org.ametys.cms.repository.Content; 036import org.ametys.runtime.i18n.I18nizableText; 037 038/** 039 * Generates content type's definition. 040 */ 041public class ContentTypeGenerator extends AbstractGenerator implements Serviceable 042{ 043 private ContentTypeExtensionPoint _cTypeEp; 044 private ContentTypesHelper _cTypeHelper; 045 046 public void service(ServiceManager manager) throws ServiceException 047 { 048 _cTypeEp = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE); 049 _cTypeHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 050 } 051 052 @Override 053 public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par) throws ProcessingException, SAXException, IOException 054 { 055 super.setup(resolver, objectModel, src, par); 056 } 057 058 public void generate() throws IOException, SAXException, ProcessingException 059 { 060 Request request = ObjectModelHelper.getRequest(objectModel); 061 Content content = (Content) request.getAttribute(Content.class.getName()); 062 063 if (content == null) 064 { 065 throw new IllegalArgumentException("Content not present in request. Cannot compute rendering from model."); 066 } 067 068 String viewName = parameters.getParameter("metadataSet", "main"); 069 070 // TODO NEWATTRIBUTEAPI_CONTENT: Use the new API method (cTypeHelper.getView()) when the API is ready 071// View view = _cTypeHelper.getView(viewName, content.getTypes(), content.getMixinTypes()); 072 MetadataSet metadataSet = _cTypeHelper.getMetadataSetForView(viewName, content.getTypes(), content.getMixinTypes()); 073 074 contentHandler.startDocument(); 075 076 AttributesImpl atts = new AttributesImpl(); 077 atts.addCDATAAttribute("id", _cTypeHelper.getContentTypeIdForRendering(content)); 078 atts.addCDATAAttribute("metadataSet", viewName); 079 XMLUtils.startElement(contentHandler, "contentType", atts); 080 081 I18nizableText label = _cTypeHelper.getContentTypeLabel(content); 082 if (label != null) 083 { 084 XMLUtils.startElement(contentHandler, "label"); 085 label.toSAX(contentHandler); 086 XMLUtils.endElement(contentHandler, "label"); 087 } 088 089 I18nizableText description = _cTypeHelper.getContentTypeDescription(content); 090 if (description != null) 091 { 092 XMLUtils.startElement(contentHandler, "description"); 093 description.toSAX(contentHandler); 094 XMLUtils.endElement(contentHandler, "description"); 095 } 096 097 // TODO NEWATTRIBUTEAPI_CONTENT: Use the new API method (_saxView()) when the API is ready 098// _saxView(view, null); 099 if (metadataSet != null) 100 { 101 _saxMetadataSetElement(metadataSet, null, content.getTypes(), content.getMixinTypes()); 102 } 103 104 XMLUtils.endElement(contentHandler, "contentType"); 105 contentHandler.endDocument(); 106 } 107 108 // TODO NEWATTRIBUTEAPI_CONTENT: Look what is wrong in this new API method 109// private void _saxView(ViewItemContainer view, String prefix) throws SAXException 110// { 111// for (ViewItem item : view.getViewItems()) 112// { 113// if (item instanceof ModelViewItem) 114// { 115// ModelViewItem modelViewItem = (ModelViewItem) item; 116// ModelItem modelItem = modelViewItem.getDefinition(); 117// String name = modelItem.getName(); 118// 119// AttributesImpl atts = new AttributesImpl(); 120// atts.addCDATAAttribute("name", name); 121// atts.addCDATAAttribute("path", prefix == null ? name : prefix + name); 122// 123// if (modelItem instanceof ElementDefinition) 124// { 125// ElementDefinition definition = (ElementDefinition) modelItem; 126// 127// atts.addCDATAAttribute("type", definition.getType().getId()); 128// atts.addCDATAAttribute("multiple", String.valueOf(definition.isMultiple())); 129// } 130// else if (modelItem instanceof CompositeDefinition) 131// { 132// atts.addCDATAAttribute("type", "composite"); 133// } 134// else if (modelItem instanceof org.ametys.plugins.repository.model.RepeaterDefinition) 135// { 136// atts.addCDATAAttribute("type", "repeater"); 137// } 138// 139// XMLUtils.startElement(contentHandler, "metadata", atts); 140// 141// I18nizableText label = modelItem.getLabel(); 142// if (label != null) 143// { 144// XMLUtils.startElement(contentHandler, "label"); 145// label.toSAX(contentHandler); 146// XMLUtils.endElement(contentHandler, "label"); 147// } 148// 149// I18nizableText description = modelItem.getDescription(); 150// if (description != null) 151// { 152// XMLUtils.startElement(contentHandler, "description"); 153// description.toSAX(contentHandler); 154// XMLUtils.endElement(contentHandler, "description"); 155// } 156// 157// if (item instanceof ViewItemContainer) 158// { 159// _saxView((ViewItemContainer) item, prefix == null ? name + "/" : prefix + name + "/"); 160// } 161// 162// XMLUtils.endElement(contentHandler, "metadata"); 163// } 164// else if (item instanceof ViewItemGroup) 165// { 166// ViewItemGroup group = (ViewItemGroup) item; 167// AttributesImpl atts = new AttributesImpl(); 168// 169// if (group.getRole() != null) 170// { 171// atts.addCDATAAttribute("role", group.getRole()); 172// } 173// 174// XMLUtils.startElement(contentHandler, "fieldset", atts); 175// 176// if (item instanceof Labelable) 177// { 178// I18nizableText label = ((Labelable) item).getLabel(); 179// if (label != null) 180// { 181// XMLUtils.startElement(contentHandler, "label"); 182// label.toSAX(contentHandler); 183// XMLUtils.endElement(contentHandler, "label"); 184// } 185// } 186// 187// _saxView(group, prefix); 188// 189// XMLUtils.endElement(contentHandler, "fieldset"); 190// } 191// } 192// } 193 194 private void _saxMetadataSetElement(AbstractMetadataSetElement container, String prefix, String[] contentTypes, String[] mixinTypes) throws SAXException 195 { 196 for (AbstractMetadataSetElement element : container.getElements()) 197 { 198 if (element instanceof Fieldset) 199 { 200 AttributesImpl atts = new AttributesImpl(); 201 202 if (((Fieldset) element).getRole() != null) 203 { 204 atts.addCDATAAttribute("role", ((Fieldset) element).getRole()); 205 } 206 207 XMLUtils.startElement(contentHandler, "fieldset", atts); 208 209 I18nizableText label = ((Fieldset) element).getLabel(); 210 if (label != null) 211 { 212 XMLUtils.startElement(contentHandler, "label"); 213 label.toSAX(contentHandler); 214 XMLUtils.endElement(contentHandler, "label"); 215 } 216 217 _saxMetadataSetElement(element, prefix, contentTypes, mixinTypes); 218 219 XMLUtils.endElement(contentHandler, "fieldset"); 220 } 221 else if (element instanceof MetadataDefinitionReference) 222 { 223 MetadataDefinitionReference metadataDefRef = (MetadataDefinitionReference) element; 224 String metadataName = metadataDefRef.getMetadataName(); 225// MetadataDefinition metadataDefinition = contentType.getMetadataDefinitionByPath(prefix == null ? metadataName : prefix + metadataName); 226 MetadataDefinition metadataDefinition = _getDefinition(prefix == null ? metadataName : prefix + metadataName, contentTypes, mixinTypes); 227 MetadataType metadataType = metadataDefinition.getType(); 228 String type = (metadataType == MetadataType.COMPOSITE && metadataDefinition instanceof RepeaterDefinition) ? "repeater" : metadataType.toString().toLowerCase(); 229 230 AttributesImpl atts = new AttributesImpl(); 231 atts.addCDATAAttribute("name", metadataName); 232 atts.addCDATAAttribute("path", prefix == null ? metadataName : prefix + metadataName); 233 atts.addCDATAAttribute("type", type); 234 atts.addCDATAAttribute("multiple", String.valueOf(metadataDefinition.isMultiple())); 235 XMLUtils.startElement(contentHandler, "metadata", atts); 236 237 I18nizableText label = metadataDefinition.getLabel(); 238 if (label != null) 239 { 240 XMLUtils.startElement(contentHandler, "label"); 241 label.toSAX(contentHandler); 242 XMLUtils.endElement(contentHandler, "label"); 243 } 244 245 I18nizableText description = metadataDefinition.getDescription(); 246 if (description != null) 247 { 248 XMLUtils.startElement(contentHandler, "description"); 249 description.toSAX(contentHandler); 250 XMLUtils.endElement(contentHandler, "description"); 251 } 252 253 switch (metadataType) 254 { 255 case COMPOSITE: 256 _saxMetadataSetElement(element, prefix == null ? metadataName + "/" : prefix + metadataName + "/", contentTypes, mixinTypes); 257 break; 258 default: 259 break; 260 } 261 262 XMLUtils.endElement(contentHandler, "metadata"); 263 } 264 else 265 { 266 throw new IllegalArgumentException("A metadataSet may only contain Fieldset and MetadataDefinitionReference"); 267 } 268 } 269 } 270 271 private MetadataDefinition _getDefinition(String path, String[] contentTypes, String[] mixins) 272 { 273 String[] allContentTypes = ArrayUtils.addAll(contentTypes, mixins); 274 275 for (String cTypeId : allContentTypes) 276 { 277 ContentType cType = _cTypeEp.getExtension(cTypeId); 278 MetadataDefinition definition = cType.getMetadataDefinitionByPath(path); 279 if (definition != null) 280 { 281 return definition; 282 } 283 } 284 285 throw new IllegalArgumentException("Unknown metadata " + path); 286 } 287}