001    /**
002     * Copyright 2005-2014 The Kuali Foundation
003     *
004     * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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    package org.kuali.rice.krad.datadictionary.validation;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.kuali.rice.krad.datadictionary.exception.AttributeValidationException;
020    import org.kuali.rice.krad.datadictionary.validation.capability.CaseConstrainable;
021    import org.kuali.rice.krad.datadictionary.validation.capability.Constrainable;
022    import org.kuali.rice.krad.datadictionary.validation.capability.MustOccurConstrainable;
023    import org.kuali.rice.krad.datadictionary.validation.capability.PrerequisiteConstrainable;
024    import org.kuali.rice.krad.datadictionary.validation.capability.SimpleConstrainable;
025    import org.kuali.rice.krad.datadictionary.validation.capability.ValidCharactersConstrainable;
026    import org.kuali.rice.krad.datadictionary.validation.constraint.CaseConstraint;
027    import org.kuali.rice.krad.datadictionary.validation.constraint.MustOccurConstraint;
028    import org.kuali.rice.krad.datadictionary.validation.constraint.PrerequisiteConstraint;
029    import org.kuali.rice.krad.datadictionary.validation.constraint.SimpleConstraint;
030    import org.kuali.rice.krad.datadictionary.validation.constraint.ValidCharactersConstraint;
031    import org.kuali.rice.krad.uif.UifConstants;
032    import org.kuali.rice.krad.uif.UifPropertyPaths;
033    import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata;
034    import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
035    import org.kuali.rice.krad.uif.view.ViewModel;
036    
037    import java.util.ArrayList;
038    import java.util.HashMap;
039    import java.util.List;
040    import java.util.Map;
041    
042    /**
043     * AttributeValueReader which can read the correct values from all InputFields which exist on the View
044     *
045     * @author Kuali Rice Team (rice.collab@kuali.org)
046     */
047    public class ViewAttributeValueReader extends BaseAttributeValueReader {
048        private ViewModel form;
049    
050        private List<Constrainable> inputFields = new ArrayList<Constrainable>();
051        private Map<String, InputFieldConstrainableInfo> inputFieldMap = new HashMap<String, InputFieldConstrainableInfo>();
052    
053        /**
054         * Constructor for ViewAttributeValueReader, the View must already be indexed and
055         * the InputFields must have already be initialized for this reader to work properly
056         *
057         * @param form model object representing the View's form data
058         */
059        public ViewAttributeValueReader(ViewModel form) {
060            this.form = form;
061    
062            ViewPostMetadata viewPostMetadata = form.getViewPostMetadata();
063    
064            // Copying information stored about InputField in the post metadata to info objects for use by this reader
065            for (String id : viewPostMetadata.getInputFieldIds()) {
066                InputFieldConstrainableInfo info = new InputFieldConstrainableInfo();
067    
068                Object label = viewPostMetadata.getComponentPostData(id, UifConstants.PostMetadata.LABEL);
069                if (label != null) {
070                    info.setLabel((String) label);
071                }
072    
073                Object name = viewPostMetadata.getComponentPostData(id, UifConstants.PostMetadata.PATH);
074                if (name != null) {
075                    info.setName((String) name);
076                }
077    
078                Object validCharactersConstraint = viewPostMetadata.getComponentPostData(id,
079                        UifConstants.PostMetadata.VALID_CHARACTER_CONSTRAINT);
080                if (validCharactersConstraint != null) {
081                    info.setValidCharactersConstraint((ValidCharactersConstraint) validCharactersConstraint);
082                }
083    
084                Object caseConstraint = viewPostMetadata.getComponentPostData(id,
085                        UifConstants.PostMetadata.CASE_CONSTRAINT);
086                if (caseConstraint != null) {
087                    info.setCaseConstraint((CaseConstraint) caseConstraint);
088                }
089    
090                Object prerequisiteConstraints = viewPostMetadata.getComponentPostData(id,
091                        UifConstants.PostMetadata.PREREQ_CONSTSTRAINTS);
092                if (prerequisiteConstraints != null) {
093                    info.setPrerequisiteConstraints((List<PrerequisiteConstraint>) prerequisiteConstraints);
094                }
095    
096                Object mustOccurConstraints = viewPostMetadata.getComponentPostData(id,
097                        UifConstants.PostMetadata.MUST_OCCUR_CONSTRAINTS);
098                if (mustOccurConstraints != null) {
099                    info.setMustOccurConstraints((List<MustOccurConstraint>) mustOccurConstraints);
100                }
101    
102                Object simpleConstraint = viewPostMetadata.getComponentPostData(id,
103                        UifConstants.PostMetadata.SIMPLE_CONSTRAINT);
104                if (simpleConstraint != null) {
105                    info.setSimpleConstraint((SimpleConstraint) simpleConstraint);
106                }
107    
108                inputFields.add(info);
109                inputFieldMap.put(info.getName(), info);
110            }
111        }
112    
113        /**
114         * Gets the definition which is an InputField on the View/Page
115         */
116        @Override
117        public Constrainable getDefinition(String attributeName) {
118            InputFieldConstrainableInfo field = inputFieldMap.get(attributeName);
119            if (field != null) {
120                return field;
121            } else {
122                return null;
123            }
124        }
125    
126        /**
127         * Gets all InputFields (which extend Constrainable)
128         *
129         * @return constrainable input fields
130         */
131        @Override
132        public List<Constrainable> getDefinitions() {
133            return inputFields;
134        }
135    
136        /**
137         * Returns the label associated with the InputField which has that AttributeName
138         *
139         * @param attributeName attribute name
140         * @return label associated with the named attribute
141         */
142        @Override
143        public String getLabel(String attributeName) {
144            InputFieldConstrainableInfo field = inputFieldMap.get(attributeName);
145            if (field != null) {
146                return field.getLabel();
147            } else {
148                return "";
149            }
150        }
151    
152        /**
153         * Returns the Form object
154         *
155         * @return form set in the constructor
156         */
157        @Override
158        public Object getObject() {
159            return form;
160        }
161    
162        /**
163         * Not used for this reader, returns null
164         *
165         * @return null
166         */
167        @Override
168        public Constrainable getEntry() {
169            return null;
170        }
171    
172        /**
173         * Returns current attributeName which represents the path
174         *
175         * @return attributeName set on this reader
176         */
177        @Override
178        public String getPath() {
179            return this.attributeName;
180        }
181    
182        /**
183         * Gets the type of value for this AttributeName as represented on the Form
184         *
185         * @param attributeName
186         * @return attribute type
187         */
188        @Override
189        public Class<?> getType(String attributeName) {
190            Object fieldValue = ObjectPropertyUtils.getPropertyValue(form, attributeName);
191            return fieldValue.getClass();
192        }
193    
194        /**
195         * If the current attribute being evaluated is a field of an addLine return false because it should not
196         * be evaluated during Validation.
197         *
198         * @return false if InputField is part of an addLine for a collection, true otherwise
199         */
200        @Override
201        public boolean isReadable() {
202            if (attributeName != null && attributeName.contains(UifPropertyPaths.NEW_COLLECTION_LINES)) {
203                return false;
204            }
205            return true;
206        }
207    
208        /**
209         * Return value of the field for the attributeName currently set on this reader
210         *
211         * @param <X> return type
212         * @return value of the field for the attributeName currently set on this reader
213         * @throws AttributeValidationException
214         */
215        @Override
216        public <X> X getValue() throws AttributeValidationException {
217            X fieldValue = null;
218            if (StringUtils.isNotBlank(this.attributeName)) {
219                fieldValue = ObjectPropertyUtils.<X>getPropertyValue(form, this.attributeName);
220            }
221            return fieldValue;
222        }
223    
224        /**
225         * Return value of the field for the attributeName passed in
226         *
227         * @param attributeName name (which represents a path) of the value to be retrieved on the Form
228         * @param <X> return type
229         * @return value of that attributeName represents on the form
230         * @throws AttributeValidationException
231         */
232        @Override
233        public <X> X getValue(String attributeName) throws AttributeValidationException {
234            X fieldValue = null;
235            if (StringUtils.isNotBlank(attributeName)) {
236                fieldValue = ObjectPropertyUtils.<X>getPropertyValue(form, this.attributeName);
237            }
238            return fieldValue;
239        }
240    
241        /**
242         * Cones this AttributeValueReader
243         *
244         * @return AttributeValueReader
245         */
246        @Override
247        public AttributeValueReader clone() {
248            ViewAttributeValueReader clone = new ViewAttributeValueReader(form);
249            clone.setAttributeName(this.attributeName);
250            return clone;
251        }
252    
253        /**
254         * This is a simple object used to contain information about InputFields that are being evaluated and used by
255         * this ViewAttributeValueReader.
256         *
257         * <p>For full documentation refer to the {@link org.kuali.rice.krad.uif.field.InputField} class.</p>
258         */
259        public class InputFieldConstrainableInfo implements SimpleConstrainable, CaseConstrainable, PrerequisiteConstrainable, MustOccurConstrainable, ValidCharactersConstrainable {
260    
261            private String label;
262            private String name;
263            private ValidCharactersConstraint validCharactersConstraint;
264            private CaseConstraint caseConstraint;
265            private List<PrerequisiteConstraint> prerequisiteConstraints;
266            private List<MustOccurConstraint> mustOccurConstraints;
267            private SimpleConstraint simpleConstraint;
268    
269            /**
270             * Get the field's label
271             *
272             * @return the label
273             */
274            public String getLabel() {
275                return label;
276            }
277    
278            /**
279             * @see org.kuali.rice.krad.datadictionary.validation.ViewAttributeValueReader.InputFieldConstrainableInfo#getLabel()
280             */
281            public void setLabel(String label) {
282                this.label = label;
283            }
284    
285            /**
286             * {@inheritDoc}
287             */
288            @Override
289            public String getName() {
290                return name;
291            }
292    
293            /**
294             * @see org.kuali.rice.krad.datadictionary.validation.ViewAttributeValueReader.InputFieldConstrainableInfo#getName()
295             */
296            public void setName(String name) {
297                this.name = name;
298            }
299    
300            /**
301             * {@inheritDoc}
302             */
303            @Override
304            public ValidCharactersConstraint getValidCharactersConstraint() {
305                return validCharactersConstraint;
306            }
307    
308            /**
309             * @see org.kuali.rice.krad.datadictionary.validation.ViewAttributeValueReader.InputFieldConstrainableInfo#getValidCharactersConstraint()
310             */
311            public void setValidCharactersConstraint(ValidCharactersConstraint validCharactersConstraint) {
312                this.validCharactersConstraint = validCharactersConstraint;
313            }
314    
315            /**
316             * {@inheritDoc}
317             */
318            @Override
319            public CaseConstraint getCaseConstraint() {
320                return caseConstraint;
321            }
322    
323            /**
324             * @see org.kuali.rice.krad.datadictionary.validation.ViewAttributeValueReader.InputFieldConstrainableInfo#getCaseConstraint()
325             */
326            public void setCaseConstraint(CaseConstraint caseConstraint) {
327                this.caseConstraint = caseConstraint;
328            }
329    
330            /**
331             * {@inheritDoc}
332             */
333            @Override
334            public List<PrerequisiteConstraint> getPrerequisiteConstraints() {
335                return prerequisiteConstraints;
336            }
337    
338            /**
339             * @see org.kuali.rice.krad.datadictionary.validation.ViewAttributeValueReader.InputFieldConstrainableInfo#getPrerequisiteConstraints()
340             */
341            public void setPrerequisiteConstraints(List<PrerequisiteConstraint> prerequisiteConstraints) {
342                this.prerequisiteConstraints = prerequisiteConstraints;
343            }
344    
345            /**
346             * {@inheritDoc}
347             */
348            @Override
349            public List<MustOccurConstraint> getMustOccurConstraints() {
350                return mustOccurConstraints;
351            }
352    
353            /**
354             * @see org.kuali.rice.krad.datadictionary.validation.ViewAttributeValueReader.InputFieldConstrainableInfo#getMustOccurConstraints()
355             */
356            public void setMustOccurConstraints(List<MustOccurConstraint> mustOccurConstraints) {
357                this.mustOccurConstraints = mustOccurConstraints;
358            }
359    
360            /**
361             * {@inheritDoc}
362             */
363            @Override
364            public SimpleConstraint getSimpleConstraint() {
365                return simpleConstraint;
366            }
367    
368            /**
369             * @see org.kuali.rice.krad.datadictionary.validation.ViewAttributeValueReader.InputFieldConstrainableInfo#getSimpleConstraint()
370             */
371            public void setSimpleConstraint(SimpleConstraint simpleConstraint) {
372                this.simpleConstraint = simpleConstraint;
373            }
374        }
375    
376    }