001/**
002 * Copyright 2005-2018 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 */
016package org.kuali.rice.krad.lookup;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.krad.uif.UifConstants.ViewType;
020import org.kuali.rice.krad.util.KRADConstants;
021import org.kuali.rice.krad.util.KRADUtils;
022import org.kuali.rice.krad.web.bind.RequestAccessible;
023import org.kuali.rice.krad.web.form.UifFormBase;
024import org.springframework.http.HttpMethod;
025
026import javax.servlet.http.HttpServletRequest;
027import java.util.ArrayList;
028import java.util.Collection;
029import java.util.HashMap;
030import java.util.List;
031import java.util.Map;
032
033/**
034 * Form class containing backing data for {@link LookupView}.
035 *
036 * @author Kuali Rice Team (rice.collab@kuali.org)
037 */
038public class LookupForm extends UifFormBase {
039    private static final long serialVersionUID = -7323484966538685327L;
040    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LookupForm.class);
041
042    @RequestAccessible
043    private String dataObjectClassName;
044
045    @RequestAccessible
046    private boolean multipleValuesSelect;
047
048    @RequestAccessible
049    private boolean redirectedLookup;
050
051    @RequestAccessible
052    private boolean returnByScript;
053
054    @RequestAccessible
055    private String returnTarget;
056
057    @RequestAccessible
058    private String lookupCollectionName;
059
060    @RequestAccessible
061    private String lookupCollectionId;
062
063    @RequestAccessible
064    private String referencesToRefresh;
065
066    @RequestAccessible
067    private String quickfinderId;
068
069    @RequestAccessible
070    private Map<String, String> fieldConversions;
071    private List<String> multiValueReturnFields;
072
073    @RequestAccessible
074    private Map<String, String> lookupCriteria;
075
076    private Collection<?> lookupResults;
077
078    @RequestAccessible
079    private boolean displayResults;
080
081    public LookupForm() {
082        super();
083
084        setViewTypeName(ViewType.LOOKUP);
085
086        lookupCriteria = new HashMap<String, String>();
087        fieldConversions = new HashMap<String, String>();
088        multiValueReturnFields = new ArrayList<String>();
089    }
090
091    /**
092     * Picks out data object name from the request to retrieve a lookupable and for the initial get request
093     * populates the {@link #getFieldConversions()} property.
094     *
095     * {@inheritDoc}
096     */
097    @Override
098    public void postBind(HttpServletRequest request) {
099        super.postBind(request);
100
101        if (StringUtils.isBlank(getDataObjectClassName())) {
102            setDataObjectClassName(((LookupView) getView()).getDataObjectClass().getName());
103        }
104
105        Lookupable lookupable = getLookupable();
106        if (lookupable != null) {
107            Class<?> dataObjectClass;
108            try {
109                dataObjectClass = Class.forName(getDataObjectClassName());
110            } catch (ClassNotFoundException e) {
111                throw new RuntimeException("Object class " + getDataObjectClassName() + " not found", e);
112            }
113
114            lookupable.setDataObjectClass(dataObjectClass);
115        }
116
117        // populate field conversions map on initial GET request
118        if (request.getMethod().equals(HttpMethod.GET.name()) && (request.getParameter(
119                KRADConstants.CONVERSION_FIELDS_PARAMETER) != null)) {
120            String conversionFields = request.getParameter(KRADConstants.CONVERSION_FIELDS_PARAMETER);
121            setFieldConversions(KRADUtils.convertStringParameterToMap(conversionFields));
122        }
123    }
124
125    /**
126     * Returns an {@link Lookupable} instance associated with the lookup view.
127     *
128     * @return Lookupable instance or null if one does not exist
129     */
130    public Lookupable getLookupable() {
131        if (getViewHelperService() != null) {
132            return (Lookupable) getViewHelperService();
133        }
134
135        return null;
136    }
137
138    /**
139     * Class name for the data object the lookup should be performed against.
140     *
141     * <p>The object class name is used to pick up a dictionary entry which will feed the attribute field
142     * definitions and other configuration. In addition it is to configure the
143     * {@link org.kuali.rice.krad.lookup.Lookupable} which will carry out the search action</p>
144     *
145     * @return lookup data object class
146     */
147    public String getDataObjectClassName() {
148        return this.dataObjectClassName;
149    }
150
151    /**
152     * Setter for {@link LookupForm#getDataObjectClassName()}
153     * 
154     * @param dataObjectClassName property value
155     */
156    public void setDataObjectClassName(String dataObjectClassName) {
157        this.dataObjectClassName = dataObjectClassName;
158    }
159
160    /**
161     * Indicates whether multiple values select should be enabled for the lookup.
162     *
163     * <p>When set to true, the select field is enabled for the lookup results group that allows the user
164     * to select one or more rows for returning</p>
165     *
166     * @return boolean true if multiple values should be enabled, false otherwise
167     */
168    public boolean isMultipleValuesSelect() {
169        return multipleValuesSelect;
170    }
171
172    /**
173     * @see LookupForm#isMultipleValuesSelect()
174     */
175    public void setMultipleValuesSelect(boolean multipleValuesSelect) {
176        this.multipleValuesSelect = multipleValuesSelect;
177    }
178
179    /**
180     * Indicates whether the requested was redirected from the lookup framework due to an external object
181     * request.
182     *
183     * <p>This prevents the framework from performing another redirect check</p>
184     *
185     * @return boolean true if request was a redirect, false if not
186     */
187    public boolean isRedirectedLookup() {
188        return redirectedLookup;
189    }
190
191    /**
192     * @see LookupForm#isRedirectedLookup()
193     */
194    public void setRedirectedLookup(boolean redirectedLookup) {
195        this.redirectedLookup = redirectedLookup;
196    }
197
198    /**
199      * Indicates whether the return value from the lookup should occur through script or a server side
200      * post (default is false, server side post).
201      *
202      * @return boolean true if return should occur though script, false if return should be done through server
203      *         side post
204      */
205     public boolean isReturnByScript() {
206         return returnByScript;
207     }
208
209     /**
210      * @see LookupForm#isReturnByScript()
211      */
212     public void setReturnByScript(boolean returnByScript) {
213         this.returnByScript = returnByScript;
214     }
215
216    /**
217     * Name of the window the lookup should return to.
218     *
219     * <p>The lookup can be invoked from several different contexts: new tab, lightbox within top window, lightbox
220     * within portal window. When the request is made, this parameter can be sent to specify the target for
221     * the return links.</p>
222     *
223     * @return String return target window name
224     */
225    public String getReturnTarget() {
226        return returnTarget;
227    }
228
229    /**
230     * org.kuali.rice.krad.lookup.LookupForm#getReturnTarget()
231     */
232    public void setReturnTarget(String returnTarget) {
233        this.returnTarget = returnTarget;
234    }
235
236    /**
237     * For the case of multi-value lookup, indicates the collection that should be populated with
238     * the return results.
239     *
240     * @return String collection name (must be full binding path)
241     */
242    public String getLookupCollectionName() {
243        return lookupCollectionName;
244    }
245
246    /**
247     * @see LookupForm#getLookupCollectionName()
248     */
249    public void setLookupCollectionName(String lookupCollectionName) {
250        this.lookupCollectionName = lookupCollectionName;
251    }
252
253    public String getLookupCollectionId() {
254        return lookupCollectionId;
255    }
256
257    public void setLookupCollectionId(String lookupCollectionId) {
258        this.lookupCollectionId = lookupCollectionId;
259    }
260
261    /**
262     * String containing references that should be refreshed when the lookup returns, passed back on the
263     * return URL.
264     *
265     * @return String containing references that should be refreshed on return from lookup
266     */
267    public String getReferencesToRefresh() {
268        return referencesToRefresh;
269    }
270
271    /**
272     * @see LookupForm#getReferencesToRefresh()
273     */
274    public void setReferencesToRefresh(String referencesToRefresh) {
275        this.referencesToRefresh = referencesToRefresh;
276    }
277
278    /**
279     * Id for the quickfinder that triggered the lookup action (if any).
280     *
281     * <p>When the lookup is triggered from a quickfinder, the return URLs will be present on the lookup
282     * results. In addition, the quickfinder id is passed back on the return URL so the caller can perform logic
283     * based on which quickfinder was invoked.</p>
284     *
285     * @return String id for quickfinder that invoked the lookup
286     */
287    public String getQuickfinderId() {
288        return quickfinderId;
289    }
290
291    /**
292     * @see LookupForm#getQuickfinderId()
293     */
294    public void setQuickfinderId(String quickfinderId) {
295        this.quickfinderId = quickfinderId;
296    }
297
298    /**
299     * Map of conversions that should occur on the lookup return between properties on the lookup data object
300     * and properties on the calling view.
301     *
302     * <p>When a lookup is invoked from a calling view, the purpose is to return one or more values that will
303     * populate fields on the calling view. To accomplish this, values for properties on the selected record
304     * are passed back on the URL as values for properties on the calling view. This map specifies which properties
305     * on the lookup data object should be pulled, and for each one what is the property on the caller to
306     * send the value back as.</p>
307     *
308     * <p>For example, suppose the map contained the entries id:document.bookId and title:document.bookTitle. When the
309     * return URL is selected for a record, the value for the id property will be retrieved and added to the return
310     * URL query string as 'document.bookId={idValue}'. Likewise the value for the title property will be pulled
311     * and added to the return URL query string as 'document.bookTitle={titleValue}'. So the query string will contain
312     * something like 'document.bookId=3&document.bookTitle=Animals'</p>
313     *
314     * @return Map of field conversions, each entry is a conversion between two properties. Key is property name
315     *         on the lookup data object, entry value is the property name on the calling view/model
316     */
317    public Map<String, String> getFieldConversions() {
318        return this.fieldConversions;
319    }
320
321    /**
322     * @see LookupForm#getFieldConversions()
323     */
324    public void setFieldConversions(Map<String, String> fieldConversions) {
325        this.fieldConversions = fieldConversions;
326    }
327
328    /**
329     * Holds the column names for the multi-value lookup selected values
330     *
331     * Note: as of KULRICE-12125 secure field names will not be stored in this parameter
332     * @return a list of column names for the multi-value lookup
333     */
334    public List<String> getMultiValueReturnFields() {
335        return multiValueReturnFields;
336    }
337
338    /**
339     * @see LookupForm#getMultiValueReturnFields()
340     */
341    public void setMultiValueReturnFields(List<String> multiValueReturnFields) {
342        this.multiValueReturnFields = multiValueReturnFields;
343    }
344
345    /**
346     * Map containing the criteria to be used for performing the search.
347     *
348     * <p>Fields that are defined in the {@link org.kuali.rice.krad.lookup.LookupView#getCriteriaGroup()} bind
349     * to this map. The key of the map is the property path specified for the field, and the value of the map
350     * is the search value (if any) entered by the user. This map is then passed into the {@link Lookupable} to
351     * carry out the search.</p>
352     *
353     * @return Map of search criteria where key is the property the criteria will be applied to and the value is
354     *         the search value entered by the user (if any)
355     */
356    public Map<String, String> getLookupCriteria() {
357        return this.lookupCriteria;
358    }
359
360    /**
361     * @see LookupForm#getLookupCriteria()
362     */
363    public void setLookupCriteria(Map<String, String> lookupCriteria) {
364        this.lookupCriteria = lookupCriteria;
365    }
366
367    /**
368     * Holds the results of a search action.
369     *
370     * <p>After the search action is invoked, the results of the search will be held by this property. The
371     * {@link org.kuali.rice.krad.lookup.LookupView#getResultsGroup()} binds to this property for displaying
372     * the results.</p>
373     *
374     * @return Collection of data objects that are the result of a search
375     */
376    public Collection<?> getLookupResults() {
377        return this.lookupResults;
378    }
379
380    /**
381     * @see LookupForm#getLookupResults()
382     */
383    public void setLookupResults(Collection<?> lookupResults) {
384        this.lookupResults = lookupResults;
385    }
386
387    public boolean isDisplayResults() {
388        return displayResults;
389    }
390
391    public void setDisplayResults(boolean displayResults) {
392        this.displayResults = displayResults;
393    }
394}