/*
* @(#)InputLineStringParser.java
*
* Copyright (C) 2006 www.interpss.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
* as published by the Free Software Foundation; either version 2.1
* 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.
*
* @Author Mike Zhou
* @Version 1.0
* @Date 09/15/2012
*
* Revision History
* ================
*
*/
package org.ieee.odm.adapter.pwd;
import java.util.ArrayList;
import java.util.List;
import org.ieee.odm.adapter.BaseInputLineStringParser;
import org.ieee.odm.common.ODMLogger;
/**
* It first parses the meta data definition string, and save the attributes in a LinkedHashMap,
* named positionTable. Then it parses the data string according to the field definition as
* name-value pairs. For example,
*
[BusNum,BusNum:1,LineCircuit,LineStatus,LineR,LineX,LineC,LineG,LineAMVA,LineBMVA,
LineCMVA,LineShuntMW,LineShuntMW:1,LineShuntMVR,LineShuntMVR:1,LineXfmr,LineTap,
LinePhase,SeriesCapStatus]
4 5 " 1" "Closed" 0.000000 0.100000 0.000000 0.000000 1000.000 1000.000 1000.000 0.000 0.000 0.000 0.000 "YES" 0.993750 0.000000 "Not Bypassed"
*
* after the parsing, the nv pairs in the fieldTable will store
*
* <"BusNum","4">, <"BusNum:1","5">, ....
*
* @author mzhou
*
*/
public class InputLineStringParser extends BaseInputLineStringParser {
//private List<String> dataListx;
/**
* constructor
*/
public InputLineStringParser() {
super();
//this.dataList = new ArrayList<String>();
}
/**
* Parse metadata. The LinkedHashMap storing meta data will be renewed
* for each data section, therefore, make sure the input string for the
* metaData is completed by itself.
*
* @param data
*/
public void parseMetadata(String data) {
setMetadata(parseMetaData(data));
}
/**
* parse the data string.
*
* @param data
* @return true if all fields are parsed
*/
public boolean parseData(String data) {
//renew the fieldTable before processing each model definition
this.fieldTable.clear();
int cnt=0;
String[] sAry = parseDataFields(data);
for (String s : sAry) {
//System.out.print(s+", ");
this.fieldTable.put(this.positionTable.get(cnt++), s.trim());
}
return this.positionTable.size() == this.fieldTable.size();
}
/**
* parse the string data. The append mode is an option, if it is set
* to be true, then the data will be appended to the fieldTable, while the fiedTable will
* not be renewed or cleared.
*
* @param data
* @param appendMode
* @return
*/
public boolean parseData(String data, boolean appendMode){
//System.out.println(data);
if(!appendMode)
parseData(data);
else{
int cnt =this.fieldTable.size();
String[] sAry = parseDataFields(data);
for (String s : sAry) {
this.fieldTable.put(this.positionTable.get(cnt++), s.trim());
}
//Add because the PWD output IEEE14 data detected meta data duplication issue
if(sAry.length==this.positionTable.size()){
if(this.fieldTable.size()!=this.positionTable.size()){
ODMLogger.getLogger().severe("Duplicated meta data definition detected! "
+"\n"+this.positionTable.toString());
}
}
}
//System.out.println("position table="+this.positionTable.size()+", fieldTable ="+this.fieldTable.size());
return this.positionTable.size() == this.fieldTable.size();
}
/**
* parse a complete data section metaData definition and return as an string array.
*
* [BusNum,BusNum:1,LineCircuit,LineStatus,LineR,LineX,LineC,LineG,LineAMVA,LineBMVA]
*
* { "BusNum", "BusNum:1", "LineCircuit", "LineStatus" }
*
* @param str
* @return A String array storing the metaData definition
*/
private String[] parseMetaData(String str){
int indexOfLeftBracket=str.indexOf("[");
int indexOfRightBracket=str.indexOf("]");
String[] arguFields=str.substring(indexOfLeftBracket+1,
indexOfRightBracket).split(",");
return arguFields;
}
/**
* Parse an input string to a string array
* input string : 4 5 " 1" "Closed" 0.000000 0.100000 0.000000 0.000000
* to a string array : { "4", "5", " 1", "Closed", "0.000000", "0.100000", "0.000000", "0.000000"}
*
* @param Str
* @return
*/
public String[] parseDataFields(String Str){
List<String> dataList = new ArrayList<>();
boolean quotBegin = false;
int beginIdx =0, endIdx=0;
String s=Str.trim();
int length = s.length();
int length_1 = length-1;
//convert the input string to a char array
char[] charAry =s.toCharArray();
for( int i = 0;i<charAry.length;i++){
//string within a quotation is processed separately
// and treated as a whole
if (!(charAry[i] == '"' || charAry[i] == '\'')) {
// PWD uses the space to separate data by default, the consecutive non-space
// characters together form a string
if (i > 0 && !quotBegin) {
if (i <= length_1) {
if (Character.isWhitespace(charAry[i-1])
&& (!Character.isWhitespace(charAry[i]))) {
beginIdx = i;
} else if (Character.isWhitespace(charAry[i])&&
(!Character.isWhitespace(charAry[i-1]) &&
!(charAry[i-1] == '"' || charAry[i-1] == '\''))) {
endIdx = i;
dataList.add(s.substring(beginIdx, endIdx));
//this.dataList.add(new String(charAry, beginIdx, endIdx-beginIdx));
}
}
// if the processing data is the last one, since no
// space after it, it needs to be treated specially.
if (i == (length_1)) {
endIdx = length;
dataList.add(s.substring(beginIdx, endIdx));
//this.dataList.add(new String(charAry, beginIdx, endIdx-beginIdx));
}
} // end if i>1 && !quotBegin
}
else{ // The following processes the string within quotations.
if (!quotBegin){
quotBegin = true;
beginIdx=i+1;
}else{//this quotation completes a pair
endIdx=i;
dataList.add(s.substring(beginIdx, endIdx));
//this.dataList.add(new String(charAry, beginIdx, endIdx-beginIdx));
quotBegin = false;
}
}
}
//System.out.println(dataList.toString());
return dataList.toArray(new String[1]);
}
}