Java tutorial
/******************************************************************************* * Copyright 2008(c) The OBiBa Consortium. All rights reserved. * * This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package org.obiba.onyx.quartz.editor.question.condition; import static org.obiba.onyx.quartz.editor.question.condition.Condition.Type.JAVASCRIPT; import static org.obiba.onyx.quartz.editor.question.condition.Condition.Type.NONE; import static org.obiba.onyx.quartz.editor.question.condition.Condition.Type.QUESTION_CATEGORY; import static org.obiba.onyx.quartz.editor.question.condition.Condition.Type.VARIABLE; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.wicket.AttributeModifier; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormChoiceComponentUpdatingBehavior; import org.apache.wicket.ajax.form.OnChangeAjaxBehavior; import org.apache.wicket.ajax.markup.html.AjaxLink; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow; import org.apache.wicket.markup.html.CSSPackageResource; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.basic.MultiLineLabel; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.Radio; import org.apache.wicket.markup.html.form.RadioGroup; import org.apache.wicket.markup.html.form.SimpleFormComponentLabel; import org.apache.wicket.markup.html.form.TextArea; import org.apache.wicket.markup.html.image.Image; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; import org.apache.wicket.model.ResourceModel; import org.apache.wicket.spring.injection.annot.SpringBean; import org.apache.wicket.validation.IValidatable; import org.apache.wicket.validation.IValidator; import org.obiba.magma.Variable; import org.obiba.magma.type.BooleanType; import org.obiba.onyx.core.data.IDataSource; import org.obiba.onyx.core.data.JavascriptDataSource; import org.obiba.onyx.core.data.VariableDataSource; import org.obiba.onyx.quartz.core.engine.questionnaire.question.Category; import org.obiba.onyx.quartz.core.engine.questionnaire.question.Question; import org.obiba.onyx.quartz.core.engine.questionnaire.question.QuestionType; import org.obiba.onyx.quartz.core.engine.questionnaire.question.Questionnaire; import org.obiba.onyx.quartz.core.engine.questionnaire.util.QuestionnaireBuilder; import org.obiba.onyx.quartz.core.engine.questionnaire.util.QuestionnaireElementComparator; import org.obiba.onyx.quartz.core.engine.questionnaire.util.QuestionnaireFinder; import org.obiba.onyx.quartz.core.engine.questionnaire.util.builder.QuestionBuilder; import org.obiba.onyx.quartz.editor.behavior.syntaxHighlighter.SyntaxHighlighterBehavior; import org.obiba.onyx.quartz.editor.behavior.tooltip.TooltipBehavior; import org.obiba.onyx.quartz.editor.question.condition.Condition.Type; import org.obiba.onyx.quartz.editor.utils.JavascriptUtils; import org.obiba.onyx.quartz.editor.utils.QuestionnaireElementNameRenderer; import org.obiba.onyx.quartz.editor.variable.VariablePanel; import org.obiba.onyx.quartz.editor.variable.VariableRenderer; import org.obiba.onyx.quartz.editor.variable.VariableUtils; import org.obiba.onyx.wicket.Images; import com.google.common.base.Predicate; import com.google.common.collect.Collections2; /** * */ @SuppressWarnings("serial") public class ConditionPanel extends Panel { @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "SE_BAD_FIELD", justification = "Need to be be re-initialized upon deserialization") @SpringBean private VariableUtils variableUtils; private final IModel<Questionnaire> questionnaireModel; private final IModel<Question> questionModel; private final ModalWindow variableWindow; private DropDownChoice<Question> questionName; public ConditionPanel(String id, final IModel<Question> questionModel, final IModel<Questionnaire> questionnaireModel) { super(id); this.questionModel = questionModel; this.questionnaireModel = questionnaireModel; add(CSSPackageResource.getHeaderContribution(ConditionPanel.class, "ConditionPanel.css")); variableWindow = new ModalWindow("variableWindow"); variableWindow.setCssClassName("onyx"); variableWindow.setInitialWidth(950); variableWindow.setInitialHeight(540); variableWindow.setResizable(true); variableWindow.setTitle(new ResourceModel("Variable")); add(variableWindow); add(new MultiLineLabel("explain", new ResourceModel("Explain"))); Condition condition = new Condition(); final Question question = questionModel.getObject(); final Questionnaire questionnaire = questionnaireModel.getObject(); QuestionnaireFinder questionnaireFinder = QuestionnaireFinder.getInstance(questionnaire); questionnaireFinder.buildQuestionnaireCache(); // need a fresh cache final IDataSource initialCondition = question.getCondition(); if (initialCondition != null) { if (initialCondition instanceof VariableDataSource) { VariableDataSource variableDataSource = (VariableDataSource) initialCondition; if (questionnaire.getName().equals(variableDataSource.getTableName())) { try { condition.setVariable(questionnaire.getVariable(variableDataSource.getVariableName())); condition.setType(Type.VARIABLE); } catch (IllegalArgumentException e) { // not found in this questionnaire } } if (condition.getType() == NONE) { // not found yet Variable variable = variableUtils.findVariable(variableDataSource); if (variable != null) { try { condition.setVariable(questionnaire.getVariable(variable.getName())); condition.setType(Type.VARIABLE); } catch (IllegalArgumentException e) { // not found Question questionCondition = VariableUtils.findQuestion(variable, questionnaireFinder); condition.setType(Type.QUESTION_CATEGORY); condition.setQuestion(questionCondition); condition.setCategory(VariableUtils.findCategory(variable, questionCondition)); } } } } else if (initialCondition instanceof JavascriptDataSource) { condition.setType(JAVASCRIPT); condition.setScript(((JavascriptDataSource) initialCondition).getScript()); } } Model<Condition> model = new Model<Condition>(condition); setDefaultModel(model); final Form<Void> form = new Form<Void>("form"); add(form); final RadioGroup<Type> conditionType = new RadioGroup<Type>("conditionType", new PropertyModel<Type>(model, "type")); conditionType.setLabel(new ResourceModel("ConditionType")).setRequired(true); form.add(conditionType); final Radio<Type> noneType = new Radio<Type>("none", new Model<Type>(NONE)); noneType.setLabel(new ResourceModel("NoCondition")); conditionType.add(noneType).add(new SimpleFormComponentLabel("noneLabel", noneType)); final Radio<Type> questionType = new Radio<Type>("questionType", new Model<Type>(QUESTION_CATEGORY)); questionType.setLabel(new ResourceModel("QuestionType")); conditionType.add(questionType).add(new SimpleFormComponentLabel("questionTypeLabel", questionType)); final WebMarkupContainer questionTypeContainer = new WebMarkupContainer("questionTypeContainer"); questionTypeContainer.setOutputMarkupId(true); conditionType.add(questionTypeContainer); final WebMarkupContainer questionConditionContainer = new WebMarkupContainer("questionConditionContainer"); questionConditionContainer.setVisible(condition.getType() == QUESTION_CATEGORY); questionTypeContainer.add(questionConditionContainer); final List<Question> questions = new ArrayList<Question>(Collections2.filter( questionnaire.getQuestionnaireCache().getQuestionCache().values(), new Predicate<Question>() { @Override public boolean apply(Question q) { return !q.equals(question) && q.getType() != QuestionType.BOILER_PLATE; } })); Collections.sort(questions, new QuestionnaireElementComparator()); questionName = new DropDownChoice<Question>("question", new PropertyModel<Question>(model, "question"), questions, new QuestionnaireElementNameRenderer()) { @Override public boolean isRequired() { return conditionType.getModelObject() == QUESTION_CATEGORY; } }; questionName.setLabel(new ResourceModel("Question")); questionName.setNullValid(false); questionConditionContainer.add(questionName) .add(new SimpleFormComponentLabel("questionLabel", questionName)); final List<Category> categories = findCategories(); final DropDownChoice<Category> categoryName = new DropDownChoice<Category>("category", new PropertyModel<Category>(model, "category"), categories, new QuestionnaireElementNameRenderer()) { @Override public boolean isRequired() { return conditionType.getModelObject() == QUESTION_CATEGORY; } }; categoryName.setLabel(new ResourceModel("Category")); categoryName.setNullValid(false); questionConditionContainer.add(categoryName) .add(new SimpleFormComponentLabel("categoryLabel", categoryName)); questionName.add(new OnChangeAjaxBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { categories.clear(); categories.addAll(findCategories()); target.addComponent(categoryName); } }); Radio<Type> variableType = new Radio<Type>("variableType", new Model<Type>(VARIABLE)); variableType.setLabel(new ResourceModel("VariableType")); conditionType.add(variableType).add(new SimpleFormComponentLabel("variableTypeLabel", variableType)); final WebMarkupContainer variableTypeContainer = new WebMarkupContainer("variableTypeContainer"); variableTypeContainer.setOutputMarkupId(true); conditionType.add(variableTypeContainer); final WebMarkupContainer variableContainer = new WebMarkupContainer("variableContainer"); variableContainer.setVisible(condition.getType() == VARIABLE); variableTypeContainer.add(variableContainer); final List<Variable> variables = new ArrayList<Variable>( Collections2.filter(questionnaire.getVariables(), new Predicate<Variable>() { @Override public boolean apply(Variable v) { return v.getValueType().equals(BooleanType.get()); } })); final DropDownChoice<Variable> variableDropDown = new DropDownChoice<Variable>("variable", new PropertyModel<Variable>(model, "variable"), variables, new VariableRenderer()) { @Override public boolean isRequired() { return conditionType.getModelObject() == VARIABLE; } }; variableDropDown.setLabel(new ResourceModel("Variable")).setOutputMarkupId(true); variableContainer.add(variableDropDown); final WebMarkupContainer previewVariableVisibility = new WebMarkupContainer("previewVariableVisibility"); variableContainer.add(previewVariableVisibility.setOutputMarkupId(true)); final Image previewVariable = new Image("previewVariable", Images.ZOOM); previewVariable.add(new AttributeModifier("title", true, new ResourceModel("Preview"))); previewVariable.setVisible(variableDropDown.getModelObject() != null); previewVariableVisibility.add(previewVariable); final Label previewScript = new Label("previewScript", variableDropDown.getModelObject() == null ? "" : variableDropDown.getModelObject().getAttributeStringValue("script")); previewScript.add(new SyntaxHighlighterBehavior()); previewScript.add(new AttributeAppender("style", true, new Model<String>("display: none;"), " ")); previewVariableVisibility.add(previewScript); final Map<String, Object> tooltipCfg = new HashMap<String, Object>(); tooltipCfg.put("delay", 100); tooltipCfg.put("showURL", false); tooltipCfg.put("top", -30); tooltipCfg.put("bodyHandler", "function() { return $(\"#" + previewScript.getMarkupId(true) + "\").html(); }"); previewVariable.add(new TooltipBehavior(null, tooltipCfg)); variableContainer.add(new AjaxLink<Void>("newVariable") { @Override public void onClick(AjaxRequestTarget target) { @SuppressWarnings({ "rawtypes", "unchecked" }) VariablePanel variablePanel = new VariablePanel("content", new Model(null), questionnaireModel, BooleanType.get()) { @Override public void onSave(@SuppressWarnings("hiding") AjaxRequestTarget target, Variable createdVariable) { variables.add(createdVariable); questionnaire.addVariable(createdVariable); variableDropDown.setModelObject(createdVariable); previewVariable.setVisible(true); previewScript.setDefaultModelObject(createdVariable.getAttributeStringValue("script")); variableWindow.close(target); target.addComponent(variableDropDown); target.addComponent(previewVariableVisibility); } @Override public void onCancel(@SuppressWarnings("hiding") AjaxRequestTarget target) { variableWindow.close(target); } }; variableWindow.setContent(variablePanel); variableWindow.show(target); } }.add(new Image("newVariableImg", Images.ADD)) .add(new AttributeModifier("title", true, new ResourceModel("NewVariable")))); variableDropDown.add(new OnChangeAjaxBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { Variable variable = variableDropDown.getModelObject(); previewVariable.setVisible(variable != null); previewScript.setDefaultModelObject( variable == null ? null : variable.getAttributeStringValue("script")); target.addComponent(previewVariableVisibility); } }); Radio<Type> javascriptType = new Radio<Type>("javascriptType", new Model<Type>(JAVASCRIPT)); javascriptType.setLabel(new ResourceModel("JavascriptType")); conditionType.add(javascriptType).add(new SimpleFormComponentLabel("javascriptTypeLabel", javascriptType)); final TextArea<String> javascriptField = new TextArea<String>("javascriptField", new PropertyModel<String>(condition, "script")); javascriptField.setOutputMarkupPlaceholderTag(true); javascriptField.setVisible(condition.getType() == JAVASCRIPT); conditionType.add(javascriptField); javascriptField.add(new IValidator<String>() { @Override public void validate(final IValidatable<String> validatable) { JavascriptUtils.compile(validatable.getValue(), question.getName(), ConditionPanel.this, form); } }); conditionType.add(new AjaxFormChoiceComponentUpdatingBehavior() { @Override protected void onUpdate(AjaxRequestTarget target) { Type type = conditionType.getModelObject(); switch (type) { case NONE: questionName.setModelObject(null); categoryName.setModelObject(null); variableDropDown.setModelObject(null); javascriptField.setModelObject(null); break; case QUESTION_CATEGORY: variableDropDown.setModelObject(null); javascriptField.setModelObject(null); break; case VARIABLE: questionName.setModelObject(null); categoryName.setModelObject(null); javascriptField.setModelObject(null); break; case JAVASCRIPT: questionName.setModelObject(null); categoryName.setModelObject(null); variableDropDown.setModelObject(null); break; } questionConditionContainer.setVisible(type == QUESTION_CATEGORY); variableContainer.setVisible(type == VARIABLE); javascriptField.setVisible(type == JAVASCRIPT); target.addComponent(questionTypeContainer); target.addComponent(variableTypeContainer); target.addComponent(javascriptField); } }); } private List<Category> findCategories() { final List<Category> categories = new ArrayList<Category>(); final Question selectedQuestion = questionName.getModelObject(); if (selectedQuestion != null) { if (selectedQuestion.getParentQuestion() == null) { categories.addAll(selectedQuestion.getCategories()); } else { // get parent categories for array categories.addAll(selectedQuestion.getParentQuestion().getCategories()); } } return categories; } public void onSave(@SuppressWarnings("unused") AjaxRequestTarget target) { Condition condition = (Condition) getDefaultModelObject(); if (condition.getType() == null) return; Questionnaire questionnaire = questionnaireModel.getObject(); QuestionnaireBuilder questionnaireBuilder = QuestionnaireBuilder.getInstance(questionnaire); Question question = questionModel.getObject(); QuestionBuilder questionBuilder = QuestionBuilder.inQuestion(questionnaireBuilder, question); switch (condition.getType()) { case NONE: question.setCondition(null); break; case QUESTION_CATEGORY: questionBuilder.setCondition(condition.getQuestion().getName(), condition.getCategory().getName()); break; case VARIABLE: questionBuilder.setVariableCondition(questionnaire.getName() + ":" + condition.getVariable().getName()); break; case JAVASCRIPT: JavascriptDataSource datasource = new JavascriptDataSource(condition.getScript(), BooleanType.get().getName(), questionnaire.getName()); question.setCondition(datasource); break; } } }