001/*
002 *  Copyright 2015 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;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Optional;
021import java.util.Set;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.avalon.framework.service.Serviceable;
026import org.apache.commons.lang3.StringUtils;
027import org.w3c.dom.Node;
028import org.w3c.dom.NodeList;
029
030import org.ametys.cms.repository.Content;
031import org.ametys.core.util.dom.AmetysNodeList;
032import org.ametys.odf.enumeration.OdfReferenceTableEntry;
033import org.ametys.odf.enumeration.OdfReferenceTableHelper;
034import org.ametys.odf.orgunit.RootOrgUnitProvider;
035import org.ametys.odf.program.AbstractProgram;
036import org.ametys.odf.program.Program;
037import org.ametys.odf.program.SubProgram;
038import org.ametys.odf.xslt.OdfReferenceTableElement;
039import org.ametys.odf.xslt.ProgramElement;
040import org.ametys.odf.xslt.SubProgramElement;
041import org.ametys.plugins.repository.AmetysObjectResolver;
042import org.ametys.plugins.repository.AmetysRepositoryException;
043import org.ametys.runtime.config.Config;
044
045/**
046 * Helper component to be used from XSL stylesheets.
047 */
048public class OdfXSLTHelper implements Serviceable
049{
050    /** The ODF reference helper */
051    protected static OdfReferenceTableHelper _odfRefTableHelper;
052    /** The Ametys resolver */
053    protected static AmetysObjectResolver _ametysObjectResolver;
054    /** The orgunit root provider */
055    protected static RootOrgUnitProvider _rootOrgUnitProvider;
056    
057    @Override
058    public void service(ServiceManager smanager) throws ServiceException
059    {
060        _odfRefTableHelper = (OdfReferenceTableHelper) smanager.lookup(OdfReferenceTableHelper.ROLE);
061        _ametysObjectResolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
062        _rootOrgUnitProvider = (RootOrgUnitProvider) smanager.lookup(RootOrgUnitProvider.ROLE);
063    }
064    
065    /**
066     * Get the label associated with the degree key
067     * @param cdmValue The code of degree
068     * @return The label of degree or code if not found
069     */
070    public static String degreeLabel (String cdmValue)
071    {
072        return degreeLabel(cdmValue, Config.getInstance().getValue("odf.programs.lang"));
073    }
074    
075    /**
076     * Get the code associated with the given reference table's entry
077     * @param tableRefEntryId The id of entry
078     * @return the code or <code>null</code> if not found
079     */
080    public static String getCode (String tableRefEntryId)
081    {
082        try
083        {
084            Content content = _ametysObjectResolver.resolveById(tableRefEntryId);
085            return content.getValue(OdfReferenceTableEntry.CODE);
086        }
087        catch (AmetysRepositoryException e)
088        {
089            return null;
090        }
091    }
092    
093    /**
094     * Get the id of reference table's entry
095     * @param tableRefId The id of content type
096     * @param code The code
097     * @return the id or <code>null</code> if not found
098     */
099    public static String getEntryId (String tableRefId, String code)
100    {
101        OdfReferenceTableEntry entry = _odfRefTableHelper.getItemFromCode(tableRefId, code);
102        if (entry != null)
103        {
104            return entry.getId();
105        }
106        return null;
107    }
108    
109    /**
110     * Get the label associated with the degree key
111     * @param cdmValue The cdm value of degree
112     * @param lang The language
113     * @return The label of degree or empty string if not found
114     */
115    public static String degreeLabel (String cdmValue, String lang)
116    {
117        return Optional
118            .ofNullable(_odfRefTableHelper.getItemFromCDM(OdfReferenceTableHelper.DEGREE, cdmValue))
119            .map(degree -> degree.getLabel(lang))
120            .orElse(StringUtils.EMPTY);
121    }
122    
123    /**
124     * Get the whole structure of a subprogram, including the structure of child subprograms
125     * @param subprogramId The id of subprogram
126     * @return Node with the subprogram structure
127     */
128    public static Node getSubProgramStructure (String subprogramId)
129    {
130        SubProgram subProgram = _ametysObjectResolver.resolveById(subprogramId);
131        return new SubProgramElement(subProgram, _ametysObjectResolver);
132    }
133    
134    /**
135     * Get the structure of a subprogram, including the structure of child subprograms until the given depth
136     * @param subprogramId The id of subprogram
137     * @param depth Set a positive number to get structure of child subprograms until given depth. Set a negative number to get the whole structure recursively, including the structure of child subprograms. This parameter concerns only subprograms.
138     * @return Node with the subprogram structure
139     */
140    public static Node getSubProgramStructure (String subprogramId, int depth)
141    {
142        SubProgram subProgram = _ametysObjectResolver.resolveById(subprogramId);
143        return new SubProgramElement(subProgram, depth, null, _ametysObjectResolver);
144    }
145    
146    /**
147     * Get the parent program information 
148     * @param subprogramId The id of subprogram
149     * @return a node for each program's information
150     */
151    public static NodeList getParentProgram (String subprogramId)
152    {
153        return getParentProgramStructure(subprogramId, 0);
154    }
155    
156    /**
157     * Get the certification label of a {@link AbstractProgram}.
158     * Returns null if the program is not certified.
159     * @param abstractProgramId the id of program or subprogram
160     * @return the certification label
161     */
162    public static String getCertificationLabel(String abstractProgramId)
163    {
164        AbstractProgram abstractProgram = _ametysObjectResolver.resolveById(abstractProgramId);
165        if (abstractProgram.isCertified())
166        {
167            String degreeId = null;
168            if (abstractProgram instanceof Program)
169            {
170                degreeId = abstractProgram.getDegree();
171            }
172            else if (abstractProgram instanceof SubProgram)
173            {
174                // Get degree from parent
175                Set<Program> rootPrograms = abstractProgram.getRootPrograms();
176                if (rootPrograms.size() > 0)
177                {
178                    degreeId = rootPrograms.iterator().next().getDegree();
179                }
180            }
181            
182            if (StringUtils.isNotEmpty(degreeId))
183            {
184                Content degree = _ametysObjectResolver.resolveById(degreeId);
185                return degree.getValue("certificationLabel");
186            }
187        }
188        
189        return null;
190    }
191    
192    /**
193     * Get the program information 
194     * @param programId The id of program
195     * @return Node with the program's information
196     */
197    public static Node getProgram (String programId)
198    {
199        return getProgramStructure(programId, 0);
200    }
201    
202    /**
203     * Get the structure of a parent programs, including the structure of child subprograms until the given depth.
204     * @param subprogramId The id of subprogram
205     * @param depth Set a positive number to get structure of child subprograms until given depth. Set a negative number to get the whole structure recursively, including the structure of child subprograms. This parameter concerns only subprograms.
206     * @return a node for each program's structure
207     */
208    public static NodeList getParentProgramStructure (String subprogramId, int depth)
209    {
210        List<ProgramElement> programs = new ArrayList<>();
211        
212        SubProgram subProgram = _ametysObjectResolver.resolveById(subprogramId);
213        
214        Set<Program> rootPrograms = subProgram.getRootPrograms();
215        if (rootPrograms.size() > 0)
216        {
217            programs.add(new ProgramElement(rootPrograms.iterator().next(), depth, null, _ametysObjectResolver));
218        }
219        
220        return new AmetysNodeList(programs);
221    }
222    
223    /**
224     * Get the structure of a program until the given depth.
225     * @param programId The id of program
226     * @param depth Set a positive number to get structure of child subprograms until given depth. Set a negative number to get the whole structure recursively, including the structure of child subprograms. This parameter concerns only subprograms.
227     * @return Node with the program structure
228     */
229    public static Node getProgramStructure (String programId, int depth)
230    {
231        Program program = _ametysObjectResolver.resolveById(programId);
232        return new ProgramElement(program, depth, null, _ametysObjectResolver);
233    }
234    
235    /**
236     * Get the items of a reference table
237     * @param tableRefId the id of reference table
238     * @param lang the language to use for labels
239     * @return the items
240     */
241    public static Node getTableRefItems(String tableRefId, String lang)
242    {
243        return getTableRefItems(tableRefId, lang, false);
244    }
245    
246    /**
247     * Get the items of a reference table
248     * @param tableRefId the id of reference table
249     * @param lang the language to use for labels
250     * @param ordered true to sort items by 'order' attribute
251     * @return the items
252     */
253    public static Node getTableRefItems(String tableRefId, String lang, boolean ordered)
254    {
255        return new OdfReferenceTableElement(tableRefId, _odfRefTableHelper, lang, ordered);
256    }
257    
258    /**
259     * Get the id of root orgunit
260     * @return The id of root
261     */
262    public static String getRootOrgUnitId()
263    {
264        return _rootOrgUnitProvider.getRootId();
265    }
266}