/* * Copyright (c) 2013-2017 Cinchapi Inc. * * 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 com.cinchapi.concourse.lang; import java.text.MessageFormat; import java.util.List; import com.cinchapi.concourse.thrift.TCriteria; import com.cinchapi.concourse.thrift.TSymbol; import com.cinchapi.concourse.thrift.TSymbolType; import com.google.common.collect.Lists; /** * Tools for translating aspects of the language. * * @author Jeff Nelson */ public final class Language { /** * Translate the {@link TSymbol} to its Java analog. * * @param tsymbol * @return the analogous Symbol */ public static Symbol translateFromThriftSymbol(TSymbol tsymbol) { if(tsymbol.getType() == TSymbolType.CONJUNCTION) { return ConjunctionSymbol.valueOf(tsymbol.getSymbol().toUpperCase()); } else if(tsymbol.getType() == TSymbolType.KEY) { return KeySymbol.parse(tsymbol.getSymbol()); } else if(tsymbol.getType() == TSymbolType.VALUE) { return ValueSymbol.parse(tsymbol.getSymbol()); } else if(tsymbol.getType() == TSymbolType.PARENTHESIS) { return ParenthesisSymbol.parse(tsymbol.getSymbol()); } else if(tsymbol.getType() == TSymbolType.OPERATOR) { return OperatorSymbol.parse(tsymbol.getSymbol()); } else if(tsymbol.getType() == TSymbolType.TIMESTAMP) { return TimestampSymbol.parse(tsymbol.getSymbol()); } else { throw new IllegalArgumentException("Unrecognized TSymbol " + tsymbol); } } /** * Translate the {@code criteria} to its Thrift analog. * * @param criteria * @return the analogous TCriteria */ public static TCriteria translateToThriftCriteria(Criteria criteria) { List<TSymbol> symbols = Lists.newArrayList(); for (Symbol symbol : criteria.getSymbols()) { symbols.add(translateToThriftSymbol(symbol)); } return new TCriteria(symbols); } /** * Translate the {@code tcriteria} to its Java analog. * * @param tcriteria * @return the analogous Java {@link Criteria} */ public static Criteria translateFromThriftCriteria(TCriteria tcriteria) { Criteria criteria = new Criteria(); for (TSymbol tsymbol : tcriteria.getSymbols()) { criteria.add(translateFromThriftSymbol(tsymbol)); } return criteria; } /** * Translate {@code symbol} to its Thrift analog. * * @param symbol * @return The analogous TSymbol */ public static TSymbol translateToThriftSymbol(Symbol symbol) { if(symbol.getClass() == ConjunctionSymbol.class) { return new TSymbol(TSymbolType.CONJUNCTION, symbol.toString()); } else if(symbol.getClass() == KeySymbol.class) { return new TSymbol(TSymbolType.KEY, symbol.toString()); } else if(symbol.getClass() == ValueSymbol.class) { return new TSymbol(TSymbolType.VALUE, escape(symbol.toString())); } else if(symbol.getClass() == ParenthesisSymbol.class) { return new TSymbol(TSymbolType.PARENTHESIS, symbol.toString()); } else if(symbol.getClass() == OperatorSymbol.class) { return new TSymbol(TSymbolType.OPERATOR, symbol.toString()); } else if(symbol.getClass() == TimestampSymbol.class) { return new TSymbol(TSymbolType.TIMESTAMP, symbol.toString()); } else { throw new IllegalArgumentException(MessageFormat.format( "Cannot translate {0} to Thrift", symbol)); } } /** * Do any escaping of the {@code value} in order to preserve it during the * translation. * * @param value * @return the escaped value */ private static String escape(String value) { if(value.matches("`([^`]+)`")) { // CON-167: surround by quotes so the // backticks are not interpreted as // indicators of an encoded Tag. This // case would happen if the user // manually placed text wrapped in // backticks in the Criteria instead of // using the #Tag.create() method. return "\"" + value + "\""; } else { return value; } } private Language() {/* noop */} }