/*****************************************************************************
* Copyright (C) 2008 EnterpriseDB Corporation.
* Copyright (C) 2011 Stado Global Development Group.
*
* This file is part of Stado.
*
* Stado 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 3 of the License, or
* (at your option) any later version.
*
* Stado 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 Stado. If not, see <http://www.gnu.org/licenses/>.
*
* You can find Stado at http://www.stado.us
*
****************************************************************************/
package org.postgresql.stado.parser.handler;
import org.postgresql.stado.common.util.Props;
import org.postgresql.stado.parser.core.syntaxtree.Identifier;
import org.postgresql.stado.parser.core.syntaxtree.NodeToken;
import org.postgresql.stado.parser.core.syntaxtree.UnreservedWords;
import org.postgresql.stado.parser.core.visitor.DepthFirstRetArguVisitor;
/**
* @author amart
*
*/
public class IdentifierHandler extends DepthFirstRetArguVisitor {
public static String quote(String identifier) {
StringBuffer sbQuoted = new StringBuffer(identifier.length() * 2 + 2);
sbQuoted.append(Props.XDB_IDENTIFIER_QUOTE_OPEN);
int pos = 0;
for (int quotePos = identifier.indexOf(Props.XDB_IDENTIFIER_QUOTE_CLOSE);
quotePos != -1; quotePos = identifier.indexOf(Props.XDB_IDENTIFIER_QUOTE_CLOSE, pos)) {
if (quotePos > pos) {
sbQuoted.append(identifier.substring(pos, quotePos - 1));
}
sbQuoted.append(Props.XDB_IDENTIFIER_QUOTE_ESCAPE);
sbQuoted.append(Props.XDB_IDENTIFIER_QUOTE_CLOSE);
pos = quotePos + 1;
}
sbQuoted.append(identifier.substring(pos));
sbQuoted.append(Props.XDB_IDENTIFIER_QUOTE_CLOSE);
return sbQuoted.toString();
}
public static String stripQuotes(String identifier) {
if (identifier.length() >= 2 && identifier.startsWith(Props.XDB_IDENTIFIER_QUOTE_OPEN)
&& identifier.endsWith(Props.XDB_IDENTIFIER_QUOTE_CLOSE)) {
identifier = identifier.substring(1, identifier.length() - 1);
StringBuffer newImage = new StringBuffer();
int pos = 0;
for (int quotePos = identifier.indexOf(Props.XDB_IDENTIFIER_QUOTE_OPEN); quotePos != -1;
quotePos = identifier.indexOf(Props.XDB_IDENTIFIER_QUOTE_OPEN, pos)) {
int endPos = identifier.indexOf(Props.XDB_IDENTIFIER_QUOTE_CLOSE);
if (endPos >= 0) {
newImage.append(identifier.substring(pos, endPos + 1));
}
pos = quotePos + 1 + Props.XDB_IDENTIFIER_QUOTE_CLOSE.length();
}
newImage.append(identifier.substring(pos));
return newImage.toString();
}
return identifier;
}
public static String normalizeCase(String identifier) {
if (Props.XDB_IDENTIFIER_CASE == Props.XDB_IDENTIFIER_CASE_LOWER) {
return identifier.toLowerCase();
} else if (Props.XDB_IDENTIFIER_CASE == Props.XDB_IDENTIFIER_CASE_UPPER) {
return identifier.toUpperCase();
} else {
return identifier;
}
}
private String identifier = null;
/**
* Grammar production:
* f0 -> <IDENTIFIER>
* | <QUOTED_IDENTIFIER>
* | UnreservedWords(prn)
*/
@Override
public Object visit(Identifier n, Object argu) {
switch (n.f0.which) {
case 0:
identifier = normalizeCase(((NodeToken) n.f0.choice).tokenImage);
break;
case 1:
identifier = stripQuotes(((NodeToken) n.f0.choice).tokenImage);
break;
case 2:
identifier = normalizeCase((String) n.f0.choice.accept(this, argu));
break;
}
return identifier;
}
/**
* Grammar production:
* f0 -> <POSITION_>
* | <DATE_>
* | <DAY_>
* -snip-
* | <REGEXP_REPLACE_>
*/
@Override
public Object visit(UnreservedWords n, Object argu) {
return ((NodeToken) n.f0.choice).tokenImage;
}
public String getIdentifier() {
return identifier;
}
}