View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.service.impl;
17  
18  import org.kuali.rice.core.api.CoreApiServiceLocator;
19  import org.kuali.rice.core.api.config.property.ConfigurationService;
20  import org.kuali.rice.core.api.data.DataType;
21  import org.kuali.rice.core.api.exception.RiceRuntimeException;
22  import org.kuali.rice.core.api.uif.RemotableAbstractControl;
23  import org.kuali.rice.core.api.uif.RemotableAbstractWidget;
24  import org.kuali.rice.core.api.uif.RemotableAttributeField;
25  import org.kuali.rice.core.api.uif.RemotableCheckbox;
26  import org.kuali.rice.core.api.uif.RemotableCheckboxGroup;
27  import org.kuali.rice.core.api.uif.RemotableHiddenInput;
28  import org.kuali.rice.core.api.uif.RemotableQuickFinder;
29  import org.kuali.rice.core.api.uif.RemotableRadioButtonGroup;
30  import org.kuali.rice.core.api.uif.RemotableSelect;
31  import org.kuali.rice.core.api.uif.RemotableTextInput;
32  import org.kuali.rice.core.api.uif.RemotableTextarea;
33  import org.kuali.rice.core.api.util.KeyValue;
34  import org.kuali.rice.krad.bo.BusinessObject;
35  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
36  import org.kuali.rice.krad.service.DataDictionaryRemoteFieldService;
37  import org.kuali.rice.krad.service.DataDictionaryService;
38  import org.kuali.rice.krad.service.DataObjectMetaDataService;
39  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
40  import org.kuali.rice.krad.service.LegacyDataAdapter;
41  import org.kuali.rice.krad.uif.control.CheckboxControl;
42  import org.kuali.rice.krad.uif.control.CheckboxGroupControl;
43  import org.kuali.rice.krad.uif.control.Control;
44  import org.kuali.rice.krad.uif.control.GroupControl;
45  import org.kuali.rice.krad.uif.control.HiddenControl;
46  import org.kuali.rice.krad.uif.control.MultiValueControl;
47  import org.kuali.rice.krad.uif.control.RadioGroupControl;
48  import org.kuali.rice.krad.uif.control.SelectControl;
49  import org.kuali.rice.krad.uif.control.TextAreaControl;
50  import org.kuali.rice.krad.uif.control.TextControl;
51  import org.kuali.rice.krad.uif.control.UserControl;
52  import org.kuali.rice.krad.util.DataTypeUtil;
53  
54  import java.util.Collections;
55  import java.util.HashMap;
56  import java.util.List;
57  import java.util.Map;
58  
59  /**
60   * Implementation of the {@link DataDictionaryRemoteFieldService} service
61   *
62   * @author Kuali Rice Team (rice.collab@kuali.org)
63   */
64  public class DataDictionaryRemoteFieldServiceImpl implements DataDictionaryRemoteFieldService {
65  
66      @Override
67      public RemotableAttributeField buildRemotableFieldFromAttributeDefinition(String componentClassName,
68              String attributeName) {
69          AttributeDefinition baseDefinition;
70          Class<?> componentClass;
71          // try to resolve the component name - if not possible - try to pull the definition from the app mediation service
72          try {
73              componentClass = Class.forName(componentClassName);
74              baseDefinition = getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(componentClassName)
75                      .getAttributeDefinition(attributeName);
76          } catch (ClassNotFoundException ex) {
77              throw new RiceRuntimeException("Unable to find attribute definition for attribute : " + attributeName);
78          }
79  
80          RemotableAttributeField.Builder definition = RemotableAttributeField.Builder.create(baseDefinition.getName());
81  
82          definition.setLongLabel(baseDefinition.getLabel());
83          definition.setShortLabel(baseDefinition.getShortLabel());
84          definition.setMaxLength(baseDefinition.getMaxLength());
85  
86          if (baseDefinition.isRequired() != null) {
87              definition.setRequired(baseDefinition.isRequired().booleanValue());
88          }
89  
90          definition.setForceUpperCase(baseDefinition.getForceUppercase().booleanValue());
91  
92          //set the datatype - needed for successful custom doc searches
93          String dataType = DataTypeUtil.determineFieldDataType((Class<? extends BusinessObject>) componentClass,
94                  attributeName);
95          definition.setDataType(DataType.valueOf(dataType.toUpperCase()));
96  
97          RemotableAbstractControl.Builder control = createControl(baseDefinition);
98          if (control != null) {
99              definition.setControl(control);
100         }
101 
102         RemotableQuickFinder.Builder qf = createQuickFinder(componentClass, attributeName);
103         if (qf != null) {
104             definition.setWidgets(Collections.<RemotableAbstractWidget.Builder>singletonList(qf));
105         }
106 
107         return definition.build();
108     }
109 
110     /**
111      * Creates a {@link RemotableAbstractControl} instance based on the control definition within the given
112      * attribute definition
113      *
114      * @param attr - attribute definition instance to pull control from
115      * @return RemotableAbstractControl instance or null if one could not be built
116      */
117     protected RemotableAbstractControl.Builder createControl(AttributeDefinition attr) {
118         Control control = attr.getControlField();
119 
120         if (control != null) {
121             if (control instanceof CheckboxControl) {
122                 return RemotableCheckbox.Builder.create();
123             } else if (control instanceof CheckboxGroupControl) {
124                 return RemotableCheckboxGroup.Builder.create(getValues(attr));
125             } else if (control instanceof HiddenControl) {
126                 return RemotableHiddenInput.Builder.create();
127             } else if (control instanceof SelectControl) {
128                 RemotableSelect.Builder b = RemotableSelect.Builder.create(getValues(attr));
129                 b.setMultiple(((SelectControl) control).isMultiple());
130                 b.setSize(((SelectControl) control).getSize());
131             } else if (control instanceof RadioGroupControl) {
132                 return RemotableRadioButtonGroup.Builder.create(getValues(attr));
133             } else if (control instanceof TextControl) {
134                 final RemotableTextInput.Builder b = RemotableTextInput.Builder.create();
135                 b.setSize(((TextControl) control).getSize());
136                 return b;
137             } else if (control instanceof UserControl) {
138                 final RemotableTextInput.Builder b = RemotableTextInput.Builder.create();
139                 b.setSize(((UserControl) control).getSize());
140                 return b;
141             } else if (control instanceof GroupControl) {
142                 final RemotableTextInput.Builder b = RemotableTextInput.Builder.create();
143                 b.setSize(((GroupControl) control).getSize());
144                 return b;
145             } else if (control instanceof TextAreaControl) {
146                 final RemotableTextarea.Builder b = RemotableTextarea.Builder.create();
147                 b.setCols(((TextAreaControl) control).getCols());
148                 b.setRows(((TextAreaControl) control).getRows());
149                 return b;
150             }
151         }
152         
153         return null;
154     }
155 
156     /**
157      * Will first try to retrieve options configured on the control.  If that doesn't return any values then will
158      * try to use the optionfinder on the AttributeDefinition.
159      *
160      * @param attr - AttributeDefinition
161      * @return Map of key value pairs
162      */
163     protected Map<String, String> getValues(AttributeDefinition attr) {
164         Control control = attr.getControlField();
165 
166         if ((control instanceof MultiValueControl)
167                 && (((MultiValueControl) control).getOptions() != null)
168                 && !((MultiValueControl) control).getOptions().isEmpty()) {
169             List<KeyValue> keyValues = ((MultiValueControl) control).getOptions();
170                     Map<String, String> options = new HashMap<String, String> ();
171                     for (KeyValue keyValue : keyValues) {
172                         options.put(keyValue.getKey(), keyValue.getValue());
173                     }
174                     return options;
175         } else if (attr.getOptionsFinder() != null) {
176             return attr.getOptionsFinder().getKeyLabelMap();
177         }
178 
179         return Collections.emptyMap();
180     }
181 
182     /**
183      * Builds a {@link RemotableQuickFinder} instance for the given attribute based on determined relationships
184      *
185      * <p>
186      * Uses the {@link DataObjectMetaDataService} to find relationships the given attribute participates in within the
187      * given class. If a relationship is not found, the title attribute is also checked to determine if a lookup should
188      * be rendered back to the component class itself. If a relationship suitable for lookup is found, the associated
189      * field conversions and lookup parameters are built
190      * </p>
191      *
192      * @param componentClass - class that attribute belongs to and should be checked for relationships
193      * @param attributeName - name of the attribute to determine quickfinder for
194      * @return RemotableQuickFinder.Builder instance for the configured lookup, or null if one could not be found
195      */
196     protected RemotableQuickFinder.Builder createQuickFinder(Class<?> componentClass, String attributeName) {
197         return getLegacyDataAdapter().createQuickFinder(componentClass, attributeName);
198     }
199 
200     protected DataDictionaryService getDataDictionaryService() {
201         return KRADServiceLocatorWeb.getDataDictionaryService();
202     }
203 
204     protected ConfigurationService getKualiConfigurationService() {
205         return CoreApiServiceLocator.getKualiConfigurationService();
206     }
207 
208     protected LegacyDataAdapter getLegacyDataAdapter() {
209         return KRADServiceLocatorWeb.getLegacyDataAdapter();
210     }
211 }