001/* 002 * Copyright 2019 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.tree; 017 018import java.util.HashMap; 019import java.util.Map; 020 021import org.apache.avalon.framework.service.ServiceException; 022import org.apache.avalon.framework.service.ServiceManager; 023import org.apache.commons.lang3.StringUtils; 024 025import org.ametys.cms.repository.Content; 026import org.ametys.cms.repository.WorkflowAwareContent; 027import org.ametys.core.ui.Callable; 028import org.ametys.odf.ODFHelper; 029import org.ametys.odf.ProgramItem; 030import org.ametys.odf.course.Course; 031import org.ametys.odf.course.ShareableCourseHelper; 032import org.ametys.odf.course.ShareableCourseStatusHelper; 033import org.ametys.odf.course.ShareableCourseStatusHelper.ShareableStatus; 034import org.ametys.odf.courselist.CourseList; 035import org.ametys.odf.orgunit.OrgUnit; 036import org.ametys.plugins.contentstree.ContentsTreeHelper; 037import org.ametys.plugins.workflow.repository.WorkflowAwareAmetysObject; 038import org.ametys.plugins.workflow.support.WorkflowProvider; 039import org.ametys.plugins.workflow.support.WorkflowProvider.AmetysObjectWorkflow; 040import org.ametys.runtime.i18n.I18nizableText; 041 042import com.opensymphony.workflow.loader.StepDescriptor; 043import com.opensymphony.workflow.loader.WorkflowDescriptor; 044 045/** 046 * Helper ODF contents tree 047 * 048 */ 049public class ODFContentsTreeHelper extends ContentsTreeHelper 050{ 051 /** The Avalon role */ 052 @SuppressWarnings("hiding") 053 public static final String ROLE = ODFContentsTreeHelper.class.getName(); 054 055 /** The ODF helper */ 056 protected ODFHelper _odfHelper; 057 /** The workflow provider */ 058 protected WorkflowProvider _workflowProvider; 059 /** The shareable course status helper */ 060 protected ShareableCourseStatusHelper _shareableStatusHelper; 061 /** The shareable course helper */ 062 protected ShareableCourseHelper _shareableCourseHelper; 063 064 @Override 065 public void service(ServiceManager smanager) throws ServiceException 066 { 067 super.service(smanager); 068 069 _workflowProvider = (WorkflowProvider) smanager.lookup(WorkflowProvider.ROLE); 070 _odfHelper = (ODFHelper) smanager.lookup(ODFHelper.ROLE); 071 _shareableCourseHelper = (ShareableCourseHelper) smanager.lookup(ShareableCourseHelper.ROLE); 072 _shareableStatusHelper = (ShareableCourseStatusHelper) smanager.lookup(ShareableCourseStatusHelper.ROLE); 073 } 074 075 @Override 076 @Callable 077 public Map<String, Object> getRootNodeInformations(String contentId) 078 { 079 Map<String, Object> infos = super.getRootNodeInformations(contentId); 080 infos.put("handleShareableCourse", _shareableCourseHelper.handleShareableCourse()); 081 return infos; 082 } 083 084 @Override 085 protected Map<String, Object> content2Json(Content content) 086 { 087 Map<String, Object> infos = super.content2Json(content); 088 if (content instanceof ProgramItem) 089 { 090 boolean isShared = isShared((ProgramItem) content); 091 boolean isSharedByParents = !isShared ? isSharedByParents((ProgramItem) content) : false; 092 infos.put("code", getProgramItemDisplayCode((Content & ProgramItem) content)); 093 infos.put("workflowStep", getWorkflowStep(content)); 094 infos.put("isShared", isShared); 095 infos.put("isParentShared", isSharedByParents); 096 097 if (content instanceof Course) 098 { 099 infos.put("shareableStatus", getShareableStatus((Course) content)); 100 } 101 else if (content instanceof CourseList) 102 { 103 CourseList courseList = (CourseList) content; 104 infos.put("courseList-type", courseList.getType()); 105 } 106 } 107 else if (content instanceof OrgUnit) 108 { 109 infos.put("code", ((OrgUnit) content).getUAICode()); 110 } 111 112 return infos; 113 } 114 115 /** 116 * Get the ProgramItem code we want to display. 117 * @param <T> The type of the program element, should be a subclasse of {@link ProgramItem} and {@link Content} 118 * @param programItem The program item 119 * @return The code to display 120 */ 121 protected <T extends ProgramItem & Content> Object getProgramItemDisplayCode(T programItem) 122 { 123 return programItem.getCode(); 124 } 125 126 @Override 127 protected boolean isContentMatching(Content content, String value) 128 { 129 boolean matchTitle = super.isContentMatching(content, value); 130 if (!matchTitle) 131 { 132 if (content instanceof ProgramItem) 133 { 134 // Try with code 135 String code = StringUtils.stripAccents(((ProgramItem) content).getCode().toLowerCase()); 136 return code.contains(value); 137 } 138 else if (content instanceof OrgUnit) 139 { 140 // Try with code 141 String code = StringUtils.stripAccents(((OrgUnit) content).getUAICode().toLowerCase()); 142 return code.contains(value); 143 } 144 } 145 146 return matchTitle; 147 } 148 149 /** 150 * Get workflow step information 151 * @param content the content the content 152 * @return the workflow step information 153 */ 154 protected Map<String, Object> getWorkflowStep(Content content) 155 { 156 Map<String, Object> workflowInfos = new HashMap<>(); 157 158 if (content instanceof WorkflowAwareAmetysObject) 159 { 160 WorkflowAwareContent waContent = (WorkflowAwareContent) content; 161 162 long workflowId = waContent.getWorkflowId(); 163 int currentStepId = Math.toIntExact(waContent.getCurrentStepId()); 164 165 AmetysObjectWorkflow workflow = _workflowProvider.getAmetysObjectWorkflow(waContent); 166 167 String workflowName = workflow.getWorkflowName(workflowId); 168 WorkflowDescriptor workflowDescriptor = workflow.getWorkflowDescriptor(workflowName); 169 170 if (workflowDescriptor != null) 171 { 172 StepDescriptor stepDescriptor = workflowDescriptor.getStep(currentStepId); 173 if (stepDescriptor != null) 174 { 175 I18nizableText workflowStepName = new I18nizableText("application", stepDescriptor.getName()); 176 177 workflowInfos.put("stepId", currentStepId); 178 workflowInfos.put("name", workflowStepName); 179 180 String[] icons = new String[] {"small", "medium", "large"}; 181 for (String icon : icons) 182 { 183 if ("application".equals(workflowStepName.getCatalogue())) 184 { 185 workflowInfos.put(icon + "Icon", "/plugins/cms/resources_workflow/" + workflowStepName.getKey() + "-" + icon + ".png"); 186 } 187 else 188 { 189 String pluginName = workflowStepName.getCatalogue().substring("plugin.".length()); 190 workflowInfos.put(icon + "Icon", "/plugins/" + pluginName + "/resources/img/workflow/" + workflowStepName.getKey() + "-" + icon + ".png"); 191 } 192 } 193 } 194 } 195 } 196 197 return workflowInfos; 198 } 199 200 /** 201 * Get the shared status of this program item 202 * @param programItem the program item 203 * @return true if the program item belongs to more than one program item 204 */ 205 protected boolean isShared(ProgramItem programItem) 206 { 207 return _odfHelper.getParentProgramItems(programItem).size() > 1; 208 } 209 210 /** 211 * Check if the parent of a program item is shared 212 * @param programItem the program item 213 * @return true if the parent of the program item is shared 214 */ 215 protected boolean isSharedByParents(ProgramItem programItem) 216 { 217 for (ProgramItem parent : _odfHelper.getParentProgramItems(programItem)) 218 { 219 return _odfHelper.getParentProgramItems(parent).size() > 1 ? true : isSharedByParents(parent); 220 } 221 return false; 222 } 223 224 /** 225 * Get the shareable course status as String 226 * @param course the course 227 * @return the shareable status 228 */ 229 protected String getShareableStatus(Course course) 230 { 231 if (_shareableCourseHelper.handleShareableCourse()) 232 { 233 ShareableStatus shareableStatus = _shareableStatusHelper.getShareableStatus(course); 234 return shareableStatus.name().toLowerCase(); 235 } 236 237 return null; 238 } 239}