001 package com.sptci.echo2;
002
003 import java.lang.reflect.Method;
004 import java.util.ArrayList;
005
006 import nextapp.echo2.app.Column;
007 import nextapp.echo2.app.Component;
008 import nextapp.echo2.app.Row;
009 import nextapp.echo2.app.WindowPane;
010
011 import nextapp.echo2.app.event.ActionEvent;
012 import nextapp.echo2.app.event.ActionListener;
013
014 import echopointng.DirectHtml;
015
016 import com.sptci.ReflectionUtility;
017
018 /**
019 * A confirmation dialogue component used to display a confirmation
020 * message prior to executin a specified method.
021 *
022 * <p>Copyright 2006 Sans Pareil Technologies, Inc.</p>
023 * @author Rakesh Vidyadharan 2006-03-01
024 * @version $Id: Confirmation.java 3111 2007-04-23 14:04:59Z rakesh $
025 */
026 public class Confirmation extends WindowPane
027 {
028 /**
029 * The component used to display the message.
030 */
031 private final DirectHtml message;
032
033 /**
034 * The executor instance to use to execute the action required
035 * after user confirmation.
036 */
037 private final Executor executor;
038
039 /**
040 * Construct a new pane with the specified title and message.
041 *
042 * @param title The title to use for the dialogue.
043 * @param message The confirmation message to display in the dialogue.
044 * The message can be plain text or valid HTML.
045 */
046 public Confirmation( String title, String message, Executor executor )
047 {
048 setStyleName( "Default.WindowPane" );
049 this.executor = executor;
050 setTitle( title );
051 setDefaultCloseOperation( WindowPane.DO_NOTHING_ON_CLOSE );
052 setModal( true );
053
054 Column column = new Column();
055 this.message = new DirectHtml( message );
056 column.add( this.message );
057 column.add( createButtons() );
058 add( column );
059 }
060
061 /**
062 * Create the standard buttons that will be displayed in the dialogue.
063 */
064 private Component createButtons()
065 {
066 Row row = new Row();
067
068 ConfirmationListener listener = new ConfirmationListener();
069 row.add( Utilities.createButton( getClass().getName(),
070 "yes", "", listener ) );
071 row.add( Utilities.createButton( getClass().getName(),
072 "no", "", listener ) );
073
074 return row;
075 }
076
077 /**
078 * The action listener for the buttons in the confirmation dialogue.
079 */
080 class ConfirmationListener implements ActionListener
081 {
082 /**
083 * Implementation of the action listener interface method.
084 */
085 public void actionPerformed( ActionEvent event )
086 {
087 String command = event.getActionCommand();
088 if ( command.equals( "yes" ) )
089 {
090 executor.execute();
091 }
092
093 getParent().remove( Confirmation.this );
094 }
095 }
096
097 /**
098 * The executor used to execute the desired action after user
099 * confirmation. You must use the {@link #addParameter} method
100 * if the method you specified requires parameters.
101 */
102 public static class Executor<S>
103 {
104 /**
105 * The source object whose {@link #methodName} should be invoked after
106 * user confirmation.
107 */
108 private final S source;
109
110 /**
111 * The method that is to be executed if the user confirms the
112 * action.
113 */
114 private final String methodName;
115
116 /**
117 * The arguments to be passed to the method. A two-dimensional
118 * array with each row containing the source at index 1 and
119 * the class of the source object at index 0. This is necessary to be
120 * able to correctly handle <code>null</code> objects.
121 */
122 private ArrayList<ArrayList> args;
123
124 /**
125 * Create a new instance of the class with the specified parameters
126 *
127 * @param source The {@link #source} to set.
128 * @param methodName The {@link #methodName} to set.
129 */
130 public Executor( S source, String methodName )
131 {
132 this.source = source;
133 this.methodName = methodName;
134 args = new ArrayList<ArrayList>();
135 }
136
137 /**
138 * Add the specified source and class combination to {@link #args}.
139 * This method should be invoked as many times are required by
140 * specifying the class and object parameters in the same order
141 * required to execute {@link #methodName}.
142 *
143 * @param cls The class of the parameter
144 * @param object The parameter value
145 */
146 public void addParameter( Class cls, Object object )
147 {
148 ArrayList list = new ArrayList( 2 );
149 list.add( cls );
150 list.add( object );
151 args.add( list );
152 }
153
154 /**
155 * Execute the {@link #methodName} on the {@link #source} with the
156 * {@link #args} parameters.
157 *
158 * @see ReflectionUtility#fetchMethod( Object, String, Class[] )
159 */
160 void execute()
161 {
162 Object[] objs = new Object[ args.size() ];
163 Class[] cls = new Class[ args.size() ];
164 for ( int i = 0; i < args.size(); ++i )
165 {
166 ArrayList list = args.get( i );
167 cls[i] = (Class) list.get( 0 );
168 objs[i] = list.get( 1 );
169 }
170
171 try
172 {
173 Method method = ReflectionUtility.fetchMethod(
174 source, methodName, cls );
175 method.invoke( source, objs );
176 }
177 catch ( Throwable t )
178 {
179 throw new RuntimeException( t );
180 }
181 }
182 }
183 }