001/* 002 * Copyright 2018 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.userdirectory.generator; 017 018import java.io.IOException; 019import java.util.List; 020 021import org.apache.avalon.framework.service.ServiceException; 022import org.apache.avalon.framework.service.ServiceManager; 023import org.apache.cocoon.ProcessingException; 024import org.apache.cocoon.components.source.impl.SitemapSource; 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.lang.StringUtils; 031import org.apache.excalibur.source.SourceResolver; 032import org.xml.sax.SAXException; 033 034import org.ametys.cms.data.ContentValue; 035import org.ametys.cms.repository.Content; 036import org.ametys.core.util.IgnoreRootHandler; 037import org.ametys.plugins.repository.AmetysObjectIterable; 038import org.ametys.plugins.repository.UnknownAmetysObjectException; 039import org.ametys.plugins.repository.data.holder.group.impl.ModelAwareRepeater; 040import org.ametys.plugins.repository.data.holder.group.impl.ModelAwareRepeaterEntry; 041import org.ametys.plugins.userdirectory.OrganisationChartPageHandler; 042import org.ametys.web.WebConstants; 043 044/** 045 * Generate information to render the organization chart service. 046 */ 047public class OrgChartGenerator extends ServiceableGenerator 048{ 049 private static final String __VIEW_NAME = "organizationChart"; 050 051 private OrganisationChartPageHandler _organizationChartPageHandler; 052 private SourceResolver _sourceResolver; 053 054 @Override 055 public void service(ServiceManager serviceManager) throws ServiceException 056 { 057 super.service(serviceManager); 058 _organizationChartPageHandler = (OrganisationChartPageHandler) serviceManager.lookup(OrganisationChartPageHandler.ROLE); 059 _sourceResolver = (SourceResolver) serviceManager.lookup(SourceResolver.ROLE); 060 } 061 062 public void generate() throws IOException, SAXException, ProcessingException 063 { 064 Request request = ObjectModelHelper.getRequest(objectModel); 065 String language = (String) request.getAttribute(WebConstants.REQUEST_ATTR_SITEMAP_NAME); 066 067 contentHandler.startDocument(); 068 XMLUtils.startElement(contentHandler, "orgUnits"); 069 070 AmetysObjectIterable<Content> contents = _organizationChartPageHandler.getFirstLevelOfContents(language); 071 for (Content content : contents) 072 { 073 saxOrganizationUnit(content); 074 } 075 076 XMLUtils.endElement(contentHandler, "orgUnits"); 077 contentHandler.endDocument(); 078 } 079 080 /** 081 * SAX an organization unit content 082 * @param orgUnit the organization unit to sax. 083 * @throws SAXException if an error occurs 084 */ 085 protected void saxOrganizationUnit(Content orgUnit) throws SAXException 086 { 087 SitemapSource src = null; 088 try 089 { 090 AttributesImpl attrs = new AttributesImpl(); 091 attrs.addCDATAAttribute("id", orgUnit.getId()); 092 attrs.addCDATAAttribute("unique-id", org.ametys.core.util.StringUtils.md5Base64(orgUnit.getId())); 093 attrs.addCDATAAttribute("name", orgUnit.getName()); 094 095 XMLUtils.startElement(contentHandler, "orgUnit", attrs); 096 097 String format = parameters.getParameter("output-format", "html"); 098 String uri = "cocoon://_content." + format + "?contentId=" + orgUnit.getId() + "&viewName=" + __VIEW_NAME + "&output-format=" + format; 099 src = (SitemapSource) _sourceResolver.resolveURI(uri); 100 src.toSAX(new IgnoreRootHandler(contentHandler)); 101 102 saxFirstUserOfOrganizationUnit(orgUnit); 103 saxOrganizationUnitChildren(orgUnit); 104 105 XMLUtils.endElement(contentHandler, "orgUnit"); 106 } 107 catch (IOException e) 108 { 109 throw new SAXException(e); 110 } 111 finally 112 { 113 _sourceResolver.release(src); 114 } 115 } 116 117 /** 118 * SAX the first user with a role in the organization unit content 119 * @param orgUnit the organization unit 120 * @throws SAXException if an error occurred 121 */ 122 protected void saxFirstUserOfOrganizationUnit(Content orgUnit) throws SAXException 123 { 124 if (orgUnit.hasValue("users")) 125 { 126 ModelAwareRepeater repeaters = orgUnit.getRepeater("users"); 127 for (ModelAwareRepeaterEntry entry : repeaters.getEntries()) 128 { 129 String role = entry.getValue("role"); 130 ContentValue userValue = entry.getValue("user"); 131 if (StringUtils.isNotEmpty(role) && userValue != null) 132 { 133 try 134 { 135 Content user = userValue.getContent(); 136 saxUser(user, role); 137 } 138 catch (UnknownAmetysObjectException e) 139 { 140 getLogger().error("The entity " + orgUnit.getTitle() + " (" + orgUnit.getId() + ") is referencing an unexisting user '" + userValue.getContentId() + "'"); 141 } 142 catch (Exception e) 143 { 144 getLogger().error("Fail to sax main user '" + userValue.getContentId() + "' for entity " + orgUnit.getTitle() + " (" + orgUnit.getId() + ")", e); 145 } 146 147 break; 148 } 149 } 150 } 151 } 152 153 /** 154 * SAX a user content 155 * @param user the user to sax. 156 * @param role the user's role 157 * @throws SAXException if an error occurs 158 */ 159 protected void saxUser(Content user, String role) throws SAXException 160 { 161 SitemapSource src = null; 162 try 163 { 164 AttributesImpl attrs = new AttributesImpl(); 165 attrs.addCDATAAttribute("id", user.getId()); 166 attrs.addCDATAAttribute("name", user.getName()); 167 168 XMLUtils.startElement(contentHandler, "main-user", attrs); 169 170 XMLUtils.createElement(contentHandler, "role", role); 171 172 String format = parameters.getParameter("output-format", "html"); 173 String uri = "cocoon://_content." + format + "?contentId=" + user.getId() + "&viewName=" + __VIEW_NAME + "&output-format=" + format; 174 src = (SitemapSource) _sourceResolver.resolveURI(uri); 175 src.toSAX(new IgnoreRootHandler(contentHandler)); 176 177 XMLUtils.endElement(contentHandler, "main-user"); 178 } 179 catch (IOException e) 180 { 181 throw new SAXException(e); 182 } 183 finally 184 { 185 _sourceResolver.release(src); 186 } 187 } 188 189 /** 190 * SAX children of an organization unit 191 * @param orgUnit the organization unit 192 * @throws SAXException if an error occurred 193 */ 194 protected void saxOrganizationUnitChildren(Content orgUnit) throws SAXException 195 { 196 List<Content> children = _organizationChartPageHandler.getChildContents(orgUnit); 197 198 if (!children.isEmpty()) 199 { 200 XMLUtils.startElement(contentHandler, "orgUnits"); 201 202 for (Content child : children) 203 { 204 saxOrganizationUnit(child); 205 } 206 207 XMLUtils.endElement(contentHandler, "orgUnits"); 208 } 209 } 210}