uppercase() function is implemented. - documentation added.

Change-Id: I88f5404009564fb6be00a784484b43e8abd41664
Reviewed-on: http://fulliautomatix.ics.uci.edu:8443/109
Reviewed-by: Inci Cetindil <icetindil@gmail.com>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
diff --git a/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.1.ddl.aql
new file mode 100644
index 0000000..754ea81
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.1.ddl.aql
@@ -0,0 +1,3 @@
+drop dataverse test if exists;
+create dataverse test;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.2.update.aql
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.2.update.aql
diff --git a/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.3.query.aql
new file mode 100644
index 0000000..92d7e87
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/string/uppercase/uppercase.3.query.aql
@@ -0,0 +1,6 @@
+use dataverse test;
+
+let $c1 := uppercase("Hellow")
+let $c2 := uppercase("")
+let $c3 := uppercase(null)
+return {"result1": $c1, "result2": $c2, "result3": $c3}
diff --git a/asterix-app/src/test/resources/runtimets/results/string/uppercase/uppercase.1.adm b/asterix-app/src/test/resources/runtimets/results/string/uppercase/uppercase.1.adm
new file mode 100644
index 0000000..64a3222
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/string/uppercase/uppercase.1.adm
@@ -0,0 +1 @@
+{ "result1": "HELLOW", "result2": "", "result3": null }
diff --git a/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterix-app/src/test/resources/runtimets/testsuite.xml
index fa187d0..96efb8a 100644
--- a/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -4195,6 +4195,11 @@
         <output-dir compare="Text">toLowerCase04</output-dir>
       </compilation-unit>
     </test-case>
+    <test-case FilePath="string">
+      <compilation-unit name="uppercase">
+        <output-dir compare="Text">uppercase</output-dir>
+      </compilation-unit>
+    </test-case>
   </test-group>
   <test-group name="subset-collection">
     <test-case FilePath="subset-collection">
diff --git a/asterix-doc/src/site/markdown/aql/functions.md b/asterix-doc/src/site/markdown/aql/functions.md
index 5688d06..f246dc0 100644
--- a/asterix-doc/src/site/markdown/aql/functions.md
+++ b/asterix-doc/src/site/markdown/aql/functions.md
@@ -372,6 +372,30 @@
         asterix
 
 
+### uppercase ###
+ * Syntax:
+
+        uppercase(string_expression)
+
+ * Converts a given string `string_expression` to its uppercase form.
+ * Arguments:
+    * `string_expression` : A `string` to be converted.
+ * Return Value:
+    * Returns a `string` as the uppercase form of the given `string_expression`.
+
+ * Example:
+
+        use dataverse TinySocial;
+
+        let $i := "asterix"
+        return uppercase($i)
+
+
+ * The expected result is:
+
+        ASTERIX
+        
+
 ### matches ###
  * Syntax:
 
@@ -545,7 +569,7 @@
         " its touch-screen is horrible"
         " the voice-command is bad:("
         " the voicemail-service is awesome"
-
+        
 ## <a id="AggregateFunctions">Aggregate Functions</a> <font size="4"><a href="#toc">[Back to TOC]</a></font> ##
 ### count ###
  * Syntax:
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
index 004c09a..caec0f6 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixBuiltinFunctions.java
@@ -220,6 +220,8 @@
             FunctionConstants.ASTERIX_NS, "matches", 3);
     public final static FunctionIdentifier STRING_LOWERCASE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "lowercase", 1);
