/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * 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.jkiss.dbeaver.ui.editors.sql.syntax; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.StringTokenizer; /** * Determines whether a given character is valid as part of an SQL identifier. */ public class SQLIdentifierDetector extends SQLWordDetector { private char structSeparator; private final String quoteSymbol; public SQLIdentifierDetector(char structSeparator, String quoteSymbol) { this.structSeparator = structSeparator; this.quoteSymbol = quoteSymbol; } protected boolean isQuote(char c) { return quoteSymbol != null && quoteSymbol.indexOf(c) != -1; } public boolean containsSeparator(String identifier) { return identifier.indexOf(structSeparator) != -1; } public List<String> splitIdentifier(String identifier) { if (!containsSeparator(identifier)) { return Collections.singletonList(identifier); } List<String> tokens = new ArrayList<>(); StringTokenizer st = new StringTokenizer(identifier, String.valueOf(structSeparator)); while (st.hasMoreTokens()) { tokens.add(st.nextToken()); } return tokens; } @Override public boolean isWordPart(char c) { return super.isWordPart(c) || isQuote(c) || structSeparator == c; } public boolean isPlainWordPart(char c) { return super.isWordPart(c); } public boolean isQuoted(String token) { return quoteSymbol != null && !quoteSymbol.isEmpty() && token.startsWith(quoteSymbol); } public String removeQuotes(String name) { if (quoteSymbol == null || quoteSymbol.isEmpty()) { return name; } if (name.startsWith(quoteSymbol)) { name = name.substring(quoteSymbol.length()); } if (name.endsWith(quoteSymbol)) { name = name.substring(0, name.length() - quoteSymbol.length()); } return name; } public WordRegion detectIdentifier(IDocument document, IRegion region) { final WordRegion id = new WordRegion(region.getOffset()); int docLength = document.getLength(); try { if (!isPlainWordPart(document.getChar(region.getOffset()))) { return id; } while (id.identStart >= 0) { char ch = document.getChar(id.identStart); if (!isWordPart(ch)) { break; } if (id.wordStart < 0 && !isPlainWordPart(ch)) { id.wordStart = id.identStart + 1; } id.identStart--; } id.identStart++; while (id.identEnd < docLength) { char ch = document.getChar(id.identEnd); if (!isWordPart(ch)) { break; } if (!isPlainWordPart(ch)) { id.wordEnd = id.identEnd; } id.identEnd++; } id.extract(document); } catch (BadLocationException e) { // ignore } return id; } public static class WordRegion { public int identStart; public int identEnd; public int wordStart = -1, wordEnd = -1; public String identifier = ""; public String word = ""; WordRegion(int offset) { identStart = offset; identEnd = offset; } void extract(IDocument document) throws BadLocationException { if (wordStart < 0) wordStart = identStart; if (wordEnd < 0) wordEnd = identEnd; identifier = document.get(identStart, identEnd - identStart); word = document.get(wordStart, wordEnd - wordStart); } public boolean isEmpty() { return word.isEmpty(); } } }