001/*
002 *  Copyright 2012 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.core.ui;
017
018import java.util.List;
019import java.util.Locale;
020import java.util.Map;
021import java.util.Map.Entry;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.context.Context;
025import org.apache.avalon.framework.context.ContextException;
026import org.apache.avalon.framework.context.Contextualizable;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.avalon.framework.service.Serviceable;
030import org.apache.avalon.framework.thread.ThreadSafe;
031import org.apache.cocoon.components.ContextHelper;
032import org.apache.cocoon.xml.AttributesImpl;
033import org.apache.cocoon.xml.XMLUtils;
034import org.apache.commons.lang3.StringUtils;
035import org.xml.sax.ContentHandler;
036import org.xml.sax.SAXException;
037
038import org.ametys.core.ui.ClientSideElement.Script;
039import org.ametys.core.ui.ClientSideElement.ScriptFile;
040import org.ametys.core.util.JSONUtils;
041import org.ametys.plugins.core.ui.help.HelpManager;
042import org.ametys.runtime.plugin.component.AbstractLogEnabled;
043
044/**
045 * This helper allow to sax a client side element
046 */
047public class SAXClientSideElementHelper extends AbstractLogEnabled implements Contextualizable, Component, Serviceable, ThreadSafe
048{
049    /** Avalon role */
050    public static final String ROLE = SAXClientSideElementHelper.class.getName();
051    /** The avalon context */
052    protected Context _context;
053    
054    private JSONUtils _jsonUtils;
055    private HelpManager _helpManager;
056
057    @Override
058    public void service(ServiceManager smanager) throws ServiceException
059    {
060        _jsonUtils = (JSONUtils) smanager.lookup(JSONUtils.ROLE);
061        _helpManager = (HelpManager) smanager.lookup(HelpManager.ROLE);
062    }
063    
064    @Override
065    public void contextualize(Context context) throws ContextException
066    {
067        _context = context;
068    }
069    /**
070     * SAX a client side element
071     * @param tagName the tag name to create
072     * @param element The client side element to sax. Can not be null.
073     * @param extensionPoint the extension point of the element. 
074     * @param handler The handler where to sax
075     * @param contextualParameters Contextuals parameters transmitted by the environment.
076     * @return true if effectively saxed something, false otherwise (rights ko for example)
077     * @throws SAXException If an error occured
078     */
079    public boolean saxDefinition(String tagName, ClientSideElement element, String extensionPoint, ContentHandler handler, Map<String, Object> contextualParameters) throws SAXException
080    {
081        try
082        {
083            List<Script> scripts = element.getScripts(contextualParameters);
084            Map objectModel = ContextHelper.getObjectModel(_context);
085            
086            Locale locale = org.apache.cocoon.i18n.I18nUtils.findLocale(objectModel, "locale", null, Locale.getDefault(), true);
087            String langCode = locale.getLanguage();
088            
089            for (Script script : scripts)
090            {
091                AttributesImpl clientSideElementAttrs = new AttributesImpl();
092                String scriptId = script.getId();
093                try
094                {
095                    String help = _helpManager.getHelp(extensionPoint, scriptId, langCode);
096                    if (StringUtils.isNotBlank(help))
097                    {
098                        clientSideElementAttrs.addCDATAAttribute("help", help);
099                    }
100                }
101                catch (Exception e)
102                {
103                    getLogger().warn("Error while getting help url for extion point : '{}' for id : '{}'", extensionPoint, scriptId, e);
104                }
105                clientSideElementAttrs.addCDATAAttribute("id", scriptId);
106                clientSideElementAttrs.addCDATAAttribute("serverId", script.getServerId());
107                clientSideElementAttrs.addCDATAAttribute("plugin", element.getPluginName());
108                XMLUtils.startElement(handler, tagName, clientSideElementAttrs);
109                
110                // Initial parameters
111                Map<String, Object> parameters = script.getParameters();
112                
113                // SAX Action (classname and initial parameters)
114                AttributesImpl attrs = new AttributesImpl();
115                attrs.addCDATAAttribute("class", script.getScriptClassname());
116                XMLUtils.createElement(handler, "action", attrs, _jsonUtils.convertObjectToJson(parameters));
117                
118                // SAX Scripts
119                XMLUtils.startElement(handler, "scripts");
120                for (ScriptFile scriptFile : script.getScriptFiles())
121                {
122                    saxScriptFile(handler, scriptFile);
123                }
124                XMLUtils.endElement(handler, "scripts");
125        
126                // SAX CSS
127                XMLUtils.startElement(handler, "css");
128                for (ScriptFile scriptFile : script.getCSSFiles())
129                {
130                    saxScriptFile(handler, scriptFile);
131                }
132                XMLUtils.endElement(handler, "css");
133        
134                XMLUtils.endElement(handler, tagName);
135            }
136            
137            return !scripts.isEmpty();
138        }
139        catch (Exception e)
140        {
141            throw new SAXException("An error occurred while saxing '" + extensionPoint + "#" + element.getPluginName() + "/" + element.getId() + "'", e);
142        }
143    }
144    
145    private void saxScriptFile(ContentHandler handler, ScriptFile scriptFile) throws SAXException
146    {
147        AttributesImpl fileAttrs = new AttributesImpl();
148        if (!scriptFile.isLangSpecific())
149        {
150            String rtlMode = scriptFile.getRtlMode();
151            if (rtlMode != null && !"all".equals(rtlMode))
152            {
153                fileAttrs.addCDATAAttribute("rtl", rtlMode);
154            }
155            
156            XMLUtils.createElement(handler, "file", fileAttrs, scriptFile.getPath());
157        }
158        else
159        {
160            fileAttrs.addCDATAAttribute("lang", "true");
161            XMLUtils.startElement(handler, "file", fileAttrs);
162            
163            String defaultLang = scriptFile.getDefaultLang();
164            Map<String, String> langPaths = scriptFile.getLangPaths();
165            
166            for (Entry<String, String> langPath : langPaths.entrySet())
167            {
168                AttributesImpl langAttrs = new AttributesImpl();
169                
170                String codeLang = langPath.getKey();
171                langAttrs.addCDATAAttribute("code", codeLang);
172                if (codeLang.equals(defaultLang))
173                {
174                    langAttrs.addCDATAAttribute("default", "true");
175                }
176                
177                XMLUtils.createElement(handler, "lang", langAttrs, langPath.getValue());
178            }
179
180            XMLUtils.endElement(handler, "file");
181        }
182        
183    }
184}