001/* 002 * Ad Hoc Polling Application 003 * Copyright (C) 2018 Michael N. Lipp 004 * 005 * This program is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU Affero General Public License as published by 007 * the Free Software Foundation; either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, but 011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 013 * for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License along 016 * with this program; if not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jgrapes.core.internal; 020 021import java.util.concurrent.Callable; 022import org.jgrapes.core.Channel; 023import org.jgrapes.core.Components; 024import org.jgrapes.core.Event; 025import org.jgrapes.core.EventPipeline; 026 027/** 028 * A base class for events that perform an action instead of being 029 * handled. Use to synchronize some action with the other events on 030 * an {@link EventPipeline}. 031 */ 032public abstract class ActionEvent<T> extends Event<T> { 033 034 private static Object defaultCriterion = new Object(); 035 protected String name; 036 037 /** 038 * Instantiates a new action event. 039 * 040 * @param name the name 041 */ 042 protected ActionEvent(String name) { 043 this.name = name; 044 } 045 046 /* default */ static <V> ActionEvent<V> create(String name, 047 Callable<V> action) { 048 return new CallableActionEvent<>(name, action); 049 } 050 051 /* default */ static ActionEvent<Void> create(String name, 052 Runnable action) { 053 return new RunnableActionEvent(name, action); 054 } 055 056 @SuppressWarnings("PMD.SignatureDeclareThrowsException") 057 /* default */ abstract void execute() throws Exception; 058 059 @Override 060 public boolean isEligibleFor(Object criterion) { 061 return criterion == defaultCriterion; // NOPMD, comparing references 062 } 063 064 @Override 065 public Object defaultCriterion() { 066 return defaultCriterion; 067 } 068 069 @Override 070 public String toString() { 071 StringBuilder builder = new StringBuilder(); 072 builder.append(Components.objectName(this)); 073 if (name != null) { 074 builder.append('(').append(name).append(')'); 075 } 076 builder.append(" ["); 077 if (channels() != null) { 078 builder.append("channels="); 079 builder.append(Channel.toString(channels())); 080 } 081 builder.append(']'); 082 return builder.toString(); 083 } 084 085 /** 086 * An {@link ActionEvent} that executes a {@link Callable}. 087 * 088 * @param <V> the value type 089 */ 090 private static class CallableActionEvent<V> extends ActionEvent<V> { 091 private final Callable<V> action; 092 093 /** 094 * Instantiates a new callable action event. 095 * 096 * @param name the name 097 * @param callable the callable 098 */ 099 public CallableActionEvent(String name, Callable<V> callable) { 100 super(name); 101 this.action = callable; 102 } 103 104 @SuppressWarnings("PMD.SignatureDeclareThrowsException") 105 @Override 106 /* default */ void execute() throws Exception { 107 setResult(action.call()); 108 } 109 } 110 111 /** 112 * An {@link ActionEvent} that executes a {@link Runnable}. 113 */ 114 private static class RunnableActionEvent extends ActionEvent<Void> { 115 private final Runnable action; 116 117 /** 118 * Instantiates a new runnable action event. 119 * 120 * @param name the name 121 * @param action the action 122 */ 123 public RunnableActionEvent(String name, Runnable action) { 124 super(name); 125 this.action = action; 126 } 127 128 @SuppressWarnings("PMD.SignatureDeclareThrowsException") 129 @Override 130 /* default */ void execute() throws Exception { 131 action.run(); 132 } 133 134 } 135}