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.plugins.glossary; 017 018import java.io.IOException; 019import java.text.Normalizer; 020import java.text.Normalizer.Form; 021import java.util.Arrays; 022import java.util.Collections; 023import java.util.HashMap; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.ProcessingException; 030import org.apache.cocoon.environment.ObjectModelHelper; 031import org.apache.cocoon.environment.Request; 032import org.apache.cocoon.generation.ServiceableGenerator; 033import org.apache.cocoon.xml.AttributesImpl; 034import org.apache.cocoon.xml.XMLUtils; 035import org.apache.commons.lang.StringUtils; 036import org.xml.sax.SAXException; 037 038import org.ametys.plugins.glossary.theme.ThemeExpression; 039import org.ametys.plugins.glossary.theme.ThemesDAO; 040import org.ametys.plugins.repository.AmetysObjectIterable; 041import org.ametys.plugins.repository.AmetysObjectResolver; 042import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 043import org.ametys.plugins.repository.query.expression.Expression; 044import org.ametys.plugins.repository.query.expression.OrExpression; 045import org.ametys.web.repository.page.Page; 046import org.ametys.web.repository.page.ZoneItem; 047import org.ametys.web.repository.site.SiteManager; 048 049/** 050 * Generate the list of word definitions as XML. 051 */ 052public class DefinitionsGenerator extends ServiceableGenerator 053{ 054 private SiteManager _siteManager; 055 private ThemesDAO _themesDAO; 056 private AmetysObjectResolver _ametysObjectResolver; 057 058 @Override 059 public void service(ServiceManager serviceManager) throws ServiceException 060 { 061 super.service(serviceManager); 062 _siteManager = (SiteManager) serviceManager.lookup(SiteManager.ROLE); 063 _themesDAO = (ThemesDAO) serviceManager.lookup(ThemesDAO.ROLE); 064 _ametysObjectResolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 065 } 066 067 @Override 068 public void generate() throws IOException, SAXException, ProcessingException 069 { 070 Request request = ObjectModelHelper.getRequest(objectModel); 071 String siteName = parameters.getParameter("siteName", (String) request.getAttribute("site")); 072 String language = parameters.getParameter("language", (String) request.getAttribute("sitemapLanguage")); 073 String letter = parameters.getParameter("letter", request.getParameter("letter")); 074 letter = StringUtils.isBlank(letter) ? "A" : letter.toUpperCase(); 075 Page page = (Page) request.getAttribute(Page.class.getName()); 076 ZoneItem zoneItem = (ZoneItem) request.getAttribute(ZoneItem.class.getName()); 077 ModelAwareDataHolder serviceParameters = zoneItem.getServiceParameters(); 078 String[] themes = serviceParameters.getValue("themes", false, new String[0]); 079 080 contentHandler.startDocument(); 081 082 AttributesImpl attrs = new AttributesImpl(); 083 attrs.addCDATAAttribute("siteName", siteName); 084 attrs.addCDATAAttribute("language", language); 085 attrs.addCDATAAttribute("letter", letter); 086 if (page != null) 087 { 088 attrs.addCDATAAttribute("page", page.getId()); 089 } 090 XMLUtils.startElement(contentHandler, "wordDefinitions", attrs); 091 092 Expression themeExpression = _getThemeExpression(siteName, language, themes); 093 094 String definitionQuery = GlossaryHelper.getDefinitionQuery(siteName, language, themeExpression); 095 try (AmetysObjectIterable<DefaultDefinition> definitions = _ametysObjectResolver.query(definitionQuery);) 096 { 097 for (DefaultDefinition definition : definitions) 098 { 099 saxDefinition(definition); 100 } 101 } 102 103 XMLUtils.endElement(contentHandler, "wordDefinitions"); 104 contentHandler.endDocument(); 105 } 106 107 /** 108 * Get the list of theme expressions to filter the definitions with 109 * @param siteName the site's name 110 * @param language the site's language 111 * @param themes the array of theme Ids to create expressions 112 * @return a list of ThemeExpression 113 */ 114 protected Expression _getThemeExpression(String siteName, String language, String[] themes) 115 { 116 ThemeExpression[] themeExpressions = Arrays.stream(themes) 117 .filter(StringUtils::isNotBlank) 118 .filter(id -> themeExists(id, siteName, language)) 119 .map(id -> new ThemeExpression(id)) 120 .toArray(ThemeExpression[]::new); 121 122 return themeExpressions.length == 0 ? null : new OrExpression(themeExpressions); 123 } 124 125 /** 126 * Generate a word definition. 127 * @param definition the definition to generate. 128 * @throws SAXException If an error occurs while generating the XML. 129 */ 130 protected void saxDefinition(DefaultDefinition definition) throws SAXException 131 { 132 AttributesImpl attrs = new AttributesImpl(); 133 attrs.addCDATAAttribute("id", definition.getId()); 134 135 String word = definition.getWord(); 136 if (StringUtils.isNotEmpty(word)) 137 { 138 String firstLetter = Normalizer.normalize(word.substring(0, 1), Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""); 139 attrs.addCDATAAttribute("firstLetter", firstLetter.toUpperCase()); 140 } 141 attrs.addCDATAAttribute("word", definition.getWord()); 142 attrs.addCDATAAttribute("variantsText", StringUtils.join(definition.getVariants(), ", ")); 143 attrs.addCDATAAttribute("displayOnText", Boolean.toString(definition.displayOnText())); 144 145 XMLUtils.startElement(contentHandler, "wordDefinition", attrs); 146 147 // Variants. 148 XMLUtils.startElement(contentHandler, "variants"); 149 150 for (String variant : definition.getVariants()) 151 { 152 AttributesImpl variantAttrs = new AttributesImpl(); 153 variantAttrs.addCDATAAttribute("word", variant); 154 XMLUtils.createElement(contentHandler, "variant", variantAttrs); 155 } 156 157 XMLUtils.endElement(contentHandler, "variants"); 158 159 // Content 160 XMLUtils.createElement(contentHandler, "content", definition.getContent()); 161 162 XMLUtils.endElement(contentHandler, "wordDefinition"); 163 } 164 165 /** 166 * Verify the existence of a theme 167 * @param themeName the id of the theme to verify 168 * @param siteName the site's name 169 * @param language the site's language 170 * @return true if the theme exists, false otherwise 171 */ 172 public boolean themeExists(String themeName, String siteName, String language) 173 { 174 if (StringUtils.isBlank(themeName)) 175 { 176 return false; 177 } 178 Map<String, Object> contextualParameters = new HashMap<>(); 179 contextualParameters.put("language", language); 180 contextualParameters.put("siteName", siteName); 181 List<String> checkTags = _themesDAO.checkTags(List.of(themeName), false, Collections.EMPTY_MAP, contextualParameters); 182 return !checkTags.isEmpty(); 183 } 184}