1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.lum.common.client.lo;
17
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.kuali.student.r1.common.assembly.data.Metadata;
24 import org.kuali.student.r2.common.dto.ValidationResultInfo;
25 import org.kuali.student.r2.common.infc.ValidationResult.ErrorLevel;
26 import org.kuali.student.common.ui.client.application.Application;
27 import org.kuali.student.common.ui.client.application.ApplicationContext;
28 import org.kuali.student.common.ui.client.configurable.mvc.CanProcessValidationResults;
29 import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
30 import org.kuali.student.common.ui.client.configurable.mvc.sections.Section;
31 import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
32 import org.kuali.student.common.ui.client.event.ValidateRequestEvent;
33 import org.kuali.student.common.ui.client.widgets.KSButton;
34 import org.kuali.student.common.ui.client.widgets.KSLabel;
35 import org.kuali.student.common.ui.client.widgets.KSButtonAbstract.ButtonStyle;
36 import org.kuali.student.common.ui.client.widgets.field.layout.element.FieldElement;
37 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeEvent;
38 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler;
39 import org.kuali.student.common.ui.client.widgets.search.KSPicker;
40 import org.kuali.student.lum.common.client.lu.LUUIConstants;
41 import org.kuali.student.r2.lum.lo.dto.LoCategoryInfo;
42
43 import com.google.gwt.core.client.GWT;
44 import com.google.gwt.event.dom.client.ChangeEvent;
45 import com.google.gwt.event.dom.client.ChangeHandler;
46 import com.google.gwt.event.dom.client.ClickEvent;
47 import com.google.gwt.event.dom.client.ClickHandler;
48 import com.google.gwt.event.logical.shared.ValueChangeEvent;
49 import com.google.gwt.event.logical.shared.ValueChangeHandler;
50 import com.google.gwt.event.shared.HandlerRegistration;
51 import com.google.gwt.user.client.ui.HasValue;
52 import com.google.gwt.user.client.ui.HorizontalPanel;
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public class LOBuilder extends VerticalSection implements HasValue<List<OutlineNode<LOPicker>>>, CanProcessValidationResults {
67
68 private static String type;
69 private static String state;
70 private static String repoKey;
71 private static String messageGroup;
72 private static String startOfPath;
73 private static String endOfPath = "loInfo/descr/plain";
74 private static String middleOfPath = "loDisplayInfoList";
75 HorizontalPanel searchMainPanel = new HorizontalPanel();
76 KSPicker searchWindow;
77
78 LearningObjectiveList loList;
79 KSLabel instructions;
80
81 private static int loListDescLength;
82
83 private boolean onTheFlyValidation = true;
84
85 protected LOBuilder() {
86 }
87
88 public LOBuilder(String luType, String luState, String luGroup, String loRepoKey, String queryPathStart, final Metadata metadata) {
89 super();
90
91 loListDescLength = metadata.getProperties().get("plain").getConstraints().get(0).getMaxLength();
92
93 type = luType;
94 state = luState;
95 repoKey = loRepoKey;
96 messageGroup = luGroup;
97 startOfPath = queryPathStart;
98
99 if (metadata.getInitialLookup() != null) {
100 searchWindow = GWT.create(KSPicker.class);
101 searchWindow.init(metadata.getInitialLookup(), metadata.getAdditionalLookups());
102 searchWindow.addValuesChangeHandler(new ValueChangeHandler<List<String>>() {
103 public void onValueChange(ValueChangeEvent<List<String>> event) {
104 List<String> selection = event.getValue();
105 loList.addSelectedLOs(selection);
106 }
107 });
108 searchMainPanel.add(searchWindow);
109 }
110
111 Metadata descMeta = new Metadata();
112 descMeta = metadata.getProperties().get("plain");
113
114 instructions = new KSLabel(getLabel(LUUIConstants.LO_INSTRUCTIONS_KEY, descMeta));
115
116 loList = GWT.create(LearningObjectiveList.class);
117 loList.setLoInfoMaxLength(loListDescLength);
118
119 searchMainPanel.addStyleName("KS-LOBuilder-Search-Panel");
120
121 loList.addStyleName(LUUIConstants.STYLE_SECTION);
122 loList.addStyleName(LUUIConstants.STYLE_SECTION_DIVIDER);
123
124 instructions.addStyleName("KS-LOBuilder-Instructions");
125
126 this.addWidget(searchMainPanel);
127 this.addWidget(instructions);
128 this.addSection(loList);
129
130 }
131
132
133
134
135
136 @Override
137 public void setValue(List<OutlineNode<LOPicker>> value, boolean fireEvents) {
138 setValue(value);
139 }
140
141
142
143
144 @Override
145 public void setValue(List<OutlineNode<LOPicker>> data) {
146 loList.setValue(data);
147 }
148
149
150
151
152 @Override
153 public List<OutlineNode<LOPicker>> getValue() {
154 return loList.getValue();
155 }
156
157
158
159
160 @Override
161 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<List<OutlineNode<LOPicker>>> handler) {
162 return loList.addValueChangeHandler(handler);
163 }
164
165 private static String getLabel(String labelKey) {
166 return Application.getApplicationContext().getUILabel(messageGroup, type, state, labelKey);
167 }
168
169 private static String getLabel(String labelKey, Metadata metadata) {
170 return Application.getApplicationContext().getUILabel(messageGroup, type, state, labelKey, metadata);
171 }
172
173
174
175
176 public static String getType() {
177 return type;
178 }
179
180
181
182
183 public static String getState() {
184 return state;
185 }
186
187 public static String getRepoKey() {
188 return repoKey;
189 }
190
191
192
193
194 public static String getMessageGroup() {
195 return messageGroup;
196 }
197
198 public static class LearningObjectiveList extends VerticalSection implements HasValue<List<OutlineNode<LOPicker>>> {
199 OutlineNodeModel<LOPicker> outlineModel = new OutlineNodeModel<LOPicker>();
200 protected KSButton addNew;
201 OutlineManager outlineComposite;
202
203 private int loInfoMaxLength = 0;
204
205 SelectionChangeHandler loPickerChangeHandler = new SelectionChangeHandler(){
206 public void onSelectionChange(SelectionChangeEvent event) {
207 fireChangeEvent();
208 }
209 };
210
211 public LearningObjectiveList() {
212 addNew = new KSButton(getLabel(LUUIConstants.LEARNING_OBJECTIVE_ADD_LABEL_KEY), ButtonStyle.SECONDARY,
213 new ClickHandler() {
214 public void onClick(ClickEvent event) {
215 setValue(getValue());
216 appendLO("");
217 reDraw();
218 }
219 });
220
221 addNew.addStyleName("KS-LOBuilder-New");
222
223 outlineModel.addChangeHandler(new ChangeHandler() {
224 public void onChange(ChangeEvent event) {
225 reDraw();
226 fireChangeEvent();
227 }
228 });
229
230 initEmptyLoList();
231
232 }
233
234 protected void initEmptyLoList(){
235 List<String> list = new ArrayList<String>();
236 list.add("");
237 list.add("");
238 list.add("");
239 list.add("");
240 list.add("");
241 addSelectedLOs(list);
242 }
243
244 protected void fireChangeEvent(){
245 ValueChangeEvent.fire(this, outlineModel.getOutlineNodes());
246 }
247
248 public List<OutlineNode<LOPicker>> getValue() {
249 return outlineModel.getOutlineNodes();
250 }
251
252 public void setValue(List<OutlineNode<LOPicker>> value) {
253 outlineModel.clearNodes();
254 outlineModel.getOutlineNodes().addAll(value);
255
256 if (value == null || value.isEmpty()){
257 initEmptyLoList();
258 } else {
259
260 for (OutlineNode<LOPicker> node:value){
261 LOPicker picker = node.getUserObject();
262 if (!picker.hasChangeHandler()){
263 picker.addSelectionChangeHandler(loPickerChangeHandler);
264 }
265 }
266
267 reDraw();
268 }
269 }
270
271 public void setLoInfoMaxLength(int loInfoMaxLength) {
272 this.loInfoMaxLength = loInfoMaxLength;
273 }
274
275 private void appendLO(String loValue) {
276 OutlineNode<LOPicker> aNode = new OutlineNode<LOPicker>();
277 LOPicker newPicker = new LOPicker(messageGroup, type, state, repoKey, this.loInfoMaxLength);
278
279 newPicker.addSelectionChangeHandler(loPickerChangeHandler);
280 newPicker.setLOText(loValue);
281 aNode.setUserObject(newPicker);
282 aNode.setModel(outlineModel);
283
284 outlineModel.addOutlineNode(aNode);
285 }
286
287
288
289
290 public void addSelectedLOs(List<String> loDescription) {
291
292 List<OutlineNode<LOPicker>> existingLOs = outlineModel.getOutlineNodes();
293
294 int ix = existingLOs.size();
295 for (String strValue : loDescription) {
296
297 boolean foundEmptyBox = false;
298
299 for(int i=0;i<ix;i++)
300 {
301 if (existingLOs.get(i).getUserObject().getLOText().trim()
302 .length() == 0) {
303 existingLOs.get(i).getUserObject().setLOText(strValue);
304 foundEmptyBox = true;
305 i=ix;
306 }
307 }
308
309
310 if (foundEmptyBox == false) {
311 appendLO(strValue);
312 }
313 }
314 reDraw();
315 }
316
317 private void reDraw() {
318 if (null != outlineComposite) {
319 this.removeSection(outlineComposite);
320 }
321 this.removeWidget(addNew);
322 outlineComposite = new OutlineManager(startOfPath, middleOfPath, endOfPath);
323 outlineComposite.setValue(outlineModel);
324 this.addSection(outlineComposite);
325 this.addWidget(addNew);
326 outlineComposite.render();
327 }
328
329 public HandlerRegistration addValueChangeHandler(ValueChangeHandler<List<OutlineNode<LOPicker>>> handler) {
330 return addHandler(handler, ValueChangeEvent.getType());
331 }
332
333 public SelectionChangeHandler getChangeHandlerForLOPicker(){
334 return loPickerChangeHandler;
335 }
336
337 @Override
338 public void setValue(List<OutlineNode<LOPicker>> value,
339 boolean fireEvents) {
340 setValue(value);
341 }
342 }
343
344 @Override
345 public ErrorLevel processValidationResults(FieldDescriptor fd, List<ValidationResultInfo> results) {
346 return processValidationResults(fd, results, true);
347 }
348
349 @Override
350 public ErrorLevel processValidationResults(FieldDescriptor fd, List<ValidationResultInfo> results, boolean clearErrors) {
351
352 ErrorLevel status = ErrorLevel.OK;
353
354 for (Section section : getSections()) {
355 ErrorLevel level = section.processValidationResults(results, clearErrors);
356 if (level.getLevel() > status.getLevel()) {
357 status = level;
358 }
359 }
360 return status;
361 }
362
363 public static int getLoListDescLength() {
364 return loListDescLength;
365
366 }
367
368 @Override
369 public boolean doesOnTheFlyValidation() {
370 return onTheFlyValidation;
371 }
372
373 @Override
374 public void Validate(ValidateRequestEvent event, List<ValidationResultInfo> result) {
375
376 if (event.getFieldDescriptor().hasHadFocus()) {
377 Map<String, FieldElement> loFieldModelMapping = doLOFieldModelMapping();
378
379 for (int i = 0; i < result.size(); i++) {
380 ValidationResultInfo vr = result.get(i);
381 FieldElement element = loFieldModelMapping.get(vr.getElement());
382
383 if (element != null) {
384 element.clearValidationErrors();
385 element.processValidationResult(vr);
386 }
387 }
388 }
389
390 }
391
392 private Map<String, FieldElement> doLOFieldModelMapping() {
393 Map<String, FieldElement> loFieldModelMapping = new HashMap<String, FieldElement>();
394
395 int z = 0;
396
397 for (int i = 0; i < this.getValue().size(); i++) {
398 String startPath = startOfPath + "/";
399 String endPathFormatted = "/" + "loInfo/desc/formatted";
400 String endPathPlain = "/" + "loInfo/desc/plain";
401
402 this.getFields().get(i).getFieldElement().clearValidationErrors();
403
404 String desc = this.getValue().get(i).getUserObject().getLOText();
405 int indentLevel = this.getValue().get(i).getIndentLevel();
406 List<LoCategoryInfo> categories = this.getValue().get(i).getUserObject().getLoCategories();
407
408 if (desc != null && desc.trim().length() > 0 || indentLevel > 0 || categories != null && !categories.isEmpty()) {
409 loFieldModelMapping.put(startPath + z + endPathFormatted, this.getFields().get(i).getFieldElement());
410 loFieldModelMapping.put(startPath + z++ + endPathPlain, this.getFields().get(i).getFieldElement());
411 }
412
413 }
414 return loFieldModelMapping;
415 }
416
417 }