/*
* Copyright 2010 the original author or authors.
*
* 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.
*/
package org.gradle.foundation.output;
import org.gradle.foundation.output.definitions.*;
import java.util.List;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
This parses gradle's output text looking for links to files. We use RegEx to
do the bulk of the matching. However, we want this to be 'pluggable' (to a
degree) so new file links can be added easily. To accomplish this, this works
with FileLinkDefinitions. They require a basic RegEx pattern to match some
initial part of the a file link, however, they can be implemented to do more
advanced parsing of the text. The definitions are built-up and held by
FileLinkDefinitionLord. This just handles the tedium of matching the
all-inclusive pattern with text, managing indices, and calling the matching
FileLinkDefinition to refine the match.
@author mhunsicker
*/
public class OutputParser
{
private FileLinkDefinitionLord fileLinkDefinitionLord;
private boolean verifyFileExists; //this is really only for testing where the file will not exist.
public OutputParser( FileLinkDefinitionLord fileLinkDefinitionLord, boolean verifyFileExists )
{
this.fileLinkDefinitionLord = fileLinkDefinitionLord;
this.verifyFileExists = verifyFileExists;
}
public boolean isVerifyFileExists() { return verifyFileExists; }
public FileLinkDefinitionLord getFileLinkDefinitionLord() { return fileLinkDefinitionLord; }
/**
This parses the text looking for file links
@param text the text to parse
@return a list of FileLinks for each file that was found in the text.
*/
public List<FileLink> parseText( String text )
{
List<FileLink> fileLinks = new ArrayList<FileLink>();
Pattern combinedSearchPattern = fileLinkDefinitionLord.getSearchPattern();
Matcher matcher = combinedSearchPattern.matcher( text );
int index = 0;
boolean foundAMatch = matcher.find( index );
while( foundAMatch )
{
// Retrieve matching string
String matchedText = matcher.group();
// Retrieve indices of matching string
int start = matcher.start();
int end = matcher.end();
int nextStarting = start;
//now that we have a match, we have to find the one FileLinkDefinition that actually matches so it
//can determine the actual file. This makes the matcher more plugable.
FileLinkDefinition fileLinkDefinition = fileLinkDefinitionLord.getMatchingFileLinkDefinition( matchedText );
if( fileLinkDefinition != null )
{
nextStarting = fileLinkDefinition.parseFileLink( text, matchedText, start, end, verifyFileExists, fileLinks );
}
else
{
//this is probably a serious problem that needs to be reported. However, we'll continue as if nothing bad happened.
System.out.println( "We found a match but didn't find the matching definition. Matched text:\n" + text );
}
if( nextStarting == -1 || nextStarting < start )
{
nextStarting = start;
}
index = nextStarting + 1;
if( index < text.length() )
{
foundAMatch = matcher.find( index );
}
else
{
foundAMatch = false; //don't continue searching if we've found the end
}
}
return fileLinks;
}
}