001/* 002 * Copyright 2016 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.repository.events; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023 024import javax.jcr.Node; 025import javax.jcr.NodeIterator; 026import javax.jcr.RepositoryException; 027 028import org.ametys.runtime.plugin.component.AbstractThreadSafeComponentExtensionPoint; 029 030/** 031 * This class is in charge of loading the various {@link EventType}. 032 * It also allows to communicate with them for the retrieval of events in JSON 033 */ 034public class EventTypeExtensionPoint extends AbstractThreadSafeComponentExtensionPoint<EventType> 035{ 036 /** The Avalon Role */ 037 public static final String ROLE = EventTypeExtensionPoint.class.getName(); 038 039 /** 040 * Add an event in the wanted event holder 041 * @param eventId the id of the event 042 * @param parameters the parameters of the event 043 * @param eventHolder the event holder node 044 * @return the created node 045 * @throws RepositoryException if an exception occurs while manipulating the repository 046 */ 047 public Node addEvent(String eventId, Map<String, Object> parameters, EventHolder eventHolder) throws RepositoryException 048 { 049 return getEventType(eventId).storeEvent(eventId, parameters, eventHolder); 050 } 051 052 /** 053 * Returns events of an event holder as JSON object 054 * @param eventHolder the event holder 055 * @return the events 056 * @throws RepositoryException if an exception occurs while manipulating the repository 057 */ 058 public List<Map<String, Object>> getEvents(EventHolder eventHolder) throws RepositoryException 059 { 060 return getEvents(eventHolder, null); 061 } 062 063 /** 064 * Returns events of an event holder as JSON object 065 * @param eventHolder the event holder 066 * @param eventIds the event's types to retrieve. Can be <code>null</code> to retrieve all events. 067 * @return the events 068 * @throws EventTypeProcessingException if failed to get events 069 */ 070 public List<Map<String, Object>> getEvents(EventHolder eventHolder, Set<String> eventIds) throws EventTypeProcessingException 071 { 072 return getEvents(eventHolder, eventIds, Integer.MAX_VALUE); 073 } 074 075 /** 076 * Returns events of an event holder as JSON object 077 * @param eventHolder the event holder 078 * @param eventIds the event's types to retrieve. Can be <code>null</code> to retrieve all events. 079 * @param limit The max number of events 080 * @return the events 081 * @throws EventTypeProcessingException if failed to get events 082 */ 083 public List<Map<String, Object>> getEvents(EventHolder eventHolder, Set<String> eventIds, int limit) throws EventTypeProcessingException 084 { 085 try 086 { 087 // TODO Do a Solr query and filter events on user rights 088 NodeIterator nodesIt = JCREventHelper.getEvents(eventHolder, eventIds != null ? eventIds.toArray(new String[eventIds.size()]) : null); 089 090 List<Map<String, Object>> events = new ArrayList<>(); 091 092 int count = 0; 093 while (nodesIt.hasNext() && count < limit) 094 { 095 Node eventNode = nodesIt.nextNode(); 096 String type = eventNode.getProperty(EventType.EVENT_TYPE).getString(); 097 098 Map<String, Object> event2json = getEventType(type).event2JSON(eventNode); 099 if (!event2json.isEmpty()) 100 { 101 events.add(event2json); 102 } 103 104 count++; 105 } 106 107 return events; 108 } 109 catch (RepositoryException e) 110 { 111 throw new EventTypeProcessingException("Failed to get events", e); 112 } 113 } 114 115 /** 116 * Merge events 117 * @param initialEvents The events to merge 118 * @return The merged events 119 */ 120 public List<Map<String, Object>> mergeEvents(List<Map<String, Object>> initialEvents) 121 { 122 List<Map<String, Object>> mergedEvents = new ArrayList<>(); 123 124 List<Map<String, Object>> events = new ArrayList<>(initialEvents); 125 Map<String, List<Map<String, Object>>> mergeableEvents = new HashMap<>(); 126 127 for (Map<String, Object> event : events) 128 { 129 List<Map<String, Object>> clonedEvents = new ArrayList<>(initialEvents); 130 131 for (Map<String, Object> clonedEvent : clonedEvents) 132 { 133 String eventName = (String) event.get("eventName"); 134 String clonedEventName = (String) clonedEvent.get("eventName"); 135 136 if (!eventName.equals(clonedEventName)) 137 { 138 EventType eventType = getEventType((String) event.get("type")); 139 EventType clonedEventType = getEventType((String) clonedEvent.get("type")); 140 141 if (eventType == clonedEventType && eventType.isMergeable(event, clonedEvent)) 142 { 143 // The two events can be merged 144 if (!mergeableEvents.containsKey(eventName)) 145 { 146 mergeableEvents.put(eventName, new ArrayList<>()); 147 mergeableEvents.get(eventName).add(event); 148 } 149 150 mergeableEvents.get(eventName).add(clonedEvent); 151 152 // The events were merged : no need to re-process them 153 initialEvents.remove(event); 154 initialEvents.remove(clonedEvent); 155 } 156 } 157 else 158 { 159 mergeableEvents.put(eventName, new ArrayList<>()); 160 mergeableEvents.get(eventName).add(event); 161 } 162 } 163 } 164 165 for (List<Map<String, Object>> evts : mergeableEvents.values()) 166 { 167 EventType eventType = getEventType((String) evts.get(0).get("type")); 168 mergedEvents.add(eventType.mergeEvents(evts)); 169 } 170 171 return mergedEvents; 172 } 173 174 /** 175 * Returns the first {@link EventType} matching the provided event id 176 * @param eventId the id of the event 177 * @return The event type 178 */ 179 public EventType getEventType(String eventId) 180 { 181 for (String extensionId : getExtensionsIds()) 182 { 183 EventType eventType = getExtension(extensionId); 184 if (eventType.getSupportedTypes().keySet().contains(eventId)) 185 { 186 return eventType; 187 } 188 } 189 190 throw new EventTypeProcessingException("There is no EventType corresponding with the id '" + eventId + "'."); 191 } 192}