/* * Encog(tm) Core v3.4 - Java Version * http://www.heatonresearch.com/encog/ * https://github.com/encog/encog-java-core * Copyright 2008-2016 Heaton Research, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * For more information on Heaton Research copyrights, licenses * and trademarks visit: * http://www.heatonresearch.com/copyright */ package org.encog.app.analyst.util; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.encog.app.analyst.AnalystError; import org.encog.util.csv.CSVFormat; import org.encog.util.csv.ReadCSV; /** * Utility class to help deal with CSV headers. */ public class CSVHeaders { /** * Parse a timeslice from a header such as (t-1). * @param name The column name. * @return The timeslice. */ public static int parseTimeSlice(final String name) { final int index1 = name.indexOf('('); if (index1 == -1) { return 0; } final int index2 = name.indexOf(')'); if (index2 == -1) { return 0; } if (index2 < index1) { return 0; } final String list = name.substring(index1 + 1, index2); final String[] values = list.split(","); for (final String value : values) { final String str = value.trim(); if (str.toLowerCase().startsWith("t")) { final int slice = Integer.parseInt(str.substring(1)); return slice; } } return 0; } /** * Tag a column with part # and timeslice. * @param name The name of the column. * @param part The part #. * @param timeSlice The timeslice. * @param multiPart True if this is a multipart column. * @return The new tagged column. */ public static String tagColumn(final String name, final int part, final int timeSlice, final boolean multiPart) { final StringBuilder result = new StringBuilder(); result.append(name); // is there any suffix? if (multiPart || (timeSlice != 0)) { result.append('('); // is there a part? if (multiPart) { result.append('p'); result.append(part); } // is there a timeslice? if (timeSlice != 0) { if (multiPart) { result.append(','); } result.append('t'); if (timeSlice > 0) { result.append('+'); } result.append(timeSlice); } result.append(')'); } return result.toString(); } /** * The header list. */ private final List<String> headerList = new ArrayList<String>(); /** * The column mapping, maps column name to column index. */ private final Map<String, Integer> columnMapping = new HashMap<String, Integer>(); /** * Construct the object. * @param filename The filename. * @param headers False if headers are not extended. * @param format The CSV format. */ public CSVHeaders(final File filename, final boolean headers, final CSVFormat format) { ReadCSV csv = null; try { csv = new ReadCSV(filename.toString(), headers, format); if (csv.next()) { if (headers) { for (final String str : csv.getColumnNames()) { this.headerList.add(str); } } else { for (int i = 0; i < csv.getColumnCount(); i++) { this.headerList.add("field:" + (i + 1)); } } } init(); } finally { if (csv != null) { csv.close(); } } } /** * Construct the object. * @param inputHeadings The input headings. */ public CSVHeaders(final List<String> inputHeadings) { for (final String header : inputHeadings) { this.headerList.add(header); } init(); } /** * Construct the object. * @param inputHeadings The input headings. */ public CSVHeaders(final String[] inputHeadings) { for (final String header : inputHeadings) { this.headerList.add(header); } init(); } /** * Find the specified column. * @param name The column name. * @return The index of the column. */ public int find(final String name) { String key = name.toLowerCase(); if (!this.columnMapping.containsKey(key)) { throw new AnalystError("Can't find column: " + name.toLowerCase()); } return this.columnMapping.get(key); } /** * Get the base header, strip any (...). * @param index The index of the header. * @return The base header. */ public String getBaseHeader(final int index) { String result = this.headerList.get(index); final int loc = result.indexOf('('); if (loc != -1) { result = result.substring(0, loc); } return result.trim(); } /** * Get the specified header. * @param index The index of the header to get. * @return The header value. */ public String getHeader(final int index) { return this.headerList.get(index); } /** * @return The headers. */ public List<String> getHeaders() { return this.headerList; } /** * Get the timeslice for the specified index. * @param currentIndex The index to get the time slice for. * @return The timeslice. */ public int getSlice(final int currentIndex) { final String name = this.headerList.get(currentIndex); final int index1 = name.indexOf('('); if (index1 == -1) { return 0; } final int index2 = name.indexOf(')'); if (index2 == -1) { return 0; } if (index2 < index1) { return 0; } final String list = name.substring(index1 + 1, index2); final String[] values = list.split(","); for (final String value : values) { String str = value.trim(); if (str.toLowerCase().startsWith("t")) { str = value.trim().substring(1).trim(); if (str.charAt(0) == '+') { // since Integer.parseInt can't handle +1 str = str.substring(1); } final int slice = Integer.parseInt(str); return slice; } } return 0; } /** * Setup the column mapping and validate. */ private void init() { int index = 0; for (final String str : this.headerList) { this.columnMapping.put(str.toLowerCase(), index++); } validateSameName(); } /** * @return The number of headers. */ public int size() { return this.headerList.size(); } /** * Validate that two columns do not have the same name. This is an error. */ private void validateSameName() { for (int i = 0; i < this.headerList.size(); i++) { for (int j = 0; j < this.headerList.size(); j++) { if (i == j) { continue; } if (this.headerList.get(i).equalsIgnoreCase( this.headerList.get(j))) { throw new AnalystError("Multiple fields named: " + this.headerList.get(i)); } } } } }