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.plugins.thesaurus;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.parameters.Parameters;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.acting.ServiceableAction;
027import org.apache.cocoon.environment.ObjectModelHelper;
028import org.apache.cocoon.environment.Redirector;
029import org.apache.cocoon.environment.Request;
030import org.apache.cocoon.environment.SourceResolver;
031import org.apache.commons.lang3.StringUtils;
032
033import org.ametys.cms.repository.Content;
034import org.ametys.core.cocoon.JSonReader;
035import org.ametys.core.util.I18nUtils;
036import org.ametys.plugins.repository.AmetysObject;
037import org.ametys.plugins.repository.AmetysObjectIterable;
038import org.ametys.plugins.repository.AmetysObjectResolver;
039import org.ametys.plugins.repository.TraversableAmetysObject;
040import org.ametys.plugins.thesaurus.content.ThesaurusItemContentType;
041import org.ametys.runtime.i18n.I18nizableText;
042
043/**
044 * Generates a subtree of the resources explorer.
045 */
046public class GetTermsAction extends ServiceableAction
047{
048    /** The Ametys object resolver */
049    protected AmetysObjectResolver _resolver;
050    /** The thesaurus DAO */
051    protected ThesaurusDAO _thesaurusDAO;
052    /** The I18n Utils */
053    private I18nUtils _i18nUtils;
054    
055    @Override
056    public void service(ServiceManager serviceManager) throws ServiceException
057    {
058        super.service(serviceManager);
059        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
060        _thesaurusDAO = (ThesaurusDAO) serviceManager.lookup(ThesaurusDAO.ROLE);
061        _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE);
062    }
063    
064    @SuppressWarnings("unchecked")
065    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
066    {
067        Map jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT);
068        
069        String parentId = (String) jsParameters.get("node");
070        boolean hideCandidates = (boolean) jsParameters.get("hideCandidates");
071        boolean checkMode = (boolean) jsParameters.get("checkMode");
072        
073        List<Map<String, Object>> nodes = new ArrayList<>();
074        
075        TraversableAmetysObject parent =  _resolver.hasAmetysObjectForId(parentId) ? (TraversableAmetysObject) _resolver.resolveById(parentId) : null;
076        
077        if (parent != null)
078        {
079            try (AmetysObjectIterable<Content> terms = _thesaurusDAO.getChildTerms(parentId))
080            {
081                for (Content term : terms)
082                {
083                    nodes.add(termToJSON(term, parent instanceof Content ? (Content) parent : null, checkMode));
084                }
085            }
086        }
087        
088        if (parent instanceof MicroThesaurus && !hideCandidates)
089        {
090            if (parent.hasChild(ThesaurusDAO.ROOT_CANDIDATES_NODENAME))
091            {
092                TraversableAmetysObject rootCandidates = parent.getChild(ThesaurusDAO.ROOT_CANDIDATES_NODENAME);
093                nodes.add(rootCandidatesToJSON(rootCandidates));
094            }
095        }
096        
097        Map<String, Object> result = new HashMap<>();
098        result.put("children", nodes);
099        
100        Request request = ObjectModelHelper.getRequest(objectModel);
101        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
102        
103        return EMPTY_MAP;
104    }
105    
106    /**
107     * Gets the root candidates to JSON format
108     * @param rootCandidates The root node for candidates
109     * @return The candidates' properties
110     */
111    protected Map<String, Object> rootCandidatesToJSON(TraversableAmetysObject rootCandidates)
112    {
113        Map<String, Object> infos = new HashMap<>();
114        
115        infos.put("id", rootCandidates.getId());
116        infos.put("name", rootCandidates.getName());
117        infos.put("label", _i18nUtils.translate(new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_CONTENT_TYPE_CANDIDATES_LABEL")));
118        infos.put("type", "root-candidates");
119        
120        return infos;
121    }
122    
123    /**
124     * Gets a term to JSON format
125     * @param term The term
126     * @param genericTerm The generic term. Can be null.
127     * @param checkMode True for checked mode
128     * @return The term's properties
129     */
130    protected Map<String, Object> termToJSON(Content term, Content genericTerm, boolean checkMode)
131    {
132        Map<String, Object> infos = new HashMap<>();
133        
134        String type = term.getTypes()[0];
135        
136        infos.put("id", term.getId());
137        infos.put("name", term.getName());
138        infos.put("label", term.getTitle());
139        
140        if (ThesaurusItemContentType.TERM_CONTENT_TYPE_ID.equals(type))
141        {
142            infos.put("type", "term");
143         
144            // Related terms
145            String ta = _getRelatedTerms(term);
146            if (StringUtils.isNotEmpty(ta))
147            {
148                infos.put("ta", ta);
149            }
150            
151            // Specifics terms
152            String ts = _getSpecificTerms(term);
153            if (StringUtils.isNotEmpty(ts))
154            {
155                infos.put("ts", ts);
156                infos.put("leaf", "false");
157            }
158            else
159            {
160                infos.put("leaf", "true");
161            }
162            
163            // Synonyms
164            if (term.getMetadataHolder().hasMetadata(ThesaurusDAO.METADATA_SYNONYMS))
165            {
166                String[] synonyms = term.getMetadataHolder().getStringArray(ThesaurusDAO.METADATA_SYNONYMS); 
167                infos.put("synonyms", StringUtils.join(synonyms, ", "));
168            }
169            
170            // Generic term
171            if (genericTerm != null)
172            {
173                infos.put("tg", genericTerm.getTitle());
174            }
175        }
176        else if (ThesaurusItemContentType.CANDIDAT_CONTENT_TYPE_ID.equals(type))
177        {
178            infos.put("type", "candidate");
179            infos.put("leaf", "true");
180            infos.put("comment", term.getMetadataHolder().getString("comment", ""));
181        }
182        
183        if (checkMode)
184        {
185            infos.put("checked", "false");
186        }
187        
188        return infos;
189    }
190    
191    private String _getRelatedTerms (Content term)
192    {
193        List<String> relatedTerms = new ArrayList<>();
194        
195        if (term.getMetadataHolder().hasMetadata(ThesaurusDAO.METADATA_RELATED_TERMS))
196        {
197            String[] ids = term.getMetadataHolder().getStringArray(ThesaurusDAO.METADATA_RELATED_TERMS);
198            for (String id : ids)
199            {
200                Content relatedTerm = _resolver.resolveById(id);
201                relatedTerms.add(relatedTerm.getTitle());
202            }
203        }
204        
205        return StringUtils.join(relatedTerms, ", ");
206    }
207    
208    private String _getSpecificTerms (Content term)
209    {
210        List<String> specificTerms = new ArrayList<>();
211        
212        if (term.getMetadataHolder().hasMetadata(ThesaurusDAO.METADATA_SPECIFIC_TERMS))
213        {
214            TraversableAmetysObject ts = term.getMetadataHolder().getObjectCollection(ThesaurusDAO.METADATA_SPECIFIC_TERMS);
215            for (AmetysObject child : ts.getChildren())
216            {
217                if (child instanceof Content)
218                {
219                    specificTerms.add(((Content) child).getTitle());
220                } 
221            }
222        }
223        
224        return StringUtils.join(specificTerms, ", ");
225    }
226
227}