/*
* Copyright (C) 2001, 2002 Robert MacGrogan
*
* This library 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 library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* $Archive: SourceJammer$
* $FileName: KeywordExpander.java$
* $FileID: 4474$
*
* Last change:
* $AuthorName: Rob MacGrogan$
* $Date: 9/1/03 9:26 PM$
* $Comment: Remove debug messages.$
*/
package org.sourcejammer.server.keywords;
import java.util.Vector;
import java.util.Iterator;
import org.sourcejammer.util.BufferedLineReader;
import java.io.IOException;
import org.sourcejammer.project.controller.FileNode;
/**
* Title: $FileName: KeywordExpander.java$
* @version $VerNum: 4$
* @author $AuthorName: Rob MacGrogan$<br><br>
*
* $Description: Parse and expand keywords.$<br>
* $KeyWordsOff: $
*/
public abstract class KeywordExpander implements KeywordTags{
/**
* Expand any keywords in current line.
*
* @return Number of characters in all Strings added to lines Vector.
*/
public abstract int expand(String line, int keywordBeginIndex,
Vector lines, ProjectObjects obj,
BufferedLineReader reader)
throws KeywordExpansionException, IOException;
public int getSeparatorIndex(int keywordBeginIndex, String keyword){
return keywordBeginIndex + (keyword.length() - 1);
}
public String getBeginNewLine(int keywordBeginIndex, String line){
return line.substring(0, keywordBeginIndex);
}
public String getBeginNewLineIndent(int keywordBeginIndex, String line, String keyword){
char[] spaces = new char[keyword.length()];
java.util.Arrays.fill(spaces, ' ');
return getBeginNewLine(keywordBeginIndex, line) + new String(spaces);
}
/**
* separatorIndex is index of separator char for keyword. Look for end of keyword value marker either in
* line or in a subsequent line returned from reader. Replace keyword value iwth
* value. Convert to a series of one or m ore lines which are then
* added to Vector.
*/
protected int replaceKeywordWithValue(int separatorIndex, String value,
Vector lines, String line,
BufferedLineReader reader, String commentStyle)
throws KeywordExpansionException, IOException{
int iNumChars = 0;
int iBeginValueIndex = separatorIndex + 1;
//First check if end of keyword marker is found in line.
int iValueEndIndex = line.indexOf(KEYWORD_INDICATOR, iBeginValueIndex);
if (iValueEndIndex > -1 ){
//Found end of value marker in line. No need for subsequent lines.
iNumChars = replaceSingleLine(line, iBeginValueIndex, iValueEndIndex, lines, value, commentStyle);
}
else{
iNumChars = replaceMultiLine(line, iBeginValueIndex, lines, value, reader, commentStyle);
}
return iNumChars;
}
/**
* Replaces multiple lines in text file with keyword value.
*/
private int replaceMultiLine(String line, int iBeginValueIndex,
Vector lines, String value,
BufferedLineReader reader,
String commentStyle)
throws KeywordExpansionException, IOException{
//We need to scroll through subsequent lines looking for end of
//value marker. Since we are replacing everything before the marker,
//we can ignore any lines that don't contain the marker. All we need
//are the first and final lines.
//Also, if we don't find the marker anywhere in the file, we will throw
//an exception. The add/check in operation will be hosed and user will
//be required to correct the keyword problem before the add/checkin
//can be completed.
int iNumChars = 0;
boolean bIndicatorFound = false;
String nextLine = line;
while (! bIndicatorFound){
if (nextLine != null){
//Look for indicator.
int iValueEndIndex = -1;
if (nextLine == line){
//It's the first line.
nextLine.indexOf(KEYWORD_INDICATOR, iBeginValueIndex);
}
else {
iValueEndIndex = nextLine.indexOf(KEYWORD_INDICATOR);
}
if (iValueEndIndex > -1){
//Found it.
String endLine = nextLine.substring(iValueEndIndex);
String beginLine = line.substring(0, iBeginValueIndex);
iNumChars = addValue(beginLine, endLine, value, lines, commentStyle);
bIndicatorFound = true;
}
}//end if nextLine not null
else{
//end of file before indicator found. Throw exception.
throw new KeywordExpansionException("End of file reached before end of keyword indicator found.");
}
if (! bIndicatorFound ){
nextLine = reader.readLine();
}
}//end while
return iNumChars;
}
/**
* Replaces value in a single line with keyword value.
*/
private int replaceSingleLine(String line, int iBeginValueIndex,
int iValueEndIndex,
Vector lines, String value,
String commentStyle)
throws KeywordExpansionException{
String beginLine = line.substring(0, iBeginValueIndex);
String endLine = line.substring(iValueEndIndex);
return addValue(beginLine, endLine, value, lines, commentStyle);
}
/**
* Adds the value to the lines Vector.
*/
private int addValue(String beginLine, String endLine, String value,
Vector lines, String commentStyle)
throws KeywordExpansionException{
String expandedLine = beginLine + " " + value + endLine;
boolean bCommentFirstLine = (beginLine.length() <= 0);
int iTestLineLength = expandedLine.length();
if (iTestLineLength <= LINE_MAX_LENGTH){
lines.add(expandedLine);
}
else {
Iterator itrFormattedLines = formatLines(commentStyle, expandedLine, bCommentFirstLine);
while (itrFormattedLines.hasNext()){
lines.add(itrFormattedLines.next());
}
}
return iTestLineLength;
}
protected Iterator formatLines(String commentStyle, String unformattedLines,
boolean commentFirstLine){
Vector lineBuilder = new Vector();
int iStartLineIndex= 0;
int iLineLengthMinusComment = LINE_MAX_LENGTH - commentStyle.length();
boolean bContinue = true;
boolean bFirstLine = true;
while (bContinue){
int iEndLineIndex = iStartLineIndex + iLineLengthMinusComment;
int iSpaceIndex = unformattedLines.lastIndexOf(SPACE, iEndLineIndex);
int iCRIndex = unformattedLines.indexOf("\r", iStartLineIndex);
int iLFIndex = unformattedLines.indexOf("\n", iStartLineIndex);
if (iEndLineIndex >= unformattedLines.length() || iSpaceIndex == -1){
iSpaceIndex = unformattedLines.length();
}
if (iCRIndex < iSpaceIndex && iCRIndex != -1){
//Carriage Return found in line.
iEndLineIndex = iCRIndex;
}
else if (iLFIndex < iSpaceIndex && iLFIndex != -1){
//Line Feed found in line.
iEndLineIndex = iLFIndex;
}
else if (iSpaceIndex > iStartLineIndex){
//Space found in line.
iEndLineIndex = iSpaceIndex;
}
else{
//Space, CR, and LF not found in line.
iEndLineIndex = unformattedLines.indexOf(SPACE, iEndLineIndex);
if (iEndLineIndex < 0){
iEndLineIndex = unformattedLines.length();
}//end if no space found after max characters.
}
String line = unformattedLines.substring(iStartLineIndex, iEndLineIndex);
if (! bFirstLine || commentFirstLine){
line = commentStyle + line;
}
bFirstLine = false;
lineBuilder.add(line);
iStartLineIndex = iEndLineIndex; //add one to skip the space.
//Skip past any CR or LF.
if (iStartLineIndex < unformattedLines.length()){
char checkChr = unformattedLines.charAt(iStartLineIndex);
int crCount = 0;
int lfCount = 0;
while (checkChr == '\r' ||
checkChr == '\n' ||
checkChr == ' '){
iStartLineIndex++;
if (checkChr == '\r'){
crCount++;
}
if (checkChr == '\n'){
lfCount++;
}
if ( (crCount > 1 || lfCount > 1) &&
crCount != lfCount &&
(checkChr == '\r' || checkChr == '\n')){
//Means we need to add a blank line.
lineBuilder.add(commentStyle);
}
if (iStartLineIndex >= unformattedLines.length()){
break;
}
checkChr = unformattedLines.charAt(iStartLineIndex);
}//end while
}
if (iStartLineIndex >= unformattedLines.length()){
bContinue = false;
}
}//end while
return lineBuilder.iterator();
}
/*
public static void main(String[] args){
try{
String s = "This is a very very very long string. Check it out! This is a very very very long string. Check it out! This is a very very very long string. Check it out! \r\n\r\nThis is a very very very long string. Check it out! This is a very very very long string. Check it out! This is a very very very long string. Check it out!\r\n\r\nThis is a very very very long string. Check it out! This is a very very very long string. Check it out! ";
System.out.println("got line. Calling formatLines");
Iterator itr = formatLines("", s, true);
System.out.println();
System.out.println();
while (itr.hasNext()){
System.out.println(itr.next());
}
}
catch(Throwable thr){
thr.printStackTrace();
}
}
*/
}
|