Regex for a proper closure of checkstyle - java

Is there a way to create a regex, that will check for proper 'closure' of a checkstyle (which begins with //)?
// CHECKSTYLE:OFF
protected void doSomething() {
}
// CHECKSTYLE:ON
// CHECKSTYLE:OFF
protected void doSomethingElse() {
// CHECKSTYLE:ON
}
If there is a typo in the first CHECKSTYLE:ON, the rest of checkstyles will be ignored.

I don't know if a pure regex would be appropriate here. Your problem is the really the stuff with which parsers are concerned. Actually, I don't even know how we would detect // CHECKSTYLE:ON with a typo in it. But, one option here would be to simply scan your file line by line, and fail if we ever encounter two // CHECKSTYLE:OFF in a row. If that happens, then it implies that either the ON checkstyle was completely omitted, or it was mispelled.
static final String CHECK_ON = "// CHECKSTYLE:ON";
static final String CHECK_OFF = "// CHECKSTYLE:OFF";
File file = new File("your_input.ext");
boolean checkstyleIsOn = false;
try {
Scanner sc = new Scanner(file);
int lineNum = 0;
while (sc.hasNextLine()) {
++lineNum;
String line = sc.nextLine();
if (CHECK_OFF.equals(line)( {
if (!checkStyleIsOn) {
System.out.println("Found extra checkstyle off at line " + lineNum);
break;
}
else {
checkStyleIsOn = false;
}
}
if (CHECK_ON.equals(line)( {
if (checkStyleIsOn) {
System.out.println("Found extra checkstyle on at line " + lineNum);
break;
}
else {
checkStyleIsOn = true;
}
}
}
sc.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}

Related

How to refactor this messy code

I have this code that I need to re-write and make a little prettier. It reads lines from a config.txt file and sets variables based on the contents of the file. As you can see, the code is ugly in many ways. There is a lot of duplicated code and the way the program checks the contents of the file is not very elegant (it should probably iterate over the lines instead of checking if the file contains a specific text). Overall, I think it would be nice to avoid having a huge wall of if/else blocks, which actually continues further down but I felt no need to include all of it.
All the program code is written in one main method and I would like to create some classes. I was thinking of a Config class that should handle reading from a config file, and it would have a list of lines (Line objects maybe?) and handle them in order. I've been reading about things like Strategy pattern and Command pattern recently and would like to apply something like that to this case, but I'm unsure any of that is appropriate here. If anyone experienced has any input on this I would greatly appreciate it!
...
try {
reader = new BufferedReader(new FileReader(pathToConfig));
line = reader.readLine();
while(line!=null){
if(line.contains("//")|| line.equals(""));
else{
if(line.contains("inputFolderPath")) {
pathToFolder=line.split("=")[1];
}
else if(line.contains("defaultOutputPath")){
defaultOutputPath=line.split("=")[1];
}
else if(line.contains("checkStyleAttribute")&&!line.contains("Path")){
lineAfterSplit=line.split("=")[1];
checkStyle=Boolean.parseBoolean(lineAfterSplit);
errorListStyleAttribute=new ArrayList<String>();
}
else if(line.contains("checkXrefAndNormalLinks")&&!line.contains("Path")){
lineAfterSplit=line.split("=")[1];
checkXref=Boolean.parseBoolean(lineAfterSplit);
errorListXref = new ArrayList<String>();
}
else if(line.contains("checkThatAllTopicsHaveConceptKeywords")&&!line.contains("Path")){
lineAfterSplit=line.split("=")[1];
checkThatAllTopicsHaveConceptKeywords=Boolean.parseBoolean(lineAfterSplit);
errorListConceptKeywords=new ArrayList<String>();
}
else if(line.contains("checkThatAllTopicsHaveIndexKeywords")&&!line.contains("Path")){
lineAfterSplit=line.split("=")[1];
checkThatAllTopicsHaveIndexKeywords=Boolean.parseBoolean(lineAfterSplit);
errorListIndexKeywords=new ArrayList<String>();
}
else if(line.contains("checkForNoUIElementsInHeadings")&&!line.contains("Path")){
lineAfterSplit=line.split("=")[1];
checkForNoUIElementsInHeadings=Boolean.parseBoolean(lineAfterSplit);
errorListUiElements=new ArrayList<String>();
}
else if(line.contains("whatElementToCheckForStyle")){
tag=line.split("=")[1];
if(tag.charAt(0)=='['){
tag=tag.substring(1, tag.length()-1);
String[] tags = tag.split(",");
for(int i=0;i<tags.length;i++){
tagsToCheck.add(tags[i]);
}
}
else if(tag.equals("all")){
checkEveryTag=true;
}
else{
tagsToCheck.add(tag);
}
}
else if(line.contains("checkForProductNamesWithoutDNTTag")&&!line.contains("Path")){
lineAfterSplit=line.split("=")[1];
checkForProductNamesWithoutDNTTag=Boolean.parseBoolean(lineAfterSplit);
errorProductNamesWithoutDNTTag=new ArrayList<String>();
}
... and it just goes on
As i see most of your code is doing repetitive work ( check if like has some text and perform some action on it.)
I suggest you create pluggable matchAndPerform methods. i.e. encapsulate string matching and related method calls into a class (strategy pattern) and have some class where you can dynamically register and remove these matcher objects.
example of strategy pattern:
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
public class OperationMultiply implements Strategy{
#Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
well, I hope this helps
try (BufferedReader reader = new BufferedReader(new FileReader(pathToConfig))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("//") || line.isEmpty()) {
continue;
}
String[] parts = line.split("=", 2);
String key = parts[0].trim();
String value = parts[1].trim();
switch (key) {
case "inputFolderPath":
pathToFolder = value;
break;
case "defaultOutputPath":
defaultOutputPath = value;
break;
case "checkStyleAttribute":
if (!value.contains("Path")) {
checkStyle = Boolean.parseBoolean(value);
errorListStyleAttribute = new ArrayList<>();
}
break;
case "checkXrefAndNormalLinks":
if (!value.contains("Path")) {
checkXref = Boolean.parseBoolean(value);
errorListXref = new ArrayList<>();
}
break;
case "checkThatAllTopicsHaveConceptKeywords":
if (!value.contains("Path")) {
checkThatAllTopicsHaveConceptKeywords = Boolean.parseBoolean(value);
errorListConceptKeywords = new ArrayList<>();
}
break;
case "checkThatAllTopicsHaveIndexKeywords":
if (!value.contains("Path")) {
checkThatAllTopicsHaveIndexKeywords = Boolean.parseBoolean(value);
errorListIndexKeywords = new ArrayList<>();
}
break;
case "checkForNoUIElementsInHeadings":
if (!value.contains("Path")) {
checkForNoUIElementsInHeadings = Boolean.parseBoolean(value);
errorListUiElements = new ArrayList<>();
}
break;
case "whatElementToCheckForStyle":
tag = value;
if (tag.charAt(0) == '[') {
tag = tag.substring(1, tag.length() - 1);
String[] tags = tag.split(",");
for (String t : tags) {
tagsToCheck.add(t.trim());
}
} else if (tag.equals("all")) {
checkEveryTag = true;
} else {
tagsToCheck.add(tag);
}
break;
case "checkForProductNamesWithoutDNTTag":
if (!value.contains("Path")) {
checkForProductNamesWithoutDNTTag = Boolean.parseBoolean(value);
errorProductNamesWithoutDNTTag = new ArrayList<>();
}
break;
default:
// ignore unrecognized keys
break;
}
}
} catch (IOException e) {
// handle exception
}

Refactoring two code

My project need to parse two type of text data into database.
one format is like this:
<lineNumber>19</lineNumber>
<begin>
2013-08-15,2013-08-15,pek001,123456,08654071,CANX,,,,,,011
<end>
one is like that
<lineNumber>27</lineNumber>
<begin>
2012-11-02,08683683,pek001,00001234,vvip,1
<end>
the difference of the two text is between the begin and end tag.
so our parsing code come out:
first one is:
inputStreamReader = new InputStreamReader(new FileInputStream(FileOne),"gbk"); --different place
br=new BufferedReader(inputStreamReader);
lineNumber = 0;
boolean isDataContent = false;
while (br.ready()) {
String line = br.readLine();
if(line == null){
continue;
}
if(line.contains("<lineNumber>"))
{
try {
lineNumber = Integer.parseInt(StringTools.getDigitalInString(line));
} catch (NumberFormatException e) {
log.error("there is no lineNumber。");
}
continue;
}
if(line.trim().equals("<begin>"))
{
isDataContent = true;
continue;
}
if(line.trim().equals("<end>"))
{
break;
}
if(isDataContent)
{
insertFirstToDatabase(line,vo); --just this is different.
}
}
second one is :
inputStreamReader = new InputStreamReader(new FileInputStream(FileTwo),"gbk");
--different place
br=new BufferedReader(inputStreamReader);
lineNumber = 0;
boolean isDataContent = false;
while (br.ready()) {
String line = br.readLine();
if(line == null){
continue;
}
if(line.contains("<lineNumber>"))
{
try {
lineNumber = Integer.parseInt( StringTools.getDigitalInString(line));
} catch (NumberFormatException e) {
log.error("there is no lineNumber");
}
continue;
}
if(line.trim().equals("<begin>"))
{
isDataContent = true;
continue;
}
if(line.trim().equals("<end>"))
{
break;
}
if(isDataContent)
{
insertSecondToDatabase(line,vo); --only this is different.
}
}
The two piece of code is in two different service code. How can I refactor this reduplicate code? so that each place Just only call one same function to check the lineNumber.
Have the duplicated code in a class that both the other classes either inherit (inheritance) or include a copy of (composition). Alternatively you could even make it a static method in a utility class.
Your code is identical until a single statement, and it's not shown how you determined which of these sequences of code you should be executing, but just move that branching into the if (isDataContent):
// copy/paste from your own, change the if to:
if(isDataContent) {
if (flagFirst) {
insertFirstToDatabase(line,vo); --just this is different.
} else {
insertSecondToDatabase(line,vo); --only this is different.
}
}
Where flagFirst is either a boolean variable or a boolean expression to determine which of the inserts should be done.
You can add 'kind' parameter for selecting usded inserting method as following:
public void process(int kind) {
....
while (br.ready()) {
String line = br.readLine();
if(line == null){
continue;
}
if(line.contains("<lineNumber>"))
{
try {
lineNumber = Integer.parseInt( StringTools.getDigitalInString(line));
} catch (NumberFormatException e) {
log.error("there is no lineNumber");
}
continue;
}
if(line.trim().equals("<begin>"))
{
isDataContent = true;
continue;
}
if(line.trim().equals("<end>"))
{
break;
}
if(isDataContent)
{
if (kind == 1) {
insertFirstToDatabase(line,vo); --just this is different.
}
if (kind == 2) {
insertSecondToDatabase(line,vo); --only this is different.
}
}
}
}
2 things:
duplicated code? - put in static method in utility class
how to differentiate dataContent? -
i. this can be determined while parsing the line depending on the order of fields
(or)
ii. the callee of the static method can determine the same by sending a flag. But this is not good design. You are placing too much implementation i.e. 2 behaviors in a utility method.
(or)
iii. Let the static method parse the XML and return just the line details to the callee. Let the callee handle however it likes. First callee might just want to print, second callee might want to put into db.
So, here it goes,
public static LineDetails parseXML(String filename)
{
inputStreamReader = new InputStreamReader(new FileInputStream(new File(filename));
br=new BufferedReader(inputStreamReader);
lineNumber = 0;
boolean isDataContent = false;
LineDetails lineDetails = new LineDetails();
while (br.ready()) {
String line = br.readLine();
if(line == null){
continue;
}
if(line.contains("<lineNumber>"))
{
try {
lineNumber = Integer.parseInt( StringTools.getDigitalInString(line));
} catch (NumberFormatException e) {
log.error("there is no lineNumber");
}
lineDetails.setLineNumber(lineNumber);
continue;
}
if(line.trim().equals("<begin>"))
{
isDataContent = true;
continue;
}
if(line.trim().equals("<end>"))
{
break;
}
if(isDataContent)
{
// parse line
lineDetails.setLine(line);
}
}
return lineDetails;
}
public class LineDetails
{
private int lineNumber=0;
private String line="";
// getters setters
}
//First callee
methodA()
{
LineDetails lineDetails = parseXML(filename);
if(lineDetails!=null && lineDetails.getLineNumber==19 && lineDetails.getLine()!=null && !lineDetails.getLine.equals(""))
{
insertFirstToDatabase(line);
}
}
//Second callee
methodB()
{
LineDetails lineDetails = parseXML(filename);
if(lineDetails!=null && lineDetails.getLineNumber==27 && lineDetails.getLine()!=null && !lineDetails.getLine.equals(""))
{
insertSecondToDatabase(line);
}
}

Java StreamTokenizer for non-character input?

I have a java binary search tree and I want to create a menu.
To this day I used StreamTokenizer to get the user input,
But now it doesn't seem to work with "+", "-", "?".
My code:
public void listen() throws IOException {
boolean stay = true;
System.out.println("Give me commands .. ");
while(stay) {
tokens.nextToken();
if(tokens.sval.equals("+")) {
tree.insert(new PositiveInt((int) tokens.nval));
} else if(tokens.sval.equals("?")) {
System.out.println(
tree.retrieve(new PositiveInt((int) tokens.nval)) == null ? "Not exist" : "exist");
} else if(tokens.sval.equals("-")) {
tree.remove(new PositiveInt((int) tokens.nval));
} else if(tokens.sval.equalsIgnoreCase("K")) {
tree.writeKeys();
} else if(tokens.sval.equalsIgnoreCase("E")) {
System.out.println("Empty = " + tree.isEmpty());
} else if(tokens.sval.equalsIgnoreCase("F")) {
System.out.println("Full = " + tree.isFull());
} else if(tokens.sval.equalsIgnoreCase("C")) {
tree.clear();
} else if(tokens.sval.equalsIgnoreCase("P")) {
tree.showStructure();
} else if(tokens.sval.equalsIgnoreCase("Q")) {
stay = false;
} else {
System.out.println("Unaccaptable input.");
}
}
}
When I enter "P" , for example, or any other character, everything's alright.
When I enter "?", "+", "-", I'm getting:
Exception in thread "main" java.lang.NullPointerException
at TestBSTree.listen(TestBSTree.java:27)
at TestBSTree.main(TestBSTree.java:54)
As Line 27 is :
if(tokens.sval.equals("+")) {
In other words, a non-charater is not accaptable with the tokenizer.
Why and how can I fix it?
Whole code:
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
public class TestBSTree {
// Test class variables
BSTree<PositiveInt> tree;
InputStreamReader reader;
StreamTokenizer tokens;
PositiveInt key;
int in;
public TestBSTree(PositiveInt root) {
tree = new BSTree<PositiveInt>(new BSTreeNode<>(root, null, null));
reader = new InputStreamReader(System.in);
tokens = new StreamTokenizer(reader);
key = null;
}
public void listen() throws IOException {
boolean stay = true;
System.out.println("Give me commands .. ");
while(stay) {
tokens.nextToken();
if(tokens.sval.equals("+")) {
tree.insert(new PositiveInt((int) tokens.nval));
} else if(tokens.sval.equals("?")) {
System.out.println(
tree.retrieve(new PositiveInt((int) tokens.nval)) == null ? "Not exist" : "exist");
} else if(tokens.sval.equals("-")) {
tree.remove(new PositiveInt((int) tokens.nval));
} else if(tokens.sval.equalsIgnoreCase("K")) {
tree.writeKeys();
} else if(tokens.sval.equalsIgnoreCase("E")) {
System.out.println("Empty = " + tree.isEmpty());
} else if(tokens.sval.equalsIgnoreCase("F")) {
System.out.println("Full = " + tree.isFull());
} else if(tokens.sval.equalsIgnoreCase("C")) {
tree.clear();
} else if(tokens.sval.equalsIgnoreCase("P")) {
tree.showStructure();
} else if(tokens.sval.equalsIgnoreCase("Q")) {
stay = false;
} else {
System.out.println("Unaccaptable input.");
}
}
}
public static void main(String[] args) throws IOException {
TestBSTree test = new TestBSTree(new PositiveInt(0));
test.listen();
}
}
It doesn't matter how does the tree or PositiveInt implemented, the main issue is the tokenizer.
if you want so split a string containg a '?' or a plus ('+'), you cannot simply use this symbol to split this String; they are reserved 'words' and need a exclude sign '\' which itself needs an exclusion sign ^^ (so you need two '\\' and the special sign)
try to use something like that:
StringTokenizer tokenizer = new StringTokenizer("ghj?klm", "\\?");
System.out.println(tokenizer.countTokens() );
-> result: the count is 2 !
you can also apply this method for String.split("\+");
//wont work!!
String str = "ghj?klm";
String[] s = str.split("?");
System.out.println(s.length );
but this code will work!
String str = "ghj?klm";
String[] s = str.split("\\?");
System.out.println(s.length );
it's the same 'problem' ^^ i hope this helped!
unfortunaltely i don't know which other symbols require a slahs... :-(

Return to ... in Java (like goto)

I just started to learn Java, so have a lot of questions. And now I need to return to the beginning of program if a problem occurs.
public static int getchartoint() throws IOException {
int a;
try {
BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
String k = bReader.readLine();
a = Integer.parseInt(k);
return a;
}
catch (NumberFormatException exc) {
System.out.println(exc);
return a = 0;
}
finally {
}
}
and I have a = 0, I could write case in main() body:
case 0: {
System.out.println("Your entered an incorrect number...");
}
My question is: how can I add a line that moves me to exactly that line of code?
Call the "getchartoint" method before your switch/case statements.
Then when it returns integer 0 it will execute the case statement.
It looks like you just want to return 0; instead of return a=0;.

Where is the specification that defines this behavior for InputStreamReader?

Considering the below code for an exercise problem, where is the specification that says roughly: "Upon the call to readTokens(), wait for the user to press carriage return and then continue execution."
I'm not fully understanding why my code works, why does the program pause after "Enter Data: " is displayed and wait for a carriage return? Where is this behavior defined and how can it be changed?
import java.io.*;
import java.util.LinkedList;
public class StreamTokeTwo {
private int ttype = 0;
StreamTokenizer tokenizer = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
private void setupTokenizer() {
tokenizer.resetSyntax();
tokenizer.wordChars(33, 126);
tokenizer.whitespaceChars(0, 32);
tokenizer.whitespaceChars(44,44);
tokenizer.whitespaceChars(47,47);
tokenizer.eolIsSignificant(true);
}
private String[] readTokens() {
LinkedList<String> list = new LinkedList<String>();
String[] array = null;
do {
try {
ttype = tokenizer.nextToken();
} catch (Exception e) {
System.exit(1);
}
if (ttype == StreamTokenizer.TT_WORD) {
list.add(tokenizer.sval);
}
} while (ttype != StreamTokenizer.TT_EOL);
array = list.toArray(new String[0]);
return array;
}
public static void main(String[] args) {
StreamTokeTwo streamToke = new StreamTokeTwo();
streamToke.setupTokenizer();
for (int i = 0; i < 5; ++i) {
System.out.print("Enter data: ");
String[] array = streamToke.readTokens();
for (String str : array) {
System.out.print(str + " ");
}
System.out.println();
}
}
}
The wait-for-typing behavior is a feature of the operating system and shell. They turn your typing into standard input for the JVM, and decide what constitutes end of file and what makes data available to pass to a program that is reading its standard input.
As far as the JVM is concerned, it is just asking for data from standard input, in a way that will block if there is no data available and it is not at end of file. It would be doing the same if standard input were a disk file.
This is implied by the statement that the InputStreamReader has blocking behavior: the reading methods will not return until there is something to be read, or an error occurs.

Categories