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.cms.search.systemprop;
017
018import java.util.Collection;
019import java.util.Iterator;
020import java.util.LinkedHashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.apache.avalon.framework.configuration.Configuration;
025import org.apache.avalon.framework.configuration.DefaultConfiguration;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028
029import org.ametys.cms.contenttype.MetadataType;
030import org.ametys.cms.repository.Content;
031import org.ametys.cms.repository.WorkflowAwareContent;
032import org.ametys.cms.search.SearchField;
033import org.ametys.cms.search.model.SystemProperty;
034import org.ametys.cms.search.query.Query;
035import org.ametys.cms.search.query.Query.Operator;
036import org.ametys.cms.search.query.WorkflowStepQuery;
037import org.ametys.cms.search.solr.field.WorkflowStepSearchField;
038import org.ametys.cms.workflow.DefaultWorkflowStepEnumerator;
039import org.ametys.plugins.workflow.support.WorkflowHelper;
040import org.ametys.plugins.workflow.support.WorkflowProvider;
041import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow;
042import org.ametys.runtime.i18n.I18nizableText;
043
044import com.opensymphony.workflow.loader.StepDescriptor;
045import com.opensymphony.workflow.loader.WorkflowDescriptor;
046import com.opensymphony.workflow.spi.Step;
047
048/**
049 * {@link SystemProperty} which represents the current workflow step ID of a content.
050 */
051public class WorkflowStepSystemProperty extends AbstractSystemProperty
052{
053    /** The workflow provider */
054    protected WorkflowProvider _workflowProvider;
055    
056    /** The workflow helper */
057    protected WorkflowHelper _workflowHelper;
058    
059    @Override
060    public void service(ServiceManager manager) throws ServiceException
061    {
062        super.service(manager);
063        _workflowProvider = (WorkflowProvider) manager.lookup(WorkflowProvider.ROLE);
064        _workflowHelper = (WorkflowHelper) manager.lookup(WorkflowHelper.ROLE);
065    }
066    
067    @Override
068    public MetadataType getType()
069    {
070        return MetadataType.LONG;
071    }
072    
073    @Override
074    public boolean isMultiple()
075    {
076        return false;
077    }
078    
079    @Override
080    public boolean isSortable()
081    {
082        return true;
083    }
084    
085    @Override
086    public Query getQuery(Object value, Operator operator, String language, Map<String, Object> contextualParameters)
087    {
088        long stepId = parseLong(value);
089        if (stepId != 0)
090        {
091            return new WorkflowStepQuery(operator, (int) stepId);
092        }
093        
094        return null;
095    }
096    
097    @Override
098    public SearchField getSearchField()
099    {
100        return new WorkflowStepSearchField();
101    }
102    
103    @Override
104    public String getRenderer()
105    {
106        return "Ametys.cms.content.EditContentsGrid.renderWorkflowStep";
107    }
108    
109    @Override
110    public String getConverter()
111    {
112        return "Ametys.cms.content.EditContentsGrid.convertWorkflowStep";
113    }
114    
115    @Override
116    public Integer getColumnWidth()
117    {
118        return 60;
119    }
120    
121    @Override
122    public Object getValue(Content content)
123    {
124        if (content instanceof WorkflowAwareContent)
125        {
126            WorkflowAwareContent waContent = (WorkflowAwareContent) content;
127            AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(waContent);
128            
129            long workflowId = waContent.getWorkflowId();
130            List<Step> currentSteps = workflow.getCurrentSteps(workflowId);
131            
132            if (!currentSteps.isEmpty())
133            {
134                return currentSteps.iterator().next().getStepId();
135            }
136        }
137        
138        return null;
139    }
140    
141    @Override
142    public Object getFullValue(Content content)
143    {
144        Map<String, Object> workflowInfos = new LinkedHashMap<>();
145        
146        if (content instanceof WorkflowAwareContent)
147        {
148            WorkflowAwareContent waContent = (WorkflowAwareContent) content;
149            AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(waContent);
150            
151            int currentStepId = 0;
152            
153            long workflowId = waContent.getWorkflowId();
154            Iterator<Step> currentSteps = workflow.getCurrentSteps(workflowId).iterator();
155            
156            while (currentSteps.hasNext())
157            {
158                Step step = currentSteps.next();
159                currentStepId = step.getStepId();
160            }
161            
162            String workflowName = workflow.getWorkflowName(workflowId);
163            WorkflowDescriptor workflowDescriptor = workflow.getWorkflowDescriptor(workflowName);
164            
165            if (workflowDescriptor != null)
166            {
167                StepDescriptor stepDescriptor = workflowDescriptor.getStep(currentStepId);
168                if (stepDescriptor != null)
169                {
170                    I18nizableText workflowStepName = new I18nizableText("application", stepDescriptor.getName());
171                    
172                    workflowInfos.put("stepId", currentStepId);
173                    workflowInfos.put("name", workflowStepName);
174                    
175                    String[] icons = new String[] {"small", "medium", "large"};
176                    for (String icon : icons)
177                    {
178                        if ("application".equals(workflowStepName.getCatalogue()))
179                        {
180                            workflowInfos.put(icon + "Icon", "/plugins/cms/resources_workflow/" + workflowStepName.getKey() + "-" + icon + ".png");
181                        }
182                        else
183                        {
184                            String pluginName = workflowStepName.getCatalogue().substring("plugin.".length());
185                            workflowInfos.put(icon + "Icon", "/plugins/" + pluginName + "/resources/img/workflow/" + workflowStepName.getKey() + "-" + icon + ".png");
186                        }
187                    }
188                }
189                else if (getLogger().isWarnEnabled())
190                {
191                    getLogger().warn("Unknown step id '" + currentStepId + "' for workflow for name : " + workflowName);
192                }
193            }
194            else if (getLogger().isWarnEnabled())
195            {
196                getLogger().warn("Unknown workflow for name : " + workflowName);
197            }
198        }
199        
200        return workflowInfos;
201    }
202    
203    @Override
204    public EnumeratorDefinition getEnumeratorDefinition(Collection<String> contentTypes, Configuration configuration)
205    {
206        DefaultConfiguration conf = new DefaultConfiguration("criteria");
207        
208        String workflowName = configuration.getChild("workflow").getAttribute("name", "content");
209        
210        DefaultConfiguration enumConf = new DefaultConfiguration("enumeration");
211        
212        DefaultConfiguration customEnumerator = new DefaultConfiguration("custom-enumerator");
213        customEnumerator.setAttribute("class", DefaultWorkflowStepEnumerator.class.getName());
214        enumConf.addChild(customEnumerator);
215        
216        DefaultConfiguration wfNameConf = new DefaultConfiguration("workflow-name");
217        wfNameConf.setValue(workflowName);
218        customEnumerator.addChild(wfNameConf);
219        
220        DefaultConfiguration excludeConf = new DefaultConfiguration("exclude-workflow-steps");
221        
222        // Exclude workflow steps greater than 9000
223        List<StepDescriptor> steps = _workflowHelper.getWorkflowDescriptor(workflowName).getSteps();
224        for (StepDescriptor stepDescriptor : steps)
225        {
226            if (stepDescriptor.getId() >= 9000)
227            {
228                DefaultConfiguration stepId = new DefaultConfiguration("id");
229                stepId.setValue(stepDescriptor.getId());
230                excludeConf.addChild(stepId);
231            }
232        }
233        
234        customEnumerator.addChild(excludeConf);
235        
236        conf.addChild(enumConf);
237        
238        return new EnumeratorDefinition(DefaultWorkflowStepEnumerator.class, conf);
239    }
240
241}