/*
Copyright (C) 2003-2005 Know Gate S.L. All rights reserved.
C/Oña, 107 1º2 28050 Madrid (Spain)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. The end-user documentation included with the redistribution,
if any, must include the following acknowledgment:
"This product includes software parts from hipergate
(http://www.hipergate.org/)."
Alternately, this acknowledgment may appear in the software itself,
if and wherever such third-party acknowledgments normally appear.
3. The name hipergate must not be used to endorse or promote products
derived from this software without prior written permission.
Products derived from this software may not be called hipergate,
nor may hipergate appear in their name, without prior written
permission.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
You should have received a copy of hipergate License with this code;
if not, visit http://www.hipergate.org or mail to info@hipergate.org
*/
package com.knowgate.surveys;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;
import java.sql.SQLException;
import org.jibx.runtime.JiBXException;
import com.knowgate.jdc.JDCConnection;
import com.knowgate.debug.DebugFile;
import com.knowgate.dataobjs.DB;
import com.knowgate.dataobjs.DBSubset;
import com.knowgate.misc.Gadgets;
/**
* <p>Data Minning routines for Surveys</p>
* This is an experimental module, not yet ready for production purposes.
* @author Sergio Montoro Ten
* @version 0.1
*/
public class DataMiner {
// ---------------------------------------------------------------------------
public DataMiner() { }
// ---------------------------------------------------------------------------
public static String getAnswerResults(JDCConnection oConn, String sGuPageSet,
String sStorage, String sEnc,
String sNmQuestion,
int iResultsType, int iOutputType)
throws UnsupportedEncodingException,FileNotFoundException,IOException,
SQLException,JiBXException,IllegalArgumentException,
ArrayIndexOutOfBoundsException,OutOfMemoryError {
if (DebugFile.trace) {
DebugFile.writeln("Begin DataMiner.getAnswerResults([JDCConnection],"+
sGuPageSet+","+sStorage+","+sEnc+","+sNmQuestion+","+
(RESULTS_ABSOLUTE==iResultsType ? "RESULTS_ABSOLUTE" :
(RESULTS_PERCENTAGE==iResultsType ? "RESULTS_PERCENTAGE" :
String.valueOf(iResultsType)))+
(OUTPUT_CSV==iOutputType ? "OUTPUT_CSV" :
(OUTPUT_XML==iOutputType ? "OUTPUT_XML" :
(OUTPUT_TSV==iOutputType ? "OUTPUT_TSV" :
String.valueOf(iOutputType))))+")");
DebugFile.incIdent();
}
if (null==sEnc) sEnc="UTF-8";
// Retrive full set of answers into memory
DBSubset oAnswers = new DBSubset(DB.k_pageset_answers,
DB.gu_page+","+DB.tx_answer,
DB.gu_pageset+"=? AND "+DB.nm_answer+"=?",
2000);
int iAnswers = oAnswers.load(oConn, new Object[]{sGuPageSet,sNmQuestion});
if (DebugFile.trace) DebugFile.writeln(String.valueOf(iAnswers) + " answers found");
String sRetVal;
if (0==iAnswers) {
// If there are no answers the return null
sRetVal = null;
}
else {
// Get Survey object for this PageSet
Survey oSrvy = new Survey(oConn, sGuPageSet);
// Get Page for requested Answer
SurveyPage oPage = oSrvy.getPage(oConn, oAnswers.getString(0,0), sStorage, sEnc);
// Get Question object description for Answer
Question oQuest = oPage.getQuestion(sNmQuestion);
// Grids for storing results while iterating and before printing
String[][] oGrid;
float[][] fGrid;
int iRows=0, iCols=0;
// A Map for storing the vertical positition of each value on the titles
Map oValueMap;
// Intermediate variables holding vertical position for value while iterating answers
Integer oValuePos;
int[] oValueXY;
String sValue;
String[] aValues;
Iterator oValues;
switch (oQuest.getClassId()) {
// *********************************************************************
// Process TEXT and MULTITEXT type answers
case Question.SubTypes.TEXT:
case Question.SubTypes.MULTITEXT:
case Question.SubTypes.LICKERT:
oValueMap = new TreeMap();
if (oQuest.getClassId()==Question.SubTypes.TEXT) {
if (DebugFile.trace) {
DebugFile.writeln("Question type is TEXT");
DebugFile.writeln("reading "+String.valueOf(iAnswers)+" answers");
}
for (int a = 0; a < iAnswers; a++) {
sValue = oAnswers.getStringNull(1, a, "");
if (sValue.length() > 0) {
sValue = Gadgets.ASCIIEncode(sValue);
if (oValueMap.containsKey(sValue)) {
oValuePos = (Integer) oValueMap.get(sValue);
oValueMap.remove(sValue);
oValueMap.put(sValue, new Integer(oValuePos.intValue() + 1));
} else {
oValueMap.put(sValue, new Integer(1));
}
} // fi (sValue.length()>0)
} // next
} else if (oQuest.getClassId()==Question.SubTypes.MULTITEXT) {
if (DebugFile.trace) {
DebugFile.writeln("Question type is MULTITEXT");
DebugFile.writeln("reading "+String.valueOf(iAnswers)+" answers");
}
for (int a = 0; a < iAnswers; a++) {
sValue = oAnswers.getStringNull(1, a, "");
if (sValue.length() > 0) {
aValues = Gadgets.split(sValue, ';');
for (int v=0; v<aValues.length; v++) {
sValue = Gadgets.ASCIIEncode(aValues[v]);
if (oValueMap.containsKey(sValue)) {
oValuePos = (Integer) oValueMap.get(sValue);
oValueMap.remove(sValue);
oValueMap.put(sValue, new Integer(oValuePos.intValue() + 1));
} else {
oValueMap.put(sValue, new Integer(1));
}
} // next (v)
} // fi (sValue.length()>0)
} // next
} else if (oQuest.getClassId()==Question.SubTypes.LICKERT) {
if (DebugFile.trace) {
DebugFile.writeln("Question type is LICKERT");
DebugFile.writeln("reading "+String.valueOf(iAnswers)+" answers");
}
for (int a = 0; a < iAnswers; a++) {
sValue = oAnswers.getStringNull(1, a, "");
if (sValue.length() > 0) {
if (oValueMap.containsKey(sValue)) {
oValuePos = (Integer) oValueMap.get(sValue);
oValueMap.remove(sValue);
oValueMap.put(sValue, new Integer(oValuePos.intValue() + 1));
} else {
oValueMap.put(sValue, new Integer(1));
}
} // fi (sValue.length()>0)
} // next
}
if (DebugFile.trace) DebugFile.writeln("writting words frecuency");
oGrid = new String[2][oValueMap.size()+1];
oGrid[0][0] = oQuest.getCaption();
oGrid[1][0] = "";
oValues = oValueMap.keySet().iterator();
int iValueIndex = 1;
while (oValues.hasNext()) {
sValue = (String) oValues.next();
oGrid[0][iValueIndex] = sValue;
oGrid[1][iValueIndex] = ((Integer)oValueMap.get(sValue)).toString();
iValueIndex++;
} // wend
break;
// *********************************************************************
// Process CHOICE and MULTICHOICE type answers
case Question.SubTypes.CHOICE:
case Question.SubTypes.MULTICHOICE:
case Question.SubTypes.LISTCHOICE:
if (DebugFile.trace) DebugFile.writeln("Question type is CHOICE");
// Cast Question to Choice
Choice oChoice = (Choice) oQuest;
// Get count of distinct choice elements
iRows = oChoice.getChoiceElementCount();
iCols = 2;
if (DebugFile.trace) DebugFile.writeln(String.valueOf(iRows) + " distinct choices");
// Create map for holding the vertical position of each value on the grid
oValueMap = new HashMap(iRows*2);
oGrid = new String[3][iRows+1];
fGrid = new float[2][iRows+1];
// Fill the lefmost column of the grid with choice captions,
// initialize map with value vertical positions and set all numeric
// total to zero.
for (int c=0; c<iRows; c++) {
oValueMap.put(oChoice.getChoiceElement(c).value, new Integer(c));
oGrid[0][c] = oChoice.getChoiceElement(c).getCaptionAlt();
fGrid[0][c] = 0f;
} // next
// Print allowed values debug trace
if (DebugFile.trace) {
Iterator oKeySet = oValueMap.keySet().iterator();
StringBuffer oValsBuff = new StringBuffer();
oValsBuff.append("value set {");
if (oKeySet.hasNext()) oValsBuff.append((String) oKeySet.next());
while (oKeySet.hasNext()) oValsBuff.append("," + (String) oKeySet.next());
oValsBuff.append("}");
DebugFile.writeln(oValsBuff.toString());
oValsBuff=null;
oKeySet=null;
}
// Fill the last row for total
oGrid[0][iRows] = "Total"; // Title
fGrid[0][iRows] = 0f; // Total count
fGrid[1][iRows] = 1f; // Percentage
// Read all pre-fetched answers and compute totals
if (oQuest.getClassId()==Question.SubTypes.CHOICE ||
oQuest.getClassId()==Question.SubTypes.LISTCHOICE) {
if (DebugFile.trace) DebugFile.writeln("Computing choice totals");
for (int a=0; a<iAnswers; a++) {
sValue = oAnswers.getStringNull(1,a,"");
if (sValue.length()>0) {
// Get vertical position of current value on the grid
oValuePos = (Integer) oValueMap.get(sValue);
if (null==oValuePos) {
// Raise exception if value readed from the database does not match
// with any value for choice elements
if (DebugFile.trace) {
DebugFile.writeln("Choices count is "+String.valueOf(oValueMap.size()));
DebugFile.writeln("Invalid value \"" + sValue + "\" for answer "
+ String.valueOf(a+1));
DebugFile.decIdent();
}
throw new SQLException("Invalid value \"" + sValue +
"\" for answer " + String.valueOf(a+1),
"23000", 23000);
} else {
// Increment absolute count for this value and for total values
fGrid[0][oValuePos.intValue()] += 1;
fGrid[0][iRows] += 1;
}
} // fi (sValue!="")
} // next (a)
} else { // Question.SubTypes.MULTICHOICE
if (DebugFile.trace) DebugFile.writeln("Computing multichoice totals");
for (int a=0; a<iAnswers; a++) {
sValue = oAnswers.getStringNull(1,a,"");
if (sValue.length()>0) {
String[] aChoiceValues = Gadgets.split(sValue,';');
for (int v=0; v<aChoiceValues.length; v++) {
// Get vertical position of current value on the grid
if (aChoiceValues[v].length()>0) {
oValuePos = (Integer) oValueMap.get(aChoiceValues[v]);
if (null==oValuePos) {
// Raise exception if value readed from the database does not match
// with any value for choice elements
if (DebugFile.trace) DebugFile.decIdent();
throw new SQLException("Invalid value " +
aChoiceValues[v] +
" for answer " + String.valueOf(a+1) +
" column " + String.valueOf(v+1),
"23000", 23000);
} else {
// Increment absolute count for this value and for total values
fGrid[0][oValuePos.intValue()] += 1f;
fGrid[0][iRows] += 1f;
}
} // fi (aChoiceValues[v]!="")
} // next (v)
} // fi (sValue!="")
} // next (a)
}
// Convert results to percentages
if (DebugFile.trace) DebugFile.writeln("Converting results to percentages");
float fTotalChoices = fGrid[0][iRows];
for (int p=0; p<iRows; p++) {
fGrid[1][p] = fGrid[0][p]/fTotalChoices;
} // next
if (DebugFile.trace) DebugFile.writeln("Casting percentages as text");
for (int f=0; f<iRows; f++) {
oGrid[1][f] = String.valueOf(fGrid[0][f]);
oGrid[2][f] = String.valueOf(fGrid[1][f]);
} // next f
if (DebugFile.trace) DebugFile.writeln("Writting absolute and percentual total");
oGrid[1][iRows] = String.valueOf(fGrid[0][iRows]);
oGrid[2][iRows] = "1";
iRows++;
break;
// *********************************************************************
// Process MATRIX type answers
case Question.SubTypes.MATRIX:
if (DebugFile.trace) DebugFile.writeln("Question type is MATRIX");
// Cast Question to Matrix
Matrix oMtrx = (Matrix) oQuest;
iRows = oMtrx.rowCount();
iCols = oMtrx.columnCount();
if (DebugFile.trace) DebugFile.writeln("rows="+String.valueOf(iRows)+" cols="+String.valueOf(iCols));
// Create map for holding the vertical position of each value on the grid
oValueMap = new HashMap((iRows*iCols*13)/10);
oGrid = new String[iCols+1][iRows+2];
fGrid = new float[iCols+1][iRows+2];
if (oMtrx.uniquecolumns && oMtrx.uniquerows) {
if (DebugFile.trace) DebugFile.writeln("Computing uniquecolumns && uniquerows totals");
// *************
// *** TO DO ***
// *************
}
else if (oMtrx.uniquerows) {
if (DebugFile.trace) DebugFile.writeln("Computing uniquerows totals");
// Fill the top row of the grid with column captions
for (int c=1; c<iCols; c++) {
oGrid[c][0] = oMtrx.getCell(c,0).getCaptionAlt();
} // next
// Fill the lefmost column of the grid with row captions
for (int r=0; r<iRows; r++) {
oGrid[0][r] = oMtrx.getRow(r).getCaptionAlt();
} // next
oGrid[0][iRows] = "Total";
// Initialize value maps, one map per row
HashMap[] aRowMaps = new HashMap[iRows];
for (int r=1; r<iRows; r++) {
aRowMaps[r-1] = new HashMap(iCols*2);
for (int c=0; c<iCols; c++) {
fGrid[c][r] = 0f;
aRowMaps[r-1].put(oMtrx.getCell(c,r).getValue(), new int[]{c,r});
} // next (c)
if (DebugFile.trace) {
Iterator oRowSet = aRowMaps[r-1].keySet().iterator();
StringBuffer oRowBuff = new StringBuffer();
oRowBuff.append("value set for row "+String.valueOf(r)+" {");
if (oRowSet.hasNext()) oRowBuff.append((String) oRowSet.next());
while (oRowSet.hasNext()) oRowBuff.append("," + (String) oRowSet.next());
oRowBuff.append("}");
DebugFile.writeln(oRowBuff.toString());
oRowBuff=null;
oRowSet=null;
} // fi (DegugFile.trace)
} // next (r)
if (DebugFile.trace) DebugFile.writeln("Row maps successfully initialized");
// Read all pre-fetched answers and compute totals
for (int a=0; a<iAnswers; a++) {
sValue = oAnswers.getStringNull(1,a,"");
if (sValue.length()>0) {
String[] aRowValues = Gadgets.split(sValue,'|');
if (DebugFile.trace) {
if (aRowValues.length<iRows) {
DebugFile.writeln("Matrix row count ("+String.valueOf(iRows)+") is not equal to number of values ("+String.valueOf(aRowValues.length)+")");
DebugFile.decIdent();
throw new ArrayIndexOutOfBoundsException("Matrix row count ("+String.valueOf(iRows)+") is not equal to number of values ("+String.valueOf(aRowValues.length)+")");
}
}
for (int w=0; w<aRowValues.length; w++) {
// If value for this cell is not empty then find corresponding
// position in results grid.
if (aRowValues[w].length()>0) {
oValueXY = (int[]) aRowMaps[w].get(aRowValues[w]);
if (null==oValueXY) {
// Raise exception if value readed from the database does
// not match any value for cell elements.
if (DebugFile.trace) DebugFile.decIdent();
throw new SQLException("Invalid value " +
aRowValues[w] +
" for answer " + String.valueOf(a+1) +
" row " + String.valueOf(w+1),
"23000", 23000);
} else {
fGrid[oValueXY[0]][oValueXY[1]] += 1f;
fGrid[oValueXY[0]][iRows] += 1f;
}
} // fi (aRowValues[w]!="")
} // next (w)
} // fi (sValue!="")
} // next (a)
if (DebugFile.trace) DebugFile.writeln("Done filling the grid");
}
else if (oMtrx.uniquecolumns) {
if (DebugFile.trace) DebugFile.writeln("Computing uniquecolumns totals");
// Fill the top row of the grid with column captions
for (int c=1; c<iCols; c++) {
oGrid[c][0] = oMtrx.getCell(c,0).getCaptionAlt();
} // next
for (int r=0; r<iRows; r++) {
oGrid[0][r] = oMtrx.getRow(r).getCaptionAlt();
} // next
oGrid[0][iRows] = "Total";
// Initialize value maps, one map per column
HashMap[] aColMaps = new HashMap[iCols];
for (int c=0; c<iCols; c++) {
aColMaps[c] = new HashMap(iRows*2);
for (int r=0; r<iRows; r++) {
fGrid[c][r] = 0f;
aColMaps[c].put(oMtrx.getCell(c,r).getValue(), new int[]{c,r});
} // next (c)
} // next (r)
if (DebugFile.trace) DebugFile.writeln("Column maps successfully initialized");
// Read all pre-fetched answers and compute totals
for (int a=0; a<iAnswers; a++) {
sValue = oAnswers.getStringNull(1,a,"");
if (sValue.length()>0) {
String[] aColValues = Gadgets.split(sValue,'|');
for (int l=0; l<aColValues.length; l++) {
// If value for this cell is not empty then find corresponding
// position in results grid.
if (aColValues[l].length()>0) {
oValueXY = (int[]) aColMaps[l].get(aColValues[l]);
if (null==oValueXY) {
// Raise exception if value readed from the database does
// not match any value for cell elements.
if (DebugFile.trace) DebugFile.decIdent();
throw new SQLException("Invalid value " +
aColValues[l] +
" for answer " + String.valueOf(a+1) +
" column " + String.valueOf(l+1),
"23000", 23000);
} else {
fGrid[oValueXY[0]][oValueXY[1]] += 1f;
fGrid[oValueXY[0]][iRows] += 1f;
}
} // fi (aColValues[l]!="")
} // next (l)
} // fi (sValue!="")
} // next (a)
if (DebugFile.trace) DebugFile.writeln("Done filling the grid");
}
else {
if (DebugFile.trace) DebugFile.writeln("Computing multirows & multicolumns totals");
// Fill the top row of the grid with column captions
for (int c=0; c<iCols; c++) {
oGrid[c+1][0] = oMtrx.getCell(c,0).getCaptionAlt();
} // next
for (int r=0; r<iRows; r++) {
oGrid[0][r] = oMtrx.getRow(r).getCaptionAlt();
} // next
oGrid[0][iRows] = "Total";
// Initialize counter to zero
for (int c=0; c<iCols; c++) for (int r=0; r<iRows; r++) fGrid[c][r] = 0f;
for (int a=0; a<iAnswers; a++) {
sValue = oAnswers.getStringNull(1, a, "");
if (sValue.length() > 0) {
String[] aRowValues = Gadgets.split(sValue, '|');
int iRowVals = aRowValues.length;
for (int r=0; r<iRowVals; r++) {
String[] aColvalues = Gadgets.split(aRowValues[r],';');
int iColVals = aColvalues.length;
for (int c=0; c<iColVals; c++) {
if (aColvalues[c].length()>0) {
fGrid[c+1][r+1] += 1f;
fGrid[c+1][iRows+1] += 1f;
} // fi (aColvalues[c]!="")
} // next (c)
} // next (r)
} // fi (sValue!="")
} // next (answer)
} // fi (oMtrx.uniquerows || oMtrx.uniquecolumns)
// ******************************
// Convert results to percentages
if (RESULTS_PERCENTAGE==iResultsType) {
if (DebugFile.trace) DebugFile.writeln("Converting results to percentages");
for (int y=1; y<=iRows; y++) {
for (int x=1; x<iCols; x++) {
fGrid[x][y] *= 100f;
fGrid[x][y] /= fGrid[x][iRows];
oGrid[x][y] = String.valueOf(fGrid[x][y])+"%";
} // next (x)
} // next (y)
} else {
for (int y=1; y<=iRows; y++) {
for (int x=1; x<iCols; x++) {
oGrid[x][y] = String.valueOf(fGrid[x][y]);
} // next (x)
} // next (y)
} // fi (RESULTS_PERCENTAGE)
break;
// *********************************************************************
// Process HOTORNOT type answers
case Question.SubTypes.HOTORNOT:
if (DebugFile.trace) DebugFile.writeln("Question type is HOTORNOT");
// Determine number of columns by looking at minimum and maximum values
// for all lickerts on the HotOrNot question
HotOrNot oHot = (HotOrNot) oQuest;
float fMin = 100, fMax=-100;
iRows = oHot.getLickertCount();
for (int l=0; l<iRows; l++) {
if (oHot.getLickert(l).leftTag()<fMin)
fMin = oHot.getLickert(l).leftTag();
if (oHot.getLickert(l).rightTag()>fMax)
fMax = oHot.getLickert(l).rightTag();
} // next (l)
iRows++;
iCols = (int) ((fMax-fMin)+2);
// Allocate grid space
oGrid = new String[iCols][iRows];
fGrid = new float[iCols][iRows];
// Initialize absolute frecuencies grid to zero
for (int r=0; r<iRows; r++) {
for (int c=0; c<iCols; c++) {
if (0==r && c>0) oGrid[c][0]=String.valueOf((int)(fMin+c-1));
if (0==c && r>0 && r<iRows-1) {
if (oHot.getLickert(r-1).getCaption()!=null)
oGrid[0][r]=oHot.getLickert(r-1).getCaption();
else
oGrid[0][r]=oHot.getLickert(r-1).leftcapt+" - "+oHot.getLickert(r-1).rightcapt;
}
fGrid[c][r]=0f;
}
}
// Iterate answers
for (int a=0; a<iAnswers; a++) {
sValue = oAnswers.getStringNull(1,a,"");
if (sValue.length()>0) {
aValues = Gadgets.split(sValue, '|');
for (int v=0; v<aValues.length; v++) {
if (aValues[v].length()>0) {
fGrid[Integer.parseInt(aValues[v])-((int)fMin)+1][v+1]+=1f;
}
} // next (v)
} // fi (sValue!="")
} // next (a)
for (int r=1; r<iRows; r++) {
for (int c=1; c<iCols; c++) {
oGrid[c][r]=String.valueOf((int) fGrid[c][r]);
}
}
break;
// *********************************************************************
// Raise error if answer type is not recognized
default:
if (DebugFile.trace) {
DebugFile.writeln("Unrecognized type "+String.valueOf(oQuest.getClassId())+" for question "+sNmQuestion);
DebugFile.decIdent();
}
throw new IllegalArgumentException("Unrecognized type "+String.valueOf(oQuest.getClassId())+" for question "+sNmQuestion);
} // end switch
// ***********************************************************************
// Print results grid to a StringBuffer
if (DebugFile.trace) DebugFile.writeln("Printing results grid to StringBuffer");
StringBuffer oBuffer = new StringBuffer();
if ((OUTPUT_CSV==iOutputType) || (OUTPUT_TSV==iOutputType )) {
char cDelimiter = (OUTPUT_CSV==iOutputType ? ';' : '\t');
final int iGridCols=oGrid.length;
final int iGridRows=oGrid[0].length;
for (int n=0; n<iGridRows; n++) {
if (oGrid[0][n]!=null)
oBuffer.append(oGrid[0][n]);
for (int m=1; m<iGridCols; m++) {
oBuffer.append(cDelimiter);
if (oGrid[m][n]!=null) oBuffer.append(oGrid[m][n]);
} // next
oBuffer.append('\n');
} // next
} // fi
sRetVal = oBuffer.toString();
}
// Done!
if (DebugFile.trace) {
DebugFile.writeln("End DataMiner.getAnswerResults()");
DebugFile.decIdent();
}
return sRetVal;
} // getAnswerResults
// ---------------------------------------------------------------------------
public static String getAnswerCross(JDCConnection oConn, String sGuPageSet,
String sStorage, String sEnc,
String sNmQuestion, String sNmCross,
int iResultsType, int iOutputType)
throws UnsupportedEncodingException,FileNotFoundException,IOException,
SQLException,JiBXException,IllegalArgumentException,
ArrayIndexOutOfBoundsException,OutOfMemoryError {
if (DebugFile.trace) {
DebugFile.writeln("Begin DataMiner.getAnswerCross([JDCConnection],"+
sGuPageSet+","+sStorage+","+sEnc+","+sNmQuestion+","+
sNmCross+","+
(RESULTS_ABSOLUTE==iResultsType ? "RESULTS_ABSOLUTE" :
(RESULTS_PERCENTAGE==iResultsType ? "RESULTS_PERCENTAGE" :
String.valueOf(iResultsType)))+
(OUTPUT_CSV==iOutputType ? "OUTPUT_CSV" :
(OUTPUT_XML==iOutputType ? "OUTPUT_XML" :
(OUTPUT_TSV==iOutputType ? "OUTPUT_TSV" :
String.valueOf(iOutputType))))+")");
DebugFile.incIdent();
}
if (null==sEnc) sEnc="UTF-8";
DBSubset oCross = new DBSubset(DB.k_pageset_datasheets,
"DISTINCT("+sNmCross+")",
DB.gu_pageset+"=? ORDER BY 1", 100);
DBSubset oCrossVal = new DBSubset(DB.k_pageset_datasheets,
sNmCross,
DB.gu_datasheet+"=? ORDER BY 1", 100);
// Retrive full set of answers into memory
DBSubset oAnswers = new DBSubset(DB.k_pageset_answers,
DB.gu_page+","+DB.tx_answer+","+DB.gu_datasheet,
DB.gu_pageset+"=? AND "+DB.nm_answer+"=?",
2000);
int iAnswers = oAnswers.load(oConn, new Object[]{sGuPageSet,sNmQuestion});
if (DebugFile.trace) DebugFile.writeln(String.valueOf(iAnswers) + " answers found");
String sRetVal;
if (0==iAnswers) {
// If there are no answers the return null
sRetVal = null;
}
else {
int iCross = oCross.load(oConn, new Object[]{sGuPageSet});
HashMap oCrossMap = new HashMap(iCross*2);
for (int x=0; x<iCross; x++) {
}
// Get Survey object for this PageSet
Survey oSrvy = new Survey(oConn, sGuPageSet);
// Get Page for requested Answer
SurveyPage oPage = oSrvy.getPage(oConn, oAnswers.getString(0, 0),
sStorage, sEnc);
// Get Question object description for Answer
Question oQuest = oPage.getQuestion(sNmQuestion);
// Grids for storing results while iterating and before printing
String[][] oGrid;
float[][] fGrid;
int iRows = 0, iCols = 0;
// A Map for storing the vertical positition of each value on the titles
Map oValueMap;
// Intermediate variables holding vertical position for value while iterating answers
Integer oValuePos;
int[] oValueXY;
String sValue;
String[] aValues;
Iterator oValues;
switch (oQuest.getClassId()) {
// *********************************************************************
// Process TEXT and MULTITEXT type answers
case Question.SubTypes.CHOICE:
case Question.SubTypes.LISTCHOICE:
} // end switch
} // fi
return null;
} // getAnswersCross
// ---------------------------------------------------------------------------
public static final int RESULTS_ABSOLUTE = 1;
public static final int RESULTS_PERCENTAGE = 2;
public static final int OUTPUT_XML = 4;
public static final int OUTPUT_CSV = 8;
public static final int OUTPUT_TSV = 16;
}