001/* 002 * Copyright 2012 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.odf.oai; 017 018import java.io.IOException; 019import java.text.ParseException; 020import java.text.SimpleDateFormat; 021import java.time.ZoneOffset; 022import java.time.ZonedDateTime; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Collection; 026import java.util.Date; 027import java.util.TimeZone; 028 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.avalon.framework.service.Serviceable; 032import org.apache.cocoon.ProcessingException; 033import org.apache.cocoon.environment.ObjectModelHelper; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.xml.XMLUtils; 036import org.apache.commons.lang.StringUtils; 037import org.xml.sax.SAXException; 038 039import org.ametys.cms.CmsConstants; 040import org.ametys.cms.repository.Content; 041import org.ametys.core.util.DateUtils; 042import org.ametys.odf.ODFHelper; 043import org.ametys.odf.catalog.CatalogsManager; 044import org.ametys.odf.program.Program; 045import org.ametys.odf.program.ProgramFactory; 046import org.ametys.plugins.repository.AmetysObjectIterable; 047import org.ametys.plugins.repository.UnknownAmetysObjectException; 048import org.ametys.plugins.repository.query.SortCriteria; 049import org.ametys.plugins.repository.query.expression.AndExpression; 050import org.ametys.plugins.repository.query.expression.DateExpression; 051import org.ametys.plugins.repository.query.expression.Expression; 052import org.ametys.plugins.repository.query.expression.Expression.Operator; 053 054/** 055 * Generator for the <code>ListIdentifiers</code> verb. 056 */ 057public class ListIdentifiersGenerator extends AbstractOAIVerbGenerator implements Serviceable 058{ 059 /** The OAI-PMH Sets Extension Point*/ 060 private OaiSetExtensionPoint _oaiSetEP; 061 062 private CatalogsManager _catalogsManager; 063 064 private ODFHelper _odfHelper; 065 066 @Override 067 public void service(ServiceManager serviceManager) throws ServiceException 068 { 069 _oaiSetEP = (OaiSetExtensionPoint) serviceManager.lookup(OaiSetExtensionPoint.ROLE); 070 _catalogsManager = (CatalogsManager) serviceManager.lookup(CatalogsManager.ROLE); 071 _odfHelper = (ODFHelper) serviceManager.lookup(ODFHelper.ROLE); 072 } 073 074 @Override 075 protected Collection<String> getRequiredParameters() 076 { 077 return Arrays.asList("verb", "metadataPrefix"); 078 } 079 080 @Override 081 protected Collection<String> getAllowedParameters() 082 { 083 return Arrays.asList("verb", "from", "until", "metadataPrefix", "resumptionToken", "set"); 084 } 085 086 @Override 087 protected void generateVerb() throws IOException, SAXException, ProcessingException 088 { 089 Request request = ObjectModelHelper.getRequest(objectModel); 090 091 String token = request.getParameter("resumptionToken"); 092 093 if (StringUtils.isNotEmpty(token)) 094 { 095 generateError("badResumptionToken ", "This repository does not support resumption tokens"); 096 return; 097 } 098 099 String metadataPrefix = request.getParameter("metadataPrefix"); 100 101 if (!metadataPrefix.equals("cdm") && !metadataPrefix.equals("oai_dc")) 102 { 103 generateError("cannotDisseminateFormat", "The value of the metadataPrefix argument is not supported by the repository."); 104 return; 105 } 106 107 SimpleDateFormat fullFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 108 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 109 TimeZone tz = TimeZone.getTimeZone("UTC"); 110 fullFormat.setTimeZone(tz); 111 format.setTimeZone(tz); 112 113 ArrayList<Expression> expressions = new ArrayList<>(); 114 115 try 116 { 117 String fromParam = request.getParameter("from"); 118 119 if (fromParam != null) 120 { 121 Date from; 122 if (fromParam.indexOf('T') == -1) 123 { 124 from = format.parse(fromParam); 125 } 126 else 127 { 128 from = fullFormat.parse(fromParam); 129 } 130 131 expressions.add(new DateExpression("lastModified", Operator.GE, from)); 132 } 133 134 String untilParam = request.getParameter("until"); 135 136 if (untilParam != null) 137 { 138 Date until; 139 if (untilParam.indexOf('T') == -1) 140 { 141 until = format.parse(untilParam); 142 } 143 else 144 { 145 until = fullFormat.parse(untilParam); 146 } 147 148 expressions.add(new DateExpression("lastModified", Operator.LE, until)); 149 } 150 } 151 catch (ParseException ex) 152 { 153 generateError("badArgument", "One or more aguments are malformed."); 154 return; 155 } 156 157 OaiSet oaiSet = null; 158 String set = request.getParameter("set"); 159 160 if (StringUtils.isNotEmpty(set)) 161 { 162 oaiSet = _oaiSetEP.getExtension(set); 163 if (oaiSet == null) 164 { 165 generateError("noRecordsMatch", "The set specified as an argument does not exists."); 166 return; 167 } 168 } 169 170 Expression expression = new AndExpression(expressions.toArray(new Expression[]{})); 171 172 SortCriteria sortCriteria = new SortCriteria(); 173 sortCriteria.addCriterion(Content.ATTRIBUTE_TITLE, true, true); 174 175 try (AmetysObjectIterable<Program> programs = oaiSet != null 176 ? oaiSet.getRecords(expression, sortCriteria) 177 // FIXME Generate identifier for language "fr" and default catalog only 178 : _odfHelper.getProgramItems(ProgramFactory.PROGRAM_CONTENT_TYPE, null, _catalogsManager.getDefaultCatalogName(), "fr", expression, sortCriteria)) 179 { 180 181 XMLUtils.startElement(contentHandler, getTagName()); 182 183 for (Program program : programs) 184 { 185 try 186 { 187 String[] labels = program.getAllLabels(); 188 189 if (Arrays.asList(labels).contains(CmsConstants.LIVE_LABEL)) 190 { 191 program.switchToLabel(CmsConstants.LIVE_LABEL); 192 saxProgram(program); 193 } 194 } 195 catch (UnknownAmetysObjectException e) 196 { 197 // no "Live" label, continue 198 } 199 } 200 201 XMLUtils.endElement(contentHandler, getTagName()); 202 } 203 } 204 205 /** 206 * Returns the surrounding tag name. 207 * @return the surrounding tag name. 208 */ 209 protected String getTagName() 210 { 211 return "ListIdentifiers"; 212 } 213 214 /** 215 * Generate the program information. 216 * @param program the program 217 * @throws SAXException if an error occurs 218 */ 219 protected void saxProgram(Program program) throws SAXException 220 { 221 XMLUtils.startElement(contentHandler, "header"); 222 223 XMLUtils.createElement(contentHandler, "identifier", program.getCDMId()); 224 225 ZonedDateTime date = program.getLastModified(); 226 XMLUtils.createElement(contentHandler, "datestamp", DateUtils.zonedDateTimeToString(date, ZoneOffset.UTC, "yyyy-MM-dd'T'HH:mm:ssXXX")); 227 228 XMLUtils.endElement(contentHandler, "header"); 229 } 230}