package net.sourceforge.squirrel_sql.client.util.codereformat;
/*
* Copyright (C) 2003 Gerd Wagner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
import java.util.Vector;
public class CodeReformatorKernel
{
private String _statementSeparator;
private CommentSpec[] _commentSpecs;
private PieceMarkerSpec[] _pieceSpecs;
private StateOfPosition[] _statesOfPosition;
public CodeReformatorKernel(String statementSeparator, PieceMarkerSpec[] pieceSpecs, CommentSpec[] commentSpecs)
{
_commentSpecs = commentSpecs;
_pieceSpecs = pieceSpecs;
_statementSeparator = statementSeparator;
}
public String[] toPieces(String in)
{
_statesOfPosition = getStatesOfPosition(in);
Vector<String> ret = new Vector<String>();
// toUpperCase replaces the German ß by ss.
// This will kill reformating later.
// Since upperIn is just for building pieces
// it is OK to place ß here.
String upperIn = in.replaceAll("ß", "s");
upperIn = upperIn.toUpperCase();
int begin = 0;
while(begin < in.length())
{
Piece p = getNextToplevelPiece(begin, upperIn);
if(null == p.spec)
{
ret.add(in.substring(begin).trim());
begin = in.length();
}
else
{
int type = p.spec.getType();
switch(type)
{
case PieceMarkerSpec.TYPE_PIECE_MARKER_AT_BEGIN:
if(begin < p.beginsAt && 0 < in.substring(begin, p.beginsAt).trim().length())
{
ret.add(in.substring(begin, p.beginsAt).trim());
}
int afterPieceMarker = p.beginsAt + p.spec.getLengthRightSpaced();
Piece nextP = getNextToplevelPiece(afterPieceMarker, upperIn);
if(null == nextP.spec)
{
ret.add( in.substring(p.beginsAt).trim() );
begin = in.length();
}
else
{
if(PieceMarkerSpec.TYPE_PIECE_MARKER_AT_END == nextP.spec.getType())
{
if(nextP.beginsAt + nextP.spec.getLengthRightSpaced() < in.length())
{
ret.add( in.substring(p.beginsAt, nextP.beginsAt + nextP.spec.getLengthRightSpaced()).trim() );
}
else
{
ret.add( in.substring(p.beginsAt).trim() );
}
begin = nextP.beginsAt + nextP.spec.getLengthRightSpaced();
}
else
{
ret.add( in.substring(p.beginsAt, nextP.beginsAt).trim() );
begin = nextP.beginsAt;
}
}
break;
case PieceMarkerSpec.TYPE_PIECE_MARKER_AT_END:
if(p.beginsAt + p.spec.getLengthRightSpaced() < in.length())
{
ret.add( in.substring(begin, p.beginsAt + p.spec.getLengthRightSpaced() ).trim() );
}
else
{
ret.add( in.substring(begin).trim() );
}
begin = p.beginsAt + p.spec.getLengthRightSpaced();
break;
case PieceMarkerSpec.TYPE_PIECE_MARKER_IN_OWN_PIECE:
if(begin < p.beginsAt && 0 < in.substring(begin, p.beginsAt).trim().length())
{
ret.add(in.substring(begin, p.beginsAt).trim());
}
if(p.beginsAt + p.spec.getLengthRightSpaced() < in.length())
{
ret.add( in.substring(p.beginsAt, p.beginsAt + p.spec.getLengthRightSpaced() ).trim() );
}
else
{
ret.add( in.substring(p.beginsAt).trim() );
}
begin = p.beginsAt + p.spec.getLengthRightSpaced();
break;
}
}
}
return ret.toArray(new String[ret.size()]);
}
private Piece getNextToplevelPiece(int startAt, String in)
{
Piece ret = new Piece();
ret.beginsAt = in.length();
for(int i=0; i < _pieceSpecs.length; ++i)
{
int buf = getTopLevelIndex(startAt, in, _pieceSpecs[i]);
if(-1 < buf && buf < ret.beginsAt)
{
ret.spec = _pieceSpecs[i];
ret.beginsAt = buf;
}
}
if(null == ret.spec)
{
ret.beginsAt = startAt;
}
return ret;
}
private int getTopLevelIndex(int startAt, String in, PieceMarkerSpec pieceSpec)
{
int ix = in.indexOf(pieceSpec.getPieceMarker(), startAt);
while(-1 != ix)
{
if(_statesOfPosition[ix].isTopLevel)
{
if(pieceSpec.needsSuroundingWhiteSpaces())
{
char before = (0 == ix ? ' ': in.charAt(ix-1) );
int pieceMArkerEnd = ix + pieceSpec.getPieceMarker().length() - 1;
char after = (pieceMArkerEnd == in.length() - 1 ? ' ': in.charAt(pieceMArkerEnd+1) );
if(Character.isWhitespace(before) && Character.isWhitespace(after))
{
return ix;
}
}
else
{
return ix;
}
}
ix = in.indexOf(pieceSpec.getPieceMarker(), ix + 1);
}
return -1;
}
public StateOfPosition[] getStatesOfPosition(String in)
{
StateOfPosition[] ret = new StateOfPosition[in.length()];
StateOfPosition buf = new StateOfPosition();
for(int i=0; i < in.length(); ++i)
{
if('\'' == in.charAt(i))
{
++buf.literalSepCount;
}
if(0 == buf.literalSepCount % 2)
{
for(int j=0; j < _commentSpecs.length; ++j)
{
if(in.substring(i).startsWith(_commentSpecs[j].commentBegin))
{
if(-1 == buf.commentIndex)
{
buf.commentIndex = j;
}
}
if(in.substring(i).startsWith(_commentSpecs[j].commentEnd))
{
if(j == buf.commentIndex)
{
buf.commentIndex = -1;
}
}
}
}
if(0 == buf.literalSepCount % 2 && -1 == buf.commentIndex)
{
if('(' == in.charAt(i))
{
++buf.braketDepth;
}
if(')' == in.charAt(i))
{
--buf.braketDepth;
}
}
if(
-1 == buf.commentIndex
&& 0 == buf.literalSepCount % 2
&& 0 == buf.braketDepth
)
{
buf.isTopLevel = true;
}
else
{
buf.isTopLevel = false;
}
ret[i] = (StateOfPosition)buf.clone();
}
return ret;
}
}