/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.hadoop.hive.ql.udf.generic;
import java.util.HashSet;
import java.util.Set;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.serde.serdeConstants;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.apache.hadoop.io.Text;
/**
* Mimics oracle's function translate(str1, str2, str3).
*/
@Description(name = "test_translate",
value = "_FUNC_(str1, str2, str3) - Mimics oracle's function translate(str1, str2, str3)")
public class GenericUDFTestTranslate extends GenericUDF {
private transient ObjectInspector[] argumentOIs;
/**
* Return a corresponding ordinal from an integer.
*/
static String getOrdinal(int i) {
int unit = i % 10;
return (i <= 0) ? "" : (i != 11 && unit == 1) ? i + "st"
: (i != 12 && unit == 2) ? i + "nd" : (i != 13 && unit == 3) ? i + "rd"
: i + "th";
}
@Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
if (arguments.length != 3) {
throw new UDFArgumentLengthException(
"The function TRANSLATE(expr,from_string,to_string) accepts exactly 3 arguments, but "
+ arguments.length + " arguments is found.");
}
for (int i = 0; i < 3; i++) {
if (arguments[i].getTypeName() != serdeConstants.STRING_TYPE_NAME
&& arguments[i].getTypeName() != serdeConstants.VOID_TYPE_NAME) {
throw new UDFArgumentTypeException(i, "The " + getOrdinal(i + 1)
+ " argument of function TRANSLATE is expected to \""
+ serdeConstants.STRING_TYPE_NAME + "\", but \""
+ arguments[i].getTypeName() + "\" is found");
}
}
argumentOIs = arguments;
return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
}
private final Text resultText = new Text();
@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
if (arguments[0].get() == null || arguments[1].get() == null
|| arguments[2].get() == null) {
return null;
}
String exprString = ((StringObjectInspector) argumentOIs[0])
.getPrimitiveJavaObject(arguments[0].get());
String fromString = ((StringObjectInspector) argumentOIs[1])
.getPrimitiveJavaObject(arguments[1].get());
String toString = ((StringObjectInspector) argumentOIs[2])
.getPrimitiveJavaObject(arguments[2].get());
char[] expr = exprString.toCharArray();
char[] from = fromString.toCharArray();
char[] to = toString.toCharArray();
char[] result = new char[expr.length];
System.arraycopy(expr, 0, result, 0, expr.length);
Set<Character> seen = new HashSet<Character>();
for (int i = 0; i < from.length; i++) {
if (seen.contains(from[i])) {
continue;
}
seen.add(from[i]);
for (int j = 0; j < expr.length; j++) {
if (expr[j] == from[i]) {
result[j] = (i < to.length) ? to[i] : 0;
}
}
}
int pos = 0;
for (int i = 0; i < result.length; i++) {
if (result[i] != 0) {
result[pos++] = result[i];
}
}
resultText.set(new String(result, 0, pos));
return resultText;
}
@Override
public String getDisplayString(String[] children) {
assert (children.length == 3);
return getStandardDisplayString("translate", children, ",");
}
}