001/* 002 * Copyright 2013 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.thesaurus.search; 017 018import java.io.IOException; 019import java.util.LinkedHashSet; 020import java.util.List; 021import java.util.Locale; 022import java.util.Map; 023import java.util.Set; 024 025import javax.jcr.RepositoryException; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.ProcessingException; 030import org.apache.cocoon.generation.ServiceableGenerator; 031import org.apache.cocoon.xml.AttributesImpl; 032import org.apache.cocoon.xml.XMLUtils; 033import org.apache.commons.lang3.StringUtils; 034import org.xml.sax.SAXException; 035 036import org.ametys.cms.content.SAXContentHelper; 037import org.ametys.cms.contenttype.ContentType; 038import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 039import org.ametys.cms.contenttype.ContentTypesHelper; 040import org.ametys.cms.contenttype.MetadataDefinition; 041import org.ametys.cms.contenttype.MetadataDefinitionReference; 042import org.ametys.cms.contenttype.MetadataManager; 043import org.ametys.cms.contenttype.MetadataSet; 044import org.ametys.cms.contenttype.MetadataType; 045import org.ametys.cms.repository.Content; 046import org.ametys.core.util.ServerCommHelper; 047import org.ametys.plugins.thesaurus.ThesaurusDAO; 048import org.ametys.plugins.thesaurus.content.ThesaurusItemContentType; 049 050/** 051 * SAX the contents indexed with one or more terms 052 * 053 */ 054public class IndexedContentsGenerator extends ServiceableGenerator 055{ 056 private ThesaurusDAO _thesaurusDAO; 057 058 private ContentTypeExtensionPoint _contentTypeExtensionPoint; 059 private MetadataManager _metadataManager; 060 private ContentTypesHelper _contentTypesHelper; 061 private ServerCommHelper _serverCommHelper; 062 private SAXContentHelper _saxContentHelper; 063 064 @Override 065 public void service(ServiceManager smanager) throws ServiceException 066 { 067 super.service(smanager); 068 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE); 069 _metadataManager = (MetadataManager) smanager.lookup(MetadataManager.ROLE); 070 _contentTypesHelper = (ContentTypesHelper) smanager.lookup(ContentTypesHelper.ROLE); 071 _serverCommHelper = (ServerCommHelper) smanager.lookup(ServerCommHelper.ROLE); 072 _saxContentHelper = (SAXContentHelper) smanager.lookup(SAXContentHelper.ROLE); 073 _thesaurusDAO = (ThesaurusDAO) smanager.lookup(ThesaurusDAO.ROLE); 074 } 075 076 @Override 077 public void generate() throws IOException, SAXException, ProcessingException 078 { 079 Map<String, Object> jsParameters = _serverCommHelper.getJsParameters(); 080 081 @SuppressWarnings("unchecked") 082 List<String> termIds = (List<String>) jsParameters.get("termIds"); 083 084 int begin = jsParameters.containsKey("start") ? (Integer) jsParameters.get("start") : 0; // Index of search 085 int offset = jsParameters.containsKey("limit") ? (Integer) jsParameters.get("limit") : Integer.MAX_VALUE; // Number of results to SAX 086 087 String lang = (String) jsParameters.get("lang"); 088 Locale defaultLocale = StringUtils.isNotEmpty(lang) ? new Locale(lang) : null; 089 090 Set<Content> indexedContents = new LinkedHashSet<>(); 091 092 int index = 0; 093 for (String termId : termIds) 094 { 095 if (index == 0) 096 { 097 indexedContents.addAll(_thesaurusDAO.getIndexedContents(termId)); 098 } 099 else 100 { 101 indexedContents.retainAll(_thesaurusDAO.getIndexedContents(termId)); 102 } 103 index++; 104 } 105 106 try 107 { 108 // SAX results between begin and begin + offset 109 contentHandler.startDocument(); 110 contentHandler.startPrefixMapping("i18n", "http://apache.org/cocoon/i18n/2.1"); 111 112 XMLUtils.startElement(contentHandler, "contents"); 113 114 index = 0; 115 for (Content content : indexedContents) 116 { 117 if (index >= begin && index < begin + offset) 118 { 119 _saxContent(content, defaultLocale); 120 } 121 122 index++; 123 } 124 125 XMLUtils.createElement(contentHandler, "total", String.valueOf(indexedContents.size())); 126 XMLUtils.endElement(contentHandler, "contents"); 127 128 contentHandler.endPrefixMapping("i18n"); 129 contentHandler.endDocument(); 130 } 131 catch (Exception e) 132 { 133 getLogger().error("Cannot search for contents : " + e.getMessage(), e); 134 throw new ProcessingException("Cannot search for contents : " + e.getMessage(), e); 135 } 136 } 137 138 private void _saxContent (Content content, Locale defaultLocale) throws SAXException, RepositoryException, IOException 139 { 140 AttributesImpl attrs = new AttributesImpl(); 141 142 attrs.addCDATAAttribute("smallIcon", _contentTypesHelper.getSmallIcon(content)); 143 attrs.addCDATAAttribute("mediumIcon", _contentTypesHelper.getMediumIcon(content)); 144 attrs.addCDATAAttribute("largeIcon", _contentTypesHelper.getLargeIcon(content)); 145 attrs.addCDATAAttribute("id", content.getId()); 146 attrs.addCDATAAttribute("name", content.getName()); 147 attrs.addCDATAAttribute("title", content.getTitle(defaultLocale)); 148 149 String contentLanguage = content.getLanguage(); 150 if (contentLanguage != null) 151 { 152 attrs.addCDATAAttribute("language", contentLanguage); 153 } 154 155 XMLUtils.startElement(contentHandler, "content", attrs); 156 157 // System properties 158 _saxSystemProperties(content); 159 160 // Metadata 161 XMLUtils.startElement(contentHandler, "metadata"); 162 XMLUtils.createElement(contentHandler, "title", content.getTitle(defaultLocale)); 163 164 MetadataSet metadataSet = getMetadataToSAX(content); 165 Locale locale = contentLanguage != null ? new Locale(contentLanguage) : defaultLocale; 166 _metadataManager.saxReadableMetadata(contentHandler, content, metadataSet, locale); 167 168 XMLUtils.endElement(contentHandler, "metadata"); 169 170 XMLUtils.endElement(contentHandler, "content"); 171 } 172 173 /** 174 * Get the metadata set to sax 175 * @param content the content 176 * @return the metadata to sax 177 */ 178 protected MetadataSet getMetadataToSAX (Content content) 179 { 180 MetadataSet metadataSet = new MetadataSet(); 181 metadataSet.addElement(new MetadataDefinitionReference("title")); 182 183 String[] ctypes = content.getTypes(); 184 for (String ctype : ctypes) 185 { 186 ContentType contentType = _contentTypeExtensionPoint.getExtension(ctype); 187 188 Set<String> metadataNames = contentType.getMetadataNames(); 189 for (String metadataName : metadataNames) 190 { 191 MetadataDefinition metadataDefinition = contentType.getMetadataDefinition(metadataName); 192 if (MetadataType.CONTENT.equals(metadataDefinition.getType()) && ThesaurusItemContentType.ITEM_CONTENT_TYPE_ID.equals(metadataDefinition.getContentType())) 193 { 194 MetadataDefinitionReference metadataRef = new MetadataDefinitionReference(metadataName); 195 metadataSet.addElement(metadataRef); 196 } 197 } 198 } 199 200 return metadataSet; 201 } 202 203 private void _saxSystemProperties (Content content) throws SAXException, RepositoryException 204 { 205 _saxContentHelper.saxContentCurrentState (contentHandler, content); 206 _saxContentHelper.saxContentTypesAndMixins(contentHandler, content); 207 _saxContentHelper.saxLastModified(contentHandler, content); 208 _saxContentHelper.saxCreationDate(contentHandler, content); 209 _saxContentHelper.saxCreator(contentHandler, content); 210 _saxContentHelper.saxContributor(contentHandler, content); 211 _saxContentHelper.saxContentLanguage(contentHandler, content); 212 } 213}