Java tutorial
/******************************************************************************* * Copyright (c) Apr 5, 2012 NetXForge. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * This program 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. See the GNU General Public License for more * details. You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * * Contributors: Christophe Bouhier - initial API and implementation and/or * initial documentation *******************************************************************************/ package com.netxforge.netxstudio.server.logic.reporting; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Map.Entry; import javax.xml.datatype.XMLGregorianCalendar; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import com.google.common.base.Predicate; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.netxforge.base.NonModelUtils; import com.netxforge.netxstudio.common.model.StudioUtils; import com.netxforge.netxstudio.generics.DateTimeRange; import com.netxforge.netxstudio.generics.Value; import com.netxforge.netxstudio.library.Component; import com.netxforge.netxstudio.library.Equipment; import com.netxforge.netxstudio.library.Function; import com.netxforge.netxstudio.library.LevelKind; import com.netxforge.netxstudio.library.LibraryPackage; import com.netxforge.netxstudio.library.NetXResource; import com.netxforge.netxstudio.metrics.MetricValueRange; import com.netxforge.netxstudio.operators.Marker; import com.netxforge.netxstudio.operators.ToleranceMarker; /** * Outputs resources reports. * * @author Christophe Bouhier * */ public class ResourceReportingEngine { private DateTimeRange period; private Workbook workBook; private static final int NODE_COLUMN = 2; public ResourceReportingEngine(DateTimeRange period, Workbook workBook) { this.period = period; this.workBook = workBook; } public void writeComponentLine(int newRow, Sheet sheet, Component component) { Row componentRow = sheet.createRow(newRow); Cell componentCell = componentRow.createCell(NODE_COLUMN + 1); // Build the presentation of a component. StringBuilder builder = new StringBuilder(); if (component instanceof Function) { builder.append(component.getName()); // DEBUG CODE. // if(component.getName().equals("amm02in0assoc0")){ // System.out.println("DEBUG this comp" + component.getName()); // } } else if (component instanceof Equipment) { builder.append(((Equipment) component).getEquipmentCode()); builder.append( component.eIsSet(LibraryPackage.Literals.COMPONENT__NAME) ? " name:" + component.getName() : ""); } builder.append(component.eIsSet(LibraryPackage.Literals.COMPONENT__DESCRIPTION) ? " description:" + component.getDescription() : ""); componentCell.setCellValue(builder.toString()); } public void writeComponentLine(Sheet sheet, Row row, Component component) { Cell componentCell = row.createCell(NODE_COLUMN + 1); // Build the presentation of a component. StringBuilder builder = new StringBuilder(); if (component instanceof Function) { builder.append(component.getName()); // DEBUG CODE. // if(component.getName().equals("amm02in0assoc0")){ // System.out.println("DEBUG this comp" + component.getName()); // } } else if (component instanceof Equipment) { builder.append(((Equipment) component).getEquipmentCode()); builder.append( component.eIsSet(LibraryPackage.Literals.COMPONENT__NAME) ? " name:" + component.getName() : ""); } builder.append(component.eIsSet(LibraryPackage.Literals.COMPONENT__DESCRIPTION) ? " description:" + component.getDescription() : ""); componentCell.setCellValue(builder.toString()); } /** * * @param newRow * @param sheet * @param component * @param markersForNode */ public void writeFlat(int newRow, Sheet sheet, Component component, Map<NetXResource, List<Marker>> markersForNode) { int rowIndex = newRow; // writeTS(sheet, rowIndex); // Write one line for each resource MVR. for (NetXResource resource : component.getResourceRefs()) { List<Marker> markersForResource = null; if (markersForNode != null && markersForNode.containsKey(resource)) { markersForResource = markersForNode.get(resource); if (markersForResource.size() > 0) { System.out.println("Markers found for this resource " + resource.getLongName() + " size=" + markersForResource.size()); } } for (MetricValueRange mvr : resource.getMetricValueRanges()) { if (mvr != null) { Row nextRow = this.rowForIndex(sheet, ++rowIndex); // The component name. this.writeComponentLine(sheet, nextRow, component); // The resource (metric) name. Cell resourceCell = nextRow.createCell(NODE_COLUMN + 2); resourceCell.setCellValue(resource.getLongName()); // The range name. Cell mvrCell = nextRow.createCell(NODE_COLUMN + 3); mvrCell.setCellValue(nameForValueRange(mvr)); writeRange(markersForResource, sheet, mvr, nextRow); } } { // Write the capacity. // increment the index before creating a new row. Row nextRow = this.rowForIndex(sheet, ++rowIndex); // The component name. this.writeComponentLine(sheet, nextRow, component); // The resource (metric) name. Cell resourceCell = nextRow.createCell(NODE_COLUMN + 2); resourceCell.setCellValue(resource.getLongName()); // The range name. Cell mvrCell = nextRow.createCell(NODE_COLUMN + 3); mvrCell.setCellValue("Capacity"); // !Potentially long operation, as we sort of the whole rang.e writeCapacity(sheet, nextRow, resource); } { // Write the utilization. // increment the index before creating a new row. Row nextRow = this.rowForIndex(sheet, ++rowIndex); // The component name. this.writeComponentLine(sheet, nextRow, component); // The resource (metric) name. Cell resourceCell = nextRow.createCell(NODE_COLUMN + 2); resourceCell.setCellValue(resource.getLongName()); // The range name. Cell mvrCell = nextRow.createCell(NODE_COLUMN + 3); mvrCell.setCellValue("Utilization"); // !Potentially long operation, as we sort of the whole rang.e writeUtilization(sheet, nextRow, resource); } } } /* * A map of column index and TimesStamp. */ Map<Integer, Date> columnTS = Maps.newHashMap(); /** * @param sheet * @param rowIndex */ public void writeTS(Sheet sheet, int rowIndex) { // Get the timestamps by week numbers. Multimap<Integer, XMLGregorianCalendar> timeStampsByWeek = StudioUtils .hourlyTimeStampsByWeekFor(this.getPeriod()); Row tsRow = this.rowForIndex(sheet, rowIndex); System.out.println("Analyzed weeks " + timeStampsByWeek.keySet().size()); int column = NODE_COLUMN + 4; // TODO, Should reverse the weeks. // build an index of colums and timestamps. for (int i : timeStampsByWeek.keySet()) { Collection<XMLGregorianCalendar> collection = timeStampsByWeek.get(i); List<Date> weekTS = NonModelUtils.transformXMLDateToDate(collection); Collections.sort(weekTS); // CB Apply a check, if our usemodel for POI is based on HSSF which // is < '07 excel. // if( weekTS.size() + column >= 256 ){ // // With HSSF POI model, we can't do more than 256 columns // break; // } // Write the timestamps from the specified column. column = this.writeTS(columnTS, sheet, tsRow, weekTS, i, column); System.out.println(weekTS); } } // public int writeRange(HSSFSheet sheet, int resourceIndex, // NetXResource resource, List<Marker> markersForResource, // MetricValueRange mvr) { // if (mvr != null) { // resourceIndex = writeRange(markersForResource, sheet, mvr, // resourceIndex); // } // return resourceIndex; // } public void writeCapacity(Sheet sheet, Row capRow, NetXResource resource) { List<Value> capRange = StudioUtils.sortValuesByTimeStamp(resource.getCapacityValues()); capRange = StudioUtils.valuesInsideRange(capRange, this.getPeriod()); writeRange(null, sheet, capRow, capRange); } public void writeUtilization(Sheet sheet, Row capRow, NetXResource resource) { List<Value> utilRange = StudioUtils.sortValuesByTimeStamp(resource.getUtilizationValues()); utilRange = StudioUtils.valuesInsideRange(utilRange, this.getPeriod()); writeRange(null, sheet, capRow, utilRange); } public void writeRange(List<Marker> markers, Sheet sheet, MetricValueRange mvr, Row valueRow) { // use a query, experimental. // List<Value> range = queryService.getSortedValues(mvr); // !Potentially long operation, as we sort of the whole rang.e List<Value> range = StudioUtils.sortValuesByTimeStamp(mvr.getMetricValues()); range = StudioUtils.valuesInsideRange(range, this.getPeriod()); writeRange(markers, sheet, valueRow, range); } /** * @param mvr */ private String nameForValueRange(MetricValueRange mvr) { String fromMinutes = NonModelUtils.fromMinutes(mvr.getIntervalHint()); String rangeKind = mvr.getKindHint().getName(); return fromMinutes + " (" + rangeKind + ")"; } public void writeRange(List<Marker> markers, Sheet sheet, Row valueRow, List<Value> range) { CreationHelper createHelper = this.getWorkBook().getCreationHelper(); CellStyle cellStyle = this.getWorkBook().createCellStyle(); cellStyle.setDataFormat(createHelper.createDataFormat().getFormat("m-d-yy h:mm")); // Styles for markers. // CellStyle markerStyleRed = this.getWorkBook().createCellStyle(); // markerStyleRed.setFillForegroundColor(IndexedColors.RED.getIndex()); // markerStyleRed.setFillPattern(CellStyle.SOLID_FOREGROUND); CellStyle markerStyleRed = createRedBorderStyle(); CellStyle markerStyleAmber = createAmberBorderStyle(); // CellStyle markerStyleAmber = this.getWorkBook().createCellStyle(); // markerStyleAmber.setFillPattern(CellStyle.SOLID_FOREGROUND); // markerStyleAmber // .setFillForegroundColor(IndexedColors.ORANGE.getIndex()); // Write the values. for (Value v : range) { // lookup the value. int valueIndex = tsColumnForValue(v); if (valueIndex == -1) { continue; } Cell valueCell = valueRow.createCell(valueIndex); valueCell.setCellValue(v.getValue()); // Adapt the width of the column for this value. sheet.setColumnWidth(valueIndex, 14 * 256); // Set the markers. if (markers != null) { Marker m; if ((m = StudioUtils.markerForValue(markers, v)) != null) { if (m instanceof ToleranceMarker) { switch (((ToleranceMarker) m).getLevel().getValue()) { case LevelKind.RED_VALUE: { valueCell.setCellStyle(markerStyleRed); } break; case LevelKind.AMBER_VALUE: { valueCell.setCellStyle(markerStyleAmber); } break; } } } } } } private CellStyle createAmberBorderStyle() { CellStyle style = this.getWorkBook().createCellStyle(); style.setBorderBottom(CellStyle.BORDER_THIN); style.setBottomBorderColor(IndexedColors.ORANGE.getIndex()); style.setBorderLeft(CellStyle.BORDER_THIN); style.setLeftBorderColor(IndexedColors.ORANGE.getIndex()); style.setBorderRight(CellStyle.BORDER_THIN); style.setRightBorderColor(IndexedColors.ORANGE.getIndex()); style.setBorderTop(CellStyle.BORDER_THIN); style.setTopBorderColor(IndexedColors.ORANGE.getIndex()); return style; } private CellStyle createRedBorderStyle() { CellStyle style = this.getWorkBook().createCellStyle(); style.setBorderBottom(CellStyle.BORDER_THIN); style.setBottomBorderColor(IndexedColors.RED.getIndex()); style.setBorderLeft(CellStyle.BORDER_THIN); style.setLeftBorderColor(IndexedColors.RED.getIndex()); style.setBorderRight(CellStyle.BORDER_THIN); style.setRightBorderColor(IndexedColors.RED.getIndex()); style.setBorderTop(CellStyle.BORDER_THIN); style.setTopBorderColor(IndexedColors.RED.getIndex()); return style; } private int tsColumnForValue(Value v) { final Date toLookup = NonModelUtils.fromXMLDate(v.getTimeStamp()); Map<Integer, Date> filterEntries = Maps.filterEntries(columnTS, new Predicate<Entry<Integer, Date>>() { public boolean apply(Entry<Integer, Date> input) { Date value = input.getValue(); return value.compareTo(toLookup) == 0; } }); // there should only be one entry, ugly hack. // http://work.netxforge.com/issues/292 if (filterEntries.size() == 1) { return filterEntries.keySet().iterator().next() - 1; } return -1; } /** * Has a side effect of populating the columnTSMap with the index and date. * */ public int writeTS(Map<Integer, Date> columnTSMap, Sheet sheet, Row tsRow, List<Date> range, int weekNumber, int columnIndex) { CreationHelper createHelper = this.getWorkBook().getCreationHelper(); CellStyle dateStyle = this.getWorkBook().createCellStyle(); dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("m-d-yy h:mm")); // Write the values. int valueIndex = columnIndex; for (Date d : range) { Cell tsCell = tsRow.createCell(valueIndex); // sheet.setColumnWidth(valueIndex, 14 * 256); tsCell.setCellValue(d); tsCell.setCellStyle(dateStyle); valueIndex++; columnTS.put(valueIndex, d); } return valueIndex; } // Getters and setters. public DateTimeRange getPeriod() { return period; } public void setPeriod(DateTimeRange period) { this.period = period; } public Workbook getWorkBook() { return workBook; } public void setWorkBook(Workbook workBook) { this.workBook = workBook; } public Row rowForIndex(Sheet sheet, int rowIndex) { Row tsRow = sheet.getRow(rowIndex); if (tsRow == null) { tsRow = sheet.createRow(rowIndex); } return tsRow; } }