1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.lum.program.client.requirements;
17
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21
22 import org.kuali.student.common.assembly.data.Metadata;
23 import org.kuali.student.common.ui.client.application.KSAsyncCallback;
24 import org.kuali.student.common.ui.client.configurable.mvc.SectionTitle;
25 import org.kuali.student.common.ui.client.configurable.mvc.views.VerticalSectionView;
26 import org.kuali.student.common.ui.client.mvc.Callback;
27 import org.kuali.student.common.ui.client.mvc.View;
28 import org.kuali.student.common.ui.client.service.MetadataRpcService;
29 import org.kuali.student.common.ui.client.service.MetadataRpcServiceAsync;
30 import org.kuali.student.common.ui.client.widgets.KSProgressIndicator;
31 import org.kuali.student.common.ui.client.widgets.buttongroups.ButtonEnumerations;
32 import org.kuali.student.common.ui.client.widgets.field.layout.button.ActionCancelGroup;
33 import org.kuali.student.common.ui.client.widgets.progress.BlockingTask;
34 import org.kuali.student.common.ui.client.widgets.progress.KSBlockingProgressIndicator;
35 import org.kuali.student.common.versionmanagement.dto.VersionDisplayInfo;
36 import org.kuali.student.core.statement.dto.*;
37 import org.kuali.student.core.statement.ui.client.widgets.rules.ReqCompEditWidget;
38 import org.kuali.student.core.statement.ui.client.widgets.rules.ReqComponentInfoUi;
39 import org.kuali.student.core.statement.ui.client.widgets.rules.RuleManageWidget;
40 import org.kuali.student.core.statement.ui.client.widgets.rules.RulesUtil;
41 import org.kuali.student.lum.common.client.widgets.*;
42 import org.kuali.student.lum.lu.dto.CluInfo;
43 import org.kuali.student.lum.program.client.properties.ProgramProperties;
44 import org.kuali.student.lum.program.client.rpc.StatementRpcService;
45 import org.kuali.student.lum.program.client.rpc.StatementRpcServiceAsync;
46 import org.kuali.student.lum.program.dto.ProgramRequirementInfo;
47
48
49 import com.google.gwt.core.client.GWT;
50 import com.google.gwt.user.client.Window;
51 import com.google.gwt.user.client.rpc.AsyncCallback;
52 import com.google.gwt.user.client.ui.SimplePanel;
53 import com.google.gwt.user.client.ui.VerticalPanel;
54 import com.google.gwt.user.client.ui.Widget;
55
56 public class ProgramRequirementsManageView extends VerticalSectionView {
57
58 private StatementRpcServiceAsync statementRpcServiceAsync = GWT.create(StatementRpcService.class);
59 private MetadataRpcServiceAsync metadataServiceAsync = GWT.create(MetadataRpcService.class);
60
61 protected static final String TEMLATE_LANGUAGE = "en";
62 protected static final String RULEEDIT_TEMLATE = "KUALI.RULE";
63 protected static final String RULEPREVIEW_TEMLATE = RULEEDIT_TEMLATE + ".PREVIEW";
64 protected static final String COMPOSITION_TEMLATE = "KUALI.RULE.COMPOSITION";
65 private static final String LU_NAMESPACE = "http://student.kuali.org/wsdl/lu";
66 private static final String CLU_NAMESPACE_URI = "{" + LU_NAMESPACE + "}cluInfo";
67
68 private ProgramRequirementsViewController parentController;
69
70
71 private VerticalPanel layout = new VerticalPanel();
72 private ReqCompEditWidget editReqCompWidget;
73 private RuleManageWidget ruleManageWidget;
74 private SimplePanel twiddlerPanel = new SimplePanel();
75 private ActionCancelGroup actionCancelButtons = new ActionCancelGroup(ButtonEnumerations.SaveCancelEnum.SAVE, ButtonEnumerations.SaveCancelEnum.CANCEL);
76
77
78 private StatementTreeViewInfo rule = null;
79 private boolean isInitialized = false;
80 private boolean isNewRule = false;
81 private ReqComponentInfo editedReqCompInfo = null;
82 private Integer internalProgReqID = null;
83 private String originalReqCompNL;
84 private String originalLogicExpression;
85
86
87 private BlockingTask creatingRuleTask = new BlockingTask("Creating Rule");
88
89 public ProgramRequirementsManageView(ProgramRequirementsViewController parentController, Enum<?> viewEnum, String name, String modelId) {
90 super(viewEnum, name, modelId);
91 this.parentController = parentController;
92 }
93
94 @Override
95 public void beforeShow(final Callback<Boolean> onReadyCallback) {
96
97 retrieveAndSetupReqCompTypes();
98 if (!isInitialized) {
99 setupHandlers();
100 draw();
101 isInitialized = true;
102 }
103
104 onReadyCallback.exec(true);
105 }
106
107 private void setupHandlers() {
108 editReqCompWidget.setReqCompConfirmButtonClickCallback(actionButtonClickedReqCompCallback);
109 editReqCompWidget.setNewReqCompSelectedCallbackCallback(newReqCompSelectedCallbackCallback);
110 editReqCompWidget.setRetrieveCompositionTemplateCallback(retrieveCompositionTemplateCallback);
111 editReqCompWidget.setRetrieveFieldsMetadataCallback(retrieveFieldsMetadataCallback);
112 editReqCompWidget.setRetrieveCustomWidgetCallback(retrieveCustomWidgetCallback);
113 ruleManageWidget.setReqCompEditButtonClickCallback(editReqCompCallback);
114 }
115
116 private void draw() {
117
118 remove(layout);
119 layout.clear();
120
121
122 SectionTitle title = SectionTitle.generateH3Title(ProgramProperties.get().programRequirements_manageViewPageStep1Title());
123 title.setStyleName("KS-Program-Requirements-Manage-Step-header1");
124 layout.add(title);
125
126 layout.add(editReqCompWidget);
127
128
129 title = SectionTitle.generateH3Title(ProgramProperties.get().programRequirements_manageViewPageStep2Title());
130 title.setStyleName("KS-Program-Requirements-Manage-Step-header2");
131 layout.add(title);
132
133 layout.add(ruleManageWidget);
134
135
136 KSProgressIndicator twiddler = new KSProgressIndicator();
137 twiddler.setVisible(false);
138 twiddlerPanel.setWidget(twiddler);
139 layout.add(twiddlerPanel);
140
141 addWidget(layout);
142
143 displaySaveButton();
144 }
145
146 private void displaySaveButton() {
147 actionCancelButtons.addStyleName("KS-Program-Requirements-Save-Button");
148 actionCancelButtons.addCallback(new Callback<ButtonEnumerations.ButtonEnum>(){
149 @Override
150 public void exec(final ButtonEnumerations.ButtonEnum result) {
151 parentController.getView(ProgramRequirementsViewController.ProgramRequirementsViews.PREVIEW, new Callback<View>(){
152 @Override
153 public void exec(View preview) {
154
155 if ((result == ButtonEnumerations.SaveCancelEnum.SAVE) && isDirty()) {
156 ProgramRequirementInfo affectedRule = ((ProgramRequirementsSummaryView) preview).getRules().updateRules(getRuleTree(), internalProgReqID, isNewRule());
157 ((ProgramRequirementsSummaryView) preview).updateRequirementWidgets(affectedRule);
158 }
159 isDirty = false;
160 parentController.showView(ProgramRequirementsViewController.ProgramRequirementsViews.PREVIEW);
161 }
162 });
163 }
164 });
165 addWidget(actionCancelButtons);
166 }
167
168
169 public void setRuleTree(StatementTreeViewInfo stmtTreeInfo, boolean newRuleFlag, Integer internalProgReqID) {
170
171 if (!isInitialized) {
172 editReqCompWidget = new ReqCompEditWidget(ProgramRequirementsSummaryView.NEW_REQ_COMP_ID);
173 ruleManageWidget = new RuleManageWidget();
174 ruleManageWidget.setReqCompEditButtonClickCallback(editReqCompCallback);
175 ruleManageWidget.setRuleChangedButtonClickCallback(ruleChangedCallback);
176 }
177
178 this.internalProgReqID = internalProgReqID;
179 editedReqCompInfo = null;
180 rule = RulesUtil.clone(stmtTreeInfo);
181 isNewRule = newRuleFlag;
182 originalReqCompNL = getAllReqCompNLs();
183
184
185 editReqCompWidget.setupNewReqComp();
186 ruleManageWidget.redraw(rule, false);
187
188 }
189
190
191 public StatementTreeViewInfo getRuleTree() {
192 rule = ruleManageWidget.getStatementTreeViewInfo();
193 return rule;
194 }
195
196 public boolean isNewRule() {
197 return isNewRule;
198 }
199
200
201 protected Callback<ReqComponentInfo> editReqCompCallback = new Callback<ReqComponentInfo>(){
202 public void exec(ReqComponentInfo reqComp) {
203 setEnabled(false);
204 editReqCompWidget.setupExistingReqComp(reqComp);
205 editedReqCompInfo = reqComp;
206 }
207 };
208
209 protected Callback<Boolean> ruleChangedCallback = new Callback<Boolean>(){
210 public void exec(Boolean ruleChanged) {
211 actionCancelButtons.getButton(ButtonEnumerations.SaveCancelEnum.SAVE).setEnabled(ruleChanged);
212 }
213 };
214
215 protected void setEnabled(boolean enabled) {
216 ruleManageWidget.setEnabled(enabled);
217 actionCancelButtons.getButton(ButtonEnumerations.SaveCancelEnum.SAVE).setEnabled(enabled);
218 }
219
220 @Override
221 public boolean isDirty() {
222 if (!isInitialized) {
223 return false;
224 }
225
226
227 return true;
228
229
230
231
232
233
234
235
236
237
238
239
240 }
241
242 private String getAllReqCompNLs() {
243 StringBuilder NL = new StringBuilder();
244 for (StatementTreeViewInfo tree : rule.getStatements()) {
245 for (ReqComponentInfo reqComp : tree.getReqComponents()) {
246 NL.append(reqComp.getNaturalLanguageTranslation());
247 }
248 }
249 return NL.toString();
250 }
251
252
253 protected Callback<ReqComponentInfoUi> actionButtonClickedReqCompCallback = new Callback<ReqComponentInfoUi>(){
254 public void exec(final ReqComponentInfoUi reqComp) {
255
256 editReqCompWidget.setupNewReqComp();
257 setEnabled(true);
258
259
260 if (reqComp == null) {
261 return;
262 }
263
264 KSBlockingProgressIndicator.addTask(creatingRuleTask);
265
266
267 statementRpcServiceAsync.translateReqComponentToNLs(reqComp, new String[]{RULEEDIT_TEMLATE,RULEPREVIEW_TEMLATE}, TEMLATE_LANGUAGE, new KSAsyncCallback<List<String>>() {
268 public void handleFailure(Throwable caught) {
269 KSBlockingProgressIndicator.removeTask(creatingRuleTask);
270 Window.alert(caught.getMessage());
271 GWT.log("translateReqComponentToNL failed", caught);
272 }
273
274 public void onSuccess(final List<String> reqCompNL) {
275
276 reqComp.setNaturalLanguageTranslation(reqCompNL.get(0));
277 reqComp.setPreviewNaturalLanguageTranslation(reqCompNL.get(1));
278
279
280 rule = ruleManageWidget.getStatementTreeViewInfo();
281
282 if (editedReqCompInfo == null) {
283 if (rule.getStatements() != null && !rule.getStatements().isEmpty()) {
284 StatementTreeViewInfo newStatementTreeViewInfo = new StatementTreeViewInfo();
285 newStatementTreeViewInfo.setId(ProgramRequirementsSummaryView.NEW_STMT_TREE_ID + Integer.toString(ProgramRequirementsSummaryView.tempStmtTreeID++));
286 newStatementTreeViewInfo.setOperator(rule.getStatements().get(0).getOperator());
287 newStatementTreeViewInfo.getReqComponents().add(reqComp);
288 rule.getStatements().add(newStatementTreeViewInfo);
289 } else {
290 rule.getReqComponents().add(reqComp);
291
292 if (rule.getOperator() == null) {
293 rule.setOperator(StatementOperatorTypeKey.AND);
294 }
295 }
296 } else {
297 editedReqCompInfo.setNaturalLanguageTranslation(reqComp.getNaturalLanguageTranslation());
298 editedReqCompInfo.setReqCompFields(reqComp.getReqCompFields());
299 editedReqCompInfo.setType(reqComp.getType());
300 editedReqCompInfo = null;
301 }
302
303 ruleManageWidget.redraw(rule, true);
304 KSBlockingProgressIndicator.removeTask(creatingRuleTask);
305 }
306 });
307 }
308 };
309
310
311 protected Callback<ReqComponentInfo> newReqCompSelectedCallbackCallback = new Callback<ReqComponentInfo>(){
312 public void exec(final ReqComponentInfo reqComp) {
313 setEnabled(false);
314 }
315 };
316
317 private void retrieveAndSetupReqCompTypes() {
318
319 statementRpcServiceAsync.getReqComponentTypesForStatementType(rule.getType(), new KSAsyncCallback<List<ReqComponentTypeInfo>>() {
320 public void handleFailure(Throwable cause) {
321 GWT.log("Failed to get req. component types for statement of type:" + rule.getType(), cause);
322 Window.alert("Failed to get req. component types for statement of type:" + rule.getType());
323 }
324
325 public void onSuccess(final List<ReqComponentTypeInfo> reqComponentTypeInfoList) {
326 if (reqComponentTypeInfoList == null || reqComponentTypeInfoList.size() == 0) {
327 GWT.log("Missing Requirement Component Types", null);
328 Window.alert("Missing Requirement Component Types");
329 return;
330 }
331 editReqCompWidget.setReqCompList(reqComponentTypeInfoList);
332 editReqCompWidget.setCustomWidgets(getCustomWidgets(reqComponentTypeInfoList));
333 }
334 });
335 }
336
337 private Map<String, Widget> getCustomWidgets(List<ReqComponentTypeInfo> reqComponentTypeInfoList) {
338 Map<String, Widget> customWidgets = new HashMap<String, Widget>();
339
340 for (ReqComponentTypeInfo reqCompTypeInfo : reqComponentTypeInfoList) {
341 for (ReqCompFieldTypeInfo fieldTypeInfo : reqCompTypeInfo.getReqCompFieldTypeInfos()) {
342 if (RulesUtil.isGradeWidget(fieldTypeInfo.getId())) {
343 customWidgets.put("kuali.reqComponent.field.type.grade.id", new GradeWidget());
344 } else if (RulesUtil.isCourseWidget(fieldTypeInfo.getId())) {
345
346 final CourseWidget courseWidget = new CourseWidget();
347
348 courseWidget.addGetCluNameCallback(new Callback() {
349
350 @Override
351 public void exec(Object id) {
352
353 statementRpcServiceAsync.getCurrentVersion(CLU_NAMESPACE_URI, (String)id, new AsyncCallback<VersionDisplayInfo>() {
354 @Override
355 public void onFailure(Throwable throwable) {
356 Window.alert(throwable.getMessage());
357 GWT.log("Failed to retrieve clu for id: '" + "'", throwable);
358 }
359
360 @Override
361 public void onSuccess(final VersionDisplayInfo versionInfo) {
362 statementRpcServiceAsync.getClu(versionInfo.getId(), new AsyncCallback<CluInfo>() {
363 @Override
364 public void onFailure(Throwable throwable) {
365 Window.alert(throwable.getMessage());
366 GWT.log("Failed to retrieve clu", throwable);
367 }
368
369 @Override
370 public void onSuccess(CluInfo cluInfo) {
371 courseWidget.setLabelContent(cluInfo.getVersionInfo().getVersionIndId(), cluInfo.getOfficialIdentifier().getCode());
372 }
373 });
374 }
375 });
376
377
378 }
379 });
380
381 customWidgets.put("kuali.reqComponent.field.type.course.clu.id", courseWidget);
382 } else if (RulesUtil.isProgramWidget(fieldTypeInfo.getId())) {
383 final ProgramWidget programWidget = new ProgramWidget();
384
385 programWidget.addGetCluNameCallback(new Callback() {
386
387 @Override
388 public void exec(Object id) {
389
390 statementRpcServiceAsync.getCurrentVersion(CLU_NAMESPACE_URI, (String)id, new AsyncCallback<VersionDisplayInfo>() {
391 @Override
392 public void onFailure(Throwable throwable) {
393 Window.alert(throwable.getMessage());
394 GWT.log("Failed to retrieve clu for id: '" + "'", throwable);
395 }
396
397 @Override
398 public void onSuccess(final VersionDisplayInfo versionInfo) {
399 statementRpcServiceAsync.getClu(versionInfo.getId(), new AsyncCallback<CluInfo>() {
400 @Override
401 public void onFailure(Throwable throwable) {
402 Window.alert(throwable.getMessage());
403 GWT.log("Failed to retrieve clu", throwable);
404 }
405
406 @Override
407 public void onSuccess(CluInfo cluInfo) {
408 programWidget.setLabelContent(cluInfo.getVersionInfo().getVersionIndId(), cluInfo.getOfficialIdentifier().getCode());
409 }
410 });
411 }
412 });
413 }
414 });
415
416 customWidgets.put("kuali.reqComponent.field.type.program.clu.id", programWidget);
417 }
418 }
419 }
420 return customWidgets;
421 }
422
423
424 protected Callback<ReqComponentInfo> retrieveCompositionTemplateCallback = new Callback<ReqComponentInfo>(){
425 public void exec(final ReqComponentInfo reqComp) {
426 statementRpcServiceAsync.translateReqComponentToNL(reqComp, COMPOSITION_TEMLATE, TEMLATE_LANGUAGE, new KSAsyncCallback<String>() {
427 public void handleFailure(Throwable caught) {
428 Window.alert(caught.getMessage());
429 GWT.log("translateReqComponentToNL failed for req. comp. type: '" + reqComp.getType() + "'",caught);
430 }
431
432 public void onSuccess(final String compositionTemplate) {
433 editReqCompWidget.displayFieldsStart(compositionTemplate);
434 }
435 });
436 }
437 };
438
439 protected Callback<List<String>> retrieveFieldsMetadataCallback = new Callback<List<String>>(){
440 public void exec(final List<String> fieldTypes) {
441
442 if (fieldTypes.contains("kuali.reqComponent.field.type.grade.id")) {
443 fieldTypes.add("kuali.reqComponent.field.type.gradeType.id");
444 }
445
446 metadataServiceAsync.getMetadataList(ReqCompFieldInfo.class.getName(), fieldTypes, null, new KSAsyncCallback<List<Metadata>>() {
447 public void handleFailure(Throwable caught) {
448 Window.alert(caught.getMessage());
449 GWT.log("getMetadataList failed for req. comp. types: '" + fieldTypes.toString() + "'",caught);
450 }
451
452 public void onSuccess(final List<Metadata> metadataList) {
453 editReqCompWidget.displayFieldsEnd(metadataList);
454 }
455 });
456 }
457 };
458
459 protected Callback<String> retrieveCustomWidgetCallback = new Callback<String>(){
460 public void exec(final String fieldType) {
461 if (RulesUtil.isCluSetWidget(fieldType)) {
462 String clusetType = "kuali.cluSet.type.Course";
463 if (fieldType.toLowerCase().indexOf("program") > 0) {
464 clusetType = "kuali.cluSet.type.Program";
465 }
466 editReqCompWidget.displayCustomWidget(fieldType, new BuildCluSetWidget(new CluSetRetrieverImpl(), clusetType, false));
467 }
468 }
469 };
470
471 public Integer getInternalProgReqID() {
472 return internalProgReqID;
473 }
474 }