001/* 002 * Copyright 2025 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.observation.skill; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.Optional; 021 022import org.apache.avalon.framework.context.Context; 023import org.apache.avalon.framework.context.ContextException; 024import org.apache.avalon.framework.context.Contextualizable; 025import org.apache.cocoon.components.ContextHelper; 026import org.apache.cocoon.environment.Request; 027import org.apache.commons.lang3.ArrayUtils; 028 029import org.ametys.cms.data.ContentValue; 030 031/** 032 * Abstract observer to prepare skills step observer when a content is updated 033 */ 034public abstract class AbstractSkillsStepObserver extends AbstractSkillsObserver implements Contextualizable 035{ 036 /** The context */ 037 protected Context _context; 038 039 public void contextualize(Context context) throws ContextException 040 { 041 _context = context; 042 } 043 044 /** 045 * Get the skills to delete 046 * @param previousSkills The previous skills 047 * @param currentSkills The current skills 048 * @return The skills to delete 049 */ 050 protected ContentValue[] getSkillsToDelete(ContentValue[] previousSkills, ContentValue[] currentSkills) 051 { 052 // If the current skills are null or empty, we need to delete the previous skills 053 ContentValue[] skillsToDelete = previousSkills; 054 // If the current skills are not null or empty, we need to compare them with the previous skills to retrieve the ones that need to be deleted 055 if (previousSkills != null && currentSkills != null) 056 { 057 // Get the skills that were in the skills but are not after modification 058 for (ContentValue newValue : currentSkills) 059 { 060 skillsToDelete = ArrayUtils.removeElement(skillsToDelete, newValue); 061 } 062 } 063 064 return skillsToDelete; 065 } 066 067 /** 068 * Get request attribute for a content 069 * @param <T> The type of results 070 * @param attributeName The name of the attribute 071 * @param contentId The content identifier 072 * @return The value found in request or default value 073 */ 074 protected <T> T _getRequestAttribute(String attributeName, String contentId) 075 { 076 return this.<T>_getRequestAttribute(ContextHelper.getRequest(_context), attributeName) 077 .get(contentId); 078 } 079 080 @SuppressWarnings("unchecked") 081 private <T> Map<String, T> _getRequestAttribute(Request request, String attributeName) 082 { 083 return Optional.of(request) 084 .map(r -> (Map<String, T>) r.getAttribute(attributeName)) 085 .orElseGet(HashMap::new); 086 } 087 088 /** 089 * Set a request attribute for a content 090 * @param <T> The type of the attribute 091 * @param attributeName The name of the attribute 092 * @param contentId The content identifier 093 * @param value The value 094 */ 095 protected <T> void _setRequestAttribute(String attributeName, String contentId, T value) 096 { 097 Request request = ContextHelper.getRequest(_context); 098 Map<String, T> attribute = _getRequestAttribute(request, attributeName); 099 attribute.put(contentId, value); 100 request.setAttribute(attributeName, attribute); 101 } 102}