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}