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