/* * Copyright 2011 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.informer.domain.questionnaire; import java.util.ArrayList; import java.util.List; import org.drools.informer.Group; import org.drools.informer.MultipleChoiceQuestion; import org.drools.informer.Note; import org.drools.informer.Question; import org.drools.informer.InvalidAnswer; import org.drools.informer.domain.questionnaire.conditions.ConditionClause; import org.drools.informer.domain.questionnaire.conditions.PageElementCondition; import org.drools.informer.domain.questionnaire.framework.PageElementConstants; /** * The key domain object holding the details for Tohu related objects such as * <ul> * <li>{@link Group}</li> * <li>{@link Question}</li> * <li>{@link MultipleChoiceQuestion}</li> * <li>{@link Note}</li> * <li>{@link Question}</li> * </ul> * * The Spreadsheet Types are * <ul> * <li>Group</li> * <li>Question</li> * <li>MultipleChoiceQuestion</li> * <li>Note</li> * <li>Page (maps to {@link Group})</li> * <li>Branch (maps to {@link Group})</li> * <li>Impact (maps to {@link Question})</li> * <li>FunctionalImpact (maps to combination of accumulate function and {@link Question})</li> * <li>AlternateImpact (maps to {@link Question})</li> * <li>Validation (generates {@link InvalidAnswer})</li> * <li>Reuse (does a lookup on the original element by id - will be repeated in the UI)</li> * </ul> * * Each element can have a {@link PageElementCondition} which holds one or more * {@link ConditionClause} entries that describe logic elements that control show/hide or validation logic. * * The elements are linked in a tree structure (parent->child), which is used to control * groupings for layout etc. Also, each child knows what it's older sibling is and/or its parent. * This can then be used by Validation entries to know what to Question to associate the InvalidAnswer with. * * Although the one <object holds the data for all the Tohu objects, the writing of the DRL file will need to translate * method names (for example, using "name" instead of "preLabel" when relating to a Question instead of an Item). * * @author Derek Rendall */ public class PageElement implements PageElementConstants { private String id; private List<String> groupIds; /** What Object type to create as a Tohu rule object - will be mapped in the setter */ private String type; private String lookupTableId; private boolean required; private String fieldType; /** For Question this will be the name, for Validation this will be the Message */ private String preLabel; /** For pages, this will be the insertAfter page value, for Question this will be the reason */ private String postLabel; private String defaultValueStr; private List<String> styles = new ArrayList<String>(); private LookupTable lookupTable; private boolean aPageElement; private String pageType; /** Spreadsheet Type holds what the original type was. The Type will be mapped to the Tohu object when the setter is called */ private String spreadsheetType; private PageElementCondition displayCondition; private PageElementCondition currentValidationCondition; /** category applies for Question and Item, and can be used to select a group of objects, especially useful for calculations */ private String category; /** Depth is used to control nesting of elements */ private int depth; /** Row number provides a useful rule identification variation to avoid duplicate names in DRL file */ private int rowNumber; /** * Working value - especially for lines where only has the logic element, in which case the * logic will be inserted into the previous element, and this element will be "thrown away". */ private ConditionClause logicElement; protected List<PageElement> children = new ArrayList<PageElement>(); protected PageElement parent; protected PageElement previousSibling; public PageElement() { super(); } /** * @param id * Cannot have a space in the value * @param depth * @param rowNumber */ public void setId(String id, int depth, int rowNumber) { id = id.trim(); if (id.indexOf(" ") >= 0) { throw new IllegalArgumentException("You cannot have a space in an id [" + id + "]"); } this.id = id; this.depth = depth; this.rowNumber = rowNumber; } public PageElement getPreviousSibling() { return previousSibling; } public void setPreviousSibling(PageElement previousSibling) { this.previousSibling = previousSibling; } public boolean isAFunctionImpactItem() { return (spreadsheetType != null) && (spreadsheetType.equalsIgnoreCase(ITEM_TYPE_FUNCTION_IMPACT)); } public boolean isAnAlternateImpactItem() { return (spreadsheetType != null) && (spreadsheetType.equalsIgnoreCase(ITEM_TYPE_ALTERNATE_IMPACT)); } public boolean isAQuestionType() { if (getType().equals(ITEM_TYPE_QUESTION) || (getType().equals(ITEM_TYPE_MULTI_CHOICE_Q))) { return true; } return false; } public String getSpreadsheetType() { return spreadsheetType; } public int getRowNumber() { return rowNumber; } public List<String> getGroupIds() { return groupIds; } /** * @param type * Will be stored in spreadsheetType, and then cast to the right Tohu object type * For example, a Page will be turned into a Group. */ public void setType(String type) { String tempType = type.toUpperCase(); spreadsheetType = type; if (tempType.equals("PAGE")) { aPageElement = true; this.type = "Group"; pageType = "Normal"; } else if (tempType.equals("BRANCH")) { aPageElement = true; this.type = "Group"; pageType = "Branch"; } else if (tempType.equalsIgnoreCase(ITEM_TYPE_NORMAL_IMPACT) || tempType.equalsIgnoreCase(ITEM_TYPE_FUNCTION_IMPACT) || tempType.equalsIgnoreCase(ITEM_TYPE_ALTERNATE_IMPACT)) { this.type = ITEM_TYPE_DATA_ITEM; } else { this.type = type; } } public PageElementCondition getDisplayCondition() { return displayCondition; } public void setDisplayCondition(PageElementCondition displayCondition) { this.displayCondition = displayCondition; } public boolean isAGroupType() { if (getType().equals(ITEM_TYPE_GROUP)) { return true; } return false; } public boolean isANoteType() { if (getType().equals(ITEM_TYPE_NOTE)) { return true; } return false; } public boolean isAnImpactType() { if (getType().equals(ITEM_TYPE_DATA_ITEM)) { return true; } return false; } public boolean isAPageElement() { return aPageElement; } public boolean isABranchedPage() { return aPageElement && pageType.equals("Branch"); } public int getDepth() { return depth; } public String getPageType() { return pageType; } /** * Will traverse previousSiblings (the norm) and then parent looking for a Question (or subclass). * Used by the validation elements to associate an InvalidAnswer with. * * @return */ public PageElement findPreviousQuestion() { if (getPreviousSibling() != null) { if (getPreviousSibling().isAQuestionType()) { return getPreviousSibling(); } return getPreviousSibling().findPreviousQuestion(); } if (getParent() != null) { if (getParent().isAQuestionType()) { return getParent(); } return getParent().findPreviousQuestion(); } return null; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public List<PageElement> getChildren() { return children; } public String getLookupTableId() { return lookupTableId; } public void setLookupTableId(String lookupTableId) { this.lookupTableId = lookupTableId; } /** * Will add the child, set the child's previous sibling (if any) and the child's parent. * * @param child */ public void addChild(PageElement child) { //System.out.println("Adding child " + child.getId() + child.getDepth() + " to " + getId() + getDepth()); if (children.size() > 0) { child.setPreviousSibling(children.get(children.size() - 1)); } this.children.add(child); child.setParent(this); } protected void setParent(PageElement parent) { this.parent = parent; } public PageElement getParent() { return parent; } public LookupTable getLookupTable() { return lookupTable; } public void setLookupTable(LookupTable lookupTable) { this.lookupTable = lookupTable; } public boolean isRequired() { return required; } public String getDefaultValueStr() { return defaultValueStr; } public List<String> getStyles() { return styles; } public PageElementCondition getCurrentValidationCondition() { return currentValidationCondition; } public ConditionClause getLogicElement() { return logicElement; } public void setLogicElement(ConditionClause substituteLogicElement) { if (logicElement != null) { throw new IllegalArgumentException("You cannot replace the logic element"); } logicElement = substituteLogicElement; } public void setLogicDependsOnItemId(String value) { if (logicElement == null) { logicElement = new ConditionClause(); } logicElement.setItemId(value); } public void setLogicAttribute(String value) { if (logicElement == null) { logicElement = new ConditionClause(); } logicElement.setItemAttribute(value); } public void setLogicOperation(String value) { if (logicElement == null) { logicElement = new ConditionClause(); } logicElement.setOperation(value); } public void setLogicValue(String value) { if (logicElement == null) { logicElement = new ConditionClause(); } logicElement.setValue(value); } public void addGroupId(String groupId) { if (groupIds == null) { groupIds = new ArrayList<String>(); } if (groupIds.contains(groupId)) { return; } groupIds.add(groupId); } public String getPreLabel() { return preLabel; } public void setPreLabel(String preLabel) { this.preLabel = preLabel; } public String getPostLabel() { return postLabel; } public void setPostLabel(String postLabel) { this.postLabel = postLabel; } public boolean isARepeatingElement() { if ((getType() == null) || (!getType().equals(ITEM_TYPE_REUSE))) { return false; } return true; } public boolean isAValidationElement() { if ((getType() == null) || (!getType().equals(ITEM_TYPE_VALIDATION))) { return false; } return true; } public String getId() { return id; } public String getType() { return type; } public String getFieldType() { return fieldType; } public void setFieldType(String fieldType) { this.fieldType = fieldType; } public void setRequired(String requiredStr) { if ((requiredStr != null) && (requiredStr.toUpperCase().startsWith("Y"))) { this.required = true; } else { this.required = false; } } public void setDefaultValueStr(String defaultValueStr) { this.defaultValueStr = defaultValueStr; } public void addStyle(String style) { styles.add(style); } }