001// --------------------------------------------------------------------------------
002// Copyright 2002-2025 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.form.BaseForm;
025import com.echothree.util.common.form.BaseFormFactory;
026import com.echothree.view.client.web.WebConstants;
027import com.echothree.view.client.web.taglib.TagConstants;
028import com.echothree.view.common.BaseChoicesBean;
029import java.lang.reflect.InvocationTargetException;
030import java.util.ArrayList;
031import java.util.HashMap;
032import java.util.List;
033import java.util.Map;
034import javax.naming.NamingException;
035import javax.servlet.http.HttpServletRequest;
036import org.apache.struts.action.ActionForm;
037import org.apache.struts.action.ActionMapping;
038import org.apache.struts.util.LabelValueBean;
039
040public class BaseActionForm
041        extends ActionForm {
042    
043    protected UserVisitPK userVisitPK;
044    private String dtIdAttribute;
045    private String dtSortParameter;
046    private String dtPageParameter;
047    private String dtOrderParameter;
048    private String submitButton;
049    
050    /** Creates a new instance of BaseActionForm */
051    public BaseActionForm() {
052        super();
053        
054        userVisitPK = null;
055    }
056    
057    public List<LabelValueBean> convertChoices(BaseChoicesBean choices) {
058        var labels = choices.getLabels();
059        var values = choices.getValues();
060        var labelsSize = labels.size();
061        var valuesSize = values.size();
062        List<LabelValueBean> result = null;
063        
064        if(labelsSize == valuesSize) {
065            result = new ArrayList<>(labelsSize);
066            var labelIterator = labels.iterator();
067            var valueIterator = values.iterator();
068            
069            while(labelIterator.hasNext() && valueIterator.hasNext()) {
070                var label = labelIterator.next();
071                var value = valueIterator.next();
072                
073                if(label == null)
074                    label = "";
075                
076                result.add(new LabelValueBean(label, value));
077            }
078        }
079        
080        return result;
081    }
082    
083    @Override
084    public void reset(ActionMapping mapping, HttpServletRequest request) {
085        super.reset(mapping, request);
086
087        var httpSession = request.getSession(true);
088        
089        userVisitPK = (UserVisitPK)httpSession.getAttribute(WebConstants.Session_USER_VISIT);
090    }
091
092    public String getDtIdAttribute() {
093        return dtIdAttribute;
094    }
095
096    public void setDtIdAttribute(String dtIdAttribute) {
097        this.dtIdAttribute = dtIdAttribute;
098    }
099
100    public String getDtSortParameter() {
101        return dtSortParameter;
102    }
103
104    public void setDtSortParameter(String dtSortParameter) {
105        this.dtSortParameter = dtSortParameter;
106    }
107
108    public String getDtPageParameter() {
109        return dtPageParameter;
110    }
111
112    public void setDtPageParameter(String dtPageParameter) {
113        this.dtPageParameter = dtPageParameter;
114    }
115
116    public String getDtOrderParameter() {
117        return dtOrderParameter;
118    }
119
120    public void setDtOrderParameter(String dtOrderParameter) {
121        this.dtOrderParameter = dtOrderParameter;
122    }
123    
124    public void saveDtParameters(HttpServletRequest request) {
125        dtIdAttribute = request.getParameter(WebConstants.Parameter_DT_ID_ATTRIBUTE);
126        dtSortParameter = request.getParameter(WebConstants.Parameter_DT_SORT_PARAMETER);
127        dtPageParameter = request.getParameter(WebConstants.Parameter_DT_PAGE_PARAMETER);
128        dtOrderParameter = request.getParameter(WebConstants.Parameter_DT_ORDER_PARAMETER);
129    }
130
131    public String getSubmitButton() {
132        return submitButton;
133    }
134
135    public void setSubmitButton(String submitButton) {
136        this.submitButton = submitButton;
137    }
138
139    private ValidateForm getValidateForm(final List<FieldDefinition> fieldDefinitions, final Map<String, Class> returnTypes)
140            throws NamingException {
141        var validateForm = CoreUtil.getHome().getValidateForm();
142        var baseForm = BaseFormFactory.createForm(BaseForm.class);
143        Class<?> clazz = this.getClass();
144
145        for(var fieldDefinition : fieldDefinitions) {
146            var fieldName = fieldDefinition.getFieldName();
147            
148            try {
149                var method = clazz.getMethod("get" + fieldName);
150                var fieldValue = method.invoke(this);
151
152                returnTypes.put(fieldName, method.getReturnType());
153
154                if(fieldValue != null) {
155                    baseForm.set(fieldName, fieldValue.toString());
156                }
157            } catch(NoSuchMethodException nsme) {
158                throw new RuntimeException(nsme);
159            } catch(IllegalAccessException iae) {
160                throw new RuntimeException(iae);
161            } catch(IllegalArgumentException iea) {
162                throw new RuntimeException(iea);
163            } catch(InvocationTargetException ite) {
164                throw new RuntimeException(ite);
165            }
166        }
167
168        validateForm.setFormFieldDefinitions(fieldDefinitions);
169        validateForm.setBaseForm(baseForm);
170
171        return validateForm;
172    }
173
174    private void setFormValidateResult(final ValidateResult validateResult, final Map<String, Class> returnTypes) {
175        var baseForm = validateResult.getBaseForm();
176        var map = baseForm.get();
177        Class<?> clazz = this.getClass();
178
179        for(var entry : map.entrySet()) {
180            var key = entry.getKey();
181            Class<?> returnType = returnTypes.get(key);
182
183            // If getValidateForm didn't add a map entry, returnType will be null. Ignore those
184            // values, as they tend to be from functions like getFomName() which don't exist on
185            // the ActionForm.
186            if(returnType != null) {
187                var methodName = "set" + key;
188                var value = entry.getValue();
189
190                if(returnType.equals(Boolean.class) && value instanceof String) {
191                    value = Boolean.valueOf((String)value);
192                } else if(returnType.equals(Integer.class) && value instanceof String) {
193                    value = Integer.valueOf((String)value);
194                } else if(returnType.equals(Long.class) && value instanceof String) {
195                    value = Long.valueOf((String)value);
196                }
197
198                try {
199                    clazz.getMethod(methodName, returnType).invoke(this, value);
200                } catch(NoSuchMethodException nsme) {
201                    throw new RuntimeException(nsme);
202                } catch(IllegalAccessException iae) {
203                    throw new RuntimeException(iae);
204                } catch(IllegalArgumentException iea) {
205                    throw new RuntimeException(iea);
206                } catch(InvocationTargetException ite) {
207                    throw new RuntimeException(ite);
208                }
209            }
210        }
211    }
212
213    protected boolean validate(final HttpServletRequest request, final List<FieldDefinition> fieldDefinitions)
214            throws NamingException {
215        Map<String, Class> returnTypes = new HashMap<>(fieldDefinitions.size());
216        var commandForm = getValidateForm(fieldDefinitions, returnTypes);
217
218        var commandResult = CoreUtil.getHome().validate(BaseAction.getUserVisitPK(request), commandForm);
219        if(!commandResult.hasErrors()) {
220            var executionResult = commandResult.getExecutionResult();
221
222            setFormValidateResult((ValidateResult)executionResult.getResult(), returnTypes);
223        }
224
225        request.setAttribute(TagConstants.CommandResultName, commandResult);
226
227        return !commandResult.hasErrors();
228    }
229    
230}