001/*
002 *  Copyright 2011 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.skinfactory.generators;
017
018import java.io.File;
019import java.io.IOException;
020import java.util.HashSet;
021import java.util.Map;
022import java.util.Set;
023
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.ProcessingException;
027import org.apache.cocoon.components.source.SourceUtil;
028import org.apache.cocoon.generation.ServiceableGenerator;
029import org.apache.cocoon.xml.XMLUtils;
030import org.apache.commons.collections.SetUtils;
031import org.apache.excalibur.source.Source;
032import org.apache.excalibur.source.SourceResolver;
033import org.apache.excalibur.source.impl.FileSource;
034import org.apache.excalibur.xml.dom.DOMParser;
035import org.apache.excalibur.xml.xpath.XPathProcessor;
036import org.w3c.dom.Document;
037import org.w3c.dom.Element;
038import org.w3c.dom.NodeList;
039import org.xml.sax.InputSource;
040import org.xml.sax.SAXException;
041
042import org.ametys.core.util.IgnoreRootHandler;
043import org.ametys.plugins.skincommons.SkinEditionHelper;
044import org.ametys.skinfactory.SkinFactoryComponent;
045import org.ametys.skinfactory.parameters.AbstractSkinParameter;
046import org.ametys.web.skin.SkinModel;
047import org.ametys.web.skin.SkinModelsManager;
048
049/**
050 * SAX ribbon definition for skin parameters
051 *
052 */
053public class RibbonGenerator extends ServiceableGenerator
054{
055    private SourceResolver _srcResolver;
056    private SkinModelsManager _modelsManager;
057    private SkinFactoryComponent _skinFactoryManager;
058    private DOMParser _domParser;
059    private XPathProcessor _xpathProcessor;
060    private SkinEditionHelper _skinHelper;
061    
062    @Override
063    public void service(ServiceManager smanager) throws ServiceException
064    {
065        super.service(smanager);
066        _srcResolver = (SourceResolver) smanager.lookup(SourceResolver.ROLE);
067        _skinHelper = (SkinEditionHelper) smanager.lookup(SkinEditionHelper.ROLE);
068        _modelsManager = (SkinModelsManager) smanager.lookup(SkinModelsManager.ROLE);
069        _skinFactoryManager = (SkinFactoryComponent) smanager.lookup(SkinFactoryComponent.ROLE);
070        _domParser = (DOMParser) smanager.lookup(DOMParser.ROLE);
071        _xpathProcessor = (XPathProcessor) smanager.lookup(XPathProcessor.ROLE);
072    }
073    
074    @Override
075    public void generate() throws IOException, SAXException, ProcessingException
076    {
077        String skinName = parameters.getParameter("skinName", null);
078        
079        String modelName = _skinHelper.getTempModel(skinName);
080        if (modelName == null)
081        {
082            throw new IllegalArgumentException("The current skin has no model");
083        }
084        
085        SkinModel model = _modelsManager.getModel(modelName);
086        if (model == null)
087        {
088            throw new IllegalArgumentException("The model '" + modelName + "' does not exit anymore");
089        }
090        
091        contentHandler.startDocument();
092        XMLUtils.startElement(contentHandler, "cms");
093        
094        Source src = null;
095        FileSource ribbonSrc = null;
096        try
097        {
098            File ribbonFile = new File (model.getFile(), "model/cms-ribbon.xml");
099            ribbonSrc = new FileSource("file", ribbonFile);
100            if (ribbonSrc.exists())
101            {
102                if (_isUpToDate(ribbonFile, modelName))
103                {
104                    SourceUtil.toSAX(ribbonSrc, new IgnoreRootHandler(contentHandler));
105                }
106                else
107                {
108                    src = _srcResolver.resolveURI("cocoon:/" + modelName + "/update/cms-ribbon.xml");
109                    SourceUtil.toSAX(src, new IgnoreRootHandler(contentHandler));
110                    
111                    // Update file
112                    org.apache.excalibur.source.SourceUtil.copy(src, ribbonSrc);
113                }
114            }
115            else
116            {
117                src = _srcResolver.resolveURI("cocoon:/" + modelName + "/create/cms-ribbon.xml");
118                SourceUtil.toSAX(src, new IgnoreRootHandler(contentHandler));
119                
120                // Create file
121                org.apache.excalibur.source.SourceUtil.copy(src, ribbonSrc);
122            }
123        }
124        finally
125        {
126            if (src != null)
127            {
128                _srcResolver.release(src);
129            }
130            
131            if (ribbonSrc != null)
132            {
133                _srcResolver.release(ribbonSrc);
134            }
135        }
136        
137        XMLUtils.startElement(contentHandler, "parameters");
138        Map<String, AbstractSkinParameter> modelParameters = _skinFactoryManager.getModelParameters(modelName);
139        for (AbstractSkinParameter parameter : modelParameters.values())
140        {
141            parameter.toSAX(contentHandler, modelName);
142        }
143        XMLUtils.endElement(contentHandler, "parameters");
144
145        XMLUtils.endElement(contentHandler, "cms");
146        contentHandler.endDocument();
147
148    }
149
150    private boolean _isUpToDate (File ribbonFile, String modelName) throws IOException, SAXException
151    {
152        Source ribbonSrc = null;
153        try
154        {
155            ribbonSrc = _srcResolver.resolveURI("file://" + ribbonFile.getAbsolutePath());
156            
157            Set<String> ribbonParams = new HashSet<>();
158            
159            Document document = _domParser.parseDocument(new InputSource(ribbonSrc.getInputStream()));
160            NodeList paramNodes = _xpathProcessor.selectNodeList(document, "/ribbon/tab/groups/group//parameter");
161            
162            for (int i = 0; i < paramNodes.getLength(); i++)
163            {
164                Element consistency = (Element) paramNodes.item(i);
165                String id = consistency.getAttribute("id");
166                
167                ribbonParams.add(id);
168            }
169            
170            return SetUtils.isEqualSet(ribbonParams, _skinFactoryManager.getModelParameters(modelName).keySet());
171        }
172        finally
173        {
174            if (ribbonSrc != null)
175            {
176                _srcResolver.release(ribbonSrc);
177            }
178        }
179    }
180    
181}