-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#1708 - Replace original implementation and remove copyright info fro…
…m license file (#6195) * #1708 - Replace original implementation and remove copyright info from license file * incorporating PR review feedback
- Loading branch information
Showing
3 changed files
with
53 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
179 changes: 53 additions & 126 deletions
179
drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvLineParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,150 +1,77 @@ | ||
/** | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you 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. | ||
*/ | ||
package org.drools.decisiontable.parser.csv; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
/** | ||
* | ||
* a CSV line, with all the normal CSV features. | ||
* A simple parser for CSV (Comma-Separated Values) format. | ||
* Supports quoted fields and escaped quotes. | ||
*/ | ||
public class CsvLineParser { | ||
private ICsvParser lineParser; | ||
|
||
public CsvLineParser() { | ||
this.lineParser = new CsvParserImpl(); | ||
} | ||
private static final char DELIMITER = ','; | ||
|
||
/** | ||
* Use the current lineParser implementation to return a CSV line as a List | ||
* of cells. (Strings). | ||
* Parses a line of CSV text into a list of fields. | ||
* | ||
* @param input The CSV line to parse | ||
* @return List of fields extracted from the CSV line | ||
*/ | ||
public List<String> parse(final CharSequence line) { | ||
return this.lineParser.parse( line.toString() ); | ||
} | ||
|
||
/** | ||
* This is insurance incase I need to replace it with more complex Csv | ||
* handlers in the future. | ||
*/ | ||
static interface ICsvParser { | ||
public List<String> parse(String line); | ||
} | ||
|
||
/** | ||
* Parse comma-separated values (CSV), a common Windows file format. Sample | ||
* input: "LU",86.25,"11/4/1998","2:19PM",+4.0625 | ||
* <p> | ||
* Inner logic adapted from a C++ original that was Copyright (C) 1999 | ||
* Lucent Technologies Excerpted from 'The Practice of Programming' by Brian | ||
* W. Kernighan and Rob Pike. | ||
* <p> | ||
* Included by permission of the http://tpop.awl.com/ web site, which says: | ||
* "You may use this code for any purpose, as long as you leave the | ||
* copyright notice and book citation attached." I have done so. | ||
* | ||
* readability) | ||
*/ | ||
static class CsvParserImpl | ||
implements | ||
ICsvParser { | ||
|
||
public static final char DEFAULT_SEP = ','; | ||
public List<String> parse(CharSequence input) { | ||
String line = input != null ? input.toString() : ""; | ||
List<String> fields = new ArrayList<>(); | ||
|
||
/** Construct a CSV parser, with the default separator (','). */ | ||
public CsvParserImpl() { | ||
this( CsvParserImpl.DEFAULT_SEP ); | ||
if (line.isEmpty()) { | ||
return Collections.singletonList(""); | ||
} | ||
|
||
/** | ||
* Construct a CSV parser with a given separator. | ||
* | ||
* @param sep | ||
* The single char for the separator (not a list of separator | ||
* characters) | ||
*/ | ||
public CsvParserImpl(final char sep) { | ||
this.fieldSep = sep; | ||
} | ||
|
||
/** The fields in the current String */ | ||
protected List<String> list = new ArrayList<>(); | ||
StringBuilder currentField = new StringBuilder(); | ||
boolean insideQuotes = false; | ||
|
||
/** the separator char for this parser */ | ||
protected char fieldSep; | ||
for (int i = 0; i < line.length(); i++) { | ||
char currentChar = line.charAt(i); | ||
|
||
/** | ||
* parse: break the input String into fields | ||
* | ||
* @return java.util.Iterator containing each field from the original as | ||
* a String, in order. | ||
*/ | ||
public List<String> parse(final String line) { | ||
final StringBuilder sb = new StringBuilder(); | ||
this.list.clear(); // recycle to initial state | ||
int i = 0; | ||
|
||
if ( line.length() == 0 ) { | ||
this.list.add( line ); | ||
return this.list; | ||
} | ||
|
||
do { | ||
sb.setLength( 0 ); | ||
if ( i < line.length() && line.charAt( i ) == '"' ) { | ||
i = advQuoted( line, | ||
sb, | ||
++i ); // skip | ||
if (currentChar == '"') { | ||
if (insideQuotes && i + 1 < line.length() && line.charAt(i + 1) == '"') { | ||
// Handle escaped quotes | ||
currentField.append('"'); | ||
i++; // Skip the next quote | ||
} else { | ||
i = advPlain( line, | ||
sb, | ||
i ); | ||
insideQuotes = !insideQuotes; | ||
} | ||
this.list.add( sb.toString() ); | ||
i++; | ||
} while ( i < line.length() ); | ||
|
||
return this.list; | ||
} | ||
|
||
/** advQuoted: quoted field; return index of next separator */ | ||
protected int advQuoted(final String s, | ||
final StringBuilder sb, | ||
final int i) { | ||
int j; | ||
final int len = s.length(); | ||
for ( j = i; j < len; j++ ) { | ||
if ( s.charAt( j ) == '"' && j + 1 < len ) { | ||
if ( s.charAt( j + 1 ) == '"' ) { | ||
j++; // skip escape char | ||
} else if ( s.charAt( j + 1 ) == this.fieldSep ) { // next delimeter | ||
j++; // skip end quotes | ||
break; | ||
} | ||
} else if ( s.charAt( j ) == '"' && j + 1 == len ) { // end quotes at end of line | ||
break; // done | ||
} | ||
sb.append( s.charAt( j ) ); // regular character. | ||
continue; | ||
} | ||
return j; | ||
} | ||
|
||
/** advPlain: unquoted field; return index of next separator */ | ||
protected int advPlain(final String s, | ||
final StringBuilder sb, | ||
final int i) { | ||
int j; | ||
|
||
j = s.indexOf( this.fieldSep, | ||
i ); // look for separator | ||
if ( j == -1 ) { // none found | ||
sb.append( s.substring( i ) ); | ||
return s.length(); | ||
} else { | ||
sb.append( s.substring( i, | ||
j ) ); | ||
return j; | ||
if (currentChar == DELIMITER && !insideQuotes) { | ||
fields.add(currentField.toString()); | ||
currentField.setLength(0); | ||
continue; | ||
} | ||
|
||
currentField.append(currentChar); | ||
} | ||
|
||
// Add the last field | ||
fields.add(currentField.toString()); | ||
|
||
return fields; | ||
} | ||
} | ||
} |