+    public final static FunctionIdentifier STRING_UPPERCASE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "uppercase", 1);
     public final static FunctionIdentifier STRING_REPLACE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "replace", 3);
     public final static FunctionIdentifier STRING_REPLACE_WITH_FLAG = new FunctionIdentifier(
@@ -788,6 +790,7 @@
         addFunction(SUBSTRING2, Substring2TypeComputer.INSTANCE, true);
         addFunction(STRING_LENGTH, UnaryStringInt32OrNullTypeComputer.INSTANCE, true);
         addFunction(STRING_LOWERCASE, UnaryStringOrNullTypeComputer.INSTANCE, true);
+        addFunction(STRING_UPPERCASE, UnaryStringOrNullTypeComputer.INSTANCE, true);
         addFunction(STRING_START_WITH, BinaryStringBoolOrNullTypeComputer.INSTANCE, true);
         addFunction(STRING_END_WITH, BinaryStringBoolOrNullTypeComputer.INSTANCE, true);
         addFunction(STRING_MATCHES, BinaryStringBoolOrNullTypeComputer.INSTANCE, true);
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/StringUpperCaseDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/StringUpperCaseDescriptor.java
new file mode 100644
index 0000000..856772b
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/StringUpperCaseDescriptor.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2009-2013 by The Regents of the University of California
+ * 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 from
+ * 
+ *     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 edu.uci.ics.asterix.runtime.evaluators.functions;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.ANull;
+import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptorFactory;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.data.std.primitive.UTF8StringPointable;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+import edu.uci.ics.hyracks.dataflow.common.data.util.StringUtils;
+
+public class StringUpperCaseDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+    private static final long serialVersionUID = 1L;
+
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new StringUpperCaseDescriptor();
+        }
+    };
+    private final static byte SER_STRING_TYPE_TAG = ATypeTag.STRING.serialize();
+    private final static byte SER_NULL_TYPE_TAG = ATypeTag.NULL.serialize();
+
+    @Override
+    public ICopyEvaluatorFactory createEvaluatorFactory(final ICopyEvaluatorFactory[] args) {
+        return new ICopyEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyEvaluator createEvaluator(final IDataOutputProvider output) throws AlgebricksException {
+                return new ICopyEvaluator() {
+
+                    private DataOutput out = output.getDataOutput();
+                    private ArrayBackedValueStorage outInput = new ArrayBackedValueStorage();
+                    private ICopyEvaluator eval = args[0].createEvaluator(outInput);
+
+                    private final byte stt = ATypeTag.STRING.serialize();
+
+                    @SuppressWarnings("unchecked")
+                    private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
+                            .getSerializerDeserializer(BuiltinType.ANULL);
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {
+
+                        try {
+                            outInput.reset();
+                            eval.evaluate(tuple);
+                            byte[] serString = outInput.getByteArray();
+
+                            if (serString[0] == SER_STRING_TYPE_TAG) {
+                                byte[] bytes = outInput.getByteArray();
+                                int len = UTF8StringPointable.getUTFLength(bytes, 1);
+
+                                out.writeByte(stt);
+                                StringUtils.writeUTF8Len(len, out);
+
+                                int pos = 3;
+                                while (pos < len + 3) {
+                                    char c1 = UTF8StringPointable.charAt(bytes, pos);
+                                    c1 = Character.toUpperCase(c1);
+                                    pos += UTF8StringPointable.charSize(bytes, pos);
+                                    StringUtils.writeCharAsModifiedUTF8(c1, out);
+                                }
+                            } else if (serString[0] == SER_NULL_TYPE_TAG)
+                                nullSerde.serialize(ANull.NULL, out);
+                            else
+                                throw new AlgebricksException(AsterixBuiltinFunctions.STRING_UPPERCASE.getName()
+                                        + ": expects input type STRING/NULL but got "
+                                        + EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serString[0]));
+                        } catch (IOException e1) {
+                            throw new AlgebricksException(e1);
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.STRING_UPPERCASE;
+    }
+
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java
index 8c5ae1f..ed0a3f3 100644
--- a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/formats/NonTaggedDataFormat.java
@@ -233,6 +233,7 @@
 import edu.uci.ics.asterix.runtime.evaluators.functions.StringReplaceWithFlagsDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.StringStartWithDescrtiptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.StringToCodePointDescriptor;
+import edu.uci.ics.asterix.runtime.evaluators.functions.StringUpperCaseDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.Substring2Descriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.SubstringAfterDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.SubstringBeforeDescriptor;
@@ -414,6 +415,7 @@
         temp.add(StringEndWithDescrtiptor.FACTORY);
         temp.add(StringMatchesDescriptor.FACTORY);
         temp.add(StringLowerCaseDescriptor.FACTORY);
+        temp.add(StringUpperCaseDescriptor.FACTORY);
         temp.add(StringMatchesWithFlagDescriptor.FACTORY);
         temp.add(StringReplaceDescriptor.FACTORY);
         temp.add(StringReplaceWithFlagsDescriptor.FACTORY);