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                        _odfRefTableHelper.saxItems(contentHandler, contentAttributeDefinition);
116                    }
117                    else if (StringUtils.isNotEmpty(contentAttributeDefinition.getContentTypeId()))
118                    {
119                        _saxContents(contentAttributeDefinition);
120                    }
121                }
122            }
123            else
124            {
125                // no attribute definition found or no attribute path has been defined
126                XMLUtils.startElement(contentHandler, "items");
127                XMLUtils.endElement(contentHandler, "items");
128            }
129            
130        }
131        catch (Exception e)
132        {
133            throw new ProcessingException("Error retrieving the values of metadata '" + attributePath + "'", e);
134        }
135        
136        contentHandler.endDocument();
137    }
138    
139    /**
140     * Get the element definition from its path.
141     * @param cType the content type.
142     * @param attributePath the attribute path.
143     * @return the element definition or null if not found.
144     */
145    protected ElementDefinition _getElementDefinition(ContentType cType, String attributePath)
146    {
147        if (StringUtils.isNotEmpty(attributePath))
148        {
149            if (cType.hasModelItem(attributePath))
150            {
151                ModelItem modelItem = cType.getModelItem(attributePath);
152                if (modelItem instanceof ElementDefinition)
153                {
154                    return (ElementDefinition) modelItem;
155                }
156                else
157                {
158                    getLogger().warn("The attribute path '" + attributePath + "' does refers an element definition");
159                }
160            }
161            else
162            {
163                getLogger().warn("There is no attribute defined at path '" + attributePath + "' for content type '" + cType.getId() + "'.");
164            }
165            
166        }
167        
168        // no attribute definition found or no attribute path has been defined
169        return null;
170    }
171    
172    /**
173     * SAX contents of the type defined by the attribute definition
174     * @param attributeDefinition The attribute definition 
175     * @throws SAXException if an error occurred while saxing
176     */
177    protected void _saxContents(ContentAttributeDefinition attributeDefinition) throws SAXException
178    {
179        AttributesImpl attrs = new AttributesImpl();
180        attrs.addCDATAAttribute("metadataName", attributeDefinition.getName());
181        attrs.addCDATAAttribute("metadataPath", attributeDefinition.getPath());
182        attrs.addCDATAAttribute("contentTypeId", attributeDefinition.getContentTypeId());
183        XMLUtils.startElement(contentHandler, "items", attrs);
184        
185        ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, attributeDefinition.getContentTypeId());
186        
187        String xpathQuery = ContentQueryHelper.getContentXPathQuery(cTypeExpr);
188        AmetysObjectIterable<Content> contents = _resolver.query(xpathQuery);
189        
190        for (Content content : contents)
191        {
192            AttributesImpl valueAttrs = new AttributesImpl();
193            valueAttrs.addCDATAAttribute("id", content.getId());
194            XMLUtils.createElement(contentHandler, "item", valueAttrs, content.getTitle());
195        }
196        
197        XMLUtils.endElement(contentHandler, "items");
198    }
199    
200}