From 4dbfd888a99158bb519e54f4b9d37a95e69abefe Mon Sep 17 00:00:00 2001 From: lernermh Date: Wed, 10 Apr 2019 17:41:17 -0400 Subject: [PATCH] When importing csv file, missing cells will no longer show [object Object] CANANOLAB-587 Server will report back to client all bad input for Characterization: Finding CANANOLAB-599 Selecting "Other" as a Column name, no longer causes error preventing editing other column headers CANANOLAB-592 --- .../dto/common/BadCellInputException.java | 74 +- .../nci/cananolab/dto/common/FindingBean.java | 1382 ++++++++++------- .../restful/CharacterizationServices.java | 15 +- .../sample/edit/setupCharacterization.js | 57 +- .../sample/edit/setupCharacterization.html | 4 +- 5 files changed, 845 insertions(+), 687 deletions(-) diff --git a/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/BadCellInputException.java b/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/BadCellInputException.java index 5983e1ba15..9efa4bfbec 100644 --- a/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/BadCellInputException.java +++ b/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/BadCellInputException.java @@ -1,78 +1,38 @@ package gov.nih.nci.cananolab.dto.common; +import java.util.ArrayList; + /** * Exception when bad data causes save to fail when saving Finding Info data. */ -public class BadCellInputException extends Exception { - - private String message; - private String badData; - private String columnName; - private String columnType; - - public BadCellInputException( String badData) { - this.badData = badData; - } - - - public BadCellInputException( String message, String badData, String columnName, String columnType ) - { - this.badData = badData; - this.message = message; - this.columnName = columnName; - this.columnType = columnType; - } - - - public String getBadData() - { - return badData; - } +public class BadCellInputException extends Exception +{ - public void setBadData( String badData ) - { - this.badData = badData; - } - - public String getColumnName() - { - return columnName; - } + ArrayList> errorData; + String errorMessage = ""; - public void setColumnName( String columnName ) + public BadCellInputException( ArrayList> errorData ) { - this.columnName = columnName; + this.errorMessage = "Cell data error"; + this.errorData = errorData; } - public String getColumnType() - { - return columnType; - } - public void setColumnType( String columnType ) + public BadCellInputException( String message, ArrayList> errorData ) { - this.columnType = columnType; + this.errorMessage = message; + this.errorData = errorData; } @Override public String getMessage() { - return message + "\nColumn: " + columnName + "\nCell data: " + badData; - } + StringBuilder sb = new StringBuilder( "Bad cell input data:\n" ); + for (ArrayList row : errorData) { + sb.append( "\nColumn: " + row.get(1) + "\nCell data: " + row.get(0) +"\n"); + } - public void setMessage( String message ) - { - this.message = message; + return sb.toString(); } - @Override - public String toString() - { - return "{\n \"BadCellInputException\":\n" - + " \"message\":\"" + message + "\",\n" - + " \"badData\":\"" + badData + "\",\n" - + " \"columnName\":\"" + columnName + "\",\n" - + " \"columnType\":\"" + columnType + "\",\n" - + "}"; - } } diff --git a/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/FindingBean.java b/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/FindingBean.java index 0601eee3dc..e17102cf5f 100644 --- a/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/FindingBean.java +++ b/software/cananolab-webapp/src/gov/nih/nci/cananolab/dto/common/FindingBean.java @@ -30,619 +30,797 @@ * View bean for Datum * * @author pansu, tanq - * */ -public class FindingBean { - public static final String DATUM_TYPE = "datum"; - public static final String CONDITION_TYPE = "condition"; - private Finding domain = new Finding(); - private List rows = new ArrayList(); - private List files = new ArrayList(); - private List columnHeaders = new ArrayList(); - private int numberOfColumns; - private int numberOfRows; - private FileBean theFile = new FileBean(); - private int theFileIndex; - - public FindingBean() { - } - - /** - * Constructor for CharBean copying & "findFindingById()". - * - * @param finding - */ - public FindingBean(Finding finding) { - domain = finding; - List data = null; - if (finding.getDatumCollection() != null) { - data = new ArrayList(finding.getDatumCollection()); - Collections.sort(data, new Comparators.DatumDateComparator()); - } - - if (finding.getFileCollection() != null - && !finding.getFileCollection().isEmpty()) { - for (File file : finding.getFileCollection()) { - files.add(new FileBean(file)); - } - Collections.sort(files, new Comparators.FileBeanDateComparator()); - } - - // generate matrix - if (data != null && !data.isEmpty()) { - // get data matrix column headers and generate a map based - // on headers. - Map> datumMap = new HashMap>(); - Map> conditionMap = new HashMap>(); - - List datumList = new ArrayList(); - List conditionList = new ArrayList(); - for (Datum datum : data) { - // add datum column - ColumnHeader datumColumn = new ColumnHeader(datum); - if (!columnHeaders.contains(datumColumn)) { - columnHeaders.add(datumColumn); - } - if (datumMap.get(datumColumn) != null) { - datumList = datumMap.get(datumColumn); - } else { - datumList = new ArrayList(); - datumMap.put(datumColumn, datumList); - } - datumList.add(datum); - // add condition columns - if (datum.getConditionCollection() != null) { - List conditions = new ArrayList(datum - .getConditionCollection()); - Collections.sort(conditions, - new Comparators.ConditionDateComparator()); - for (Condition condition : conditions) { - ColumnHeader conditionColumn = new ColumnHeader( - condition); - if (!columnHeaders.contains(conditionColumn)) { - columnHeaders.add(conditionColumn); - } - if (conditionMap.get(conditionColumn) != null) { - conditionList = conditionMap.get(conditionColumn); - } else { - conditionList = new ArrayList(); - conditionMap.put(conditionColumn, conditionList); - } - // in case of copied Finding, ids are all null before - // persisting - if (condition.getId() != null) { - if (!conditionList.contains(condition)) { - conditionList.add(condition); - } - } - // use created_by field that contains the original ID to - // test whether condition is already in the list - else { - boolean existed = false; - for (Condition cond : conditionList) { - if (cond.getCreatedBy().equals( - condition.getCreatedBy())) { - existed = true; - break; - } - } - if (!existed) { - conditionList.add(condition); - } - } - } - } - } - // sort column headers by created date and set column orders - setupColumnOrder(); - - int numRows = -1; - // iterate through all datum columns and find the biggest list size - // as the number of rows - for (Map.Entry> entry : datumMap - .entrySet()) { - int numData = entry.getValue().size(); - if (numData > numRows) { - numRows = numData; - } - } - // iterate through all condition columns and find the biggest list - // size as the number of rows - for (Map.Entry> entry : conditionMap - .entrySet()) { - int numConditions = entry.getValue().size(); - if (numConditions > numRows) { - numRows = numConditions; - } - } - numberOfRows = numRows; - numberOfColumns = columnHeaders.size(); - - for (int i = 0; i < numberOfRows; i++) { - Row row = new Row(); - for (int j = 0; j < numberOfColumns; j++) { - ColumnHeader theHeader = columnHeaders.get(j); - if (theHeader.getColumnType() - .equals(FindingBean.DATUM_TYPE)) { - Datum datum = new Datum(); - if (datumMap.get(theHeader) != null - && datumMap.get(theHeader).size() > i) { - datum = datumMap.get(theHeader).get(i); - } - row.getCells().add(new TableCell(datum)); - } else if (theHeader.getColumnType().equals( - FindingBean.CONDITION_TYPE)) { - Condition condition = new Condition(); - if (conditionMap.get(theHeader) != null - && conditionMap.get(theHeader).size() > i) { - condition = conditionMap.get(theHeader).get(i); - } - row.getCells().add(new TableCell(condition)); - } - } - rows.add(row); - } - } - } - - public List getRows() { - return rows; - } - - public void setRows(List rows) { - this.rows = rows; - } - - public List getColumnHeaders() { - return columnHeaders; - } - - public void setColumnHeaders(List columnHeaders) { - this.columnHeaders = columnHeaders; - } - - public int getNumberOfColumns() { - return numberOfColumns; - } - - public void setNumberOfColumns(int numberOfColumns) { - this.numberOfColumns = numberOfColumns; - } - - public int getNumberOfRows() { - return numberOfRows; - } - - public void setNumberOfRows(int numberOfRows) { - this.numberOfRows = numberOfRows; - } - - public void updateMatrix(int numberOfColumns, int numberOfRows) { - this.numberOfColumns = numberOfColumns; - this.numberOfRows = numberOfRows; - List newColumns = new ArrayList(); - if (columnHeaders.size() <= numberOfColumns) { - newColumns.addAll(columnHeaders); - for (int i = columnHeaders.size(); i < numberOfColumns; i++) { - newColumns.add(new ColumnHeader()); - } - } - // remove the columnHeaders from the end - else { - for (int i = 0; i < numberOfColumns; i++) { - newColumns.add(columnHeaders.get(i)); - } - } - - List newRows = new ArrayList(); - if (rows.size() <= numberOfRows) { - newRows.addAll(rows); - for (int i = rows.size(); i < numberOfRows; i++) { - newRows.add(new Row()); - } - } - // remove the rows from the end - else { - for (int i = 0; i < numberOfRows; i++) { - newRows.add(rows.get(i)); - } - } - for (int i = 0; i < numberOfRows; i++) { - Row row = newRows.get(i); - List cells = row.getCells(); - List newCells = new ArrayList(); - if (cells.size() <= numberOfColumns) { - newCells.addAll(cells); - for (int j = cells.size(); j < numberOfColumns; j++) { - newCells.add(new TableCell()); - } - } - // remove the columnHeaders from the end - else { - for (int j = 0; j < numberOfColumns; j++) { - newCells.add(cells.get(i)); - } - } - row.setCells(newCells); - } - columnHeaders = new ArrayList(newColumns); - rows = new ArrayList(); - rows.addAll(newRows); - } - - public void removeColumn(int colIndex) { - columnHeaders.remove(colIndex); - for (int i = 0; i < rows.size(); i++) { - List cells = rows.get(i).getCells(); - cells.remove(colIndex); - } - numberOfColumns--; - } - - public void removeRow(int rowIndex) { - rows.remove(rowIndex); - numberOfRows--; - } - - public void setupDomain(String internalFileUriPath, String createdBy) - throws Exception { - - if (domain.getId() != null && domain.getId() <= 0) { - domain.setId(null); - } - // updated created_date and created_by if id is null - if (domain.getId() == null) { - domain.setCreatedBy(createdBy); - domain.setCreatedDate(Calendar.getInstance().getTime()); - } - // updated created_by if created_by contains copy, but keep the original - // created_date - if (domain.getId() != null - || !StringUtils.isEmpty(domain.getCreatedBy()) - && domain.getCreatedBy().contains( - Constants.AUTO_COPY_ANNOTATION_PREFIX)) { - domain.setCreatedBy(createdBy); - } - if (domain.getDatumCollection() != null) { - domain.getDatumCollection().clear(); - } else { - domain.setDatumCollection(new HashSet()); - } - if (domain.getFileCollection() != null) { - domain.getFileCollection().clear(); - } else { - domain.setFileCollection(new HashSet()); - } - - for (FileBean fileBean : files) { - fileBean.setupDomainFile(internalFileUriPath, createdBy); - domain.getFileCollection().add(fileBean.getDomainFile()); - } - int rInd = 0; - for (Row row : rows) { - int cInd = 0; - List rowConditions = new ArrayList(); - List rowData = new ArrayList(); - for (TableCell cell : row.getCells()) { - ColumnHeader columnHeader = columnHeaders.get(cInd); - - if (FindingBean.DATUM_TYPE.equals(columnHeader.getColumnType())) { - Datum datum = cell.getDatum(); - // set bogus empty cell - if (StringUtils.isEmpty(cell.getValue())) { - datum.setValue(Float.valueOf(-1)); - datum - .setCreatedBy(createdBy - + ":" - + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY); - } else { +public class FindingBean +{ + public static final String DATUM_TYPE = "datum"; + public static final String CONDITION_TYPE = "condition"; + private Finding domain = new Finding(); + private List rows = new ArrayList(); + private List files = new ArrayList(); + private List columnHeaders = new ArrayList(); + private int numberOfColumns; + private int numberOfRows; + private FileBean theFile = new FileBean(); + private int theFileIndex; + + public FindingBean() + { + } + + /** + * Constructor for CharBean copying & "findFindingById()". + * + * @param finding + */ + public FindingBean( Finding finding ) + { + domain = finding; + List data = null; + if( finding.getDatumCollection() != null ) + { + data = new ArrayList( finding.getDatumCollection() ); + Collections.sort( data, new Comparators.DatumDateComparator() ); + } + + if( finding.getFileCollection() != null + && ! finding.getFileCollection().isEmpty() ) + { + for( File file : finding.getFileCollection() ) + { + files.add( new FileBean( file ) ); + } + Collections.sort( files, new Comparators.FileBeanDateComparator() ); + } + + // generate matrix + if( data != null && ! data.isEmpty() ) + { + // get data matrix column headers and generate a map based + // on headers. + Map> datumMap = new HashMap>(); + Map> conditionMap = new HashMap>(); + + List datumList = new ArrayList(); + List conditionList = new ArrayList(); + for( Datum datum : data ) + { + // add datum column + ColumnHeader datumColumn = new ColumnHeader( datum ); + if( ! columnHeaders.contains( datumColumn ) ) + { + columnHeaders.add( datumColumn ); + } + if( datumMap.get( datumColumn ) != null ) + { + datumList = datumMap.get( datumColumn ); + } + else + { + datumList = new ArrayList(); + datumMap.put( datumColumn, datumList ); + } + datumList.add( datum ); + // add condition columns + if( datum.getConditionCollection() != null ) + { + List conditions = new ArrayList( datum + .getConditionCollection() ); + Collections.sort( conditions, + new Comparators.ConditionDateComparator() ); + for( Condition condition : conditions ) + { + ColumnHeader conditionColumn = new ColumnHeader( + condition ); + if( ! columnHeaders.contains( conditionColumn ) ) + { + columnHeaders.add( conditionColumn ); + } + if( conditionMap.get( conditionColumn ) != null ) + { + conditionList = conditionMap.get( conditionColumn ); + } + else + { + conditionList = new ArrayList(); + conditionMap.put( conditionColumn, conditionList ); + } + // in case of copied Finding, ids are all null before + // persisting + if( condition.getId() != null ) + { + if( ! conditionList.contains( condition ) ) + { + conditionList.add( condition ); + } + } + // use created_by field that contains the original ID to + // test whether condition is already in the list + else + { + boolean existed = false; + for( Condition cond : conditionList ) + { + if( cond.getCreatedBy().equals( + condition.getCreatedBy() ) ) + { + existed = true; + break; + } + } + if( ! existed ) + { + conditionList.add( condition ); + } + } + } + } + } + // sort column headers by created date and set column orders + setupColumnOrder(); + + int numRows = - 1; + // iterate through all datum columns and find the biggest list size + // as the number of rows + for( Map.Entry> entry : datumMap + .entrySet() ) + { + int numData = entry.getValue().size(); + if( numData > numRows ) + { + numRows = numData; + } + } + // iterate through all condition columns and find the biggest list + // size as the number of rows + for( Map.Entry> entry : conditionMap + .entrySet() ) + { + int numConditions = entry.getValue().size(); + if( numConditions > numRows ) + { + numRows = numConditions; + } + } + numberOfRows = numRows; + numberOfColumns = columnHeaders.size(); + + for( int i = 0; i < numberOfRows; i++ ) + { + Row row = new Row(); + for( int j = 0; j < numberOfColumns; j++ ) + { + ColumnHeader theHeader = columnHeaders.get( j ); + if( theHeader.getColumnType() + .equals( FindingBean.DATUM_TYPE ) ) + { + Datum datum = new Datum(); + if( datumMap.get( theHeader ) != null + && datumMap.get( theHeader ).size() > i ) + { + datum = datumMap.get( theHeader ).get( i ); + } + row.getCells().add( new TableCell( datum ) ); + } + else if( theHeader.getColumnType().equals( + FindingBean.CONDITION_TYPE ) ) + { + Condition condition = new Condition(); + if( conditionMap.get( theHeader ) != null + && conditionMap.get( theHeader ).size() > i ) + { + condition = conditionMap.get( theHeader ).get( i ); + } + row.getCells().add( new TableCell( condition ) ); + } + } + rows.add( row ); + } + } + } + + public List getRows() + { + return rows; + } + + public void setRows( List rows ) + { + this.rows = rows; + } + + public List getColumnHeaders() + { + return columnHeaders; + } + + public void setColumnHeaders( List columnHeaders ) + { + this.columnHeaders = columnHeaders; + } + + public int getNumberOfColumns() + { + return numberOfColumns; + } + + public void setNumberOfColumns( int numberOfColumns ) + { + this.numberOfColumns = numberOfColumns; + } + + public int getNumberOfRows() + { + return numberOfRows; + } + + public void setNumberOfRows( int numberOfRows ) + { + this.numberOfRows = numberOfRows; + } + + public void updateMatrix( int numberOfColumns, int numberOfRows ) + { + this.numberOfColumns = numberOfColumns; + this.numberOfRows = numberOfRows; + List newColumns = new ArrayList(); + if( columnHeaders.size() <= numberOfColumns ) + { + newColumns.addAll( columnHeaders ); + for( int i = columnHeaders.size(); i < numberOfColumns; i++ ) + { + newColumns.add( new ColumnHeader() ); + } + } + // remove the columnHeaders from the end + else + { + for( int i = 0; i < numberOfColumns; i++ ) + { + newColumns.add( columnHeaders.get( i ) ); + } + } + + List newRows = new ArrayList(); + if( rows.size() <= numberOfRows ) + { + newRows.addAll( rows ); + for( int i = rows.size(); i < numberOfRows; i++ ) + { + newRows.add( new Row() ); + } + } + // remove the rows from the end + else + { + for( int i = 0; i < numberOfRows; i++ ) + { + newRows.add( rows.get( i ) ); + } + } + for( int i = 0; i < numberOfRows; i++ ) + { + Row row = newRows.get( i ); + List cells = row.getCells(); + List newCells = new ArrayList(); + if( cells.size() <= numberOfColumns ) + { + newCells.addAll( cells ); + for( int j = cells.size(); j < numberOfColumns; j++ ) + { + newCells.add( new TableCell() ); + } + } + // remove the columnHeaders from the end + else + { + for( int j = 0; j < numberOfColumns; j++ ) + { + newCells.add( cells.get( i ) ); + } + } + row.setCells( newCells ); + } + columnHeaders = new ArrayList( newColumns ); + rows = new ArrayList(); + rows.addAll( newRows ); + } + + public void removeColumn( int colIndex ) + { + columnHeaders.remove( colIndex ); + for( int i = 0; i < rows.size(); i++ ) + { + List cells = rows.get( i ).getCells(); + cells.remove( colIndex ); + } + numberOfColumns--; + } + + public void removeRow( int rowIndex ) + { + rows.remove( rowIndex ); + numberOfRows--; + } + + public void setupDomain( String internalFileUriPath, String createdBy ) + throws Exception + { + + if( domain.getId() != null && domain.getId() <= 0 ) + { + domain.setId( null ); + } + // updated created_date and created_by if id is null + if( domain.getId() == null ) + { + domain.setCreatedBy( createdBy ); + domain.setCreatedDate( Calendar.getInstance().getTime() ); + } + // updated created_by if created_by contains copy, but keep the original + // created_date + if( domain.getId() != null + || ! StringUtils.isEmpty( domain.getCreatedBy() ) + && domain.getCreatedBy().contains( + Constants.AUTO_COPY_ANNOTATION_PREFIX ) ) + { + domain.setCreatedBy( createdBy ); + } + if( domain.getDatumCollection() != null ) + { + domain.getDatumCollection().clear(); + } + else + { + domain.setDatumCollection( new HashSet() ); + } + if( domain.getFileCollection() != null ) + { + domain.getFileCollection().clear(); + } + else + { + domain.setFileCollection( new HashSet() ); + } + + for( FileBean fileBean : files ) + { + fileBean.setupDomainFile( internalFileUriPath, createdBy ); + domain.getFileCollection().add( fileBean.getDomainFile() ); + } + + + // Test each cell for valid value here, so we can give a complete error list. + ArrayList> errorDataArray = new ArrayList<>(); + boolean errorFlag = false; + for( Row row : rows ) + { + int cInd = 0; + for( TableCell cell : row.getCells() ) + { + ColumnHeader columnHeader = columnHeaders.get( cInd ); + if( FindingBean.DATUM_TYPE.equals( columnHeader.getColumnType() ) ) + { + + try + { + Float errorTestFloat = Float.valueOf( cell.getValue() ); + } + catch( NumberFormatException e ) + { + errorFlag = true; + ArrayList errorData = new ArrayList<>(); + errorData.add( cell.getValue() ); + errorData.add( columnHeader.getColumnName() ); + errorData.add( e.getMessage() ); + errorDataArray.add( errorData ); + } + } + cInd++; + } + } + + if( errorFlag ) + { + throw new BadCellInputException( "Bad cell input data", errorDataArray ); + } + + int rInd = 0; + for( Row row : rows ) + { + int cInd = 0; + List rowConditions = new ArrayList(); + List rowData = new ArrayList(); + for( TableCell cell : row.getCells() ) + { + ColumnHeader columnHeader = columnHeaders.get( cInd ); + + if( FindingBean.DATUM_TYPE.equals( columnHeader.getColumnType() ) ) + { + Datum datum = cell.getDatum(); + // set bogus empty cell + if( StringUtils.isEmpty( cell.getValue() ) ) + { + datum.setValue( Float.valueOf( - 1 ) ); + datum + .setCreatedBy( createdBy + + ":" + + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ); + } + else + { // datum.setValue(Float.valueOf(cell.getValue())); try { - datum.setValue(Float.valueOf(cell.getValue())); + datum.setValue( Float.valueOf( cell.getValue() ) ); } catch( NumberFormatException e ) { e.printStackTrace(); - throw new BadCellInputException( "Bad cell input data", cell.getValue(), columnHeader.getColumnName(), columnHeader.getColumnType() ); } - datum.setOperand(cell.getOperand()); - } - datum.setValueType(columnHeader.getValueType()); - datum.setValueUnit(columnHeader.getValueUnit()); - datum.setName(columnHeader.getColumnName()); - rowData.add(datum); - if (datum.getId() != null && datum.getId() <= 0) { - datum.setId(null); - } - // Update createdBy if createdBy is empty or if copy - // or if bogus empty when the cell is not empty - if (StringUtils.isEmpty(datum.getCreatedBy()) - || datum.getCreatedBy().contains( - Constants.AUTO_COPY_ANNOTATION_PREFIX) - || datum - .getCreatedBy() - .contains( - Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY) - && !StringUtils.isEmpty(cell.getValue())) { - datum.setCreatedBy(createdBy); - } - // Update createdDate if id is null and created_date is - // null. - // When user updated order, created_date is reset according - // to the order - if (datum.getId() == null) { - datum.setCreatedDate(DateUtils - .addSecondsToCurrentDate(rInd * 100 + cInd)); - } - - } else if (FindingBean.CONDITION_TYPE.equals(columnHeader - .getColumnType())) { - Condition condition = cell.getCondition(); - if (StringUtils.isEmpty(cell.getValue())) { - condition - .setValue(createdBy - + ":" - + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY); - condition - .setCreatedBy(createdBy - + ":" - + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY); - } else { - condition.setValue(cell.getValue()); - } - condition.setValueType(columnHeader.getValueType()); - condition.setValueUnit(columnHeader.getValueUnit()); - condition.setName(columnHeader.getColumnName()); - condition.setProperty(columnHeader.getConditionProperty()); - rowConditions.add(condition); - if (condition.getId() != null && condition.getId() <= 0) { - condition.setId(null); - } - // Update createdBy if createdBy is empty or if copy - if (StringUtils.isEmpty(condition.getCreatedBy()) - || condition.getCreatedBy().contains( - Constants.AUTO_COPY_ANNOTATION_PREFIX) - || condition - .getCreatedBy() - .contains( - Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY) - && !StringUtils.isEmpty(cell.getValue())) { - condition.setCreatedBy(createdBy); - } - // Update createdDate if id is null and created_date is - // null. - // When user updated order, created_date is reset according - // to the order - if (condition.getId() == null) { - condition.setCreatedDate(DateUtils - .addSecondsToCurrentDate(rInd * 100 + cInd)); - } - } - cInd++; - } - // associate conditions to each datum on each row - for (Datum datum : rowData) { - if (datum.getConditionCollection() == null) { - datum.setConditionCollection(new HashSet()); - } else { - datum.getConditionCollection().clear(); - } - for (Condition condition : rowConditions) { - datum.getConditionCollection().add(condition); - } - domain.getDatumCollection().add(datum); - datum.setFinding(domain); - rInd++; - } - } - } - - /** - * Compares obj to it self and returns true if they both are - * same - * - * @param obj - */ - public boolean equals(Object obj) { - if (obj instanceof FindingBean) { - FindingBean findingBean = (FindingBean) obj; - if (domain.getId() != null - && domain.getId().equals(findingBean.getDomain().getId())) - return true; - } - return false; - } - - /** - * Returns hash code for the primary key of the object - */ - public int hashCode() { - if (getDomain().getId() != null) - return getDomain().getId().hashCode(); - return 0; - } - - public FileBean getTheFile() { - return theFile; - } - - public void setTheFile(FileBean theFile) { - this.theFile = theFile; - } - - public List getFiles() { - return files; - } - - public void setFiles(List files) { - this.files = files; - } - - public Finding getDomain() { - return domain; - } - - public void addFile(FileBean file, int index) { - if (index == -1) { - files.add(file); - return; - } - if (!files.isEmpty()) { - files.remove(index); - } - files.add(index, file); - } - - public void removeFile(int index) { - files.remove(index); - } - - public int getTheFileIndex() { - return theFileIndex; - } - - public void setTheFileIndex(int theFileIndex) { - this.theFileIndex = theFileIndex; - } - - public void resetDomainCopy(String createdBy, Finding copy, Boolean copyData) { - copy.setCreatedBy(createdBy + ":" - + Constants.AUTO_COPY_ANNOTATION_PREFIX + ":" + copy.getId()); - copy.setId(null); - - // copy data and condition - if (!copyData) { - copy.setDatumCollection(null); - } else { - Collection oldDatums = copy.getDatumCollection(); - if (oldDatums == null || oldDatums.isEmpty()) { - copy.setDatumCollection(null); - } else { - copy.setDatumCollection(new HashSet(oldDatums)); - for (Datum datum : copy.getDatumCollection()) { - String originalDatumId = datum.getId().toString(); - datum.setId(null); - // keep the bogus place holder if empty datum - if (StringUtils.isEmpty(datum.getCreatedBy()) - || !datum - .getCreatedBy() - .contains( - Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY) - && datum.getValue() != -1) { - datum.setCreatedBy(createdBy + ":" - + Constants.AUTO_COPY_ANNOTATION_PREFIX + ":" - + originalDatumId); - } - // conditions - Collection oldConditions = datum - .getConditionCollection(); - if (oldConditions == null || oldConditions.isEmpty()) { - datum.setConditionCollection(null); - } else { - datum.setConditionCollection(new HashSet( - oldConditions)); - for (Condition condition : datum - .getConditionCollection()) { - String originalCondId = null; - // condition ID could have been set to null for the - // previous datum if the same condition is - // associated with multiple datum - if (condition.getId() != null) { - originalCondId = condition.getId().toString(); - } - condition.setId(null); - // keep the bogus place holder if empty - // condition - if (StringUtils.isEmpty(condition.getCreatedBy()) - || !condition - .getCreatedBy() - .contains( - Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY) - && !condition - .getValue() - .contains( - Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY)) { - if (originalCondId != null) - condition - .setCreatedBy(createdBy - + ":" - + Constants.AUTO_COPY_ANNOTATION_PREFIX - + ":" + originalCondId); - } - } - } - } - } - } - - // copy file - Collection oldFiles = copy.getFileCollection(); - if (oldFiles == null || oldFiles.isEmpty()) { - copy.setFileCollection(null); - } else { - copy.setFileCollection(new HashSet(oldFiles)); - for (File file : copy.getFileCollection()) { - FileBean fileBean = new FileBean(file); - fileBean.resetDomainCopy(createdBy, file); - } - } - } - - // FR# 26194, datum matrix column order. - public void setupColumnOrder() { - // sort columnHeaders by createdDate and set column orders - Collections.sort(columnHeaders, - new Comparators.ColumnHeaderCreatedDateComparator()); - for (int i = 0; i < columnHeaders.size(); i++) { - columnHeaders.get(i).setColumnOrder(i + 1); - } - } - - // FR# 26194, datum matrix column order. - public void updateColumnOrder() { - if (!rows.isEmpty()) { - Comparators.TableCellComparator cellComparator = new Comparators.TableCellComparator(); - - for (Row row : rows) { - int cInd = 0; - for (TableCell cell : row.getCells()) { - ColumnHeader columnHeader = columnHeaders.get(cInd++); - cell.setColumnOrder(columnHeader.getColumnOrder()); - } - Collections.sort(row.getCells(), cellComparator); - - } - Collections.sort(columnHeaders, - new Comparators.ColumnHeaderComparator()); - - // update created_date based on column order - // update the created date regardless whether created date already - // existed - int rInd = 0; - for (Row row : rows) { - int cInd = 0; - for (TableCell cell : row.getCells()) { - ColumnHeader columnHeader = columnHeaders.get(cInd); - if (FindingBean.DATUM_TYPE.equals(columnHeader - .getColumnType())) { - Datum datum = cell.getDatum(); - datum.setCreatedDate(DateUtils - .addSecondsToCurrentDate(rInd * 100 + cInd)); - } else if (FindingBean.CONDITION_TYPE.equals(columnHeader - .getColumnType())) { - Condition condition = cell.getCondition(); - condition.setCreatedDate(DateUtils - .addSecondsToCurrentDate(rInd * 100 + cInd)); - } - cInd++; - } - rInd++; - } - } - } + datum.setOperand( cell.getOperand() ); + } + datum.setValueType( columnHeader.getValueType() ); + datum.setValueUnit( columnHeader.getValueUnit() ); + datum.setName( columnHeader.getColumnName() ); + rowData.add( datum ); + if( datum.getId() != null && datum.getId() <= 0 ) + { + datum.setId( null ); + } + // Update createdBy if createdBy is empty or if copy + // or if bogus empty when the cell is not empty + if( StringUtils.isEmpty( datum.getCreatedBy() ) + || datum.getCreatedBy().contains( + Constants.AUTO_COPY_ANNOTATION_PREFIX ) + || datum + .getCreatedBy() + .contains( + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ) + && ! StringUtils.isEmpty( cell.getValue() ) ) + { + datum.setCreatedBy( createdBy ); + } + // Update createdDate if id is null and created_date is + // null. + // When user updated order, created_date is reset according + // to the order + if( datum.getId() == null ) + { + datum.setCreatedDate( DateUtils + .addSecondsToCurrentDate( rInd * 100 + cInd ) ); + } + + } + else if( FindingBean.CONDITION_TYPE.equals( columnHeader + .getColumnType() ) ) + { + Condition condition = cell.getCondition(); + if( StringUtils.isEmpty( cell.getValue() ) ) + { + condition + .setValue( createdBy + + ":" + + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ); + condition + .setCreatedBy( createdBy + + ":" + + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ); + } + else + { + condition.setValue( cell.getValue() ); + } + condition.setValueType( columnHeader.getValueType() ); + condition.setValueUnit( columnHeader.getValueUnit() ); + condition.setName( columnHeader.getColumnName() ); + condition.setProperty( columnHeader.getConditionProperty() ); + rowConditions.add( condition ); + if( condition.getId() != null && condition.getId() <= 0 ) + { + condition.setId( null ); + } + // Update createdBy if createdBy is empty or if copy + if( StringUtils.isEmpty( condition.getCreatedBy() ) + || condition.getCreatedBy().contains( + Constants.AUTO_COPY_ANNOTATION_PREFIX ) + || condition + .getCreatedBy() + .contains( + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ) + && ! StringUtils.isEmpty( cell.getValue() ) ) + { + condition.setCreatedBy( createdBy ); + } + // Update createdDate if id is null and created_date is + // null. + // When user updated order, created_date is reset according + // to the order + if( condition.getId() == null ) + { + condition.setCreatedDate( DateUtils + .addSecondsToCurrentDate( rInd * 100 + cInd ) ); + } + } + cInd++; + } + // associate conditions to each datum on each row + for( Datum datum : rowData ) + { + if( datum.getConditionCollection() == null ) + { + datum.setConditionCollection( new HashSet() ); + } + else + { + datum.getConditionCollection().clear(); + } + for( Condition condition : rowConditions ) + { + datum.getConditionCollection().add( condition ); + } + domain.getDatumCollection().add( datum ); + datum.setFinding( domain ); + rInd++; + } + } + } + + /** + * Compares obj to it self and returns true if they both are + * same + * + * @param obj + */ + public boolean equals( Object obj ) + { + if( obj instanceof FindingBean ) + { + FindingBean findingBean = (FindingBean) obj; + if( domain.getId() != null + && domain.getId().equals( findingBean.getDomain().getId() ) ) + { + return true; + } + } + return false; + } + + /** + * Returns hash code for the primary key of the object + */ + public int hashCode() + { + if( getDomain().getId() != null ) + { + return getDomain().getId().hashCode(); + } + return 0; + } + + public FileBean getTheFile() + { + return theFile; + } + + public void setTheFile( FileBean theFile ) + { + this.theFile = theFile; + } + + public List getFiles() + { + return files; + } + + public void setFiles( List files ) + { + this.files = files; + } + + public Finding getDomain() + { + return domain; + } + + public void addFile( FileBean file, int index ) + { + if( index == - 1 ) + { + files.add( file ); + return; + } + if( ! files.isEmpty() ) + { + files.remove( index ); + } + files.add( index, file ); + } + + public void removeFile( int index ) + { + files.remove( index ); + } + + public int getTheFileIndex() + { + return theFileIndex; + } + + public void setTheFileIndex( int theFileIndex ) + { + this.theFileIndex = theFileIndex; + } + + public void resetDomainCopy( String createdBy, Finding copy, Boolean copyData ) + { + copy.setCreatedBy( createdBy + ":" + + Constants.AUTO_COPY_ANNOTATION_PREFIX + ":" + copy.getId() ); + copy.setId( null ); + + // copy data and condition + if( ! copyData ) + { + copy.setDatumCollection( null ); + } + else + { + Collection oldDatums = copy.getDatumCollection(); + if( oldDatums == null || oldDatums.isEmpty() ) + { + copy.setDatumCollection( null ); + } + else + { + copy.setDatumCollection( new HashSet( oldDatums ) ); + for( Datum datum : copy.getDatumCollection() ) + { + String originalDatumId = datum.getId().toString(); + datum.setId( null ); + // keep the bogus place holder if empty datum + if( StringUtils.isEmpty( datum.getCreatedBy() ) + || ! datum + .getCreatedBy() + .contains( + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ) + && datum.getValue() != - 1 ) + { + datum.setCreatedBy( createdBy + ":" + + Constants.AUTO_COPY_ANNOTATION_PREFIX + ":" + + originalDatumId ); + } + // conditions + Collection oldConditions = datum + .getConditionCollection(); + if( oldConditions == null || oldConditions.isEmpty() ) + { + datum.setConditionCollection( null ); + } + else + { + datum.setConditionCollection( new HashSet( + oldConditions ) ); + for( Condition condition : datum + .getConditionCollection() ) + { + String originalCondId = null; + // condition ID could have been set to null for the + // previous datum if the same condition is + // associated with multiple datum + if( condition.getId() != null ) + { + originalCondId = condition.getId().toString(); + } + condition.setId( null ); + // keep the bogus place holder if empty + // condition + if( StringUtils.isEmpty( condition.getCreatedBy() ) + || ! condition + .getCreatedBy() + .contains( + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ) + && ! condition + .getValue() + .contains( + Constants.PLACEHOLDER_DATUM_CONDITION_CREATED_BY ) ) + { + if( originalCondId != null ) + { + condition + .setCreatedBy( createdBy + + ":" + + Constants.AUTO_COPY_ANNOTATION_PREFIX + + ":" + originalCondId ); + } + } + } + } + } + } + } + + // copy file + Collection oldFiles = copy.getFileCollection(); + if( oldFiles == null || oldFiles.isEmpty() ) + { + copy.setFileCollection( null ); + } + else + { + copy.setFileCollection( new HashSet( oldFiles ) ); + for( File file : copy.getFileCollection() ) + { + FileBean fileBean = new FileBean( file ); + fileBean.resetDomainCopy( createdBy, file ); + } + } + } + + // FR# 26194, datum matrix column order. + public void setupColumnOrder() + { + // sort columnHeaders by createdDate and set column orders + Collections.sort( columnHeaders, + new Comparators.ColumnHeaderCreatedDateComparator() ); + for( int i = 0; i < columnHeaders.size(); i++ ) + { + columnHeaders.get( i ).setColumnOrder( i + 1 ); + } + } + + // FR# 26194, datum matrix column order. + public void updateColumnOrder() + { + if( ! rows.isEmpty() ) + { + Comparators.TableCellComparator cellComparator = new Comparators.TableCellComparator(); + + for( Row row : rows ) + { + int cInd = 0; + for( TableCell cell : row.getCells() ) + { + ColumnHeader columnHeader = columnHeaders.get( cInd++ ); + cell.setColumnOrder( columnHeader.getColumnOrder() ); + } + Collections.sort( row.getCells(), cellComparator ); + + } + Collections.sort( columnHeaders, + new Comparators.ColumnHeaderComparator() ); + + // update created_date based on column order + // update the created date regardless whether created date already + // existed + int rInd = 0; + for( Row row : rows ) + { + int cInd = 0; + for( TableCell cell : row.getCells() ) + { + ColumnHeader columnHeader = columnHeaders.get( cInd ); + if( FindingBean.DATUM_TYPE.equals( columnHeader + .getColumnType() ) ) + { + Datum datum = cell.getDatum(); + datum.setCreatedDate( DateUtils + .addSecondsToCurrentDate( rInd * 100 + cInd ) ); + } + else if( FindingBean.CONDITION_TYPE.equals( columnHeader + .getColumnType() ) ) + { + Condition condition = cell.getCondition(); + condition.setCreatedDate( DateUtils + .addSecondsToCurrentDate( rInd * 100 + cInd ) ); + } + cInd++; + } + rInd++; + } + } + } } diff --git a/software/cananolab-webapp/src/gov/nih/nci/cananolab/restful/CharacterizationServices.java b/software/cananolab-webapp/src/gov/nih/nci/cananolab/restful/CharacterizationServices.java index e56096b42a..8c55c2a5f3 100644 --- a/software/cananolab-webapp/src/gov/nih/nci/cananolab/restful/CharacterizationServices.java +++ b/software/cananolab-webapp/src/gov/nih/nci/cananolab/restful/CharacterizationServices.java @@ -129,7 +129,6 @@ public Response setupUpdate(@Context HttpServletRequest httpRequest, public Response getCharNamesByCharType(@Context HttpServletRequest httpRequest, @DefaultValue("") @QueryParam("charType") String charType) { - logger.debug("In getCharNamesByCharType"); try { @@ -278,13 +277,15 @@ public Response getInstrumentTypesByTechniqueType(@Context HttpServletRequest ht @Produces ("application/json") public Response updateDataConditionTable(@Context HttpServletRequest httpRequest, SimpleFindingBean simpleFinding) { - logger.debug("In updateDataConditionTable"); + logger.debug("In updateDataConditionTable"); if (!SpringSecurityUtil.isUserLoggedIn()) - return Response.status(Response.Status.UNAUTHORIZED).entity(Constants.MSG_SESSION_INVALID).build(); + { + return Response.status( Response.Status.UNAUTHORIZED ).entity( Constants.MSG_SESSION_INVALID ).build(); + } try { - CharacterizationBO characterizationBO = + CharacterizationBO characterizationBO = (CharacterizationBO) SpringApplicationContext.getBean(httpRequest, "characterizationBO"); SimpleFindingBean simpleFindingBean = characterizationBO.drawMatrix(httpRequest, simpleFinding); @@ -293,7 +294,7 @@ public Response updateDataConditionTable(@Context HttpServletRequest httpRequest .header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") .header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization").build(); } catch (Exception e) { - return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(CommonUtil.wrapErrorMessageInList(e.getMessage())).build(); } } @@ -303,7 +304,7 @@ public Response updateDataConditionTable(@Context HttpServletRequest httpRequest @Produces ("application/json") public Response setColumnOrder(@Context HttpServletRequest httpRequest, SimpleFindingBean simpleFinding) { - logger.debug("In setColumnOrder"); + logger.debug("In setColumnOrder"); if (!SpringSecurityUtil.isUserLoggedIn()) return Response.status(Response.Status.UNAUTHORIZED).entity(Constants.MSG_SESSION_INVALID).build(); @@ -466,7 +467,7 @@ public Response saveFinding(@Context HttpServletRequest httpRequest, SimpleChara return Response.status(Response.Status.UNAUTHORIZED).entity(Constants.MSG_SESSION_INVALID).build(); try { - CharacterizationBO characterizationBO = + CharacterizationBO characterizationBO = (CharacterizationBO) SpringApplicationContext.getBean(httpRequest, "characterizationBO"); SimpleCharacterizationEditBean editBean = characterizationBO.saveFinding(httpRequest, charEditBean); diff --git a/software/cananolab-webapp/web/scripts/controllers/sample/edit/setupCharacterization.js b/software/cananolab-webapp/web/scripts/controllers/sample/edit/setupCharacterization.js index d6fb4494d3..4e5fc9d5c6 100644 --- a/software/cananolab-webapp/web/scripts/controllers/sample/edit/setupCharacterization.js +++ b/software/cananolab-webapp/web/scripts/controllers/sample/edit/setupCharacterization.js @@ -351,27 +351,38 @@ var app = angular.module('angularApp') $http({method: 'POST', url: '/caNanoLab/rest/characterization/updateDataConditionTable',data: $scope.currentFinding}). success(function(data, status, headers, config) { for( var y = 0; y < csvDataRowCount; y++){ - for( var x = 0; x < csvDataColCount; x++){ - data.rows[y].cells[x].value = Object(csvDataObj[y][x]); - if( x < $scope.currentFinding.length) { - data.rows[y].cells[x].datumOrCondition = $scope.currentFinding.columnHeaders[x].columnType; - } - // When the column type is set or reset, check all cell contents for valid entries for each column, one row at a time. - if( x < $scope.currentFinding.columnHeaders.length ) { - $scope.badFindingCell[x][y] = validateFindingCellInput($scope.currentFinding.columnHeaders[x].columnType, - data.rows[y].cells[x].value); - } - // If there are fewer column types/header set than there are columns. - // Data put in a cell with a column that does not have it's type set is never considered invalid. - else{ - $scope.badFindingCell[x][y] = false; + + for (var x = 0; x < csvDataColCount; x++) { + // If the user has reduced the number of columns, make sure we don't try to update columns that no longer exist. + if( (data.rows[y].cells[x] !== null) && (data.rows[y].cells[x] !== undefined)) { + data.rows[y].cells[x].value = Object(csvDataObj[y][x]); + if (x < $scope.currentFinding.length) { + data.rows[y].cells[x].datumOrCondition = $scope.currentFinding.columnHeaders[x].columnType; + } + // When the column type is set or reset, check all cell contents for valid entries for each column, one row at a time. + if (x < $scope.currentFinding.columnHeaders.length) { + $scope.badFindingCell[x][y] = validateFindingCellInput($scope.currentFinding.columnHeaders[x].columnType, + data.rows[y].cells[x].value); + } + // If there are fewer column types/header set than there are columns. + // Data put in a cell with a column that does not have it's type set is never considered invalid. + else { + $scope.badFindingCell[x][y] = false; + } } + } + } + // If there are already column headers set, preserve them. + for( var colX = 0; colX < csvDataColCount; colX++){ + if( ($scope.currentFinding.columnHeaders[colX] !== null) &&($scope.currentFinding.columnHeaders[colX] !== undefined)){ + data.columnHeaders[colX] = $scope.currentFinding.columnHeaders[colX]; } } $scope.loader = false; $scope.currentFinding=data; + }). error(function(data, status, headers, config) { $scope.loader = false; @@ -409,7 +420,10 @@ var app = angular.module('angularApp') if( ( colType === null) || ( colType === undefined)){ return false; } - return (colType === 'datum') && (isNaN(cellData.replace(/(d|f)$/, ''))); + return ( + (colType === 'datum') && + ( cellData !== null) && (isNaN(cellData.replace(/(d|f)$/, ''))) + ); } /** @@ -625,7 +639,6 @@ var app = angular.module('angularApp') var re = new RegExp(trailingCommas[0] + '$'); csvData = csvData.replace(re, replacementStr); } - // Determine cell type if (csvData.substr(i, 1) === '"') { currentCellType = 2; @@ -708,7 +721,9 @@ var app = angular.module('angularApp') } runaway--; } // End while loop + csvDataObj.push(lineOfValues); + runaway--; } // End for loop @@ -718,8 +733,14 @@ var app = angular.module('angularApp') csvImportError = 'Too many columns (' + getMaxColumnCount( csvDataObj) +')'; return null; } - return csvDataObj; - }; + let columnCount = getMaxColumnCount(csvDataObj); + for( let f = 0; f < csvDataObj.length; f++){ + while( csvDataObj[f].length < columnCount){ + csvDataObj[f].push(''); + } + } + return csvDataObj; + } /** * Returns number of columns, it is possible for csv data to have inconsistent column count for rows diff --git a/software/cananolab-webapp/web/views/sample/edit/setupCharacterization.html b/software/cananolab-webapp/web/views/sample/edit/setupCharacterization.html index 2743756e01..99e53ccfae 100644 --- a/software/cananolab-webapp/web/views/sample/edit/setupCharacterization.html +++ b/software/cananolab-webapp/web/views/sample/edit/setupCharacterization.html @@ -955,11 +955,9 @@

Sample {{sampleName.name}} {{title}} Characterization

{{cell.displayName}} - - - +

Column Definitions