/* * 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.sql.symbol; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.teiid.core.TeiidProcessingException; import org.teiid.core.types.DataTypeManager; import org.teiid.core.util.EquivalenceUtil; import org.teiid.core.util.HashCodeUtil; import org.teiid.core.util.StringUtil; import org.teiid.query.QueryPlugin; import org.teiid.query.sql.LanguageObject; import org.teiid.query.sql.LanguageVisitor; import org.teiid.query.sql.visitor.SQLStringVisitor; /** * Represents the only allowable expression for the textagg aggregate. * This is a Teiid specific construct. */ public class TextLine implements Expression { public static final String nl = System.getProperty("line.separator"); //$NON-NLS-1$ public static final char NO_QUOTE_CHAR = 0; private Character delimiter; private Character quote; private boolean includeHeader; private List<DerivedColumn> expressions; private String encoding; private String lineEnding = nl; public Character getDelimiter() { return delimiter; } public void setDelimiter(Character delimiter) { this.delimiter = delimiter; } public String getEncoding() { return encoding; } public void setEncoding(String encoding) { this.encoding = encoding; } public Character getQuote() { return quote; } public void setQuote(Character quote) { this.quote = quote; } public boolean isIncludeHeader() { return includeHeader; } public void setIncludeHeader(boolean includeHeader) { this.includeHeader = includeHeader; } public List<DerivedColumn> getExpressions() { return expressions; } public void setExpressions(List<DerivedColumn> expressions) { this.expressions = expressions; } public String getLineEnding() { return lineEnding; } public void setLineEnding(String lineEnding) { this.lineEnding = lineEnding; } @Override public Class<?> getType() { return String[].class; } @Override public void acceptVisitor(LanguageVisitor visitor) { visitor.visit(this); } @Override public TextLine clone() { TextLine clone = new TextLine(); clone.expressions = LanguageObject.Util.deepClone(this.expressions, DerivedColumn.class); clone.delimiter = this.delimiter; clone.quote = this.quote; clone.includeHeader = this.includeHeader; clone.encoding = this.encoding; return clone; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof TextLine)) { return false; } TextLine other = (TextLine)obj; return EquivalenceUtil.areEqual(this.expressions, other.expressions) && EquivalenceUtil.areEqual(this.delimiter, other.delimiter) && EquivalenceUtil.areEqual(this.quote, other.quote) && this.includeHeader == other.includeHeader && EquivalenceUtil.areEqual(this.encoding, other.encoding); } @Override public int hashCode() { return HashCodeUtil.expHashCode(0, this.expressions); } @Override public String toString() { return SQLStringVisitor.getSQLString(this); } public static interface ValueExtractor<T> { Object getValue(T t); } public static <T> String[] evaluate(final List<T> values, ValueExtractor<T> valueExtractor, TextLine textLine) throws TeiidProcessingException { Character delimeter = textLine.getDelimiter(); if (delimeter == null) { delimeter = Character.valueOf(','); } String delim = String.valueOf(delimeter.charValue()); Character quote = textLine.getQuote(); String quoteStr = null; if (quote == null) { quoteStr = "\""; //$NON-NLS-1$ } else if (quote.charValue() != NO_QUOTE_CHAR) { quoteStr = String.valueOf(quote); } String doubleQuote = null; if (quoteStr != null) { doubleQuote = quoteStr + quoteStr; } ArrayList<String> result = new ArrayList<String>(); for (Iterator<T> iterator = values.iterator(); iterator.hasNext();) { T t = iterator.next(); String text = (String)DataTypeManager.transformValue(valueExtractor.getValue(t), DataTypeManager.DefaultDataClasses.STRING); if (text != null) { if (quoteStr != null) { result.add(quoteStr); result.add(StringUtil.replaceAll(text, quoteStr, doubleQuote)); result.add(quoteStr); } else { if (text.indexOf(delimeter) > -1 || text.indexOf(textLine.getLineEnding()) > -1) { throw new TeiidProcessingException(QueryPlugin.Event.TEIID31201, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31201, text)); } result.add(text); } } if (iterator.hasNext()) { result.add(delim); } } result.add(textLine.getLineEnding()); return result.toArray(new String[result.size()]); } }