package sushi.event; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToOne; import javax.persistence.Query; import javax.persistence.Table; import sushi.correlation.ConditionParser; import sushi.event.attribute.SushiAttribute; import sushi.event.collection.SushiMapTree; import sushi.notification.SushiCondition; import sushi.persistence.Persistable; import sushi.persistence.Persistor; /** * An EventTypeRule states a rule for creating new Events from existing Events in the database. * Events from certain eventTypes (usedEventTypes), * that fulfill a certain condition (conditionString) are trigger the creation * of a new event of the eventType createdEventType. */ @Entity @Table(name = "EventTypeRule") public class EventTypeRule extends Persistable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int ID; @ManyToMany(cascade = CascadeType.PERSIST, fetch=FetchType.EAGER) private ArrayList<SushiEventType> usedEventTypes = new ArrayList<SushiEventType>();; public ArrayList<SushiEventType> getUsedEventTypes() { return usedEventTypes; } public void setUsedEventTypes(ArrayList<SushiEventType> usedEventTypes) { this.usedEventTypes = usedEventTypes; } @OneToOne(optional=true, cascade = CascadeType.PERSIST, fetch= FetchType.EAGER) private SushiCondition condition; @OneToOne(optional=true) @JoinColumn(name = "EventType_ID") private SushiEventType createdEventType; @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.REMOVE}) @JoinColumn(name="MapTreeID") private SushiMapTree<String, Serializable> eventAttributes; public EventTypeRule(){ this.ID = 0; this.condition = null; this.createdEventType = null; } /** * An EventTypeRule states a rule for creating new Events from existing Events in the database. * Events from certain eventTypes (usedEventTypes), * that fulfill a certain condition (conditionString) are trigger the creation * of a new event of the eventType createdEventType * @param usedEventTypes: eventType of events that can trigger a new event * @param conditionString: condition, that must be fulfilled to trigger a new event * @param createdEventType: eventtype of the event created */ public EventTypeRule(ArrayList<SushiEventType> usedEventTypes, SushiCondition condition, SushiEventType createdEventType){ this.ID = 0; this.usedEventTypes = usedEventTypes; this.condition = condition; this.createdEventType = createdEventType; this.eventAttributes = ConditionParser.extractEventAttributes(condition.getConditionString()); } /** * This method executes the event type rule on the existing events from the database. * It will create new events. * @return created events */ public ArrayList<SushiEvent> execute() { List<SushiEvent> chosenEvents = new ArrayList<SushiEvent>(); //find Events for EventType for (SushiEventType usedEventType : usedEventTypes) { List<SushiEvent> chosenEventsForType = SushiEvent.findByEventType(usedEventType); if (! eventAttributes.isEmpty()) { chosenEventsForType.retainAll(SushiEvent.findByValues(eventAttributes)); } chosenEvents.addAll(chosenEventsForType); } //create new Events ArrayList<SushiEvent> newEvents = new ArrayList<SushiEvent>(); for (SushiEvent event : chosenEvents) { SushiEvent newEvent = new SushiEvent(this.createdEventType, event.getTimestamp(), createValues(event.getValues())); newEvents.add(newEvent); } return newEvents; } private SushiMapTree<String, Serializable> createValues(Map<String, Serializable> values) { SushiMapTree<String, Serializable> newValues= new SushiMapTree<String, Serializable>(); for (SushiAttribute attribute : createdEventType.getValueTypes()) { String attributeName = attribute.getAttributeExpression(); if (values.containsKey(attributeName)) { newValues.put(attributeName, values.get(attributeName)); } } return newValues; } /** * Removes the event type from the source event types of this rule. * This is needed for instance if the event type will be deleted. * @param eventType * @return */ public boolean removeUsedEventType(SushiEventType eventType){ for(SushiEventType usedEventType : usedEventTypes){ if(usedEventType.equals(eventType)){ boolean result = usedEventTypes.remove(usedEventType); this.save(); return result; } } return false; } //Getter and Setter public SushiEventType getCreatedEventType() { return createdEventType; } public void setCreatedEventType(SushiEventType createdEventType) { this.createdEventType = createdEventType; } @Override public int getID() { return ID; } //JPA-Methods /** * Finds the event type rules that use a certain event type as a source. * @param eventType * @return event type rules */ public static List<EventTypeRule> findEventTypeRuleForContainedEventType(SushiEventType eventType) { Query query = Persistor.getEntityManager().createNativeQuery("" + "SELECT * " + "FROM EventTypeRule " + "WHERE ID IN (" + " SELECT A.EventTypeRule_ID " + " FROM EventTypeRule_EventType AS A " + " WHERE usedEventTypes_ID = " + eventType.getID() + ")", EventTypeRule.class); return query.getResultList(); } /** * Finds the event type rules that use a certain event type as output. * @param eventType * @return event type rules */ public static EventTypeRule findEventTypeRuleForCreatedEventType(SushiEventType eventType) { Query query = Persistor.getEntityManager().createNativeQuery("SELECT * FROM EventTypeRule WHERE EventType_ID = " + eventType.getID(), EventTypeRule.class); assert(query.getResultList().size() < 2); if (query.getResultList().size() > 0) { return (EventTypeRule) query.getResultList().get(0);} else { return null; } } }