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.lang.StringUtils;
028import org.xml.sax.SAXException;
029
030import org.ametys.cms.contenttype.ContentType;
031import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
032import org.ametys.cms.contenttype.MetadataDefinition;
033import org.ametys.cms.contenttype.MetadataType;
034import org.ametys.cms.repository.Content;
035import org.ametys.cms.repository.ContentQueryHelper;
036import org.ametys.cms.repository.ContentTypeExpression;
037import org.ametys.odf.program.ProgramFactory;
038import org.ametys.plugins.repository.AmetysObjectIterable;
039import org.ametys.plugins.repository.AmetysObjectResolver;
040import org.ametys.plugins.repository.query.expression.Expression.Operator;
041import org.ametys.runtime.i18n.I18nizableText;
042import org.ametys.runtime.parameter.Enumerator;
043
044/**
045 * Generate the values of an enumerated metadata of the program content type.
046 */
047public class EnumeratedMetadataValuesGenerator extends ServiceableGenerator
048{
049    /** The content type extension point. */
050    protected ContentTypeExtensionPoint _cTypeEP;
051    /** The ODf enumeration helper */
052    protected OdfReferenceTableHelper _odfRefTableHelper;
053    /** The Ametys resolver */
054    protected AmetysObjectResolver _resolver;
055    
056    @Override
057    public void service(ServiceManager serviceManager) throws ServiceException
058    {
059        super.service(serviceManager);
060        _cTypeEP = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE);
061        _odfRefTableHelper = (OdfReferenceTableHelper) serviceManager.lookup(OdfReferenceTableHelper.ROLE);
062        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
063    }
064    
065    @Override
066    public void generate() throws IOException, SAXException, ProcessingException
067    {
068        ContentType programCType = _cTypeEP.getExtension(ProgramFactory.PROGRAM_CONTENT_TYPE);
069        
070        String metadataPath = parameters.getParameter("metadataPath", "");
071        
072        contentHandler.startDocument();
073        
074        try
075        {
076            MetadataDefinition metaDef = _getMetadataDefinition(programCType, metadataPath);
077            if (metaDef != null)
078            {
079                Enumerator enumerator = metaDef.getEnumerator();
080                if (enumerator != null)
081                {
082                    AttributesImpl attrs = new AttributesImpl();
083                    attrs.addCDATAAttribute("metadataName", metaDef.getName());
084                    attrs.addCDATAAttribute("metadataPath", metaDef.getId().substring(1));
085                    XMLUtils.startElement(contentHandler, "items", attrs);
086                    
087                    Map<Object, I18nizableText> entries = enumerator.getEntries();
088                    for (Object code : entries.keySet())
089                    {
090                        String codeStr = code.toString();
091                        if (StringUtils.isNotEmpty(codeStr))
092                        {
093                            I18nizableText value = entries.get(code);
094                            
095                            AttributesImpl valueAttrs = new AttributesImpl();
096                            valueAttrs.addCDATAAttribute("code", codeStr);
097                            
098                            XMLUtils.startElement(contentHandler, "item", valueAttrs);
099                            value.toSAX(contentHandler);
100                            XMLUtils.endElement(contentHandler, "item");
101                        }
102                    }
103                    
104                    XMLUtils.endElement(contentHandler, "items");
105                }
106                else if (metaDef.getType() == MetadataType.CONTENT)
107                {
108                    if (_odfRefTableHelper.isTableReference(metaDef.getContentType()))
109                    {
110                        _odfRefTableHelper.saxItems(contentHandler, metaDef);
111                    }
112                    else if (StringUtils.isNotEmpty(metaDef.getContentType()))
113                    {
114                        _saxContents(metaDef);
115                    }
116                }
117            }
118            else
119            {
120                // no metadata definition found or no metadata path has been defined
121                XMLUtils.startElement(contentHandler, "items");
122                XMLUtils.endElement(contentHandler, "items");
123            }
124            
125        }
126        catch (Exception e)
127        {
128            throw new ProcessingException("Error retrieving the values of metadata '" + metadataPath + "'", e);
129        }
130        
131        contentHandler.endDocument();
132    }
133    
134    /**
135     * SAX contents of the type defined by the metadata definition
136     * @param metaDef The metadata definition 
137     * @throws SAXException if an error occurred while saxing
138     */
139    protected void _saxContents(MetadataDefinition metaDef) throws SAXException
140    {
141        AttributesImpl attrs = new AttributesImpl();
142        attrs.addCDATAAttribute("metadataName", metaDef.getName());
143        attrs.addCDATAAttribute("metadataPath", metaDef.getId());
144        attrs.addCDATAAttribute("contentTypeId", metaDef.getContentType());
145        XMLUtils.startElement(contentHandler, "items", attrs);
146        
147        ContentTypeExpression cTypeExpr = new ContentTypeExpression(Operator.EQ, metaDef.getContentType());
148        
149        String xpathQuery = ContentQueryHelper.getContentXPathQuery(cTypeExpr);
150        AmetysObjectIterable<Content> contents = _resolver.query(xpathQuery);
151        
152        for (Content content : contents)
153        {
154            AttributesImpl valueAttrs = new AttributesImpl();
155            valueAttrs.addCDATAAttribute("id", content.getId());
156            XMLUtils.createElement(contentHandler, "item", valueAttrs, content.getTitle());
157        }
158        
159        XMLUtils.endElement(contentHandler, "items");
160    }
161    
162    
163    /**
164     * Get a metadata definition from its path.
165     * @param contentType the content type.
166     * @param metadataPath the metadata path.
167     * @return the metadata definition or null if not found.
168     */
169    protected MetadataDefinition _getMetadataDefinition(ContentType contentType, String metadataPath)
170    {
171        String[] pathSegments = StringUtils.split(metadataPath, '/');
172        
173        if (pathSegments.length == 0)
174        {
175            return null;
176        }
177        
178        MetadataDefinition metadataDef = contentType.getMetadataDefinition(pathSegments[0]);
179
180        for (int i = 1;  i < pathSegments.length && metadataDef != null; i++)
181        {
182            metadataDef = metadataDef.getMetadataDefinition(pathSegments[i]);
183        }
184
185        return metadataDef;
186    }
187    
188}