001// --------------------------------------------------------------------------------
002// Copyright 2002-2024 Echo Three, LLC
003//
004// Licensed under the Apache License, Version 2.0 (the "License");
005// you may not use this file except in compliance with the License.
006// You may obtain a copy of the License at
007//
008//     http://www.apache.org/licenses/LICENSE-2.0
009//
010// Unless required by applicable law or agreed to in writing, software
011// distributed under the License is distributed on an "AS IS" BASIS,
012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013// See the License for the specific language governing permissions and
014// limitations under the License.
015// --------------------------------------------------------------------------------
016
017package com.echothree.view.client.web.struts;
018
019import com.echothree.control.user.core.common.CoreUtil;
020import com.echothree.control.user.core.common.form.ValidateForm;
021import com.echothree.control.user.core.common.result.ValidateResult;
022import com.echothree.model.data.user.common.pk.UserVisitPK;
023import com.echothree.util.common.validation.FieldDefinition;
024import com.echothree.util.common.command.CommandResult;
025import com.echothree.util.common.command.ExecutionResult;
026import com.echothree.util.common.form.BaseForm;
027import com.echothree.util.common.form.BaseFormFactory;
028import com.echothree.view.client.web.WebConstants;
029import com.echothree.view.client.web.taglib.TagConstants;
030import com.echothree.view.common.BaseChoicesBean;
031import java.lang.reflect.InvocationTargetException;
032import java.lang.reflect.Method;
033import java.util.ArrayList;
034import java.util.HashMap;
035import java.util.Iterator;
036import java.util.List;
037import java.util.Map;
038import java.util.Map.Entry;
039import javax.naming.NamingException;
040import javax.servlet.http.HttpServletRequest;
041import javax.servlet.http.HttpSession;
042import org.apache.struts.action.ActionForm;
043import org.apache.struts.action.ActionMapping;
044import org.apache.struts.util.LabelValueBean;
045
046public class BaseActionForm
047        extends ActionForm {
048    
049    protected UserVisitPK userVisitPK;
050    private String dtIdAttribute;
051    private String dtSortParameter;
052    private String dtPageParameter;
053    private String dtOrderParameter;
054    private String submitButton;
055    
056    /** Creates a new instance of BaseActionForm */
057    public BaseActionForm() {
058        super();
059        
060        userVisitPK = null;
061    }
062    
063    public List<LabelValueBean> convertChoices(BaseChoicesBean choices) {
064        List<String> labels = choices.getLabels();
065        List<String> values = choices.getValues();
066        int labelsSize = labels.size();
067        int valuesSize = values.size();
068        List<LabelValueBean> result = null;
069        
070        if(labelsSize == valuesSize) {
071            result = new ArrayList<>(labelsSize);
072            Iterator<String> labelIterator = labels.iterator();
073            Iterator<String> valueIterator = values.iterator();
074            
075            while(labelIterator.hasNext() && valueIterator.hasNext()) {
076                String label = labelIterator.next();
077                String value = valueIterator.next();
078                
079                if(label == null)
080                    label = "";
081                
082                result.add(new LabelValueBean(label, value));
083            }
084        }
085        
086        return result;
087    }
088    
089    @Override
090    public void reset(ActionMapping mapping, HttpServletRequest request) {
091        super.reset(mapping, request);
092        
093        HttpSession httpSession = request.getSession(true);
094        
095        userVisitPK = (UserVisitPK)httpSession.getAttribute(WebConstants.Session_USER_VISIT);
096    }
097
098    public String getDtIdAttribute() {
099        return dtIdAttribute;
100    }
101
102    public void setDtIdAttribute(String dtIdAttribute) {
103        this.dtIdAttribute = dtIdAttribute;
104    }
105
106    public String getDtSortParameter() {
107        return dtSortParameter;
108    }
109
110    public void setDtSortParameter(String dtSortParameter) {
111        this.dtSortParameter = dtSortParameter;
112    }
113
114    public String getDtPageParameter() {
115        return dtPageParameter;
116    }
117
118    public void setDtPageParameter(String dtPageParameter) {
119        this.dtPageParameter = dtPageParameter;
120    }
121
122    public String getDtOrderParameter() {
123        return dtOrderParameter;
124    }
125
126    public void setDtOrderParameter(String dtOrderParameter) {
127        this.dtOrderParameter = dtOrderParameter;
128    }
129    
130    public void saveDtParameters(HttpServletRequest request) {
131        dtIdAttribute = request.getParameter(WebConstants.Parameter_DT_ID_ATTRIBUTE);
132        dtSortParameter = request.getParameter(WebConstants.Parameter_DT_SORT_PARAMETER);
133        dtPageParameter = request.getParameter(WebConstants.Parameter_DT_PAGE_PARAMETER);
134        dtOrderParameter = request.getParameter(WebConstants.Parameter_DT_ORDER_PARAMETER);
135    }
136
137    public String getSubmitButton() {
138        return submitButton;
139    }
140
141    public void setSubmitButton(String submitButton) {
142        this.submitButton = submitButton;
143    }
144
145    private ValidateForm getValidateForm(final List<FieldDefinition> fieldDefinitions, final Map<String, Class> returnTypes)
146            throws NamingException {
147        ValidateForm validateForm = CoreUtil.getHome().getValidateForm();
148        BaseForm baseForm = BaseFormFactory.createForm(BaseForm.class);
149        Class<?> clazz = this.getClass();
150
151        for(var fieldDefinition : fieldDefinitions) {
152            String fieldName = fieldDefinition.getFieldName();
153            
154            try {
155                Method method = clazz.getMethod(new StringBuilder("get").append(fieldName).toString());
156                Object fieldValue = method.invoke(this);
157
158                returnTypes.put(fieldName, method.getReturnType());
159
160                if(fieldValue != null) {
161                    baseForm.set(fieldName, fieldValue.toString());
162                }
163            } catch(NoSuchMethodException nsme) {
164                throw new RuntimeException(nsme);
165            } catch(IllegalAccessException iae) {
166                throw new RuntimeException(iae);
167            } catch(IllegalArgumentException iea) {
168                throw new RuntimeException(iea);
169            } catch(InvocationTargetException ite) {
170                throw new RuntimeException(ite);
171            }
172        }
173
174        validateForm.setFormFieldDefinitions(fieldDefinitions);
175        validateForm.setBaseForm(baseForm);
176
177        return validateForm;
178    }
179
180    private void setFormValidateResult(final ValidateResult validateResult, final Map<String, Class> returnTypes) {
181        BaseForm baseForm = validateResult.getBaseForm();
182        Map<String, Object> map = baseForm.get();
183        Class<?> clazz = this.getClass();
184
185        for(Entry<String, Object> entry : map.entrySet()) {
186            String key = entry.getKey();
187            Class<?> returnType = returnTypes.get(key);
188
189            // If getValidateForm didn't add a map entry, returnType will be null. Ignore those
190            // values, as they tend to be from functions like getFomName() which don't exist on
191            // the ActionForm.
192            if(returnType != null) {
193                String methodName = new StringBuilder("set").append(key).toString();
194                Object value = entry.getValue();
195
196                if(returnType.equals(Boolean.class) && value instanceof String) {
197                    value = Boolean.valueOf((String)value);
198                } else if(returnType.equals(Integer.class) && value instanceof String) {
199                    value = Integer.valueOf((String)value);
200                } else if(returnType.equals(Long.class) && value instanceof String) {
201                    value = Long.valueOf((String)value);
202                }
203
204                try {
205                    clazz.getMethod(methodName, returnType).invoke(this, value);
206                } catch(NoSuchMethodException nsme) {
207                    throw new RuntimeException(nsme);
208                } catch(IllegalAccessException iae) {
209                    throw new RuntimeException(iae);
210                } catch(IllegalArgumentException iea) {
211                    throw new RuntimeException(iea);
212                } catch(InvocationTargetException ite) {
213                    throw new RuntimeException(ite);
214                }
215            }
216        }
217    }
218
219    protected boolean validate(final HttpServletRequest request, final List<FieldDefinition> fieldDefinitions)
220            throws NamingException {
221        Map<String, Class> returnTypes = new HashMap<>(fieldDefinitions.size());
222        ValidateForm commandForm = getValidateForm(fieldDefinitions, returnTypes);
223
224        CommandResult commandResult = CoreUtil.getHome().validate(BaseAction.getUserVisitPK(request), commandForm);
225        if(!commandResult.hasErrors()) {
226            ExecutionResult executionResult = commandResult.getExecutionResult();
227
228            setFormValidateResult((ValidateResult)executionResult.getResult(), returnTypes);
229        }
230
231        request.setAttribute(TagConstants.CommandResultName, commandResult);
232
233        return !commandResult.hasErrors();
234    }
235    
236}