I have a Parser
class which creates a collection of String pairs, parsed in the format key=value
.
public class Parser{
private final HashMap<String, String> val;
private final File source;
public Parser(final File path){
/*initialise stuff*/
val=new HashMap<>();
source=path; //throws exception if null but omitted for brevity
/* and finally parse the file */
parse();
}
parse()
reads source
line-by-line using Scanner
and populates the collection:
public void parse() {
final Scanner sc=new Scanner(source);
while(sc.hasNextLine()){
//do stuff
}
sc.close();
}
The problem is, there are other parsers that utilise this class, and sometimes the parser needs to parse a String
instead of a File
. This leads to duplication of effort. Basically the code snippet above, with its signature changed to public void parse(final String raw)
. This led me to the following abomination:
private void parseDecision(final String possibleStr){
final Scanner sc;
if(possibleStr==null) //use File
sc=new Scanner(source); //remember source is a field
else
sc=new Scanner(possibleStr);
/*...*/
}
The abomination is being called from both parse
(with argument null
) and parse(String)
, and thus avoids code duplication. But when I look at it I can't help thinking there's a better way to do this.
I thought about using Generics. I've never written a Generic class before and I can't coerce Scanner
into accepting T
as either String
or File
, which would have been nice.
Which leads me to my question(s):
- Is the use of
parseDecision
a code smell or am I seeing ghosts? - Can this be done in a better way?
- If yes, can it be done with Generics?