/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.query.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.sql.Clob;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TimeZone;
import java.util.regex.Pattern;
import javax.security.auth.Subject;
import org.teiid.core.types.ClobImpl;
import org.teiid.core.types.InputStreamFactory;
import org.teiid.core.util.LRUCache;
import org.teiid.designer.runtime.version.spi.ITeiidServerVersion;
import org.teiid.metadata.FunctionMethod.Determinism;
/**
* Defines the context that a command is processing in. For example, this defines
* who is processing the command and why. Also, this class (or subclasses) provide
* a means to pass context-specific information between users of the query processor
* framework.
*/
public class CommandContext implements Cloneable, org.teiid.CommandContext {
private static class GlobalState implements Cloneable {
private Random random = null;
private LRUCache<String, DecimalFormat> decimalFormatCache;
private LRUCache<String, SimpleDateFormat> dateFormatCache;
private LRUCache<Entry<String,Integer>, Pattern> patternCache;
}
private GlobalState globalState = new GlobalState();
private Determinism[] determinismLevel = new Determinism[] {Determinism.DETERMINISTIC};
private VariableContext variableContext = new VariableContext();
private final ITeiidServerVersion teiidVersion;
public CommandContext(ITeiidServerVersion teiidVersion) {
this.teiidVersion = teiidVersion;
}
/**
* @return teiid version
*/
public ITeiidServerVersion getTeiidVersion() {
return teiidVersion;
}
public VariableContext getVariableContext() {
return variableContext;
}
public Determinism getDeterminismLevel() {
return determinismLevel[0];
}
public void setDeterminismLevel(Determinism level) {
if (determinismLevel[0] == null || level.compareTo(determinismLevel[0]) < 0) {
determinismLevel[0] = level;
}
}
@Override
public double getNextRand() {
if (globalState.random == null) {
globalState.random = new Random();
}
return globalState.random.nextDouble();
}
@Override
public double getNextRand(long seed) {
if (globalState.random == null) {
globalState.random = new Random();
}
globalState.random.setSeed(seed);
return globalState.random.nextDouble();
}
public static DecimalFormat getDecimalFormat(CommandContext context, String format) {
DecimalFormat result = null;
if (context != null) {
if (context.globalState.decimalFormatCache == null) {
context.globalState.decimalFormatCache = new LRUCache<String, DecimalFormat>(32);
} else {
result = context.globalState.decimalFormatCache.get(format);
}
}
if (result == null) {
result = new DecimalFormat(format); //TODO: could be locale sensitive
result.setParseBigDecimal(true);
if (context != null) {
context.globalState.decimalFormatCache.put(format, result);
}
}
return result;
}
public static SimpleDateFormat getDateFormat(CommandContext context, String format) {
SimpleDateFormat result = null;
if (context != null) {
if (context.globalState.dateFormatCache == null) {
context.globalState.dateFormatCache = new LRUCache<String, SimpleDateFormat>(32);
} else {
result = context.globalState.dateFormatCache.get(format);
}
}
if (result == null) {
result = new SimpleDateFormat(format); //TODO: could be locale sensitive
if (context != null) {
context.globalState.dateFormatCache.put(format, result);
}
}
return result;
}
/**
* Compile a regular expression into a {@link java.util.regex.Pattern} and cache it in
* the {@link CommandContext} for future use.
*
* @param context
* @param regex Regular expression.
* @param flags Bitmask flags like {@link java.util.regex.Pattern#CASE_INSENSITIVE}.
* @return Compiled regex.
*/
public static Pattern getPattern(CommandContext context, String regex, int flags) {
Pattern result = null;
if (context != null) {
if (context.globalState.patternCache == null) {
context.globalState.patternCache = new LRUCache<Entry<String,Integer>,Pattern>(32);
} else {
result = context.globalState.patternCache.get(new SimpleEntry(result, flags));
}
}
if (result == null) {
result = Pattern.compile(regex, flags);
if (context != null) {
context.globalState.patternCache.put(new SimpleEntry(result, flags), result);
}
}
return result;
}
/**
* Used by the system table logic
* @return a clob
*/
public Clob getSpatialSysRef() {
return new ClobImpl(new InputStreamFactory() {
@Override
public InputStream getInputStream() {
return getClass().getClassLoader().getResourceAsStream("org/teiid/metadata/spatial_ref_sys.csv"); //$NON-NLS-1$
}
}, -1);
}
@Override
public String getUserName() {
throw new UnsupportedOperationException();
}
@Override
public String getVdbName() {
throw new UnsupportedOperationException();
}
@Override
public int getVdbVersion() {
throw new UnsupportedOperationException();
}
@Override
public String getConnectionId() {
throw new UnsupportedOperationException();
}
@Deprecated
@Override
public String getConnectionID() {
throw new UnsupportedOperationException();
}
@Override
public int getProcessorBatchSize() {
throw new UnsupportedOperationException();
}
@Override
public TimeZone getServerTimeZone() {
throw new UnsupportedOperationException();
}
@Override
public Subject getSubject() {
throw new UnsupportedOperationException();
}
@Override
public Serializable getCommandPayload() {
throw new UnsupportedOperationException();
}
@Override
public String getRequestId() {
throw new UnsupportedOperationException();
}
@Override
public long getReuseCount() {
throw new UnsupportedOperationException();
}
@Override
public ClassLoader getVDBClassLoader() {
throw new UnsupportedOperationException();
}
@Override
public void addWarning(Exception ex) {
throw new UnsupportedOperationException();
}
@Override
public boolean isContinuous() {
throw new UnsupportedOperationException();
}
@Override
public boolean isReturnAutoGeneratedKeys() {
throw new UnsupportedOperationException();
}
@Override
public int getSessionVariableCount() {
throw new UnsupportedOperationException();
}
@Override
public Object setSessionVariable(String key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public Object getSessionVariable(String key) {
throw new UnsupportedOperationException();
}
/**
* Used by the system table logic
* @return
*/
public Clob getSpatialRefSys() {
return new ClobImpl(new InputStreamFactory() {
@Override
public InputStream getInputStream() throws IOException {
return getClass().getClassLoader().getResourceAsStream("org/teiid/metadata/spatial_ref_sys.csv"); //$NON-NLS-1$
}
}, -1);
}
public void addCreatedLob(InputStreamFactory isf) {
// Do Nothing
}
public void disableAutoCleanLobs() {
// Do Nothing
}
}