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.HashSet;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Set;
27  
28  /**
29   * Represents a button in the form that finishes the dialog represented by that
30   * form. Each instance of Submit must be associated with a unique ID, called the
31   * submission ID in order to keep it decidable how the dialog was finished (i.e.
32   * by pressing which button). Critical submits may be associated with a
33   * confirmation message to be shown to users in order to make sure that the
34   * button was not pressed by mistake. Two types of confirmation messages are
35   * supported, either OK/Cancel or Yes/No; the type specifies which buttons
36   * should be added by a UI handler to the confirmation dialog.
37   * 
38   * @author mtazari
39   * @author Carsten Stockloew
40   * @navassoc - "mandatoryInput" * Input
41   */
42  public class Submit extends FormControl {
43      public static final String MY_URI = Form.uAAL_DIALOG_NAMESPACE + "Submit";
44  
45      /**
46       * Critical submits may be associated with a confirmation message to be
47       * shown to users in order to make sure that the button was not pressed by
48       * mistake. Two types of confirmation messages are supported, either
49       * OK/Cancel or Yes/No; the type specifies which buttons should be added by
50       * a UI handler to the confirmation dialog.
51       */
52      public static final int CONFIRMATION_TYPE_OK_CANCEL = 0;
53  
54      /**
55       * Critical submits may be associated with a confirmation message to be
56       * shown to users in order to make sure that the button was not pressed by
57       * mistake. Two types of confirmation messages are supported, either
58       * OK/Cancel or Yes/No; the type specifies which buttons should be added by
59       * a UI handler to the confirmation dialog.
60       */
61      public static final int CONFIRMATION_TYPE_YES_NO = 1;
62  
63      /**
64       * Critical submits may be associated with a confirmation message to be
65       * shown to users in order to make sure that the button was not pressed by
66       * mistake. Two types of confirmation messages are supported, either
67       * OK/Cancel or Yes/No; the type specifies which buttons should be added by
68       * a UI handler to the confirmation dialog.
69       */
70      public static final String PROP_CONFIRMATION_MESSAGE = uAAL_VOCABULARY_NAMESPACE
71  	    + "confirmationMessage";
72  
73      /**
74       * Critical submits may be associated with a confirmation message to be
75       * shown to users in order to make sure that the button was not pressed by
76       * mistake. Two types of confirmation messages are supported, either
77       * OK/Cancel or Yes/No; the type specifies which buttons should be added by
78       * a UI handler to the confirmation dialog.
79       */
80      public static final String PROP_CONFIRMATION_TYPE = uAAL_VOCABULARY_NAMESPACE
81  	    + "confirmationType";
82  
83      /**
84       * For maintaining a list of mandatory input controls associated with each
85       * submit control that have to be filled by the user before submitting a
86       * form via that submit control.
87       */
88      public static final String PROP_MANDATORY_INPUT = uAAL_VOCABULARY_NAMESPACE
89  	    + "mandatoryInput";
90  
91      /**
92       * The unique ID that helps to identify with pressing which button a dialog
93       * was finished.
94       */
95      public static final String PROP_SUBMISSION_ID = uAAL_VOCABULARY_NAMESPACE
96  	    + "submissionID";
97  
98      /**
99       * The list of Manadatory {@link Input} Controls.
100      */
101     protected List mandatoryList = null;
102 
103     /**
104      * For exclusive use by de-serializers.
105      */
106     public Submit() {
107 	super();
108 	mandatoryList = new ArrayList();
109 	props.put(PROP_MANDATORY_INPUT, mandatoryList);
110     }
111 
112     /**
113      * For exclusive use by applications.
114      * 
115      * @param parent
116      *            The mandatory parent group as the direct container of this
117      *            input field. See {@link FormControl#PROP_PARENT_CONTROL}.
118      * @param label
119      *            The optional {@link Label} to be associated with this input
120      *            field. See {@link FormControl#PROP_CONTROL_LABEL}.
121      * @param id
122      *            The mandatory submission ID. See {@link #PROP_SUBMISSION_ID}.
123      */
124     public Submit(Group parent, Label label, String id) {
125 	super(MY_URI, parent, label, null, null, null);
126 	props.put(PROP_SUBMISSION_ID, id);
127 	mandatoryList = new ArrayList();
128 	props.put(PROP_MANDATORY_INPUT, mandatoryList);
129     }
130 
131     protected Submit(String typeURI, Group parent, Label label, String id) {
132 	super(typeURI, parent, label, null, null, null);
133 	props.put(PROP_SUBMISSION_ID, id);
134 	mandatoryList = new ArrayList();
135 	props.put(PROP_MANDATORY_INPUT, mandatoryList);
136     }
137 
138     /**
139      * For use by applications.
140      * 
141      * @see #PROP_MANDATORY_INPUT
142      */
143     public void addMandatoryInput(Input in) {
144 	if (in != null) {
145 	    mandatoryList.add(in);
146 	    in.setMandatory();
147 	}
148     }
149 
150     /**
151      * @see #PROP_CONFIRMATION_MESSAGE
152      */
153     public String getConfirmationMessage() {
154 	return (String) props.get(PROP_CONFIRMATION_MESSAGE);
155     }
156 
157     /**
158      * @see #PROP_CONFIRMATION_TYPE
159      */
160     public int getConfirmationType() {
161 	Object o = props.get(PROP_CONFIRMATION_TYPE);
162 	return (o instanceof Integer) ? ((Integer) o).intValue() : -1;
163     }
164 
165     /**
166      * For use by UI handlers.
167      * 
168      * @return The ID of the dialog being finished by pressing this button.
169      */
170     public String getDialogID() {
171 	Form f = getFormObject();
172 	if (f == null)
173 	    return null;
174 
175 	Group stdButtons = f.getStandardButtons();
176 	if (stdButtons != null) {
177 	    Group parent = getParentGroup();
178 	    while (parent != null && parent != stdButtons)
179 		parent = parent.getParentGroup();
180 	    if (parent == stdButtons)
181 		return f.getStandardButtonsDialogID();
182 	}
183 
184 	return f.getDialogID();
185     }
186 
187     /**
188      * @see #PROP_SUBMISSION_ID
189      */
190     public String getID() {
191 	return (String) props.get(PROP_SUBMISSION_ID);
192     }
193 
194     /**
195      * The length of a button is the length of its label. Returns -1, if no
196      * label text is set.
197      */
198     public int getMaxLength() {
199 	Label l = getLabel();
200 	return (l == null) ? -1 : l.getMaxLength();
201     }
202 
203     /**
204      * @see #PROP_MANDATORY_INPUT
205      */
206     public Input[] getMandatoryInputControls() {
207 	if (mandatoryList == null || mandatoryList.isEmpty())
208 	    return new Input[0];
209 
210 	return (Input[]) mandatoryList.toArray(new Input[mandatoryList.size()]);
211     }
212 
213     /**
214      * UI handlers must call this method as soon as the user decides to submit
215      * the form using this submit in oder to make sure if all necessary input
216      * has been collected.
217      * 
218      * @return The input control that is missing user input or null if the form
219      *         is ready to be submitted.
220      */
221     public Input getMissingInputControl() {
222 	if (mandatoryList == null)
223 	    return null;
224 
225 	for (Iterator i = mandatoryList.iterator(); i.hasNext();) {
226 	    Input in = (Input) i.next();
227 	    if (!in.checkSubmission())
228 		return in;
229 	}
230 	return null;
231     }
232     
233     /**
234      * Same as {@link Submit#getMissingInputControl()} but returns ALL missing controls instead of the first one.
235      * @return a {@link Set} of {@link Input}s.
236      */
237     public Set getMissingInputControls() {
238 	if (mandatoryList == null)
239 	    return null;
240 	HashSet inputs = new HashSet();
241 	for (Iterator i = mandatoryList.iterator(); i.hasNext();) {
242 	    Input in = (Input) i.next();
243 	    if (!in.checkSubmission())
244 	    	inputs.add(in);
245 	}
246 	return inputs;
247     }
248 
249     /**
250      * Supports UI handlers that process a form by breaking it into several
251      * "subdialog"s, one for each alternative submission, by returning all of
252      * the UI controls that are somehow related to this submit. An UI control is
253      * relevant if it is either a mandatory input for this submit or it has the
254      * same parent group as a mandatory input. For answering the demanded array,
255      * it first finds the least common parent group among the mandatory inputs
256      * and then the whole subtree of that group is traversed based on a
257      * depth-first search. The elements of the returned array will be instances
258      * of {@link Input}, {@link Output}, {@link Repeat} or
259      * {@link SubdialogTrigger}.
260      */
261     public FormControl[] getRelatedControls() {
262 	if (mandatoryList == null || mandatoryList.isEmpty())
263 	    return new FormControl[0];
264 
265 	// find the least common parent
266 	Group[] superGroups = ((Input) mandatoryList.get(0)).getSuperGroups();
267 	int lcpIndex = superGroups.length - 1;
268 	for (int i = 1; i < mandatoryList.size(); i++) {
269 	    FormControl fc = (FormControl) mandatoryList.get(i);
270 	    while (fc != null) {
271 		fc = fc.getParentGroup();
272 		for (int j = 0; j < lcpIndex; j++)
273 		    if (fc == superGroups[j]) {
274 			lcpIndex = j;
275 			break;
276 		    }
277 	    }
278 	    if (lcpIndex == 0)
279 		break;
280 	}
281 
282 	return superGroups[lcpIndex].getSubtree(this);
283     }
284 
285     /**
286      * Checks if the given input control belongs to the list of mandatory inputs
287      * of this submit.
288      */
289     public boolean hasMandatoryInput(Input fc) {
290 	return mandatoryList != null && mandatoryList.contains(fc);
291     }
292 
293     /**
294      * @see #CONFIRMATION_TYPE_OK_CANCEL
295      * @see #PROP_CONFIRMATION_MESSAGE
296      * @see #PROP_CONFIRMATION_TYPE
297      */
298     public void setConfirmationOkCancel(String msg) {
299 	if (msg != null) {
300 	    props.put(PROP_CONFIRMATION_MESSAGE, msg);
301 	    props.put(PROP_CONFIRMATION_TYPE, new Integer(
302 		    CONFIRMATION_TYPE_OK_CANCEL));
303 	}
304     }
305 
306     /**
307      * @see #CONFIRMATION_TYPE_YES_NO
308      * @see #PROP_CONFIRMATION_MESSAGE
309      * @see #PROP_CONFIRMATION_TYPE
310      */
311     public void setConfirmationYesNo(String msg) {
312 	if (msg != null) {
313 	    props.put(PROP_CONFIRMATION_MESSAGE, msg);
314 	    props.put(PROP_CONFIRMATION_TYPE, new Integer(
315 		    CONFIRMATION_TYPE_YES_NO));
316 	}
317     }
318 
319     /**
320      * For use by de-serializers.
321      */
322     public boolean setProperty(String propURI, Object value) {
323 	if (PROP_MANDATORY_INPUT.equals(propURI)) {
324 	    if (mandatoryList.isEmpty()) {
325 		if (value instanceof List) {
326 		    boolean retVal = false;
327 		    for (Iterator i = ((List) value).iterator(); i.hasNext();) {
328 			value = i.next();
329 			if (!(value instanceof Input)) {
330 			    mandatoryList.clear();
331 			    return false;
332 			} else
333 			    retVal = mandatoryList.add(value) || retVal;
334 		    }
335 		    return retVal;
336 		} else if (value instanceof Input)
337 		    return mandatoryList.add(value);
338 		else
339 		    return false;
340 	    }
341 	} else if (PROP_SUBMISSION_ID.equals(propURI)) {
342 	    if (value instanceof String && !"".equals(value)) {
343 		props.put(propURI, value);
344 		return true;
345 	    }
346 	} else if (PROP_CONFIRMATION_MESSAGE.equals(propURI)) {
347 	    if (value instanceof String && !"".equals(value)) {
348 		props.put(propURI, value);
349 		return true;
350 	    }
351 	} else if (PROP_CONFIRMATION_TYPE.equals(propURI)) {
352 	    if (value instanceof Integer) {
353 		props.put(propURI, value);
354 		return true;
355 	    }
356 	} else
357 	    return super.setProperty(propURI, value);
358 	return false;
359     }
360 }