001/*
002 *  Copyright 2017 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.extraction.component;
017
018import java.util.Collections;
019import java.util.HashSet;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.configuration.Configuration;
024import org.apache.avalon.framework.configuration.ConfigurationException;
025import org.apache.cocoon.xml.AttributesImpl;
026import org.apache.cocoon.xml.XMLUtils;
027import org.xml.sax.ContentHandler;
028
029import org.ametys.cms.repository.ModifiableDefaultContent;
030import org.ametys.plugins.extraction.ExtractionConstants;
031import org.ametys.plugins.extraction.execution.ExtractionExecutionContext;
032import org.ametys.plugins.extraction.execution.ExtractionExecutionContextHierarchyElement;
033import org.ametys.plugins.repository.AmetysObject;
034import org.ametys.plugins.repository.AmetysObjectIterable;
035import org.ametys.plugins.repository.TraversableAmetysObject;
036import org.ametys.plugins.thesaurus.MicroThesaurus;
037import org.ametys.plugins.thesaurus.Thesaurus;
038import org.ametys.plugins.thesaurus.content.ThesaurusItemContentType;
039
040/**
041 * This class represents a thesaurus component of the extraction module
042 */
043public class ThesaurusExtractionComponent extends AbstractExtractionComponent
044{
045    private String _thesaurusName;
046    private String _microThesaurusName;
047    private int _maxLevel;
048    
049    private Thesaurus _thesaurus;
050    private MicroThesaurus _microThesaurus;
051    
052
053    @Override
054    public void configure(Configuration thesaurus) throws ConfigurationException
055    {
056        super.configure(thesaurus);
057        _thesaurusName = thesaurus.getAttribute("thesaurusName");
058        _microThesaurusName = thesaurus.getAttribute("microThesaurusName");
059        _maxLevel = thesaurus.getAttributeAsInteger("max-level", -1);
060    }
061
062    @Override
063    public void prepareComponentExecution(ExtractionExecutionContext context) throws Exception
064    {
065        super.prepareComponentExecution(context);
066        _thesaurus = _thesaurusDAO.getThesaurusByName(_thesaurusName);
067        if (null == _thesaurus)
068        {
069            throw new IllegalArgumentException(getLogsPrefix() + "thesaurus '" + _thesaurusName + "' does not exist");
070        }
071        
072        _microThesaurus = _thesaurusDAO.getMicrothesaurusByName(_thesaurusName, _microThesaurusName);
073        if (null == _microThesaurus)
074        {
075            throw new IllegalArgumentException(getLogsPrefix() + "microthesaurus '" + _microThesaurusName + "' does not exist in thesaurus '" + _thesaurusName + "'");
076        }
077    }
078        
079    @Override
080    public void executeComponent(ContentHandler contentHandler, ExtractionExecutionContext context) throws Exception
081    {
082        AttributesImpl thesaurusAttributes = new AttributesImpl();
083        thesaurusAttributes.addCDATAAttribute("thesaurusLabel", _thesaurus.getLabel());
084        thesaurusAttributes.addCDATAAttribute("microThesaurusLabel", _microThesaurus.getLabel());
085        XMLUtils.startElement(contentHandler, _tagName, thesaurusAttributes);
086        
087        AmetysObjectIterable<AmetysObject> children = _microThesaurus.getChildren();
088        _processChildren(contentHandler, children, 1, context);
089        
090        XMLUtils.endElement(contentHandler, _tagName);
091    }
092    
093    public Set<String> getContentTypes()
094    {
095        return new HashSet<>(Collections.singletonList(ThesaurusItemContentType.TERM_CONTENT_TYPE_ID));
096    }
097
098    private void _processChildren(ContentHandler contentHandler, AmetysObjectIterable<AmetysObject> children, int currentLevel, ExtractionExecutionContext context) throws Exception
099    {
100        int nbTermChildren = -1;
101        int currentChildIndex = 0;
102        if (getLogger().isDebugEnabled())
103        {
104            nbTermChildren = _getNbTermChildren(children);
105        }
106        
107        for (AmetysObject child : children)
108        {
109            if (child instanceof ModifiableDefaultContent)
110            {
111                if (getLogger().isDebugEnabled())
112                {
113                    getLogger().debug(getLogsPrefix() + "executing term " + ++currentChildIndex + "/" + nbTermChildren + " at level " + currentLevel);
114                }
115                
116                ModifiableDefaultContent term = (ModifiableDefaultContent) child;
117
118                AttributesImpl attributes = new AttributesImpl();
119                attributes.addCDATAAttribute("name", term.getTitle());
120                XMLUtils.startElement(contentHandler, "term", attributes);
121
122                if (_maxLevel < 0 || currentLevel < _maxLevel)
123                {
124                    ExtractionExecutionContextHierarchyElement currentContext = new ExtractionExecutionContextHierarchyElement(this, Collections.singleton(term), false);
125                    executeSubComponents(contentHandler, context, currentContext);
126                    _processChildren(contentHandler, term.getChildren(), currentLevel + 1, context);
127                }
128                else
129                {
130                    ExtractionExecutionContextHierarchyElement currentContext = new ExtractionExecutionContextHierarchyElement(this, Collections.singleton(term));
131                    executeSubComponents(contentHandler, context, currentContext);
132                }
133                
134                XMLUtils.endElement(contentHandler, "term");
135            }
136            else
137            {
138                _processChildren(contentHandler, ((TraversableAmetysObject) child).getChildren(), currentLevel, context);
139            }
140        }
141    }
142    
143    private int _getNbTermChildren(AmetysObjectIterable<AmetysObject> children)
144    {
145        int nbTermChildren = 0;
146        for (AmetysObject child : children)
147        {
148            if (child instanceof ModifiableDefaultContent)
149            {
150                nbTermChildren++;
151            }
152        }
153        return nbTermChildren;
154    }
155    
156    @Override
157    public Map<String, Object> getComponentDetailsForTree()
158    {
159        Map<String, Object> details = super.getComponentDetailsForTree();
160        details.put("tag", ExtractionConstants.THESAURUS_COMPONENT_TAG);
161        
162        @SuppressWarnings("unchecked")
163        Map<String, Object> data = (Map<String, Object>) details.get("data");
164        data.put("thesaurusName", this.getThesaurusName());
165        data.put("microThesaurusName", this.getMicroThesaurusName());
166        data.put("maxLevel", this.getMaxLevel());
167        details.put("iconCls", "ametysicon-books");
168        
169        return details;
170    }
171
172    @Override
173    protected String getDefaultTagName()
174    {
175        return "thesaurus";
176    }
177
178    @Override
179    protected String getLogsPrefix()
180    {
181        return "Thesaurus component '" + _tagName + "': ";
182    }
183
184    /**
185     * Retrieves the component thesaurus name
186     * @return The thesaurus name
187     */
188    public String getThesaurusName()
189    {
190        return _thesaurusName;
191    }
192
193    /**
194     * Set the thesaurus name
195     * @param thesaurusName The thesaurus name to set
196     */
197    public void setThesaurusName(String thesaurusName)
198    {
199        _thesaurusName = thesaurusName;
200    }
201
202    /**
203     * Retrieves the component microthesaurus name
204     * @return The microthesaurus name
205     */
206    public String getMicroThesaurusName()
207    {
208        return _microThesaurusName;
209    }
210
211    /**
212     * Set the microthesaurus name
213     * @param thesaurusName The microthesaurus name to set
214     */
215    public void setMicroThesaurusName(String thesaurusName)
216    {
217        _microThesaurusName = thesaurusName;
218    }
219
220    /**
221     * Retrieves the maximum level of specific terms to look at
222     * @return The maximum level
223     */
224    public int getMaxLevel()
225    {
226        return _maxLevel;
227    }
228
229    /**
230     * Set the maximum level of specific terms to look at
231     * @param maxLevel The maximum level to set
232     */
233    public void setMaxLevel(int maxLevel)
234    {
235        _maxLevel = maxLevel;
236    }
237}