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;
019
020import org.apache.avalon.framework.service.ServiceException;
021import org.apache.avalon.framework.service.ServiceManager;
022import org.apache.avalon.framework.service.Serviceable;
023import org.apache.cocoon.ProcessingException;
024import org.apache.cocoon.environment.ObjectModelHelper;
025import org.apache.cocoon.environment.Request;
026import org.apache.cocoon.generation.AbstractGenerator;
027import org.apache.cocoon.xml.AttributesImpl;
028import org.apache.cocoon.xml.XMLUtils;
029import org.apache.commons.lang3.ArrayUtils;
030import org.apache.commons.lang3.StringUtils;
031import org.xml.sax.SAXException;
032
033import org.ametys.cms.repository.Content;
034import org.ametys.plugins.repository.model.CompositeDefinition;
035import org.ametys.runtime.i18n.I18nizableText;
036import org.ametys.runtime.model.ElementDefinition;
037import org.ametys.runtime.model.ModelItem;
038import org.ametys.runtime.model.ModelViewItem;
039import org.ametys.runtime.model.View;
040import org.ametys.runtime.model.ViewItem;
041import org.ametys.runtime.model.ViewItemAccessor;
042import org.ametys.runtime.model.ViewItemGroup;
043import org.ametys.runtime.util.Labelable;
044
045/**
046 * Generates content type's definition.
047 */
048public class ContentTypeGenerator extends AbstractGenerator implements Serviceable
049{
050    private ContentTypesHelper _cTypeHelper;
051    private ContentTypeExtensionPoint _cTypeEP;
052    
053    public void service(ServiceManager manager) throws ServiceException
054    {
055        _cTypeHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE);
056        _cTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE);
057    }
058    
059    public void generate() throws IOException, SAXException, ProcessingException
060    {
061        Request request = ObjectModelHelper.getRequest(objectModel);
062        String cTypeId = parameters.getParameter("contentTypeId", null);
063        Content content = (Content) request.getAttribute(Content.class.getName());
064        
065        if (StringUtils.isBlank(cTypeId) && content == null)
066        {
067            throw new IllegalArgumentException("Missing content in request or content type id parameter. Cannot compute rendering from model.");
068        }
069        
070        String viewName = StringUtils.defaultIfBlank(parameters.getParameter("view", ""), "main");
071        
072        contentHandler.startDocument();
073        if (StringUtils.isNotBlank(cTypeId))
074        {
075            _saxViewFromContentType(cTypeId, viewName);
076        }
077        else
078        {
079            _saxViewFromContent(content, viewName);
080        }
081        contentHandler.endDocument();
082    }
083    
084    private void _saxViewFromContent(Content content, String viewName) throws SAXException
085    {
086        View view = _cTypeHelper.getView(viewName, content.getTypes(), content.getMixinTypes());
087        
088        AttributesImpl atts = new AttributesImpl();
089        atts.addCDATAAttribute("id", _cTypeHelper.getContentTypeIdForRendering(content));
090        atts.addCDATAAttribute("view", viewName);
091        XMLUtils.startElement(contentHandler, "contentType", atts);
092        
093        _saxNonNullI18nizableText(_cTypeHelper.getContentTypeLabel(content), "label");
094        _saxNonNullI18nizableText(_cTypeHelper.getContentTypeDescription(content), "description");
095        
096        _saxViewItemAccessor(view, null);
097        
098        XMLUtils.endElement(contentHandler, "contentType");
099    }
100    
101    private void _saxViewFromContentType(String cTypeId, String viewName) throws SAXException
102    {
103        View view = _cTypeHelper.getView(viewName, new String[] {cTypeId}, ArrayUtils.EMPTY_STRING_ARRAY);
104        
105        ContentType cType = _cTypeEP.getExtension(cTypeId);
106        AttributesImpl atts = new AttributesImpl();
107        atts.addCDATAAttribute("id", cTypeId);
108        atts.addCDATAAttribute("view", viewName);
109        XMLUtils.startElement(contentHandler, "contentType", atts);
110        
111        _saxNonNullI18nizableText(cType.getLabel(), "label");
112        _saxNonNullI18nizableText(cType.getDescription(), "description");
113        
114        _saxViewItemAccessor(view, null);
115        
116        XMLUtils.endElement(contentHandler, "contentType");
117    }
118    
119    private void _saxViewItemAccessor(ViewItemAccessor viewItemAccessor, String prefix) throws SAXException
120    {
121        for (ViewItem item : viewItemAccessor.getViewItems())
122        {
123            if (item instanceof ModelViewItem)
124            {
125                _saxModelViewItem((ModelViewItem) item, prefix);
126            }
127            else if (item instanceof ViewItemGroup)
128            {
129                _saxViewItemGroup((ViewItemGroup) item, prefix);
130            }
131        }
132    }
133    
134    private void _saxModelViewItem(ModelViewItem modelViewItem, String prefix) throws SAXException
135    {
136        ModelItem modelItem = modelViewItem.getDefinition();
137        String name = modelItem.getName();
138        
139        AttributesImpl atts = new AttributesImpl();
140        atts.addCDATAAttribute("name", name);
141        atts.addCDATAAttribute("path", prefix == null ? name : prefix + name);
142
143        if (modelItem instanceof ElementDefinition)
144        {
145            ElementDefinition definition = (ElementDefinition) modelItem;
146            
147            atts.addCDATAAttribute("type", definition.getType().getId());
148            atts.addCDATAAttribute("multiple", String.valueOf(definition.isMultiple()));
149        }
150        else if (modelItem instanceof CompositeDefinition)
151        {
152            atts.addCDATAAttribute("type", "composite");
153        }
154        else if (modelItem instanceof org.ametys.plugins.repository.model.RepeaterDefinition)
155        {
156            atts.addCDATAAttribute("type", "repeater");
157        }
158        
159        XMLUtils.startElement(contentHandler, "metadata", atts);
160
161        _saxNonNullI18nizableText(modelViewItem.getLabel(), "label");
162        _saxNonNullI18nizableText(modelViewItem.getDescription(), "description");
163        
164        if (modelViewItem instanceof ViewItemAccessor)
165        {
166            _saxViewItemAccessor((ViewItemAccessor) modelViewItem, prefix == null ? name  + "/" : prefix + name + "/");
167        }
168
169        XMLUtils.endElement(contentHandler, "metadata");
170    }
171    
172    private void _saxViewItemGroup(ViewItemGroup group, String prefix) throws SAXException
173    {
174        AttributesImpl atts = new AttributesImpl();
175        
176        if (group.getRole() != null)
177        {
178            atts.addCDATAAttribute("role", group.getRole());
179        }
180        if (group.getName() != null)
181        {
182            atts.addCDATAAttribute("name", group.getName());
183        }
184        
185        XMLUtils.startElement(contentHandler, "fieldset", atts);
186        
187        _saxNonNullI18nizableText(((Labelable) group).getLabel(), "label");
188        
189        _saxViewItemAccessor(group, prefix);
190        
191        XMLUtils.endElement(contentHandler, "fieldset");
192    }
193    
194    private void _saxNonNullI18nizableText(I18nizableText text, String tagName) throws SAXException
195    {
196        if (text != null)
197        {
198            text.toSAX(contentHandler, tagName);
199        }
200    }
201}