001/*
002 *  Copyright 2020 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.plugins.newsletter.content;
017
018import java.io.IOException;
019import java.util.Arrays;
020import java.util.Locale;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.xml.sax.ContentHandler;
025import org.xml.sax.SAXException;
026
027import org.ametys.cms.repository.Content;
028import org.ametys.cms.repository.ContentAttributeTypeExtensionPoint;
029import org.ametys.plugins.newsletter.NewsletterDAO;
030import org.ametys.plugins.repository.data.repositorydata.RepositoryData;
031import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
032import org.ametys.plugins.repository.data.type.RepositoryElementType;
033import org.ametys.plugins.repository.jcr.JCRAmetysObject;
034import org.ametys.runtime.model.View;
035import org.ametys.runtime.model.type.DataContext;
036import org.ametys.runtime.model.type.ModelItemTypeConstants;
037
038/**
039 * Generates SAX events for Content, including category, automatic and sent for Newsletters.
040 * TODO NEWATTRIBUTEAPI_CONTENT: do not use type implementation but the ModelAwareDataHolder#getInternalValue when this API exist
041 */
042public class ContentSaxer extends org.ametys.web.content.ContentSaxer
043{
044    /** Avalon role. */
045    public static final String NEWSLETTER_CONTENT_SAXER_ROLE = ContentSaxer.class.getName();
046    
047    private static final String __CATEGORY_METADATA_NAME = "category";
048    private static final String __CATEGORY_TAG_NAME = "category";
049    private static final String __AUTOMATIC_METADATA_NAME = "automatic";
050    private static final String __AUTOMATIC_TAG_NAME = "automatic";
051    private static final String __SENT_METADATA_NAME = "sent";
052    private static final String __SENT_TAG_NAME = "sent";
053    
054    // Content attribute types extension point
055    private ContentAttributeTypeExtensionPoint _contentAttributeTypeExtensionPoint;
056    
057    @Override
058    public void service(ServiceManager manager) throws ServiceException
059    {
060        super.service(manager);
061        _contentAttributeTypeExtensionPoint = (ContentAttributeTypeExtensionPoint) manager.lookup(ContentAttributeTypeExtensionPoint.ROLE);
062    }
063    
064    @Override
065    protected void saxBody(Content content, ContentHandler contentHandler, Locale locale, View view, String tagName, boolean saxWorkflowStep, boolean saxWorkflowInfo,
066            boolean saxLanguageInfo, String attributesTagName, boolean isEdition) throws SAXException
067    {
068        super.saxBody(content, contentHandler, locale, view, tagName, saxWorkflowStep, saxWorkflowInfo, saxLanguageInfo, attributesTagName, isEdition);
069        
070        if (Arrays.asList(content.getTypes()).contains(NewsletterDAO.__NEWSLETTER_CONTENT_TYPE))
071        {
072            saxCategory(content, contentHandler);
073            saxAutomatic(content, contentHandler);
074            saxSent(content, contentHandler);
075        }
076    }
077    
078    /**
079     * Generates SAX events for the newsletter's category.
080     * @param content the newsletter
081     * @param contentHandler the ContentHandler receiving SAX events.
082     * @throws SAXException if an error occurs during the SAX events generation.
083     */
084    @SuppressWarnings("unchecked")
085    protected void saxCategory(Content content, ContentHandler contentHandler) throws SAXException
086    {
087        try
088        {
089            if (content instanceof JCRAmetysObject)
090            {
091                RepositoryData contentRepositoryData = new JCRRepositoryData(((JCRAmetysObject) content).getNode());
092                RepositoryElementType<String> stringElementType = (RepositoryElementType<String>) _contentAttributeTypeExtensionPoint.getExtension(ModelItemTypeConstants.STRING_TYPE_ID);
093                
094                if (stringElementType.hasNonEmptyValue(contentRepositoryData, __CATEGORY_METADATA_NAME))
095                {
096                    Object category = stringElementType.read(contentRepositoryData, __CATEGORY_METADATA_NAME);
097                    stringElementType.valueToSAX(contentHandler, __CATEGORY_TAG_NAME, category, DataContext.newInstance());
098                }
099            }
100        }
101        catch (IOException e)
102        {
103            throw new RuntimeException(e);
104        }
105    }
106    
107    /**
108     * Generates SAX events for the newsletter's automatic status.
109     * @param content the newsletter
110     * @param contentHandler the ContentHandler receiving SAX events.
111     * @throws SAXException if an error occurs during the SAX events generation.
112     */
113    @SuppressWarnings("unchecked")
114    protected void saxAutomatic(Content content, ContentHandler contentHandler) throws SAXException
115    {
116        try
117        {
118            if (content instanceof JCRAmetysObject)
119            {
120                RepositoryData contentRepositoryData = new JCRRepositoryData(((JCRAmetysObject) content).getNode());
121                RepositoryElementType<String> stringElementType = (RepositoryElementType<String>) _contentAttributeTypeExtensionPoint.getExtension(ModelItemTypeConstants.STRING_TYPE_ID);
122                RepositoryElementType<Boolean> booleanElementType = (RepositoryElementType<Boolean>) _contentAttributeTypeExtensionPoint.getExtension(ModelItemTypeConstants.BOOLEAN_TYPE_ID);
123                
124                // The boolean is sometimes stored as a String :/
125                if (contentRepositoryData.hasValue(__AUTOMATIC_METADATA_NAME))
126                {
127                    RepositoryElementType type = booleanElementType.isCompatible(contentRepositoryData, __AUTOMATIC_METADATA_NAME) ? booleanElementType : stringElementType;
128                    
129                    if (type.hasNonEmptyValue(contentRepositoryData, __AUTOMATIC_METADATA_NAME))
130                    {
131                        Object automatic = type.read(contentRepositoryData, __AUTOMATIC_METADATA_NAME);
132                        if (automatic instanceof String)
133                        {
134                            automatic = Boolean.valueOf((String) automatic);
135                        }
136                        booleanElementType.valueToSAX(contentHandler, __AUTOMATIC_TAG_NAME, automatic, DataContext.newInstance());
137                    }
138                }
139            }
140        }
141        catch (IOException e)
142        {
143            throw new RuntimeException(e);
144        }
145    }
146    
147    /**
148     * Generates SAX events for the newsletter's sent status.
149     * @param content the newsletter
150     * @param contentHandler the ContentHandler receiving SAX events.
151     * @throws SAXException if an error occurs during the SAX events generation.
152     */
153    @SuppressWarnings("unchecked")
154    protected void saxSent(Content content, ContentHandler contentHandler) throws SAXException
155    {
156        try
157        {
158            if (content instanceof JCRAmetysObject)
159            {
160                RepositoryData contentRepositoryData = new JCRRepositoryData(((JCRAmetysObject) content).getNode());
161                RepositoryElementType<Boolean> booleanElementType = (RepositoryElementType<Boolean>) _contentAttributeTypeExtensionPoint.getExtension(ModelItemTypeConstants.BOOLEAN_TYPE_ID);
162                
163                if (booleanElementType.hasNonEmptyValue(contentRepositoryData, __SENT_METADATA_NAME))
164                {
165                    Object sent = booleanElementType.read(contentRepositoryData, __SENT_METADATA_NAME);
166                    booleanElementType.valueToSAX(contentHandler, __SENT_TAG_NAME, sent, DataContext.newInstance());
167                }
168            }
169        }
170        catch (IOException e)
171        {
172            throw new RuntimeException(e);
173        }
174    }
175}