001/*
002 *  Copyright 2014 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.enumeration;
017
018import java.io.IOException;
019import java.util.Map;
020
021import org.apache.avalon.framework.service.ServiceException;
022import org.apache.avalon.framework.service.ServiceManager;
023import org.apache.cocoon.ProcessingException;
024import org.apache.cocoon.generation.ServiceableGenerator;
025import org.apache.cocoon.xml.AttributesImpl;
026import org.apache.cocoon.xml.XMLUtils;
027import org.apache.commons.lang3.StringUtils;
028import org.xml.sax.SAXException;
029
030import org.ametys.cms.contenttype.ContentAttributeDefinition;
031import org.ametys.cms.contenttype.ContentType;
032import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
033import org.ametys.cms.repository.Content;
034import org.ametys.cms.repository.ContentQueryHelper;
035import org.ametys.cms.repository.ContentTypeExpression;
036import org.ametys.odf.program.ProgramFactory;
037import org.ametys.plugins.repository.AmetysObjectIterable;
038import org.ametys.plugins.repository.AmetysObjectResolver;
039import org.ametys.plugins.repository.query.expression.Expression.Operator;
040import org.ametys.runtime.i18n.I18nizableText;
041import org.ametys.runtime.model.ElementDefinition;
042import org.ametys.runtime.model.Enumerator;
043import org.ametys.runtime.model.ModelItem;
044
045/**
046 * Generate the values of an enumerated attribute of the program content type.
047 */
048public class EnumeratedAttributeValuesGenerator extends ServiceableGenerator
049{
050    /** The name of the parameter containing the path of the enumerated attribute */
051    protected static final String ATTRIBUTE_PATH_PARAMETER_NAME = "attributePath";
052    
053    /** The content type extension point. */
054    protected ContentTypeExtensionPoint _cTypeEP;
055    /** The ODf enumeration helper */
056    protected OdfReferenceTableHelper _odfRefTableHelper;
057    /** The Ametys resolver */
058    protected AmetysObjectResolver _resolver;
059    
060    @Override
061    public void service(ServiceManager serviceManager) throws ServiceException
062    {
063        super.service(serviceManager);
064        _cTypeEP = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE);
065        _odfRefTableHelper = (OdfReferenceTableHelper) serviceManager.lookup(OdfReferenceTableHelper.ROLE);
066        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
067    }
068    
069    @Override
070    public void generate() throws IOException, SAXException, ProcessingException
071    {
072        ContentType programCType = _cTypeEP.getExtension(ProgramFactory.PROGRAM_CONTENT_TYPE);
073        
074        String attributePath = parameters.getParameter(ATTRIBUTE_PATH_PARAMETER_NAME, StringUtils.EMPTY);
075        
076        contentHandler.startDocument();
077        
078        try
079        {
080            ElementDefinition elementDefinition = _getElementDefinition(programCType, attributePath);
081            if (elementDefinition != null)
082            {
083                Enumerator enumerator = elementDefinition.getEnumerator();
084                if (enumerator != null)
085                {
086                    AttributesImpl attrs = new AttributesImpl();
087                    attrs.addCDATAAttribute("metadataName", elementDefinition.getName());
088                    attrs.addCDATAAttribute("metadataPath", elementDefinition.getPath());
089                    XMLUtils.startElement(contentHandler, "items", attrs);
090                    
091                    Map<Object, I18nizableText> entries = enumerator.getTypedEntries();
092                    for (Object code : entries.keySet())
093                    {
094                        String codeStr = code.toString();
095                        if (StringUtils.isNotEmpty(codeStr))
096                        {
097                            I18nizableText value = entries.get(code);
098                            
099                            AttributesImpl valueAttrs = new AttributesImpl();
100                            valueAttrs.addCDATAAttribute("code", codeStr);
101                            
102                            XMLUtils.startElement(contentHandler, "item", valueAttrs);
103                            value.toSAX(contentHandler);
104                            XMLUtils.endElement(contentHandler, "item");
105                        }
106                    }
107                    
108                    XMLUtils.endElement(contentHandler, "items");
109                }
110                else if (elementDefinition instanceof ContentAttributeDefinition)
111                {
112                    ContentAttributeDefinition contentAttributeDefinition = (ContentAttributeDefinition) elementDefinition;
113                    if (_odfRefTableHelper.isTableReference(contentAttributeDefinition.getContentTypeId()))
114                    {
115                        String lang = parameters.getParameter("lang", null);
116                        
117                        _odfRefTableHelper.saxItems(contentHandler, contentAttributeDefinition, lang);
118                    }
119                    else if (StringUtils.isNotEmpty(contentAttributeDefinition.getContentTypeId()))
120                    {
121                        _saxContents(contentAttributeDefinition);
122                    }
123                }
124            }
125            else
126            {
127                // no attribute definition found or no attribute path has been defined
128                XMLUtils.startElement(contentHandler, "items");
129                XMLUtils.endElement(contentHandler, "items");
130            }
131            
132        }
133        catch (Exception e)
134        {
135            throw new ProcessingException("Error retrieving the values of metadata '" + attributePath + "'", e);
136        }
137        
138        contentHandler.endDocument();
139    }
140    
141    /**
142     * Get the element definition from its path.
143     * @param cType the content type.
144     * @param attributePath the attribute path.
145     * @return the element definition or null if not found.
146     */
147    protected ElementDefinition _getElementDefinition(ContentType cType, String attributePath)
148    {
149        if (StringUtils.isNotEmpty(attributePath))
150        {
151            if (cType.hasModelItem(attributePath))
152            {
153                ModelItem modelItem = cType.getModelItem(attributePath);
154                if (modelItem instanceof ElementDefinition)
155                {
156                    return (ElementDefinition) modelItem;
157                }
158                else
159                {
160                    getLogger().warn("The attribute path '" + attributePath + "' does refers an element definition");
161                }
162            }
163            else
164            {
165                getLogger().warn("There is no attribute defined at path '" + attributePath + "' for content type '" + cType.getId() + "'.");
166            }
167            
168        }
169        
170        // no attribute definition found or no attribute path has been defined
171        return null;
172    }
173    
174    /**
175     * SAX contents of the type defined by the attribute definition
176     * @param attributeDefinition The attribute definition 
177     * @throws SAXException if an error occurred while saxing
178     */
179    protected void _saxContents(ContentAttributeDefinition attributeDefinition) throws SAXException
180    {
181        AttributesImpl attrs = new AttributesImpl();
182        attrs.addCDATAAttribute("metadataName", attributeDefinition.getName());
183        attrs.addCDATAAttribute("metadataPath", attributeDefinition.getPath());
184        attrs.addCDATAAttribute("contentTypeId", attributeDefinition.getContentTypeId());
185        XMLUtils.startElement(contentHandler, "items", attrs);
186        
187        ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, attributeDefinition.getContentTypeId());
188        
189        String xpathQuery = ContentQueryHelper.getContentXPathQuery(cTypeExpr);
190        AmetysObjectIterable<Content> contents = _resolver.query(xpathQuery);
191        
192        for (Content content : contents)
193        {
194            AttributesImpl valueAttrs = new AttributesImpl();
195            valueAttrs.addCDATAAttribute("id", content.getId());
196            XMLUtils.createElement(contentHandler, "item", valueAttrs, content.getTitle());
197        }
198        
199        XMLUtils.endElement(contentHandler, "items");
200    }
201    
202}