001    package hirondelle.web4jtools.codegenerator.field;
002    
003    import hirondelle.web4j.action.ActionTemplateListAndEdit;
004    import hirondelle.web4j.action.ResponsePage;
005    import hirondelle.web4j.database.DAOException;
006    import hirondelle.web4j.database.DuplicateException;
007    import hirondelle.web4j.model.Id;
008    import hirondelle.web4j.model.ModelCtorException;
009    import hirondelle.web4j.model.ModelFromRequest;
010    import hirondelle.web4j.request.RequestParameter;
011    import hirondelle.web4j.request.RequestParser;
012    import hirondelle.web4j.util.Util;
013    
014    import java.util.ArrayList;
015    import java.util.Iterator;
016    import java.util.List;
017    import java.util.logging.Logger;
018    
019    /**
020    * Edit the fields used by the feature.
021    * 
022    * <P>The order of how items are added will be retained in generated code.
023    */
024    public final class FieldAction extends ActionTemplateListAndEdit {
025    
026      /** Constructor.  */
027      public FieldAction(RequestParser aRequestParser){
028        super(FORWARD, REDIRECT_TO_LISTING, aRequestParser);
029      }
030      
031      public static final RequestParameter ID = RequestParameter.withLengthCheck("Id");
032      public static final RequestParameter NAME = RequestParameter.withLengthCheck("Name");
033      public static final RequestParameter DESCRIPTION = RequestParameter.withLengthCheck("Description");
034      public static final RequestParameter IS_REQUIRED = RequestParameter.withLengthCheck("IsRequired");
035      public static final RequestParameter TYPE = RequestParameter.withLengthCheck("Type");
036      public static final RequestParameter CONTROL_STYLE = RequestParameter.withLengthCheck("ControlStyle");
037      public static final RequestParameter IS_PRIMARY_KEY = RequestParameter.withRegexCheck("IsPrimaryKey", "(true|false)");
038      public static final RequestParameter MINIMUM = RequestParameter.withLengthCheck("Minimum");
039      public static final RequestParameter MAXIMUM = RequestParameter.withLengthCheck("Maximum");
040      public static final RequestParameter ERROR_MESSAGE = RequestParameter.withLengthCheck("ErrorMessage");
041      public static final RequestParameter IS_HARD_VALIDATED_FOR_LENGTH = RequestParameter.withRegexCheck("IsHardValidatedForLength", "(true|false)");
042      public static final RequestParameter HARD_VALIDATON_PATTERN = RequestParameter.withLengthCheck("HardValidationPattern");
043      public static final RequestParameter CHECK_PATTERN = RequestParameter.withLengthCheck("CheckPattern");
044      public static final RequestParameter CHECK_EMAIL = RequestParameter.withLengthCheck("CheckEmail");
045      public static final RequestParameter CHECK_SPAM = RequestParameter.withLengthCheck("CheckSpam");
046      public static final RequestParameter IS_ORDER_BY_FIELD = RequestParameter.withRegexCheck("IsOrderByField", "(true|false)");
047      public static final RequestParameter IS_DESC_ORDER = RequestParameter.withRegexCheck("IsDescendingOrder", "(true|false)");
048      public static final RequestParameter NUM_DECIMALS = RequestParameter.withLengthCheck("NumDecimals");
049      public static final RequestParameter CODE_TABLE = RequestParameter.withLengthCheck("CodeTable");
050    
051      /** Key for storing fields in session scope. */
052      public static final String FIELDS_KEY = "fields";
053      
054      /** List all Fields, in the same order as created.  */
055      protected void doList() throws DAOException {
056        addToRequest(ITEMS_FOR_LISTING, list());
057      }
058    
059      /** Ensure user input can build a {@link Field}.  */
060      protected void validateUserInput() {
061        try {
062          ModelFromRequest builder = new ModelFromRequest(getRequestParser());
063          fField = builder.build(
064            Field.class, ID, NAME, DESCRIPTION, IS_REQUIRED, TYPE, CONTROL_STYLE, IS_PRIMARY_KEY, MINIMUM, 
065            MAXIMUM, NUM_DECIMALS, ERROR_MESSAGE, IS_HARD_VALIDATED_FOR_LENGTH, HARD_VALIDATON_PATTERN, 
066            CHECK_PATTERN, CHECK_EMAIL, CHECK_SPAM, IS_ORDER_BY_FIELD, IS_DESC_ORDER, CODE_TABLE
067          );
068        }
069        catch (ModelCtorException ex){
070          addError(ex);
071        }    
072      }
073      
074      /** Add a new {@link Field}.  */
075      protected void attemptAdd() throws DAOException {
076        try {
077          add(fField);
078          addMessage("_1_ added successfully.", fField.getName());
079        }
080        catch(DuplicateException ex){
081          addError("Field Name already taken. Please use another name. Must be unique.");  
082        }
083      }
084      
085      /** Fetch an existing {@link Field} in order to edit it.  */
086      protected void attemptFetchForChange() throws DAOException {
087        Field field = fetch(getIdParam(ID));
088        if( field != null ){
089          addToRequest(ITEM_FOR_EDIT, field);
090        }
091      }
092      
093      /** Apply an edit to an existing {@link Field}.  */
094      protected void attemptChange() throws DAOException {
095        boolean success = change(fField);
096        if (success){
097          addMessage("_1_ changed successfully.", fField.getName());
098        }
099        else {
100          addError("No update occurred. Item deleted?");
101        }
102      }
103      
104      /** Ensure the {@link Field} of a given id does not exist. */
105      protected void attemptDelete() throws DAOException {
106        Id id = getIdParam(ID);
107        fLogger.fine("Deleting with id " + id);
108        delete(id);
109        addMessage("Item deleted successfully.");
110      }
111      
112      // PRIVATE //
113      private Field fField;
114      private static final ResponsePage FORWARD =  new ResponsePage("Fields", "view.jsp", FieldAction.class);
115      private static final ResponsePage REDIRECT_TO_LISTING = new ResponsePage("FieldAction.do?Operation=List");
116      private static final Logger fLogger = Util.getLogger(FieldAction.class);
117      
118      private List<Field> list() {
119        List<Field> result = new ArrayList<Field>();
120        Object object = getFromSession(FIELDS_KEY);
121        if ( object != null ) {
122          result = (List<Field>)object;
123        }
124        return result;
125      }
126    
127      private Field fetch(Id aFieldId) {
128        Field result = null;
129        List<Field> fields = list();
130        if ( fields == null ) {
131          addError("Cannot fetch item. No Fields found in session.");
132        }
133        else {
134          Integer id = Integer.valueOf(aFieldId.toString());
135          if ( id > fields.size() -1) {
136            addError("Cannot find Field of index " + id);
137          }
138          else {
139            result = fields.get(id);
140          }
141        }
142        return result;
143      }
144      
145      private void add(Field aField) throws DuplicateException {
146        if ( contains(aField.getName()) ) {
147          RuntimeException ex = new RuntimeException();
148          throw new DuplicateException("That field name is already taken. Please select another name.", ex);
149        }
150        List<Field> list = list();
151        list.add(aField); //adds to the end of the list
152        applyUpdate(list);
153      }
154    
155      private void applyUpdate(List<Field> aList) {
156        fLogger.fine("Applying update to fields stored in session.");
157        addToSession(FIELDS_KEY, aList);
158      }
159    
160      private boolean contains(String aFieldName){
161        boolean result = false;
162        List<Field> fields = list();
163        for(Field field : fields ){
164          if ( field.getName().equalsIgnoreCase(aFieldName)) {
165            result = true;
166            break;
167          }
168        }
169        return result;
170      }
171      
172      private void  delete(Id aFieldId){
173        Integer id = Integer.valueOf(aFieldId.toString());
174        List<Field> fields = list();
175        if ( fields == null ) {
176          addError("No Fields in session. Cannot delete item.");
177        }
178        if ( id > fields.size() - 1 ) {
179          addError("Cannot find item using index : " + id);
180        }
181        else {
182          fLogger.fine("Removing item using id " + id);
183          fields.remove(id.intValue()); //must use int, not Integer!!! overloaded with Object
184          applyUpdate(fields);
185        }
186      }
187      
188      private boolean change(Field aReplacementField) throws DuplicateException {
189        boolean result = false;
190        Integer id = Integer.valueOf(aReplacementField.getId().toString());
191        //replace it with aReplacementField
192        List<Field> fields = list();
193        Iterator<Field> iter = fields.iterator();
194        int index = 0;
195        while ( iter.hasNext() ) {
196          if ( id == index ){
197            fields.set(index, aReplacementField);
198            result = true;
199            break;
200          }
201          ++index;
202        }
203        return result;
204      }
205    }