/* * OpenClinica is distributed under the * GNU Lesser General Public License (GNU LGPL). * For details see: http://www.openclinica.org/license * copyright 2003-2010 Akaza Research */ package org.akaza.openclinica.bean.extract; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import org.akaza.openclinica.bean.core.ResponseType; import org.akaza.openclinica.bean.core.Utils; import org.akaza.openclinica.bean.managestudy.StudyGroupClassBean; import org.akaza.openclinica.bean.submit.ItemBean; import org.akaza.openclinica.bean.submit.ItemFormMetadataBean; import org.akaza.openclinica.bean.submit.ResponseOptionBean; import org.akaza.openclinica.bean.submit.ResponseSetBean; import org.akaza.openclinica.i18n.util.ResourceBundleProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author jxu * */ @Deprecated public class SPSSReportBean extends ReportBean { protected final Logger logger = LoggerFactory.getLogger(getClass().getName()); private final static int FIRSTCASE = 2; private final static int FIRSTCASE_IND = 2; private final static int COLUMNS_IND = FIRSTCASE_IND - 1; // YW 10-31-2007, more titles have been added because of additional // attrubutes added for extracting data\ private static final String[] builtin = { "SubjID", "ProtocolID", "DOB", "YOB", "Gender", "SubjectStatus", "UniqueID", "SecondaryID", "Location", "StartDate", "EndDate", "SubjectEventStatus", "AgeAtEvent", "InterviewDate", "InterviewerName", "CRFVersionStatus", "VersionName" }; private static final String[] builtinType = { "A", "A", "ADATE10", "ADATE10", "A", "A", "A", "A", "A", "ADATE10", "ADATE10", "A", "F8.0", "ADATE10", "A", "A", "A" }; // hold validated variable name private final ArrayList itemNames = new ArrayList(); // YW >> public static final List list = Arrays.asList(builtin); public HashMap descriptions = new HashMap(); private boolean gender = false;// whether exporting gender private String datFileName = "C:\\path\\to\\your\\file.dat"; protected Locale locale = ResourceBundleProvider.getLocale(); protected String local_df_string = ResourceBundleProvider.getFormatBundle(locale).getString("date_format_string"); protected String local_datetime_string = ResourceBundleProvider.getFormatBundle(locale).getString("date_time_format_string"); /** * @return Returns the datFileName. */ public String getDatFileName() { return datFileName; } /** * @param datFileName * The datFileName to set. */ public void setDatFileName(String datFileName) { this.datFileName = datFileName; } /** * @return Returns the descriptions. */ public HashMap getDescriptions() { return descriptions; } /** * @param descriptions * The descriptions to set. */ public void setDescriptions(HashMap descriptions) { this.descriptions = descriptions; } /** * @return Returns the gender. */ public boolean isGender() { return gender; } /** * @param gender * The gender to set. */ public void setGender(boolean gender) { this.gender = gender; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { return ""; } public StringBuffer getMetadataFile(SPSSVariableNameValidator svnv, ExtractBean eb) { itemNames.clear(); String[] attributes = createAttributes(eb); // Is it necessary to // validate // StudyGroupClassBean // names? YW String[] attributeTypes = createAttributeTypes(eb); StringBuffer answer = new StringBuffer(); answer.append("* NOTE: If you have put this file in a different folder \n" + "* from the associated data file, you will have to change the FILE \n" + "* location on the line below to point to the physical location of your data file.\n"); answer.append("GET DATA " + "/TYPE = TXT" + "/FILE = '" + getDatFileName() + "' " + "/DELCASE = LINE " + "/DELIMITERS = \"\\t\" " + "/ARRANGEMENT = DELIMITED " + "/FIRSTCASE = " + FIRSTCASE + " " + "/IMPORTCASE = ALL ");// since // we // send // the // row // of column // to the .dat file, start // importing at row 2 if (data.size() <= 0) { answer.append(".\n"); } else { ArrayList columns = (ArrayList) data.get(this.COLUMNS_IND); int startItem = columns.size() - items.size(); logger.debug("--> generated start item " + startItem + " from " + columns.size() + " minus " + items.size()); answer.append("/VARIABLES = \n"); int index; for (int i = 0; i < columns.size(); i++) { String itemName = (String) columns.get(i); // YW << Why do we need "V_" here? Right now it has been // removed, because: // This "V_" exists in .sps file but not exists in .dat file. // String varLabel = "V_" + itemName; String varLabel = svnv.getValidName(itemName); itemNames.add(varLabel); // builtin attributes if (i < startItem) { if (varLabel.startsWith("Gender")) { gender = true; } index = builtinIndex(varLabel, attributes); logger.debug("varLabel[" + varLabel + "] index[" + index + "] attributeTypes[" + attributeTypes[1] + "]"); answer.append("\t" + varLabel + " " + attributeTypes[index]); // >> tbh #5524 DisplayItemHeaderBean dih = (DisplayItemHeaderBean) items.get(i); ItemBean ib = dih.getItem(); // << tbh if (attributeTypes[index].equals("A")) { int len = getDataColumnMaxLen(i); if (len == 0) { len = 1; // mininum length required by spss } // >> tbh #5524 ArrayList metas = ib.getItemMetas(); for (int k = 0; k < metas.size(); k++) { ItemFormMetadataBean ifmb = (ItemFormMetadataBean) metas.get(k); ResponseSetBean rsb = ifmb.getResponseSet(); ArrayList options = rsb.getOptions(); for (int l = 0; l < options.size(); l++) { ResponseOptionBean ro = (ResponseOptionBean) options.get(l); if (ro.getText().length() > len) { len = ro.getText().length(); } } } // << tbh if (len > 8) { len = 8; } answer.append(len); } answer.append("\n"); } // YW >> } // items logger.debug("--> looking at " + startItem + " out of " + columns.size()); for (int i = startItem; i < columns.size(); i++) { DisplayItemHeaderBean dih = (DisplayItemHeaderBean) items.get(i - startItem); ItemBean ib = dih.getItem(); // YW << String varLabel = (String) itemNames.get(i); int dataTypeId = ib.getItemDataTypeId(); // except int, float, date, all other data types are treated as // string // int has been set into two groups, one is pure integer which // can be used to do calculation // another group of int is it's item_data_type has been set as // int, but its response_type is among // one of those: checkbox, radio, select and selectmulti. So it // might be "null values". // Here the second kind of item group has been given datatype as // String. if (dataTypeId == 9) { // date answer.append("\t" + varLabel + " ADATE10\n"); } else if (dataTypeId == 7) { // float answer.append("\t" + varLabel + " F8.2\n"); } else if (dataTypeId == 6 && isIntType(ib)) { // pure int data // type for one // item. answer.append("\t" + varLabel + " F8.0\n"); } else { // string // YW >> int len = getDataColumnMaxLen(i); if (len == 0) { len = 1; // mininum length required by spss } ArrayList metas = ib.getItemMetas(); int optionCount = 0; for (int k = 0; k < metas.size(); k++) { ItemFormMetadataBean ifmb = (ItemFormMetadataBean) metas.get(k); ResponseSetBean rsb = ifmb.getResponseSet(); if (rsb.getResponseType().equals(ResponseType.CHECKBOX) || rsb.getResponseType().equals(ResponseType.RADIO) || rsb.getResponseType().equals(ResponseType.SELECT) || rsb.getResponseType().equals(ResponseType.SELECTMULTI)) { optionCount++; } // tbh >> #5524: all possible response value options should be reviewed so that length is OK ArrayList options = rsb.getOptions(); for (int l = 0; l < options.size(); l++) { ResponseOptionBean ro = (ResponseOptionBean) options.get(l); if (ro.getText().length() > len) { len = ro.getText().length(); } } // << tbh } if (optionCount == metas.size()) { // all responsetype of metas have options,need to show // value labels if (len > 8) { len = 8; } } answer.append("\t" + varLabel + " A" + len + "\n"); } } answer.append(".\n"); answer.append("VARIABLE LABELS\n"); // builtin attributes for (int i = 0; i < startItem; ++i) { String varLabel = (String) itemNames.get(i); if ((String) descriptions.get(itemNames.get(i)) != null) { answer.append("\t" + varLabel + " \"" + (String) descriptions.get(itemNames.get(i)) + "\"\n"); } else { for (int j = 0; j < eb.getStudyGroupClasses().size(); ++j) { answer.append("\t" + varLabel + " \"" + (String) descriptions.get(((StudyGroupClassBean) eb.getStudyGroupClasses().get(j)).getName()) + "\"\n"); } } } // items for (int i = startItem; i < itemNames.size(); i++) { DisplayItemHeaderBean dih = (DisplayItemHeaderBean) items.get(i - startItem); ItemBean ib = dih.getItem(); String varLabel = (String) itemNames.get(i); answer.append("\t" + varLabel + " \"" + ib.getDescription() + "\"\n"); } answer.append(".\n"); answer.append("VALUE LABELS\n"); if (isGender()) { answer.append("\t" + "Gender" + "\n"); answer.append("\t" + "'M'" + " \"" + "Male" + "\"\n"); answer.append("\t" + "'F'" + " \"" + "Female" + "\"\n\t/\n"); } for (int i = 0; i < items.size(); i++) { String temp = ""; DisplayItemHeaderBean dih = (DisplayItemHeaderBean) items.get(i); ItemBean ib = dih.getItem(); String varLabel = (String) itemNames.get(i + startItem); temp += "\t" + varLabel + "\n"; boolean allOption = true; ArrayList metas = ib.getItemMetas(); HashMap optionMap = new LinkedHashMap(); for (int k = 0; k < metas.size(); k++) { ItemFormMetadataBean ifmb = (ItemFormMetadataBean) metas.get(k); ResponseSetBean rsb = ifmb.getResponseSet(); if (rsb.getResponseType().equals(ResponseType.TEXT) || rsb.getResponseType().equals(ResponseType.FILE) || rsb.getResponseType().equals(ResponseType.TEXTAREA)) { // has text response, dont show value labels allOption = false; break; } else { for (int j = 0; j < rsb.getOptions().size(); j++) { ResponseOptionBean ob = (ResponseOptionBean) rsb.getOptions().get(j); String key = ob.getValue(); if (optionMap.containsKey(key)) { ArrayList a = (ArrayList) optionMap.get(key); if (!a.contains(ob.getText())) { a.add(ob.getText()); optionMap.put(key, a); } } else { ArrayList a = new ArrayList(); a.add(ob.getText()); optionMap.put(key, a); } } } } Iterator it = optionMap.keySet().iterator(); while (it.hasNext()) { String value = (String) it.next(); ArrayList a = (ArrayList) optionMap.get(value); String texts = ""; if (a.size() > 1) { for (int n = 0; n < a.size(); n++) { texts += (String) a.get(n); if (n < a.size() - 1) { texts += "/"; } } } else { texts = (String) a.get(0); } if (value.length() > 8) { value = value.substring(0, 8); } if (isValueText(value)) { temp += "\t'" + value + "' \"" + texts + "\"\n"; } else { temp += "\t" + value + " \"" + texts + "\"\n"; } }// end of while (it.hasNext()) if (allOption) { answer.append(temp + "\t/\n"); } } } answer.append(".\n EXECUTE.\n"); return answer; } // YW << this method has been modified to add variable name validation and // set more datatypes // and get rid of first line of *spss.sps file // YW >> public StringBuffer getDataFile() { long mytime = System.currentTimeMillis(); StringBuffer answer = new StringBuffer(); // YW << use validated variable names which match .sps file // get rid of first line of *spss.sps file // ArrayList row = (ArrayList) data.get(0); // for (int j = 0; j < row.size(); j++) { // answer += (String) row.get(j) + "\t"; // } // answer += "\n"; // YW >> ArrayList row = (ArrayList) data.get(1); for (int j = 0; j < row.size(); j++) { // answer += (String) row.get(j) + "\t"; answer.append(itemNames.get(j) + "\t"); } answer.append("\n"); for (int i = 2; i < data.size(); i++) {// if start with row 2, not // include header, just row data row = (ArrayList) data.get(i); for (int j = 0; j < row.size(); j++) { String s = ((String)row.get(j)).replaceAll("\\s", " "); // >> tbh #5523: we should catch strings of type dd-MMM-yyyy AND yyyy-MM-dd String convert = Utils.convertedItemDateValue(s, local_df_string, "MM/dd/yyyy"); String convertAgain = Utils.convertedItemDateValue(convert, "yyyy-MM-dd", "MM/dd/yyyy"); // and wait, what about date timestamps? String convertAgainAgain = Utils.convertedItemDateValue(convertAgain, local_datetime_string, "MM/dd/yyyy"); answer.append(convertAgainAgain + "\t"); // << tbh } answer.append("\n"); } return answer; } // YW private boolean isIntType(ItemBean ib) { ArrayList metas = ib.getItemMetas(); for (int k = 0; k < metas.size(); k++) { ItemFormMetadataBean ifmb = (ItemFormMetadataBean) metas.get(k); ResponseSetBean rsb = ifmb.getResponseSet(); if (rsb.getResponseType().equals(ResponseType.TEXT) || rsb.getResponseType().equals(ResponseType.TEXTAREA)) { return true; } } return false; } // YW 10-31-2007 private String[] createAttributes(ExtractBean eb) { SPSSVariableNameValidator svnv = new SPSSVariableNameValidator(); ArrayList<StudyGroupClassBean> studyGroupClasses = eb.getStudyGroupClasses(); int size = studyGroupClasses.size(); String[] atts = new String[size + builtin.length]; for (int i = 0; i < 7; ++i) { atts[i] = builtin[i]; } for (int i = 7; i < 7 + size; ++i) { atts[i] = svnv.getValidName(studyGroupClasses.get(i - 7).getName()); } for (int i = 7 + size; i < size + builtin.length; ++i) { atts[i] = builtin[i - size]; } return atts; } // YW 10-31-2007 private String[] createAttributeTypes(ExtractBean eb) { int size = eb.getStudyGroupClasses().size(); String[] types = new String[size + builtin.length]; for (int i = 0; i < 7; ++i) { types[i] = builtinType[i]; } for (int i = 7; i < 7 + size; ++i) { types[i] = "A"; } for (int i = 7 + size; i < size + builtin.length; ++i) { types[i] = builtinType[i - size]; } return types; } private boolean isDataColumnText(int col) { for (int i = FIRSTCASE_IND; i < data.size(); i++) { String entry = getDataColumnEntry(col, i); try { float f = Float.parseFloat(entry); } catch (Exception e) { return true; } } return false; } private boolean isValueText(String value) { try { float f = Float.parseFloat(value); } catch (Exception e) { return true; } return false; } private int getDataColumnMaxLen(int col) { int max = 0; for (int i = FIRSTCASE_IND; i < data.size(); i++) { String entry = getDataColumnEntry(col, i); if (entry.length() > max) { max = entry.length(); } } return max; } // private int builtinIndex(String itemName) { // for (int i = 0; i < list.size(); i++) { // String attribute = (String) list.get(i); private int builtinIndex(String itemName, String[] attributes) { for (int i = 0; i < attributes.length; ++i) { logger.debug("itemName[" + itemName + "] attribute[" + attributes[i] + "]"); if (itemName != null & itemName.startsWith(attributes[i])) { return i; } } return -1; } // private String getDescription(String itemName) { // for (int i = 0; i < list.size(); i++) { // String attribute = (String) list.get(i); private String getDescription(String itemName, String[] attributes) { for (int i = 0; i < attributes.length; ++i) { if (itemName != null & itemName.startsWith(attributes[i])) { return (String) descriptions.get(attributes[i]); } } return ""; } }