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