View Javadoc

1   /*	
2   	Copyright 2007-2014 Fraunhofer IGD, http://www.igd.fraunhofer.de
3   	Fraunhofer-Gesellschaft - Institute for Computer Graphics Research
4   	
5   	See the NOTICE file distributed with this work for additional 
6   	information regarding copyright ownership
7   	
8   	Licensed under the Apache License, Version 2.0 (the "License");
9   	you may not use this file except in compliance with the License.
10  	You may obtain a copy of the License at
11  	
12  	  http://www.apache.org/licenses/LICENSE-2.0
13  	
14  	Unless required by applicable law or agreed to in writing, software
15  	distributed under the License is distributed on an "AS IS" BASIS,
16  	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  	See the License for the specific language governing permissions and
18  	limitations under the License.
19   */
20  package org.universAAL.middleware.ui.rdf;
21  
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.universAAL.middleware.container.utils.StringUtils;
27  import org.universAAL.middleware.owl.MergedRestriction;
28  import org.universAAL.middleware.rdf.PropertyPath;
29  import org.universAAL.middleware.rdf.Resource;
30  
31  /**
32   * An input control to be used if the user input is restricted to a fixed list
33   * of acceptable values. As it allows multiple selections, it can be seen as an
34   * abbreviation for a {@link Repeat} control having only a {@link Select1} as
35   * child.
36   * 
37   * @author mtazari
38   * @author Carsten Stockloew
39   * @navassoc "" - "*" Label
40   */
41  public class Select extends Input {
42      public static final String MY_URI = Form.uAAL_DIALOG_NAMESPACE + "Select";
43  
44      /**
45       * The list of choices in a select control. List members must be instances
46       * of either {@link ChoiceItem} or {@link ChoiceList}.
47       */
48      public static final String PROP_CHOICES = Form.uAAL_DIALOG_NAMESPACE
49  	    + "choices";
50  
51      /**
52       * Just for use by de-serializers.
53       */
54      public Select() {
55  	super();
56      }
57  
58      /**
59       * For use by applications.
60       * 
61       * @param parent
62       *            The group to contain this select object.
63       * @param label
64       *            The label.
65       * @param ref
66       *            mandatory property path within the form data to which this
67       *            select object refers.
68       * @param valueRestriction
69       *            Optional local restrictions on the value of this select
70       *            object.
71       * @param initialValue
72       *            Optional initial / default value that will be made available
73       *            in the form data.
74       */
75      public Select(Group parent, Label label, PropertyPath ref,
76  	    MergedRestriction valueRestriction, Object initialValue) {
77  	super(MY_URI, parent, label, ref, valueRestriction, initialValue);
78      }
79  
80      protected Select(String typeURI, Group parent, Label label,
81  	    PropertyPath ref, MergedRestriction valueRestriction,
82  	    Object initialValue) {
83  	super(typeURI, parent, label, ref, valueRestriction, initialValue);
84      }
85  
86      /**
87       * Adds the given choice item to the list of choices in this select control.
88       */
89      public void addChoiceItem(ChoiceItem item) {
90  	if (item != null) {
91  	    List l = (List) props.get(PROP_CHOICES);
92  	    if (l == null) {
93  		l = new ArrayList();
94  		props.put(PROP_CHOICES, l);
95  	    }
96  	    l.add(item);
97  	}
98      }
99  
100     /**
101      * Adds the given choice list as a sublist to the list of choices in this
102      * select control.
103      */
104     public void addChoiceList(ChoiceList list) {
105 	if (list != null) {
106 	    List l = (List) props.get(PROP_CHOICES);
107 	    if (l == null) {
108 		l = new ArrayList();
109 		props.put(PROP_CHOICES, l);
110 	    }
111 	    l.add(list);
112 	}
113     }
114 
115     /**
116      * Having the actual values that the user should select from among them,
117      * this method automatically generates the list of choices for this select
118      * by trying to derive a label for them. No sublists can be generated by
119      * this method.
120      * 
121      * @return true if the given parameter is a non empty array without any null
122      *         element, false otherwise.
123      */
124     public boolean generateChoices(Object[] elems) {
125 	if (elems == null || elems.length == 0)
126 	    return false;
127 
128 	for (int i = 0; i < elems.length; i++) {
129 	    if (elems[i] == null)
130 		return false;
131 	    String label = (elems[i] instanceof Resource) ? ((Resource) elems[i])
132 		    .getResourceLabel()
133 		    : null;
134 	    if (label == null)
135 		label = elems[i].toString();
136 	    addChoiceItem(new ChoiceItem(StringUtils.deriveLabel(label), null,
137 		    elems[i]));
138 	}
139 
140 	return true;
141     }
142 
143     /**
144      * If the restrictions defined or derivable for this select control can be
145      * determined and a certain list of allowed values can be derived from those
146      * restriction, those values will be passed to
147      * {@link #generateChoices(Object[])} to construct the list of choices.
148      */
149     public boolean generateChoices() {
150 	MergedRestriction r = getRestrictions();
151 	return (r == null) ? false : generateChoices(r.getEnumeratedValues());
152     }
153 
154     /**
155      * Returns the list of choices in this select control. Each of the elements
156      * in the returned array is supposed to be an instance of either
157      * {@link ChoiceItem} or {@link ChoiceList}.
158      */
159     public Label[] getChoices() {
160 	List l = (List) props.get(PROP_CHOICES);
161 	if (l == null)
162 	    return new Label[0];
163 
164 	return (Label[]) l.toArray(new Label[l.size()]);
165     }
166 
167     /**
168      * Returns the maximum number of values that can be selected in the context
169      * of this select control. A negative integer is returned if there is no
170      * upper limit.
171      */
172     public int getMaxCardinality() {
173 	MergedRestriction r = getRestrictions();
174 	return (r == null) ? -1 : r.getMaxCardinality();
175     }
176 
177     /**
178      * Overrides {@link FormControl#getMaxLength()} by only considering the
179      * labels of the choices currently associated with this select control.
180      */
181     public int getMaxLength() {
182 	List l = (List) props.get(PROP_CHOICES);
183 	if (l == null)
184 	    return -1;
185 
186 	int res = -1;
187 	for (Iterator i = l.iterator(); i.hasNext();) {
188 	    Object o = i.next();
189 	    if (o instanceof Label) {
190 		int aux = ((Label) o).getMaxLength();
191 		if (aux > res)
192 		    res = aux;
193 	    }
194 	}
195 	return res;
196     }
197 
198     /**
199      * Returns the minimum number of values that must be associated with this
200      * select control as selected values. A non-positive integer is returned if
201      * there is no lower limit.
202      */
203     public int getMinCardinality() {
204 	MergedRestriction r = getRestrictions();
205 	return (r == null) ? -1 : r.getMinCardinality();
206     }
207 
208     /**
209      * Checks if any sublist is contained in the list of choices in this select
210      * control.
211      */
212     public boolean isMultilevel() {
213 	List l = (List) props.get(PROP_CHOICES);
214 	if (l == null)
215 	    return false;
216 
217 	for (Iterator i = l.iterator(); i.hasNext();)
218 	    if (i.next() instanceof ChoiceList)
219 		return true;
220 
221 	return false;
222     }
223 
224     /**
225      * Just for use by de-serializers.
226      * 
227      * @see org.universAAL.middleware.rdf.Resource#setProperty(String, Object)
228      */
229     public boolean setProperty(String propURI, Object value) {
230 	if (PROP_CHOICES.equals(propURI)) {
231 	    if (props.containsKey(propURI))
232 		return false;
233 	    else if (value instanceof List) {
234 		for (Iterator i = ((List) value).iterator(); i.hasNext();) {
235 		    Object o = i.next();
236 		    if (!(o instanceof ChoiceItem)
237 			    && !(o instanceof ChoiceList))
238 			return false;
239 		}
240 		props.put(propURI, value);
241 		return true;
242 	    } else if (value instanceof ChoiceItem
243 		    || value instanceof ChoiceList) {
244 		List l = new ArrayList(1);
245 		l.add(value);
246 		props.put(propURI, l);
247 		return true;
248 	    }
249 	} else
250 	    return super.setProperty(propURI, value);
251 	return false;
252     }
253 
254     /**
255      * Tries to find the hidden value associated with a choice item whose label
256      * has been given as input and then store that value as user input by
257      * calling {@link #storeUserInput(Object)}. If no hidden value was found,
258      * the label itself will be used as user input.
259      * 
260      * Note: for use by UI handlers that can not handle the association between
261      * labels and values internally.
262      * 
263      * @return true, if the storage was successful, false otherwise.
264      */
265     public boolean storeUserInputByLabelString(String selectedLabelString) {
266 	if (selectedLabelString != null) {
267 	    List l = (List) props.get(PROP_CHOICES);
268 	    if (l != null)
269 		for (Iterator i = l.iterator(); i.hasNext();) {
270 		    Object label = i.next();
271 		    if (label instanceof ChoiceList)
272 			label = ((ChoiceList) label)
273 				.findItem(selectedLabelString);
274 		    if (label instanceof ChoiceItem
275 			    && selectedLabelString.equals(label.toString()))
276 			return storeUserInput(((ChoiceItem) label).getValue());
277 		}
278 	}
279 	return storeUserInput(selectedLabelString);
280     }
281 }