/*
* 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.load.questionnaire;
import org.drools.informer.domain.questionnaire.Application;
import org.drools.informer.domain.questionnaire.LookupTable;
import org.drools.informer.domain.questionnaire.conditions.ConditionClause;
import org.drools.informer.load.spreadsheet.SpreadsheetItem;
import org.drools.informer.load.spreadsheet.SpreadsheetRow;
import org.drools.informer.load.spreadsheet.sections.SpreadsheetSection;
import org.drools.informer.load.questionnaire.SpreadsheetSectionConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Processes the application specific sections of the Spreadsheet, creating
* the {@link Application} object and setting it's core values. Also processes
* lookup table lists sections that are in the spreadsheet.
*
* Relates to Questionnaire type Spreadsheets.
*
* @author Derek Rendall
*/
public class ExtractApplication implements SpreadsheetSectionConstants {
// TODO all the validations - removing spaces, checking types etc
private static final Logger logger = LoggerFactory.getLogger(ExtractApplication.class);
private Application application = new Application();
private SpreadsheetSection applicationSection;
private List<SpreadsheetSection> tableSections = new ArrayList<SpreadsheetSection>();
private LookupTable currentLookupTable;
/**
* Take the Application and List sections, setting them aside for processing by this object.
*
* @param sections
*/
public ExtractApplication(List<SpreadsheetSection> sections) {
super();
for (Iterator<SpreadsheetSection> iterator = sections.iterator(); iterator.hasNext();) {
SpreadsheetSection spreadsheetSection = (SpreadsheetSection) iterator.next();
if (spreadsheetSection.getSectionHeadingString().startsWith(APPLICATION_UPPER)) {
applicationSection = spreadsheetSection;
}
else if (spreadsheetSection.getSectionHeadingString().startsWith(PAGE_LISTS_UPPER)) {
tableSections.add(spreadsheetSection);
}
}
if (applicationSection == null) {
throw new IllegalArgumentException("There was no section heading with " + APPLICATION_UPPER + " found");
}
}
/**
* Will process spreadsheet rows from application and table sections.
*
* @return
* The {@link Application} object created from processing the application section.
*/
public Application processApp() {
List<SpreadsheetRow> rows = applicationSection.getSectionRows();
if (rows.isEmpty()) {
return null;
}
for (Iterator<SpreadsheetRow> rowIter = rows.iterator(); rowIter.hasNext();) {
SpreadsheetRow spreadsheetRow = (SpreadsheetRow) rowIter.next();
processApplicationHeadingLine(applicationSection.getHeaderRow(), spreadsheetRow);
}
applicationSection.setProcessed(true);
for (Iterator<SpreadsheetSection> i = tableSections.iterator(); i.hasNext();) {
SpreadsheetSection ts = (SpreadsheetSection) i.next();
rows = ts.getSectionRows();
if (rows.isEmpty()) {
continue;
}
for (Iterator<SpreadsheetRow> rowIter = rows.iterator(); rowIter.hasNext();) {
SpreadsheetRow spreadsheetRow = (SpreadsheetRow) rowIter.next();
processListLine(ts.getHeaderRow(), spreadsheetRow);
}
ts.setProcessed(true);
}
return application;
}
/**
* Process a spreadsheet line, using the appropriate header line. The header line contains references to the
* column title, so each cell can check what value it is for, without relying on
* specific column order (other than the first column, which is used to identify the section).
*
* @param headings
* @param row
*/
protected void processApplicationHeadingLine(SpreadsheetRow headings, SpreadsheetRow row) {
// TODO handle repeated elements?
for (Iterator<SpreadsheetItem> iterator = row.getRowItems().iterator(); iterator.hasNext();) {
SpreadsheetItem item = (SpreadsheetItem) iterator.next();
String key = headings.getHeaderTextForColumnInUpperCase(item.getColumn());
if (key == null) {
// Comment item - ignore
continue;
}
String value = item.toString();
if (key.startsWith(APPLICATION_UPPER)) {
if (application.getId() != null) {
throw new IllegalStateException("You cannot have two rows with an application id!");
}
application.setId(value);
}
else if (key.startsWith("BASE")) {
application.setApplicationClass(value);
}
else if (key.equals("NAME")) {
application.setApplicationName(value);
}
else if (key.equals("COMPLETION")) {
application.setCompletionAction(value);
}
else if (key.startsWith("NOTE")) {
application.setNote(value);
}
else if (key.startsWith("ACTIVE")) {
application.setActivePage(value);
}
else if (key.startsWith("INCLUDE")) {
application.addImport(value);
}
else if (key.startsWith("ACTION")) {
application.setActionValidation(value);
}
else if (key.startsWith("MARKUP")) {
application.setMarkupAllowed(value);
}
else {
logger.debug("Unknown Application key: " + key);
}
}
}
/**
* Process a spreadsheet line, using the appropriate header line. The header line contains references to the
* column title, so each cell can check what value it is for, without relying on
* specific column order (other than the first column, which is used to identify the section).
*
* Each line may have a condition associated with it, which means that the entry will be added/removed
* based on the associated logic.
*
* @param headings
* @param row
*/
protected void processListLine(SpreadsheetRow headings, SpreadsheetRow row) {
// TODO handle repeated elements?
String itemValue = null, displayedValue = null;
String itemName = null, attributeName = null, operation = null, rhs = null;
for (Iterator<SpreadsheetItem> iterator = row.getRowItems().iterator(); iterator.hasNext();) {
SpreadsheetItem item = (SpreadsheetItem) iterator.next();
String key = headings.getHeaderTextForColumnInUpperCase(item.getColumn());
if (key == null) {
// Comment item - ignore
continue;
}
String value = item.toString();
if (key.startsWith(PAGE_LISTS_UPPER)) {
currentLookupTable = new LookupTable(value);
application.addLookupTable(currentLookupTable);
continue;
}
if (key.startsWith("ACTUAL")) {
itemValue = value;
continue;
}
if (key.startsWith("DISPLAY")) {
displayedValue = value;
continue;
}
if (key.startsWith("DEPENDS")) {
itemName = value;
continue;
}
if (key.startsWith("ATTRIBUTE")) {
attributeName = value;
continue;
}
if (key.startsWith("OP")) {
operation = value;
continue;
}
if (key.startsWith("VALUE")) {
rhs = value;
continue;
}
logger.debug("Unknown List key: " + key);
}
ConditionClause cc = null;
if (itemName != null) {
if (itemValue == null) {
// TODO handle multiple lines
throw new IllegalArgumentException("You cannot (yet) have more than one logic element for a list entry");
}
cc = new ConditionClause(itemName, attributeName, operation, rhs);
}
if (displayedValue == null) {
currentLookupTable.addEntry(itemValue, cc);
}
else {
currentLookupTable.addEntry(itemValue, displayedValue, cc);
}
}
}