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    }