[MRQL-99] Import more Java String Functions
diff --git a/core/src/main/java/org/apache/mrql/ClassImporter.java b/core/src/main/java/org/apache/mrql/ClassImporter.java
index 8efc1ae..7835af7 100644
--- a/core/src/main/java/org/apache/mrql/ClassImporter.java
+++ b/core/src/main/java/org/apache/mrql/ClassImporter.java
@@ -17,7 +17,7 @@
  */
 package org.apache.mrql;
 
-import java.lang.reflect.Method;
+import java.lang.reflect.*;
 import org.apache.mrql.gen.*;
 import java.util.*;
 
@@ -46,11 +46,19 @@
         return false;
     }
 
-    private static Tree getType ( Class<?> c ) {
+    private static Tree getType ( Class<?> c, Type[] genTypes ) {
         String cn = c.getCanonicalName();
         Class<?>[] inf = c.getInterfaces();
         if (cn.equals("org.apache.mrql.MRData"))
             return new VariableLeaf("any");
+        if (cn.equals("org.apache.mrql.MR_list")) {
+            Class ec = ((Class)((ParameterizedType)genTypes[0]).getActualTypeArguments()[0]);
+            return new Node("list",new Trees(getType(ec,new Type[0])));
+        }
+        if (cn.equals("org.apache.mrql.MR_bag")) {
+            Class ec = ((Class)((ParameterizedType)genTypes[0]).getActualTypeArguments()[0]);
+            return new Node("bag",new Trees(getType(ec,new Type[0])));
+        }
         if (cn.startsWith("org.apache.mrql.MR_"))
             return new VariableLeaf(cn.substring(19));
         if (cn.equals("org.apache.mrql.Bag"))
@@ -69,9 +77,10 @@
     private static Trees signature ( Method m ) {
         Class<?> co = m.getReturnType();
         Class<?>[] cs = m.getParameterTypes();
-        Trees as = new Trees(getType(co));
+        Type[] gs = m.getGenericParameterTypes();
+        Trees as = new Trees(getType(co,new Type[]{m.getGenericReturnType()}));
         for (int i = 0; i < cs.length; i++)
-            as = as.append(getType(cs[i]));
+            as = as.append(getType(cs[i],gs));
         return as;
     }
 
diff --git a/core/src/main/java/org/apache/mrql/SystemFunctions.java b/core/src/main/java/org/apache/mrql/SystemFunctions.java
index 62fdd50..126d854 100644
--- a/core/src/main/java/org/apache/mrql/SystemFunctions.java
+++ b/core/src/main/java/org/apache/mrql/SystemFunctions.java
@@ -21,6 +21,18 @@
 import java.lang.Math;
 
 
+final class MR_bag<T> extends Bag {
+    public MR_bag ( int size ) {
+        super(size);
+    }
+}
+
+final class MR_list<T> extends Bag {
+    public MR_list ( int size ) {
+        super(size);
+    }
+}
+
 /** System functions must be from MRData to MRData */
 final public class SystemFunctions {
 
@@ -194,6 +206,29 @@
     public static MR_bool contains ( MR_string x, MR_string y ) { return new MR_bool(x.get().contains(y.get())); }
     public static MR_int length ( MR_string x ) { return new MR_int(x.get().length()); }
     public static MR_string substring ( MR_string x, MR_int b, MR_int e ) { return new MR_string(x.get().substring(b.get(),e.get())); }
+    public static MR_string replace ( MR_string x, MR_string from, MR_string to ) { return new MR_string(x.get().replace(from.get(),to.get())); }
+    public static MR_string replaceAll ( MR_string x, MR_string from, MR_string to ) { return new MR_string(x.get().replaceAll(from.get(),to.get())); }
+    public static MR_string replaceFirst ( MR_string x, MR_string from, MR_string to ) { return new MR_string(x.get().replaceFirst(from.get(),to.get())); }
+    public static MR_bool startsWith ( MR_string x, MR_string y ) { return new MR_bool(x.get().startsWith(y.get())); }
+    public static MR_string toLowerCase ( MR_string x ) { return new MR_string(x.get().toLowerCase()); }
+    public static MR_string toUpperCase ( MR_string x ) { return new MR_string(x.get().toUpperCase()); }
+    public static MR_string trim ( MR_string x ) { return new MR_string(x.get().trim()); }
+
+    public static MR_list<MR_string> split ( MR_string x, MR_string reg ) {
+        final String[] vs = x.get().split(reg.get());
+        MR_list<MR_string> l = new MR_list<MR_string>(vs.length);
+        for (String v: vs)
+            l.add(new MR_string(v));
+        return l;
+    };
+
+    public static MR_list<MR_string> split ( MR_string x, MR_string reg, MR_int n ) {
+        final String[] vs = x.get().split(reg.get(),n.get());
+        MR_list<MR_string> l = new MR_list<MR_string>(vs.length);
+        for (String v: vs)
+            l.add(new MR_string(v));
+        return l;
+    }
 
     public static MR_bool exists ( Bag s ) {
         return (s.iterator().hasNext()) ? true_value : false_value;