com.opengamma.financial.security.equity.GICSCodeDescription.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.financial.security.equity.GICSCodeDescription.java

Source

/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.financial.security.equity;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Objects;

/**
 * The description of a GICS code.
 * <p>
 * This provides a description for {@link GICSCode}.
 * <p>
 * This is an effective singleton.
 * 
 *  S&P provides an Excel file of GICS code mappings.  To load support for these mappings, the file provided by S&P must be renamed 'gics_map.xls'
 *  and be located in the classpath. If the file does not have this name or the Classloader cannot find it, an error will be logged
 *  and GICS code mapping will not be available.
 *  
 *  @see <a href="http://www.standardandpoors.com/indices/gics/en/us">Standard and Poors</a>
 */
final class GICSCodeDescription {

    /** Logger. */
    public static final GICSCodeDescription INSTANCE = new GICSCodeDescription();
    /** Logger. */
    private static final Logger s_logger = LoggerFactory.getLogger(GICSCodeDescription.class);

    private static final String GICS_FILE_NAME = "gics_map.xls";

    /**
     * The descriptions.
     */
    private static final Map<String, String> DESCRIPTIONS = new HashMap<String, String>();
    static {
        InputStream xlsStream = GICSCodeDescription.class.getClassLoader().getResourceAsStream(GICS_FILE_NAME);
        processGICSExcelWorkbook(xlsStream, DESCRIPTIONS);
    }

    /**
     *  Load S&P GICS code mappings from an Excel file stream
     * @param inputStream opened stream based on Excel file
     * @param gicsMap Map to add mappings to
     */
    static void processGICSExcelWorkbook(InputStream inputStream, Map<String, String> gicsMap) {
        Workbook workbook;
        try {
            workbook = new HSSFWorkbook(new BufferedInputStream(inputStream));
        } catch (IOException e) {
            s_logger.warn("Unable to find S&P GICS Code Mapping file '" + GICS_FILE_NAME
                    + "' in classpath; unable to use GICS Codes: " + e);
            return;
        }
        processGICSExcelWorkbook(workbook, gicsMap);
    }

    /**
     *  Load S&P GICS code mappings from an Apace POI HSSFWorkbook 
     * @param workbook HSSFWorkbook to parse S&P GCIS Excel
     * @param gicsMap Map to add mappings to
     */
    static void processGICSExcelWorkbook(Workbook workbook, Map<String, String> gicsMap) {

        //Assume 1 sheet
        Sheet sheet = workbook.getSheetAt(0);
        if (sheet == null) {
            return;
        }
        for (int rowNum = sheet.getFirstRowNum(); rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                continue;
            }
            for (int cellNum = 0; cellNum < row.getPhysicalNumberOfCells(); cellNum++) {
                Cell cell = row.getCell(cellNum, Row.CREATE_NULL_AS_BLANK);
                if (isNumeric(cell)) {
                    //worst case if the Excel file is in an  incorrect (or updated) format
                    // is that number -> random or empty string mappings will be created
                    gicsMap.put(getGICSCellValue(cell), getGICSCellValue(row, cellNum + 1));
                }
            }
        }
    }

    /**
     * Get the value of the Apache POI Cell as a String.  If the Cell type is numeric (always a double with POI),
     * the value is converted to an integer.  The GCIS file does not contain any floating point values so (at this time)
     * this is a valid operation
     * 
     * @param cell Apache POI Cell
     * @return String value
     */
    static String getGICSCellValue(Cell cell) {
        if (cell == null) {
            return "";
        }
        switch (cell.getCellType()) {
        case Cell.CELL_TYPE_NUMERIC:
            return Integer.valueOf((int) cell.getNumericCellValue()).toString();
        case Cell.CELL_TYPE_STRING:
            return cell.getStringCellValue();
        case Cell.CELL_TYPE_BOOLEAN:
            return Boolean.toString(cell.getBooleanCellValue());
        case Cell.CELL_TYPE_BLANK:
            return "";
        default:
            return "null";
        }
    }

    /**
     * Get the value of the Apache POI Cell specified by the row and cell num (column) as a String. 
     * If row,cellNum defines a null or blank cell, an empty String is returned
     * @param row Apace POI Row
     * @param cellNum cell number in Row
     * @return String value of specified cell, or empty String if invalid cell
     */
    static String getGICSCellValue(Row row, int cellNum) {
        return getGICSCellValue(row.getCell(cellNum, Row.CREATE_NULL_AS_BLANK));

    }

    /**
     * Determine if specfied Cell contains a number or something else based on the cell 
     * type defined in the source Excel file.
     * @param cell Apace POI Cell
     * @return true if numeric, false if any other type
     */
    static boolean isNumeric(Cell cell) {
        return cell.getCellType() == Cell.CELL_TYPE_NUMERIC;
    }

    /**
     * Creates an instance.
     */
    private GICSCodeDescription() {
    }

    //-------------------------------------------------------------------------
    /**
     * Gets the description for the code.
     * 
     * @param code  the code to lookup, not null
     * @return the description, "Unknown" if not found
     */
    String getDescription(String code) {
        String desc = DESCRIPTIONS.get(code);
        return Objects.firstNonNull(desc, "Unknown");
    }

    /**
     * Gets all the sector descriptions 
     * @return a collection of all the sector description strings
     */
    Collection<String> getAllSectorDescriptions() {
        return getAllDescriptions(2);
    }

    /**
     * Gets all the industry group descriptions 
     * @return a collection of all the industry group description strings
     */
    Collection<String> getAllIndustryGroupDescriptions() {
        return getAllDescriptions(4);
    }

    /**
     * Gets all the industry descriptions 
     * @return a collection of all the industry description strings
     */
    Collection<String> getAllIndustryDescriptions() {
        return getAllDescriptions(6);
    }

    /**
     * Gets all the sub-industry descriptions 
     * @return a collection of all the sub-industry description strings
     */
    Collection<String> getAllSubIndustryDescriptions() {
        return getAllDescriptions(8);
    }

    /**
     * Get all descriptions with a particular code length
     * @param codeLength the number of digits in the code
     * @return a collection of all the description strings
     */
    private Collection<String> getAllDescriptions(int codeLength) {
        Collection<String> results = new ArrayList<String>();
        for (Map.Entry<String, String> entry : DESCRIPTIONS.entrySet()) {
            if (entry.getKey().length() == codeLength) {
                results.add(entry.getValue());
            }
        }
        return results;
    }

    //-------------------------------------------------------------------------
    /**
     * Gets a simple string description for the class.
     * 
     * @return the string, not null
     */
    @Override
    public String toString() {
        return getClass().getSimpleName();
    }

    /**
     * Output the current contents of the GICS map to the log
     * @param gicsMap Map of GICS code -> description
     */
    static void dumpGICSMap(Map<String, String> gicsMap) {
        for (Map.Entry<String, String> entry : gicsMap.entrySet()) {
            s_logger.info(" {}  -> {} ", entry.getKey(), entry.getValue());
        }
    }

    /**
     * For testing.  Logs the contents of the GICS code->description map that is loaded
     * statically
     * @param args
     * @return
     */
    private boolean run(String[] args) {
        s_logger.info(this.toString() + " is initialising...");
        s_logger.info("Current working directory is " + System.getProperty("user.dir"));
        dumpGICSMap(DESCRIPTIONS);
        s_logger.info(this.toString() + " is finished.");
        return true;
    }

    /**
     * For standalone testing 
     * @param args command line arguments
     */
    public static void main(String[] args) { // CSIGNORE
        boolean success = new GICSCodeDescription().run(args);
        System.exit(success ? 0 : 1);
    }

}