001/* 002 * Copyright 2019 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.content; 017 018import java.io.IOException; 019import java.util.Comparator; 020import java.util.List; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.cocoon.ProcessingException; 025import org.apache.cocoon.environment.ObjectModelHelper; 026import org.apache.cocoon.environment.Request; 027import org.apache.cocoon.generation.ServiceableGenerator; 028import org.apache.cocoon.xml.AttributesImpl; 029import org.apache.cocoon.xml.XMLUtils; 030import org.apache.commons.lang3.StringUtils; 031import org.xml.sax.SAXException; 032 033import org.ametys.cms.repository.Content; 034import org.ametys.odf.ODFHelper; 035import org.ametys.odf.ProgramItem; 036import org.ametys.plugins.repository.AmetysObjectResolver; 037 038/** 039 * Generates additional information about a ODF content 040 * 041 */ 042public class AdditionalOdfContentPropertiesGenerator extends ServiceableGenerator 043{ 044 private static final ListProgramItemComparator __LIST_PROGRAM_ITEM_COMPARATOR = new ListProgramItemComparator(); 045 046 /** The AmetysObject resolver. */ 047 protected AmetysObjectResolver _resolver; 048 /** The ODF helper */ 049 protected ODFHelper _odfHelper; 050 051 @Override 052 public void service(ServiceManager serviceManager) throws ServiceException 053 { 054 super.service(serviceManager); 055 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 056 _odfHelper = (ODFHelper) serviceManager.lookup(ODFHelper.ROLE); 057 } 058 059 @Override 060 public void generate() throws IOException, SAXException, ProcessingException 061 { 062 Request request = ObjectModelHelper.getRequest(objectModel); 063 064 String contentId = parameters.getParameter("contentId", request.getParameter("contentId")); 065 066 Content content = null; 067 if (StringUtils.isNotEmpty(contentId)) 068 { 069 content = _resolver.resolveById(contentId); 070 } 071 else 072 { 073 content = (Content) request.getAttribute(Content.class.getName()); 074 } 075 076 contentHandler.startDocument(); 077 XMLUtils.startElement(contentHandler, "odf"); 078 079 if (content instanceof ProgramItem) 080 { 081 XMLUtils.startElement(contentHandler, "programItem"); 082 saxProgramItemProperties((ProgramItem) content); 083 XMLUtils.endElement(contentHandler, "programItem"); 084 } 085 086 XMLUtils.endElement(contentHandler, "odf"); 087 contentHandler.startDocument(); 088 contentHandler.endDocument(); 089 } 090 091 /** 092 * SAX specifics properties for a program item 093 * @param programItem the program item 094 * @throws SAXException if an error occurs while saxing 095 */ 096 protected void saxProgramItemProperties(ProgramItem programItem) throws SAXException 097 { 098 _saxProgramItemAncestorPaths(programItem); 099 _saxChildProgramItems(programItem); 100 } 101 102 /** 103 * SAX all paths of program item 104 * @param programItem The program item 105 * @throws SAXException if an error occurs while saxing 106 */ 107 protected void _saxProgramItemAncestorPaths(ProgramItem programItem) throws SAXException 108 { 109 if (_odfHelper.hasParentProgramItems(programItem)) 110 { 111 List<List<ProgramItem>> ancestorPaths = _odfHelper.getPathOfAncestors(programItem); 112 113 if (!ancestorPaths.isEmpty()) 114 { 115 // Sort the list to display it 116 ancestorPaths.sort(__LIST_PROGRAM_ITEM_COMPARATOR); 117 XMLUtils.startElement(contentHandler, "ancestors"); 118 for (List<ProgramItem> ancestorPath : ancestorPaths) 119 { 120 XMLUtils.startElement(contentHandler, "path"); 121 for (ProgramItem ancestor : ancestorPath) 122 { 123 _saxProgramItem(ancestor); 124 } 125 XMLUtils.endElement(contentHandler, "path"); 126 } 127 128 XMLUtils.endElement(contentHandler, "ancestors"); 129 } 130 } 131 } 132 133 /** 134 * SAX the child program items 135 * @param programItem the program item 136 * @throws SAXException if an error occurs while saxing 137 */ 138 protected void _saxChildProgramItems(ProgramItem programItem) throws SAXException 139 { 140 List<ProgramItem> children = _odfHelper.getChildProgramItems(programItem); 141 142 if (!children.isEmpty()) 143 { 144 XMLUtils.startElement(contentHandler, "children"); 145 for (ProgramItem child : children) 146 { 147 _saxProgramItem(child); 148 } 149 XMLUtils.endElement(contentHandler, "children"); 150 } 151 } 152 153 /** 154 * Sax a program item 155 * @param item the program item 156 * @throws SAXException if an error occurs while saxing 157 */ 158 protected void _saxProgramItem(ProgramItem item) throws SAXException 159 { 160 Content content = (Content) item; 161 AttributesImpl attrs = new AttributesImpl(); 162 attrs.addCDATAAttribute("id", content.getId()); 163 attrs.addCDATAAttribute("code", item.getCode()); 164 XMLUtils.createElement(contentHandler, "item", attrs, content.getTitle()); 165 } 166 167 /** 168 * Comparator of {@link List} composing of {@link ProgramItem} by title. 169 */ 170 private static class ListProgramItemComparator implements Comparator<List<ProgramItem>> 171 { 172 public int compare(List<ProgramItem> l1, List<ProgramItem> l2) 173 { 174 int l1Size = l1.size(); 175 int l2Size = l2.size(); 176 177 for (int i = 0; i < l1Size; i++) 178 { 179 if (l2Size <= i) 180 { 181 // l1 is greater than l2 182 return 1; 183 } 184 else 185 { 186 // Compare title 187 int comparing = ((Content) l1.get(i)).getTitle().compareTo(((Content) l2.get(i)).getTitle()); 188 if (comparing != 0) 189 { 190 return comparing; 191 } 192 } 193 } 194 195 // Lists are the same at the end of reading l1 196 // Then compare size of the lists 197 return Integer.compare(l1Size, l2Size); 198 } 199 } 200}