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