merge asterix_lsm_stabilization
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java
index dd8791f..8523e75 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/jobgen/AqlLogicalExpressionJobGen.java
@@ -4,10 +4,13 @@
 
 import org.apache.commons.lang3.mutable.Mutable;
 
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
 import edu.uci.ics.asterix.common.functions.FunctionDescriptorTag;
+import edu.uci.ics.asterix.external.library.ExternalFunctionDescriptorProvider;
 import edu.uci.ics.asterix.formats.base.IDataFormat;
 import edu.uci.ics.asterix.metadata.declared.AqlMetadataProvider;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
 import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.comparisons.ComparisonEvalFactory;
 import edu.uci.ics.asterix.runtime.formats.FormatUtils;
@@ -124,9 +127,18 @@
         }
 
         IFunctionDescriptor fd = null;
-        AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
-        IDataFormat format = FormatUtils.getDefaultFormat();
-        fd = format.resolveFunction(expr, env);
+        if (!(expr.getFunctionInfo() instanceof IExternalFunctionInfo)) {
+            AqlMetadataProvider mp = (AqlMetadataProvider) context.getMetadataProvider();
+ IDataFormat format = FormatUtils.getDefaultFormat();
+            fd = format.resolveFunction(expr, env);
+        } else {
+            try {
+                fd = ExternalFunctionDescriptorProvider.getExternalFunctionDescriptor((IExternalFunctionInfo) expr
+                        .getFunctionInfo());
+            } catch (AsterixException ae) {
+                throw new AlgebricksException(ae);
+            }
+        }
         return fd.createEvaluatorFactory(args);
     }
 
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
index 3ba3e96..9aa19c6 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/optimizer/rules/typecast/StaticTypeCastUtil.java
@@ -233,6 +233,10 @@
      */
     private static void staticRecordTypeCast(AbstractFunctionCallExpression func, ARecordType reqType,
             ARecordType inputType, IVariableTypeEnvironment env) throws AlgebricksException {
+        if (!(func.getFunctionIdentifier() == AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR || func
+                .getFunctionIdentifier() == AsterixBuiltinFunctions.CLOSED_RECORD_CONSTRUCTOR)) {
+            return;
+        }
         IAType[] reqFieldTypes = reqType.getFieldTypes();
         String[] reqFieldNames = reqType.getFieldNames();
         IAType[] inputFieldTypes = inputType.getFieldTypes();
diff --git a/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java b/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java
index caa16d4..0a5e4c5 100644
--- a/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java
+++ b/asterix-algebra/src/main/java/edu/uci/ics/asterix/translator/AqlExpressionToPlanTranslator.java
@@ -87,6 +87,7 @@
 import edu.uci.ics.asterix.metadata.declared.ResultSetSinkId;
 import edu.uci.ics.asterix.metadata.entities.Dataset;
 import edu.uci.ics.asterix.metadata.entities.Function;
+import edu.uci.ics.asterix.metadata.functions.ExternalFunctionCompilerUtil;
 import edu.uci.ics.asterix.metadata.utils.DatasetUtils;
 import edu.uci.ics.asterix.om.base.AInt32;
 import edu.uci.ics.asterix.om.base.AString;
@@ -494,13 +495,18 @@
             return null;
         }
         AbstractFunctionCallExpression f = null;
-        if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_AQL)) {
+        if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_JAVA)) {
+            IFunctionInfo finfo = ExternalFunctionCompilerUtil.getExternalFunctionInfo(
+                    metadataProvider.getMetadataTxnContext(), function);
+            f = new ScalarFunctionCallExpression(finfo, args);
+        } else if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_AQL)) {
             IFunctionInfo finfo = new AsterixFunctionInfo(signature);
-            return new ScalarFunctionCallExpression(finfo, args);
+            f = new ScalarFunctionCallExpression(finfo, args);
         } else {
             throw new MetadataException(" User defined functions written in " + function.getLanguage()
                     + " are not supported");
         }
+        return f;
     }
 
     private AbstractFunctionCallExpression lookupBuiltinFunction(String functionName, int arity,
diff --git a/asterix-app/pom.xml b/asterix-app/pom.xml
index 2c4cf17..d517837 100644
--- a/asterix-app/pom.xml
+++ b/asterix-app/pom.xml
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<artifactId>asterix</artifactId>
@@ -76,7 +77,7 @@
 						<additionalClasspathElement>${basedir}/src/main/resources</additionalClasspathElement> 
 						</additionalClasspathElements> -->
 					<forkMode>pertest</forkMode>
-					<argLine>-enableassertions -Xmx${test.heap.size}m 
+					<argLine>-enableassertions -Xmx${test.heap.size}m
 						-Dfile.encoding=UTF-8
 						-Djava.util.logging.config.file=src/test/resources/logging.properties
 						-Xdebug
@@ -137,9 +138,9 @@
 			<artifactId>algebricks-compiler</artifactId>
 		</dependency>
 		<dependency>
-            <groupId>edu.uci.ics.hyracks</groupId>
-            <artifactId>hyracks-client</artifactId>
-        </dependency>
+			<groupId>edu.uci.ics.hyracks</groupId>
+			<artifactId>hyracks-client</artifactId>
+		</dependency>
 		<dependency>
 			<groupId>edu.uci.ics.asterix</groupId>
 			<artifactId>asterix-aql</artifactId>
@@ -175,6 +176,13 @@
 			<type>jar</type>
 			<scope>compile</scope>
 		</dependency>
+                <dependency>
+                        <groupId>edu.uci.ics.asterix</groupId>
+                        <artifactId>asterix-common</artifactId>
+                        <version>0.0.6-SNAPSHOT</version>
+                        <type>test-jar</type>
+                        <scope>test</scope>
+                </dependency>
 		<dependency>
 			<groupId>com.kenai.nbpwr</groupId>
 			<artifactId>org-apache-commons-io</artifactId>
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
index 5ab94f3..f50005a 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
@@ -53,12 +53,14 @@
 
         setupWebServer();
         webServer.start();
+        System.out.println("STARTED WEB SERVER");
 
         // Setup and start the web interface
         setupJSONAPIServer();
         jsonAPIServer.start();
 
         AsterixAppContextInfoImpl.initialize(appCtx);
+        ExternalLibraryBootstrap.setUpExternaLibraries(false);
     }
 
     @Override
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/ExternalLibraryBootstrap.java b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/ExternalLibraryBootstrap.java
new file mode 100755
index 0000000..3b214c6
--- /dev/null
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/ExternalLibraryBootstrap.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2009-2012 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.hyracks.bootstrap;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.common.functions.FunctionSignature;
+import edu.uci.ics.asterix.external.library.ExternalLibraryManager;
+import edu.uci.ics.asterix.external.library.Function;
+import edu.uci.ics.asterix.external.library.Functions;
+import edu.uci.ics.asterix.external.library.Library;
+import edu.uci.ics.asterix.metadata.MetadataManager;
+import edu.uci.ics.asterix.metadata.MetadataTransactionContext;
+import edu.uci.ics.asterix.metadata.api.IMetadataEntity;
+import edu.uci.ics.asterix.metadata.entities.Dataverse;
+import edu.uci.ics.asterix.runtime.formats.NonTaggedDataFormat;
+import edu.uci.ics.asterix.transaction.management.exception.ACIDException;
+
+public class ExternalLibraryBootstrap {
+
+    public static void setUpExternaLibraries(boolean isMetadataNode) throws Exception {
+
+        Map<String, List<String>> uninstalledLibs = null;
+        if (isMetadataNode) {
+            uninstalledLibs = uninstallLibraries();
+        }
+
+        File installLibDir = getLibraryInstallDir();
+        if (installLibDir.exists()) {
+            for (String dataverse : installLibDir.list()) {
+                File dataverseDir = new File(installLibDir, dataverse);
+                String[] libraries = dataverseDir.list();
+                for (String library : libraries) {
+                    registerLibrary(dataverse, library, isMetadataNode, installLibDir);
+                    if (isMetadataNode) {
+                        File libraryDir = new File(installLibDir.getAbsolutePath() + File.separator + dataverse
+                                + File.separator + library);
+                        installLibraryIfNeeded(dataverse, libraryDir, uninstalledLibs);
+                    }
+                }
+            }
+        }
+    }
+
+    private static Map<String, List<String>> uninstallLibraries() throws Exception {
+        Map<String, List<String>> uninstalledLibs = new HashMap<String, List<String>>();
+        File uninstallLibDir = getLibraryUninstallDir();
+        String[] uninstallLibNames;
+        if (uninstallLibDir.exists()) {
+            uninstallLibNames = uninstallLibDir.list();
+            for (String uninstallLibName : uninstallLibNames) {
+                String[] components = uninstallLibName.split("\\.");
+                String dataverse = components[0];
+                String libName = components[1];
+                uninstallLibrary(dataverse, libName);
+                new File(uninstallLibDir, uninstallLibName).delete();
+                List<String> uinstalledLibsInDv = uninstalledLibs.get(dataverse);
+                if (uinstalledLibsInDv == null) {
+                    uinstalledLibsInDv = new ArrayList<String>();
+                    uninstalledLibs.put(dataverse, uinstalledLibsInDv);
+                }
+                uinstalledLibsInDv.add(libName);
+            }
+        }
+        return uninstalledLibs;
+    }
+
+    private static boolean uninstallLibrary(String dataverse, String libraryName) throws AsterixException,
+            RemoteException, ACIDException {
+        MetadataTransactionContext mdTxnCtx = null;
+        try {
+            mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
+            Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, dataverse);
+            if (dv == null) {
+                return false;
+            }
+
+            edu.uci.ics.asterix.metadata.entities.Library library = MetadataManager.INSTANCE.getLibrary(mdTxnCtx,
+                    dataverse, libraryName);
+            if (library == null) {
+                return false;
+            }
+
+            List<edu.uci.ics.asterix.metadata.entities.Function> functions = MetadataManager.INSTANCE
+                    .getDataverseFunctions(mdTxnCtx, dataverse);
+            for (edu.uci.ics.asterix.metadata.entities.Function function : functions) {
+                if (function.getName().startsWith(libraryName + ":")) {
+                    MetadataManager.INSTANCE.dropFunction(mdTxnCtx, new FunctionSignature(dataverse,
+                            function.getName(), function.getArity()));
+                }
+            }
+
+            MetadataManager.INSTANCE.dropLibrary(mdTxnCtx, dataverse, libraryName);
+            MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
+        } catch (Exception e) {
+            MetadataManager.INSTANCE.abortTransaction(mdTxnCtx);
+            throw new AsterixException(e);
+        }
+        return true;
+    }
+
+    // Each element of a library is installed as part of a transaction. Any
+    // failure in installing an element does not effect installation of other
+    // libraries
+    private static void installLibraryIfNeeded(String dataverse, final File libraryDir,
+            Map<String, List<String>> uninstalledLibs) throws Exception {
+
+        String libraryName = libraryDir.getName();
+        List<String> uninstalledLibsInDv = uninstalledLibs.get(dataverse);
+        boolean wasUninstalled = uninstalledLibsInDv != null && uninstalledLibsInDv.contains(libraryName);
+
+        MetadataTransactionContext mdTxnCtx = null;
+        try {
+            mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
+            edu.uci.ics.asterix.metadata.entities.Library libraryInMetadata = MetadataManager.INSTANCE.getLibrary(
+                    mdTxnCtx, dataverse, libraryName);
+            if (libraryInMetadata != null && !wasUninstalled) {
+                return;
+            }
+
+            String[] libraryDescriptors = libraryDir.list(new FilenameFilter() {
+                @Override
+                public boolean accept(File dir, String name) {
+                    return name.endsWith(".xml");
+                }
+            });
+
+            Library library = getLibrary(new File(libraryDir + File.separator + libraryDescriptors[0]));
+
+            if (libraryDescriptors.length == 0) {
+                throw new Exception("No library descriptors defined");
+            } else if (libraryDescriptors.length > 1) {
+                throw new Exception("More than 1 library descriptors defined");
+            }
+
+            Dataverse dv = MetadataManager.INSTANCE.getDataverse(mdTxnCtx, dataverse);
+            if (dv == null) {
+                MetadataManager.INSTANCE.addDataverse(mdTxnCtx, new Dataverse(dataverse,
+                        NonTaggedDataFormat.NON_TAGGED_DATA_FORMAT, IMetadataEntity.PENDING_NO_OP));
+            }
+            for (Function function : library.getFunctions().getFunction()) {
+                String[] fargs = function.getArguments().trim().split(",");
+                List<String> args = new ArrayList<String>();
+                for (String arg : fargs) {
+                    args.add(arg);
+                }
+                edu.uci.ics.asterix.metadata.entities.Function f = new edu.uci.ics.asterix.metadata.entities.Function(
+                        dataverse, libraryName + ":" + function.getName(), args.size(), args, function.getReturnType(),
+                        function.getDefinition(), library.getLanguage(), function.getFunctionType());
+                MetadataManager.INSTANCE.addFunction(mdTxnCtx, f);
+            }
+
+            MetadataManager.INSTANCE.addLibrary(mdTxnCtx, new edu.uci.ics.asterix.metadata.entities.Library(dataverse,
+                    libraryName));
+            MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
+        } catch (Exception e) {
+            e.printStackTrace();
+            MetadataManager.INSTANCE.abortTransaction(mdTxnCtx);
+        }
+    }
+
+    private static void registerLibrary(String dataverse, String libraryName, boolean isMetadataNode, File installLibDir)
+            throws Exception {
+        ClassLoader classLoader = getLibraryClassLoader(dataverse, libraryName);
+        ExternalLibraryManager.registerLibraryClassLoader(dataverse, libraryName, classLoader);
+    }
+
+    private static Library getLibrary(File libraryXMLPath) throws Exception {
+        JAXBContext configCtx = JAXBContext.newInstance(Library.class);
+        Unmarshaller unmarshaller = configCtx.createUnmarshaller();
+        Library library = (Library) unmarshaller.unmarshal(libraryXMLPath);
+        return library;
+    }
+
+    private static ClassLoader getLibraryClassLoader(String dataverse, String libraryName) throws Exception {
+        System.out.println(" installing lirbary " + libraryName + " in dataverse " + dataverse);
+        File installDir = getLibraryInstallDir();
+        System.out.println(" install directory " + installDir.getAbsolutePath());
+
+        File libDir = new File(installDir.getAbsolutePath() + File.separator + dataverse + File.separator + libraryName);
+        FilenameFilter jarFileFilter = new FilenameFilter() {
+            public boolean accept(File dir, String name) {
+                return name.endsWith(".jar");
+            }
+        };
+
+        String[] jarsInLibDir = libDir.list(jarFileFilter);
+        System.out.println(" jars in lib dir " + jarsInLibDir);
+
+        if (jarsInLibDir.length > 1) {
+            throw new Exception("Incorrect library structure: found multiple library jars");
+        }
+        if (jarsInLibDir.length < 0) {
+            throw new Exception("Incorrect library structure: could not find library jar");
+        }
+
+        File libJar = new File(libDir, jarsInLibDir[0]);
+        File libDependencyDir = new File(libDir.getAbsolutePath() + File.separator + "lib");
+        int numDependencies = 1;
+        String[] libraryDependencies = null;
+        if (libDependencyDir.exists()) {
+            libraryDependencies = libDependencyDir.list(jarFileFilter);
+            numDependencies += libraryDependencies.length;
+        }
+
+        ClassLoader parentClassLoader = ExternalLibraryBootstrap.class.getClassLoader();
+        URL[] urls = new URL[numDependencies];
+        int count = 0;
+        urls[count++] = libJar.toURL();
+
+        if (libraryDependencies != null && libraryDependencies.length > 0) {
+            for (String dependency : libraryDependencies) {
+                File file = new File(libDependencyDir + File.separator + dependency);
+                urls[count++] = file.toURL();
+            }
+        }
+        ClassLoader classLoader = new URLClassLoader(urls, parentClassLoader);
+        return classLoader;
+    }
+
+    private static File getLibraryInstallDir() {
+        String workingDir = System.getProperty("user.dir");
+        return new File(workingDir + File.separator + "library");
+    }
+
+    private static File getLibraryUninstallDir() {
+        String workingDir = System.getProperty("user.dir");
+        return new File(workingDir + File.separator + "uninstall");
+    }
+
+}
+
+class ExternalLibrary {
+
+    private final String dataverse;
+    private final String name;
+    private final String language;
+    private final Functions functions;
+
+    public ExternalLibrary(String dataverse, String name, String language, Functions functions) {
+        this.dataverse = dataverse;
+        this.name = name;
+        this.language = language;
+        this.functions = functions;
+    }
+
+    public String toString() {
+        StringBuilder builder = new StringBuilder("");
+        builder.append("Library");
+        builder.append("\n");
+        builder.append("Functions");
+        builder.append("\n");
+        for (Function function : functions.getFunction()) {
+            builder.append(function);
+            builder.append("\n");
+        }
+        return new String(builder);
+    }
+
+    public String getDataverse() {
+        return dataverse;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getLanguage() {
+        return language;
+    }
+
+    public Functions getFunctions() {
+        return functions;
+    }
+
+}
diff --git a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
index f332155..25c617e 100644
--- a/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
+++ b/asterix-app/src/main/java/edu/uci/ics/asterix/hyracks/bootstrap/NCApplicationEntryPoint.java
@@ -18,153 +18,143 @@
 import edu.uci.ics.hyracks.api.application.INCApplicationEntryPoint;
 
 public class NCApplicationEntryPoint implements INCApplicationEntryPoint {
-	private static final Logger LOGGER = Logger
-			.getLogger(NCApplicationEntryPoint.class.getName());
+    private static final Logger LOGGER = Logger.getLogger(NCApplicationEntryPoint.class.getName());
 
-	private INCApplicationContext ncApplicationContext = null;
-	private AsterixAppRuntimeContext runtimeContext;
-	private String nodeId;
-	private boolean isMetadataNode = false;
-	private boolean stopInitiated = false;
-	private SystemState systemState = SystemState.NEW_UNIVERSE;
+    private INCApplicationContext ncApplicationContext = null;
+    private AsterixAppRuntimeContext runtimeContext;
+    private String nodeId;
+    private boolean isMetadataNode = false;
+    private boolean stopInitiated = false;
+    private SystemState systemState = SystemState.NEW_UNIVERSE;
 
-	@Override
-	public void start(INCApplicationContext ncAppCtx, String[] args)
-			throws Exception {
-		ncApplicationContext = ncAppCtx;
-		nodeId = ncApplicationContext.getNodeId();
-		if (LOGGER.isLoggable(Level.INFO)) {
-			LOGGER.info("Starting Asterix node controller: " + nodeId);
-		}
+    @Override
+    public void start(INCApplicationContext ncAppCtx, String[] args) throws Exception {
+        ncApplicationContext = ncAppCtx;
+        nodeId = ncApplicationContext.getNodeId();
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("Starting Asterix node controller: " + nodeId);
+        }
 
-		runtimeContext = new AsterixAppRuntimeContext(ncApplicationContext);
-		runtimeContext.initialize();
-		ncApplicationContext.setApplicationObject(runtimeContext);
-		JVMShutdownHook sHook = new JVMShutdownHook(this);
-		Runtime.getRuntime().addShutdownHook(sHook);
+        runtimeContext = new AsterixAppRuntimeContext(ncApplicationContext);
+        runtimeContext.initialize();
+        ncApplicationContext.setApplicationObject(runtimeContext);
+        JVMShutdownHook sHook = new JVMShutdownHook(this);
+        Runtime.getRuntime().addShutdownHook(sHook);
 
-		// #. recover if the system is corrupted by checking system state.
-		IRecoveryManager recoveryMgr = runtimeContext.getTransactionSubsystem()
-				.getRecoveryManager();
-		systemState = recoveryMgr.getSystemState();
-		if (systemState != SystemState.NEW_UNIVERSE) {
-			PersistentLocalResourceRepository localResourceRepository = (PersistentLocalResourceRepository) runtimeContext
-					.getLocalResourceRepository();
-			localResourceRepository.initialize(nodeId, null, false,
-					runtimeContext.getResourceIdFactory());
-		}
-		if (systemState == SystemState.CORRUPTED) {
-			recoveryMgr.startRecovery(true);
-		} else if (systemState == SystemState.NEW_UNIVERSE) {
-			recoveryMgr.checkpoint(true);
-		}
-	}
+        // #. recover if the system is corrupted by checking system state.
+        IRecoveryManager recoveryMgr = runtimeContext.getTransactionSubsystem().getRecoveryManager();
+        systemState = recoveryMgr.getSystemState();
+        if (systemState != SystemState.NEW_UNIVERSE) {
+            PersistentLocalResourceRepository localResourceRepository = (PersistentLocalResourceRepository) runtimeContext
+                    .getLocalResourceRepository();
+            localResourceRepository.initialize(nodeId, null, false, runtimeContext.getResourceIdFactory());
+        }
+        if (systemState == SystemState.CORRUPTED) {
+            System.out.println("doing recovery");
+            recoveryMgr.startRecovery(true);
+        } else if (systemState == SystemState.NEW_UNIVERSE) {
+            recoveryMgr.checkpoint(true);
+            System.out.println("new universe");
+        }
+    }
 
-	@Override
-	public void stop() throws Exception {
-		if (!stopInitiated) {
-		    runtimeContext.setShuttingdown(true);
-			stopInitiated = true;
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Stopping Asterix node controller: " + nodeId);
-			}
+    @Override
+    public void stop() throws Exception {
+        if (!stopInitiated) {
+            runtimeContext.setShuttingdown(true);
+            stopInitiated = true;
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Stopping Asterix node controller: " + nodeId);
+            }
 
-			IRecoveryManager recoveryMgr = runtimeContext
-					.getTransactionSubsystem().getRecoveryManager();
-			recoveryMgr.checkpoint(true);
+            IRecoveryManager recoveryMgr = runtimeContext.getTransactionSubsystem().getRecoveryManager();
+            recoveryMgr.checkpoint(true);
 
-			if (isMetadataNode) {
-				MetadataBootstrap.stopUniverse();
-			}
-			runtimeContext.deinitialize();
-		} else {
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Duplicate attempt to stop ignored: " + nodeId);
-			}
-		}
-	}
+            if (isMetadataNode) {
+                MetadataBootstrap.stopUniverse();
+            }
+            runtimeContext.deinitialize();
+        } else {
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Duplicate attempt to stop ignored: " + nodeId);
+            }
+        }
+    }
 
-	@Override
-	public void notifyStartupComplete() throws Exception {
-		IAsterixStateProxy proxy = (IAsterixStateProxy) ncApplicationContext
-				.getDistributedState();
+    @Override
+    public void notifyStartupComplete() throws Exception {
+        IAsterixStateProxy proxy = (IAsterixStateProxy) ncApplicationContext.getDistributedState();
 
-		if (systemState == SystemState.NEW_UNIVERSE) {
-			PersistentLocalResourceRepository localResourceRepository = (PersistentLocalResourceRepository) runtimeContext
-					.getLocalResourceRepository();
-			System.out.println("nodeid" + nodeId);
-			System.out.println("proxy" + proxy);
-			System.out.println("stores"
-					+ proxy.getAsterixProperties().getStores());
-			System.out.println("store"
-					+ proxy.getAsterixProperties().getStores().get(nodeId)[0]);
+        if (systemState == SystemState.NEW_UNIVERSE) {
+            PersistentLocalResourceRepository localResourceRepository = (PersistentLocalResourceRepository) runtimeContext
+                    .getLocalResourceRepository();
+            System.out.println("nodeid" + nodeId);
+            System.out.println("proxy" + proxy);
+            System.out.println("stores" + proxy.getAsterixProperties().getStores());
+            System.out.println("store" + proxy.getAsterixProperties().getStores().get(nodeId)[0]);
 
-			localResourceRepository.initialize(nodeId, proxy
-					.getAsterixProperties().getStores().get(nodeId)[0], true,
-					null);
-		}
+            localResourceRepository.initialize(nodeId, proxy.getAsterixProperties().getStores().get(nodeId)[0], true,
+                    null);
+        }
 
-		isMetadataNode = nodeId.equals(proxy.getAsterixProperties()
-				.getMetadataNodeName());
-		if (isMetadataNode) {
-			registerRemoteMetadataNode(proxy);
+        isMetadataNode = nodeId.equals(proxy.getAsterixProperties().getMetadataNodeName());
+        if (isMetadataNode) {
+            registerRemoteMetadataNode(proxy);
 
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Bootstrapping metadata");
-			}
-			MetadataManager.INSTANCE = new MetadataManager(proxy);
-			MetadataManager.INSTANCE.init();
-			MetadataBootstrap.startUniverse(proxy.getAsterixProperties(),
-					ncApplicationContext,
-					systemState == SystemState.NEW_UNIVERSE);
-			MetadataBootstrap.startDDLRecovery();
-		}
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Bootstrapping metadata");
+            }
+            MetadataManager.INSTANCE = new MetadataManager(proxy);
+            MetadataManager.INSTANCE.init();
+            MetadataBootstrap.startUniverse(proxy.getAsterixProperties(), ncApplicationContext,
+                    systemState == SystemState.NEW_UNIVERSE);
+            MetadataBootstrap.startDDLRecovery();
+        }
+        ExternalLibraryBootstrap.setUpExternaLibraries(isMetadataNode);
+        System.out.println("Checked for installing libraries");
 
-		IRecoveryManager recoveryMgr = runtimeContext.getTransactionSubsystem()
-				.getRecoveryManager();
-		recoveryMgr.checkpoint(true);
+        IRecoveryManager recoveryMgr = runtimeContext.getTransactionSubsystem().getRecoveryManager();
+        recoveryMgr.checkpoint(true);
+        System.out.println("bootstrap complete");
 
-		// TODO
-		// reclaim storage for orphaned index artifacts in NCs.
-	}
+        // TODO
+        // reclaim storage for orphaned index artifacts in NCs.
+    }
 
-	public void registerRemoteMetadataNode(IAsterixStateProxy proxy)
-			throws RemoteException {
-		IMetadataNode stub = null;
-		MetadataNode.INSTANCE.initialize(runtimeContext);
-		stub = (IMetadataNode) UnicastRemoteObject.exportObject(
-				MetadataNode.INSTANCE, 0);
-		proxy.setMetadataNode(stub);
+    public void registerRemoteMetadataNode(IAsterixStateProxy proxy) throws RemoteException {
+        IMetadataNode stub = null;
+        MetadataNode.INSTANCE.initialize(runtimeContext);
+        stub = (IMetadataNode) UnicastRemoteObject.exportObject(MetadataNode.INSTANCE, 0);
+        proxy.setMetadataNode(stub);
 
-		if (LOGGER.isLoggable(Level.INFO)) {
-			LOGGER.info("Metadata node bound");
-		}
-	}
+        if (LOGGER.isLoggable(Level.INFO)) {
+            LOGGER.info("Metadata node bound");
+        }
+    }
 
-	/**
-	 * Shutdown hook that invokes {@link NCApplicationEntryPoint#stop() stop}
-	 * method.
-	 */
-	private static class JVMShutdownHook extends Thread {
+    /**
+     * Shutdown hook that invokes {@link NCApplicationEntryPoint#stop() stop} method.
+     */
+    private static class JVMShutdownHook extends Thread {
 
-		private final NCApplicationEntryPoint ncAppEntryPoint;
+        private final NCApplicationEntryPoint ncAppEntryPoint;
 
-		public JVMShutdownHook(NCApplicationEntryPoint ncAppEntryPoint) {
-			this.ncAppEntryPoint = ncAppEntryPoint;
-		}
+        public JVMShutdownHook(NCApplicationEntryPoint ncAppEntryPoint) {
+            this.ncAppEntryPoint = ncAppEntryPoint;
+        }
 
-		public void run() {
-			if (LOGGER.isLoggable(Level.INFO)) {
-				LOGGER.info("Shutdown hook in progress");
-			}
-			try {
-				ncAppEntryPoint.stop();
-			} catch (Exception e) {
-				if (LOGGER.isLoggable(Level.WARNING)) {
-					LOGGER.warning("Exception in executing shutdown hook" + e);
-				}
-			}
-		}
-	}
+        public void run() {
+            if (LOGGER.isLoggable(Level.INFO)) {
+                LOGGER.info("Shutdown hook in progress");
+            }
+            try {
+                ncAppEntryPoint.stop();
+            } catch (Exception e) {
+                if (LOGGER.isLoggable(Level.WARNING)) {
+                    LOGGER.warning("Exception in executing shutdown hook" + e);
+                }
+            }
+        }
+    }
 
-}
\ No newline at end of file
+}
diff --git a/asterix-app/src/test/java/edu/uci/ics/asterix/test/aql/TestsUtils.java b/asterix-app/src/test/java/edu/uci/ics/asterix/test/aql/TestsUtils.java
deleted file mode 100644
index 04f1aae..0000000
--- a/asterix-app/src/test/java/edu/uci/ics/asterix/test/aql/TestsUtils.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package edu.uci.ics.asterix.test.aql;
-
-import static org.junit.Assert.fail;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
-
-public class TestsUtils {
-
-    private static final String EXTENSION_AQL_RESULT = "adm";
-
-    /**
-     * Probably does not work well with symlinks.
-     */
-    public static boolean deleteRec(File path) {
-        if (path.isDirectory()) {
-            for (File f : path.listFiles()) {
-                if (!deleteRec(f)) {
-                    return false;
-                }
-            }
-        }
-        return path.delete();
-    }
-
-    public static void runScriptAndCompareWithResult(File scriptFile, PrintWriter print, File expectedFile,
-            File actualFile) throws Exception {
-        BufferedReader readerExpected = new BufferedReader(new InputStreamReader(new FileInputStream(expectedFile),
-                "UTF-8"));
-        BufferedReader readerActual = new BufferedReader(
-                new InputStreamReader(new FileInputStream(actualFile), "UTF-8"));
-        String lineExpected, lineActual;
-        int num = 1;
-        try {
-            while ((lineExpected = readerExpected.readLine()) != null) {
-                lineActual = readerActual.readLine();
-                // Assert.assertEquals(lineExpected, lineActual);
-                if (lineActual == null) {
-                    if (lineExpected.isEmpty()) {
-                        continue;
-                    }
-                    throw new Exception("Result for " + scriptFile + " changed at line " + num + ":\n< " + lineExpected
-                            + "\n> ");
-                }
-
-                if (!equalStrings(lineExpected.split("Timestamp")[0], lineActual.split("Timestamp")[0])) {
-                    fail("Result for " + scriptFile + " changed at line " + num + ":\n< " + lineExpected + "\n> "
-                            + lineActual);
-                }
-
-                ++num;
-            }
-            lineActual = readerActual.readLine();
-            // Assert.assertEquals(null, lineActual);
-            if (lineActual != null) {
-                throw new Exception("Result for " + scriptFile + " changed at line " + num + ":\n< \n> " + lineActual);
-            }
-            // actualFile.delete();
-        } finally {
-            readerExpected.close();
-            readerActual.close();
-        }
-
-    }
-
-    private static boolean equalStrings(String s1, String s2) {
-        String[] rowsOne = s1.split("\n");
-        String[] rowsTwo = s2.split("\n");
-
-        for (int i = 0; i < rowsOne.length; i++) {
-            String row1 = rowsOne[i];
-            String row2 = rowsTwo[i];
-
-            if (row1.equals(row2))
-                continue;
-
-            String[] fields1 = row1.split(" ");
-            String[] fields2 = row2.split(" ");
-
-            for (int j = 0; j < fields1.length; j++) {
-                if (fields1[j].equals(fields2[j])) {
-                    continue;
-                } else if (fields1[j].indexOf('.') < 0) {
-                    return false;
-                } else {
-                    fields1[j] = fields1[j].split(",")[0];
-                    fields2[j] = fields2[j].split(",")[0];
-                    Double double1 = Double.parseDouble(fields1[j]);
-                    Double double2 = Double.parseDouble(fields2[j]);
-                    float float1 = (float) double1.doubleValue();
-                    float float2 = (float) double2.doubleValue();
-
-                    if (Math.abs(float1 - float2) == 0)
-                        continue;
-                    else {
-                        return false;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    public static String aqlExtToResExt(String fname) {
-        int dot = fname.lastIndexOf('.');
-        return fname.substring(0, dot + 1) + EXTENSION_AQL_RESULT;
-    }
-
-    public static void writeResultsToFile(File actualFile, JSONObject result) throws IOException, JSONException {
-        BufferedWriter writer = new BufferedWriter(new FileWriter(actualFile));
-        Results res = new Results(result);
-        for (String line : res) {
-            writer.write(line);
-            writer.newLine();
-        }
-        writer.close();
-    }
-
-    public static class Results implements Iterable<String> {
-        private final JSONArray chunks;
-
-        public Results(JSONObject result) throws JSONException {
-            chunks = result.getJSONArray("results");
-        }
-
-        public Iterator<String> iterator() {
-            return new ResultIterator(chunks);
-        }
-    }
-
-    public static class ResultIterator implements Iterator<String> {
-        private final JSONArray chunks;
-
-        private int chunkCounter = 0;
-        private int recordCounter = 0;
-
-        public ResultIterator(JSONArray chunks) {
-            this.chunks = chunks;
-        }
-
-        @Override
-        public boolean hasNext() {
-            JSONArray resultArray;
-            try {
-                resultArray = chunks.getJSONArray(chunkCounter);
-                if (resultArray.getString(recordCounter) != null) {
-                    return true;
-                }
-            } catch (JSONException e) {
-                return false;
-            }
-            return false;
-        }
-
-        @Override
-        public String next() throws NoSuchElementException {
-            JSONArray resultArray;
-            String item = "";
-
-            try {
-                resultArray = chunks.getJSONArray(chunkCounter);
-                item = resultArray.getString(recordCounter);
-                if (item == null) {
-                    throw new NoSuchElementException();
-                }
-                item = item.trim();
-
-                recordCounter++;
-                if (recordCounter >= resultArray.length()) {
-                    chunkCounter++;
-                    recordCounter = 0;
-                }
-            } catch (JSONException e) {
-                throw new NoSuchElementException(e.getMessage());
-            }
-            return item;
-        }
-
-        @Override
-        public void remove() {
-            throw new NotImplementedException();
-        }
-    }
-}
diff --git a/asterix-app/src/test/resources/logging.properties b/asterix-app/src/test/resources/logging.properties
index deb88307..77da7cd 100644
--- a/asterix-app/src/test/resources/logging.properties
+++ b/asterix-app/src/test/resources/logging.properties
@@ -63,3 +63,5 @@
 #edu.uci.ics.asterix.level = FINE
 #edu.uci.ics.algebricks.level = FINE
 #edu.uci.ics.hyracks.level = INFO
+edu.uci.ics.asterix.test = INFO
+edu.uci.ics.asterix.installer.test = INFO
diff --git a/asterix-app/src/test/resources/metadata/results/basic/meta16/meta16.1.adm b/asterix-app/src/test/resources/metadata/results/basic/meta16/meta16.1.adm
index b56fe7c..574a0a8 100644
--- a/asterix-app/src/test/resources/metadata/results/basic/meta16/meta16.1.adm
+++ b/asterix-app/src/test/resources/metadata/results/basic/meta16/meta16.1.adm
@@ -1,8 +1,9 @@
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "DataTypeName": "DatasetRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName" ], "PrimaryKey": [ "DataverseName", "DatasetName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "DataTypeName": "DatasourceAdapterRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name" ], "PrimaryKey": [ "DataverseName", "Name" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Datatype", "DataTypeName": "DatatypeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatatypeName" ], "PrimaryKey": [ "DataverseName", "DatatypeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "DataTypeName": "DataverseRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName" ], "PrimaryKey": [ "DataverseName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Function", "DataTypeName": "FunctionRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name", "Arity" ], "PrimaryKey": [ "DataverseName", "Name", "Arity" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Index", "DataTypeName": "IndexRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName", "IndexName" ], "PrimaryKey": [ "DataverseName", "DatasetName", "IndexName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Node", "DataTypeName": "NodeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "NodeName" ], "PrimaryKey": [ "NodeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "DataTypeName": "NodeGroupRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "GroupName" ], "PrimaryKey": [ "GroupName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Jan 29 18:54:03 PST 2013" }
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "DataTypeName": "DatasetRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName" ], "PrimaryKey": [ "DataverseName", "DatasetName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 2, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "DataTypeName": "DatasourceAdapterRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name" ], "PrimaryKey": [ "DataverseName", "Name" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 8, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Datatype", "DataTypeName": "DatatypeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatatypeName" ], "PrimaryKey": [ "DataverseName", "DatatypeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 3, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "DataTypeName": "DataverseRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName" ], "PrimaryKey": [ "DataverseName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 1, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Function", "DataTypeName": "FunctionRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name", "Arity" ], "PrimaryKey": [ "DataverseName", "Name", "Arity" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 7, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Index", "DataTypeName": "IndexRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName", "IndexName" ], "PrimaryKey": [ "DataverseName", "DatasetName", "IndexName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 4, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Library", "DataTypeName": "LibraryRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name" ], "PrimaryKey": [ "DataverseName", "Name" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 9, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Node", "DataTypeName": "NodeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "NodeName" ], "PrimaryKey": [ "NodeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 5, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "DataTypeName": "NodeGroupRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "GroupName" ], "PrimaryKey": [ "GroupName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 6, "PendingOp": 0 }
diff --git a/asterix-app/src/test/resources/metadata/results/basic/meta17/meta17.1.adm b/asterix-app/src/test/resources/metadata/results/basic/meta17/meta17.1.adm
index 2de89a6..be3ff8d 100644
--- a/asterix-app/src/test/resources/metadata/results/basic/meta17/meta17.1.adm
+++ b/asterix-app/src/test/resources/metadata/results/basic/meta17/meta17.1.adm
@@ -1,60 +1,61 @@
-{ "DataverseName": "Metadata", "DatatypeName": "DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "DataTypeName", "FieldType": "string" }, { "FieldName": "DatasetType", "FieldType": "string" }, { "FieldName": "InternalDetails", "FieldType": "Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "ExternalDetails", "FieldType": "Field_ExternalDetails_in_DatasetRecordType" }, { "FieldName": "FeedDetails", "FieldType": "Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Hints", "FieldType": "Field_Hints_in_DatasetRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "DatasourceAdapterRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Classname", "FieldType": "string" }, { "FieldName": "Type", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:30 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatatypeName", "FieldType": "string" }, { "FieldName": "Derived", "FieldType": "Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "DataverseRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DataFormat", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FieldName", "FieldType": "string" }, { "FieldName": "FieldType", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "Field_Hints_in_DatasetRecordType_ItemType", "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_NodeNames_in_NodeGroupRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "string", "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Params_in_FunctionRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:30 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_SearchKey_in_IndexRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "FunctionRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Arity", "FieldType": "string" }, { "FieldName": "Params", "FieldType": "Field_Params_in_FunctionRecordType" }, { "FieldName": "ReturnType", "FieldType": "string" }, { "FieldName": "Definition", "FieldType": "string" }, { "FieldName": "Language", "FieldType": "string" }, { "FieldName": "Kind", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:30 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "IndexRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "IndexName", "FieldType": "string" }, { "FieldName": "IndexStructure", "FieldType": "string" }, { "FieldName": "SearchKey", "FieldType": "Field_SearchKey_in_IndexRecordType" }, { "FieldName": "IsPrimary", "FieldType": "boolean" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "NodeGroupRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "NodeNames", "FieldType": "Field_NodeNames_in_NodeGroupRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "NodeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "NodeName", "FieldType": "string" }, { "FieldName": "NumberOfCores", "FieldType": "int32" }, { "FieldName": "WorkingMemorySize", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Tag", "FieldType": "string" }, { "FieldName": "IsAnonymous", "FieldType": "boolean" }, { "FieldName": "EnumValues", "FieldType": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Record", "FieldType": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Union", "FieldType": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "UnorderedList", "FieldType": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "OrderedList", "FieldType": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Function", "FieldType": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Status", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "IsOpen", "FieldType": "boolean" }, { "FieldName": "Fields", "FieldType": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "boolean", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "circle", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "date", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "datetime", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "double", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "duration", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "float", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int16", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int32", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int64", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int8", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "interval", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "line", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "null", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "point", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "point3d", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "polygon", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "rectangle", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "string", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "time", "Derived": null, "Timestamp": "Fri Feb 08 15:49:29 PST 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "DataTypeName", "FieldType": "string" }, { "FieldName": "DatasetType", "FieldType": "string" }, { "FieldName": "InternalDetails", "FieldType": "Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "ExternalDetails", "FieldType": "Field_ExternalDetails_in_DatasetRecordType" }, { "FieldName": "FeedDetails", "FieldType": "Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Hints", "FieldType": "Field_Hints_in_DatasetRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" }, { "FieldName": "DatasetId", "FieldType": "int32" }, { "FieldName": "PendingOp", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DatasourceAdapterRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Classname", "FieldType": "string" }, { "FieldName": "Type", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatatypeName", "FieldType": "string" }, { "FieldName": "Derived", "FieldType": "Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DataverseRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DataFormat", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" }, { "FieldName": "PendingOp", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FieldName", "FieldType": "string" }, { "FieldName": "FieldType", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "Field_Hints_in_DatasetRecordType_ItemType", "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_NodeNames_in_NodeGroupRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "string", "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Params_in_FunctionRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_SearchKey_in_IndexRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "FunctionRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Arity", "FieldType": "string" }, { "FieldName": "Params", "FieldType": "Field_Params_in_FunctionRecordType" }, { "FieldName": "ReturnType", "FieldType": "string" }, { "FieldName": "Definition", "FieldType": "string" }, { "FieldName": "Language", "FieldType": "string" }, { "FieldName": "Kind", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "IndexRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "IndexName", "FieldType": "string" }, { "FieldName": "IndexStructure", "FieldType": "string" }, { "FieldName": "SearchKey", "FieldType": "Field_SearchKey_in_IndexRecordType" }, { "FieldName": "IsPrimary", "FieldType": "boolean" }, { "FieldName": "Timestamp", "FieldType": "string" }, { "FieldName": "PendingOp", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "LibraryRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "NodeGroupRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "NodeNames", "FieldType": "Field_NodeNames_in_NodeGroupRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "NodeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "NodeName", "FieldType": "string" }, { "FieldName": "NumberOfCores", "FieldType": "int32" }, { "FieldName": "WorkingMemorySize", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Tag", "FieldType": "string" }, { "FieldName": "IsAnonymous", "FieldType": "boolean" }, { "FieldName": "EnumValues", "FieldType": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Record", "FieldType": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Union", "FieldType": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "UnorderedList", "FieldType": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "OrderedList", "FieldType": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Function", "FieldType": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Status", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "IsOpen", "FieldType": "boolean" }, { "FieldName": "Fields", "FieldType": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "boolean", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "circle", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "date", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "datetime", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "double", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "duration", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "float", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int16", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int32", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int64", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int8", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "interval", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "line", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "null", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "point", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "point3d", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "polygon", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "rectangle", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "string", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "time", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
diff --git a/asterix-app/src/test/resources/metadata/results/basic/meta19/meta19.1.adm b/asterix-app/src/test/resources/metadata/results/basic/meta19/meta19.1.adm
index 607bfd1..c3d4b22 100644
--- a/asterix-app/src/test/resources/metadata/results/basic/meta19/meta19.1.adm
+++ b/asterix-app/src/test/resources/metadata/results/basic/meta19/meta19.1.adm
@@ -1,11 +1,12 @@
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "Dataset", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "GroupName", "IndexStructure": "BTREE", "SearchKey": [ "GroupName", "DataverseName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "IndexName": "DatasourceAdapter", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "Datatype", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "NestedDatatypeName", "TopDatatypeName" ], "IsPrimary": false, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "IndexName": "Dataverse", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Function", "IndexName": "Function", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name", "Arity" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Index", "IndexName": "Index", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName", "IndexName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Node", "IndexName": "Node", "IndexStructure": "BTREE", "SearchKey": [ "NodeName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "IndexName": "Nodegroup", "IndexStructure": "BTREE", "SearchKey": [ "GroupName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "Dataset", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "GroupName", "IndexStructure": "BTREE", "SearchKey": [ "GroupName", "DataverseName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "IndexName": "DatasourceAdapter", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "Datatype", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "NestedDatatypeName", "TopDatatypeName" ], "IsPrimary": false, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "IndexName": "Dataverse", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Function", "IndexName": "Function", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name", "Arity" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Index", "IndexName": "Index", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName", "IndexName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Library", "IndexName": "Library", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Node", "IndexName": "Node", "IndexStructure": "BTREE", "SearchKey": [ "NodeName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "IndexName": "Nodegroup", "IndexStructure": "BTREE", "SearchKey": [ "GroupName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
diff --git a/asterix-app/src/test/resources/metadata/results/basic/metadata_dataset/metadata_dataset.1.adm b/asterix-app/src/test/resources/metadata/results/basic/metadata_dataset/metadata_dataset.1.adm
index 0078603..574a0a8 100644
--- a/asterix-app/src/test/resources/metadata/results/basic/metadata_dataset/metadata_dataset.1.adm
+++ b/asterix-app/src/test/resources/metadata/results/basic/metadata_dataset/metadata_dataset.1.adm
@@ -1,9 +1,9 @@
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "DataTypeName": "DatasetRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName" ], "PrimaryKey": [ "DataverseName", "DatasetName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "DataTypeName": "DatasourceAdapterRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name" ], "PrimaryKey": [ "DataverseName", "Name" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Datatype", "DataTypeName": "DatatypeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatatypeName" ], "PrimaryKey": [ "DataverseName", "DatatypeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "DataTypeName": "DataverseRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName" ], "PrimaryKey": [ "DataverseName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Function", "DataTypeName": "FunctionRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name", "Arity" ], "PrimaryKey": [ "DataverseName", "Name", "Arity" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Index", "DataTypeName": "IndexRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName", "IndexName" ], "PrimaryKey": [ "DataverseName", "DatasetName", "IndexName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Node", "DataTypeName": "NodeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "NodeName" ], "PrimaryKey": [ "NodeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "DataTypeName": "NodeGroupRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "GroupName" ], "PrimaryKey": [ "GroupName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "DataTypeName": "DatasetRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName" ], "PrimaryKey": [ "DataverseName", "DatasetName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 2, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "DataTypeName": "DatasourceAdapterRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name" ], "PrimaryKey": [ "DataverseName", "Name" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 8, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Datatype", "DataTypeName": "DatatypeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatatypeName" ], "PrimaryKey": [ "DataverseName", "DatatypeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 3, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "DataTypeName": "DataverseRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName" ], "PrimaryKey": [ "DataverseName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 1, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Function", "DataTypeName": "FunctionRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name", "Arity" ], "PrimaryKey": [ "DataverseName", "Name", "Arity" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 7, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Index", "DataTypeName": "IndexRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "DatasetName", "IndexName" ], "PrimaryKey": [ "DataverseName", "DatasetName", "IndexName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 4, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Library", "DataTypeName": "LibraryRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "DataverseName", "Name" ], "PrimaryKey": [ "DataverseName", "Name" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 9, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Node", "DataTypeName": "NodeRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "NodeName" ], "PrimaryKey": [ "NodeName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 5, "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "DataTypeName": "NodeGroupRecordType", "DatasetType": "INTERNAL", "InternalDetails": { "FileStructure": "BTREE", "PartitioningStrategy": "HASH", "PartitioningKey": [ "GroupName" ], "PrimaryKey": [ "GroupName" ], "GroupName": "MetadataGroup" }, "ExternalDetails": null, "FeedDetails": null, "Hints": {{  }}, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "DatasetId": 6, "PendingOp": 0 }
diff --git a/asterix-app/src/test/resources/metadata/results/basic/metadata_datatype/metadata_datatype.1.adm b/asterix-app/src/test/resources/metadata/results/basic/metadata_datatype/metadata_datatype.1.adm
index 84e2ca8..be3ff8d 100644
--- a/asterix-app/src/test/resources/metadata/results/basic/metadata_datatype/metadata_datatype.1.adm
+++ b/asterix-app/src/test/resources/metadata/results/basic/metadata_datatype/metadata_datatype.1.adm
@@ -1,60 +1,61 @@
-{ "DataverseName": "Metadata", "DatatypeName": "DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "DataTypeName", "FieldType": "string" }, { "FieldName": "DatasetType", "FieldType": "string" }, { "FieldName": "InternalDetails", "FieldType": "Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "ExternalDetails", "FieldType": "Field_ExternalDetails_in_DatasetRecordType" }, { "FieldName": "FeedDetails", "FieldType": "Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Hints", "FieldType": "Field_Hints_in_DatasetRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "DatasourceAdapterRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Classname", "FieldType": "string" }, { "FieldName": "Type", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatatypeName", "FieldType": "string" }, { "FieldName": "Derived", "FieldType": "Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "DataverseRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DataFormat", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FieldName", "FieldType": "string" }, { "FieldName": "FieldType", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "Field_Hints_in_DatasetRecordType_ItemType", "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_NodeNames_in_NodeGroupRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "string", "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Params_in_FunctionRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_SearchKey_in_IndexRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "FunctionRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Arity", "FieldType": "string" }, { "FieldName": "Params", "FieldType": "Field_Params_in_FunctionRecordType" }, { "FieldName": "ReturnType", "FieldType": "string" }, { "FieldName": "Definition", "FieldType": "string" }, { "FieldName": "Language", "FieldType": "string" }, { "FieldName": "Kind", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "IndexRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "IndexName", "FieldType": "string" }, { "FieldName": "IndexStructure", "FieldType": "string" }, { "FieldName": "SearchKey", "FieldType": "Field_SearchKey_in_IndexRecordType" }, { "FieldName": "IsPrimary", "FieldType": "boolean" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "NodeGroupRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "NodeNames", "FieldType": "Field_NodeNames_in_NodeGroupRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "NodeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "NodeName", "FieldType": "string" }, { "FieldName": "NumberOfCores", "FieldType": "int32" }, { "FieldName": "WorkingMemorySize", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Tag", "FieldType": "string" }, { "FieldName": "IsAnonymous", "FieldType": "boolean" }, { "FieldName": "EnumValues", "FieldType": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Record", "FieldType": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Union", "FieldType": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "UnorderedList", "FieldType": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "OrderedList", "FieldType": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Function", "FieldType": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Status", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "IsOpen", "FieldType": "boolean" }, { "FieldName": "Fields", "FieldType": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "boolean", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "circle", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "date", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "datetime", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "double", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "duration", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "float", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int16", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int32", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int64", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "int8", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "interval", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "line", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "null", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "point", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "point3d", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "polygon", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "rectangle", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "string", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
-{ "DataverseName": "Metadata", "DatatypeName": "time", "Derived": null, "Timestamp": "Fri Mar 29 11:19:47 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "DataTypeName", "FieldType": "string" }, { "FieldName": "DatasetType", "FieldType": "string" }, { "FieldName": "InternalDetails", "FieldType": "Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "ExternalDetails", "FieldType": "Field_ExternalDetails_in_DatasetRecordType" }, { "FieldName": "FeedDetails", "FieldType": "Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Hints", "FieldType": "Field_Hints_in_DatasetRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" }, { "FieldName": "DatasetId", "FieldType": "int32" }, { "FieldName": "PendingOp", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DatasourceAdapterRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Classname", "FieldType": "string" }, { "FieldName": "Type", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatatypeName", "FieldType": "string" }, { "FieldName": "Derived", "FieldType": "Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "DataverseRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DataFormat", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" }, { "FieldName": "PendingOp", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FieldName", "FieldType": "string" }, { "FieldName": "FieldType", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "Field_Hints_in_DatasetRecordType_ItemType", "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Hints_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_NodeNames_in_NodeGroupRecordType", "Derived": { "Tag": "UNORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": "string", "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Params_in_FunctionRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType_ItemType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Value", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_SearchKey_in_IndexRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "UNION", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": [ "null", "string" ], "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "FunctionRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Arity", "FieldType": "string" }, { "FieldName": "Params", "FieldType": "Field_Params_in_FunctionRecordType" }, { "FieldName": "ReturnType", "FieldType": "string" }, { "FieldName": "Definition", "FieldType": "string" }, { "FieldName": "Language", "FieldType": "string" }, { "FieldName": "Kind", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "IndexRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "DatasetName", "FieldType": "string" }, { "FieldName": "IndexName", "FieldType": "string" }, { "FieldName": "IndexStructure", "FieldType": "string" }, { "FieldName": "SearchKey", "FieldType": "Field_SearchKey_in_IndexRecordType" }, { "FieldName": "IsPrimary", "FieldType": "boolean" }, { "FieldName": "Timestamp", "FieldType": "string" }, { "FieldName": "PendingOp", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "LibraryRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DataverseName", "FieldType": "string" }, { "FieldName": "Name", "FieldType": "string" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "NodeGroupRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "NodeNames", "FieldType": "Field_NodeNames_in_NodeGroupRecordType" }, { "FieldName": "Timestamp", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "NodeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": false, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "NodeName", "FieldType": "string" }, { "FieldName": "NumberOfCores", "FieldType": "int32" }, { "FieldName": "WorkingMemorySize", "FieldType": "int32" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "Tag", "FieldType": "string" }, { "FieldName": "IsAnonymous", "FieldType": "boolean" }, { "FieldName": "EnumValues", "FieldType": "Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Record", "FieldType": "Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "Union", "FieldType": "Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "UnorderedList", "FieldType": "Field_UnorderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" }, { "FieldName": "OrderedList", "FieldType": "Field_OrderedList_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_EnumValues_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_ExternalDetails_in_DatasetRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" }, { "FieldName": "DatasourceAdapter", "FieldType": "string" }, { "FieldName": "Properties", "FieldType": "Field_Properties_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Function", "FieldType": "Field_Function_in_Type_#1_UnionType_Field_FeedDetails_in_DatasetRecordType" }, { "FieldName": "Status", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "FileStructure", "FieldType": "string" }, { "FieldName": "PartitioningStrategy", "FieldType": "string" }, { "FieldName": "PartitioningKey", "FieldType": "Field_PartitioningKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "PrimaryKey", "FieldType": "Field_PrimaryKey_in_Type_#1_UnionType_Field_InternalDetails_in_DatasetRecordType" }, { "FieldName": "GroupName", "FieldType": "string" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "RECORD", "IsAnonymous": true, "EnumValues": null, "Record": { "IsOpen": true, "Fields": [ { "FieldName": "IsOpen", "FieldType": "boolean" }, { "FieldName": "Fields", "FieldType": "Field_Fields_in_Type_#1_UnionType_Field_Record_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType" } ] }, "Union": null, "UnorderedList": null, "OrderedList": null }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "Type_#1_UnionType_Field_Union_in_Type_#1_UnionType_Field_Derived_in_DatatypeRecordType", "Derived": { "Tag": "ORDEREDLIST", "IsAnonymous": true, "EnumValues": null, "Record": null, "Union": null, "UnorderedList": null, "OrderedList": "string" }, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "boolean", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "circle", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "date", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "datetime", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "double", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "duration", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "float", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int16", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int32", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int64", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "int8", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "interval", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "line", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "null", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "point", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "point3d", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "polygon", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "rectangle", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "string", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
+{ "DataverseName": "Metadata", "DatatypeName": "time", "Derived": null, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013" }
diff --git a/asterix-app/src/test/resources/metadata/results/basic/metadata_index/metadata_index.1.adm b/asterix-app/src/test/resources/metadata/results/basic/metadata_index/metadata_index.1.adm
index 607bfd1..c3d4b22 100644
--- a/asterix-app/src/test/resources/metadata/results/basic/metadata_index/metadata_index.1.adm
+++ b/asterix-app/src/test/resources/metadata/results/basic/metadata_index/metadata_index.1.adm
@@ -1,11 +1,12 @@
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "Dataset", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "GroupName", "IndexStructure": "BTREE", "SearchKey": [ "GroupName", "DataverseName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "IndexName": "DatasourceAdapter", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "Datatype", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "NestedDatatypeName", "TopDatatypeName" ], "IsPrimary": false, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "IndexName": "Dataverse", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Function", "IndexName": "Function", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name", "Arity" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Index", "IndexName": "Index", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName", "IndexName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Node", "IndexName": "Node", "IndexStructure": "BTREE", "SearchKey": [ "NodeName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
-{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "IndexName": "Nodegroup", "IndexStructure": "BTREE", "SearchKey": [ "GroupName" ], "IsPrimary": true, "Timestamp": "Mon Nov 05 10:33:40 PST 2012" }
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "Dataset", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataset", "IndexName": "GroupName", "IndexStructure": "BTREE", "SearchKey": [ "GroupName", "DataverseName", "DatasetName" ], "IsPrimary": false, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "DatasourceAdapter", "IndexName": "DatasourceAdapter", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "Datatype", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatatypeName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Datatype", "IndexName": "DatatypeName", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "NestedDatatypeName", "TopDatatypeName" ], "IsPrimary": false, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Dataverse", "IndexName": "Dataverse", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Function", "IndexName": "Function", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name", "Arity" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Index", "IndexName": "Index", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "DatasetName", "IndexName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Library", "IndexName": "Library", "IndexStructure": "BTREE", "SearchKey": [ "DataverseName", "Name" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Node", "IndexName": "Node", "IndexStructure": "BTREE", "SearchKey": [ "NodeName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "Metadata", "DatasetName": "Nodegroup", "IndexName": "Nodegroup", "IndexStructure": "BTREE", "SearchKey": [ "GroupName" ], "IsPrimary": true, "Timestamp": "Tue Apr 16 20:41:54 PDT 2013", "PendingOp": 0 }
diff --git a/asterix-app/src/test/resources/nontagged/custord/local/all-scan.aql b/asterix-app/src/test/resources/nontagged/custord/local/all-scan.aql
index 1bd4b73..cd51b5e 100644
--- a/asterix-app/src/test/resources/nontagged/custord/local/all-scan.aql
+++ b/asterix-app/src/test/resources/nontagged/custord/local/all-scan.aql
@@ -52,4 +52,4 @@
 let $c3 := int32("320")
 let $c4 := int64("640")
 return {"int8": $c1,"int16": $c2,"int32": $c3, "int8co": $o.int8co, "int64": $c4}
-*/
\ No newline at end of file
+*/
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.1.ddl.aql b/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.1.ddl.aql
new file mode 100644
index 0000000..1883c94
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.1.ddl.aql
@@ -0,0 +1,24 @@
+/* 
+ * Test case Name  : insert-into-empty-dataset.aql
+ * Description     : Check that we can insert into an empty dataset 
+ * Expected Result : Success
+ * Date            : May 2 2012
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+
+use dataverse test;
+
+create type LineIDType as closed {
+  l_orderkey: int32, 
+  l_linenumber: int32, 
+  l_suppkey: int32
+}
+
+create dataset LineID(LineIDType)
+  primary key l_orderkey, l_linenumber;
+  
+create dataset LineID2(LineIDType)
+  primary key l_orderkey, l_linenumber;
+
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.2.update.aql b/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.2.update.aql
new file mode 100644
index 0000000..e155837
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.2.update.aql
@@ -0,0 +1,35 @@
+/* 
+ * Test case Name  : insert-into-empty-dataset.aql
+ * Description     : Check that we can insert into an empty dataset 
+ * Expected Result : Success
+ * Date            : May 2 2012
+ */
+
+use dataverse test;
+
+insert into dataset LineID (
+let $x:=1
+let $y:=2
+let $z:=3
+return {
+	"l_orderkey": $x,
+	"l_linenumber": $y,
+	"l_suppkey": $z
+}
+);
+
+insert into dataset LineID (
+let $x:=2
+let $y:=3
+let $z:=4
+return {
+	"l_orderkey": $x,
+	"l_linenumber": $y,
+	"l_suppkey": $z
+}
+);
+
+insert into dataset LineID2 (
+  for $x in dataset LineID
+  return flow-record($x)
+);
diff --git a/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.3.query.aql b/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.3.query.aql
new file mode 100644
index 0000000..e4763e5
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/queries/dml/insert-record-function/insert-record-function.3.query.aql
@@ -0,0 +1,12 @@
+/* 
+ * Test case Name  : insert-into-empty-dataset.aql
+ * Description     : Check that we can insert into an empty dataset 
+ * Expected Result : Success
+ * Date            : May 2 2012
+ */
+
+use dataverse test;
+
+for $c in dataset('LineID2')
+order by $c.l_orderkey, $c.l_linenumber
+return $c
diff --git a/asterix-app/src/test/resources/runtimets/results/dml/insert-record-function/insert-record-function.1.adm b/asterix-app/src/test/resources/runtimets/results/dml/insert-record-function/insert-record-function.1.adm
new file mode 100644
index 0000000..3ea2b0c
--- /dev/null
+++ b/asterix-app/src/test/resources/runtimets/results/dml/insert-record-function/insert-record-function.1.adm
@@ -0,0 +1,2 @@
+{ "l_orderkey": 1, "l_linenumber": 2, "l_suppkey": 3 }
+{ "l_orderkey": 2, "l_linenumber": 3, "l_suppkey": 4 }
\ No newline at end of file
diff --git a/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterix-app/src/test/resources/runtimets/testsuite.xml
index dd29a7b..faf635c 100644
--- a/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -818,6 +818,11 @@
         <output-dir compare="Text">insert-syntax</output-dir>
       </compilation-unit>
     </test-case>
+     <test-case FilePath="dml">
+      <compilation-unit name="insert-record-function">
+        <output-dir compare="Text">insert-record-function</output-dir>
+      </compilation-unit>
+    </test-case>
     <test-case FilePath="dml">
       <compilation-unit name="insert-into-loaded-dataset-with-index_01">
         <output-dir compare="Text">insert-into-loaded-dataset-with-index_01</output-dir>
diff --git a/asterix-aql/pom.xml b/asterix-aql/pom.xml
index 038ec62..c2573c8 100644
--- a/asterix-aql/pom.xml
+++ b/asterix-aql/pom.xml
@@ -82,6 +82,12 @@
 	</build>
 
 	<dependencies>
+                <dependency>
+                        <groupId>junit</groupId>
+                        <artifactId>junit</artifactId>
+                        <version>4.8.1</version>
+                        <scope>test</scope>
+                </dependency>
 		<dependency>
 			<groupId>edu.uci.ics.asterix</groupId>
 			<artifactId>asterix-common</artifactId>
diff --git a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/BeginFeedStatement.java b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/BeginFeedStatement.java
index 422ca79..0ff261f 100644
--- a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/BeginFeedStatement.java
+++ b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/expression/BeginFeedStatement.java
@@ -53,7 +53,7 @@
                 builder.append(" let $y:=(" + function.getFunctionBody() + ")" + " return $y");
             } else {
                 builder.append(" (" + " for $x in feed-ingest ('" + datasetName + "') ");
-                builder.append(" let $y:=" + function.getName() + "(" + "$x" + ")");
+                builder.append(" let $y:=" + dataset.getDataverseName() + "." + function.getName() + "(" + "$x" + ")");
                 builder.append(" return $y");
             }
 
diff --git a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/rewrites/AqlRewriter.java b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/rewrites/AqlRewriter.java
index 62e40fa..d295ffb 100644
--- a/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/rewrites/AqlRewriter.java
+++ b/asterix-aql/src/main/java/edu/uci/ics/asterix/aql/rewrites/AqlRewriter.java
@@ -161,34 +161,41 @@
                 continue;
             }
 
-            FunctionDecl functionDecl = lookupUserDefinedFunctionDecl(signature);
-            if (functionDecl != null) {
-                if (functionDecls.contains(functionDecl)) {
-                    throw new AsterixException(" Detected recursvity!");
-                } else {
-                    functionDecls.add(functionDecl);
-                    buildOtherUdfs(functionDecl.getFuncBody(), functionDecls, declaredFunctions);
-                }
-            } else {
+            Function function = lookupUserDefinedFunctionDecl(signature);
+            if (function == null) {
                 if (isBuiltinFunction(signature)) {
                     continue;
+                }
+                StringBuilder messageBuilder = new StringBuilder();
+                if (functionDecls.size() > 0) {
+                    messageBuilder.append(" function " + functionDecls.get(functionDecls.size() - 1).getSignature()
+                            + " depends upon function " + signature + " which is undefined");
                 } else {
-                    throw new AsterixException(" unknown function " + signature);
+                    messageBuilder.append(" function " + signature + " is undefined ");
+                }
+                throw new AsterixException(messageBuilder.toString());
+            }
+
+            if (function.getLanguage().equalsIgnoreCase(Function.LANGUAGE_AQL)) {
+                FunctionDecl functionDecl = FunctionUtils.getFunctionDecl(function);
+                if (functionDecl != null) {
+                    if (functionDecls.contains(functionDecl)) {
+                        throw new AsterixException("ERROR:Recursive invocation "
+                                + functionDecls.get(functionDecls.size() - 1).getSignature() + " <==> "
+                                + functionDecl.getSignature());
+                    }
+                    functionDecls.add(functionDecl);
+                    buildOtherUdfs(functionDecl.getFuncBody(), functionDecls, declaredFunctions);
                 }
             }
         }
     }
 
-    private FunctionDecl lookupUserDefinedFunctionDecl(FunctionSignature signature) throws AsterixException {
+    private Function lookupUserDefinedFunctionDecl(FunctionSignature signature) throws AsterixException {
         if (signature.getNamespace() == null) {
             return null;
         }
-        Function function = MetadataManager.INSTANCE.getFunction(mdTxnCtx, signature);
-        if (function == null) {
-            return null;
-        }
-        return FunctionUtils.getFunctionDecl(function);
-
+        return MetadataManager.INSTANCE.getFunction(mdTxnCtx, signature);
     }
 
     private boolean isBuiltinFunction(FunctionSignature functionSignature) {
diff --git a/asterix-aql/src/main/javacc/AQL.jj b/asterix-aql/src/main/javacc/AQL.jj
index be7d954..e234bb8 100644
--- a/asterix-aql/src/main/javacc/AQL.jj
+++ b/asterix-aql/src/main/javacc/AQL.jj
@@ -816,7 +816,9 @@
     FunctionSignature appliedFunction=null;
 	String dataverse;
 	String functionName;
+	String libraryName;
 	int arity;
+	Triple<String,String,String> functionCallComponents = null;
 }
 {
    "using"
@@ -829,11 +831,18 @@
     }
   
   ("apply" "function" 
-  {
-  nameComponents = getDotSeparatedPair();
-  dataverse = nameComponents.first != null ? nameComponents.first.getValue() : defaultDataverse;
-  functionName = nameComponents.second.getValue();
-  }
+   (
+      ( functionCallComponents = getFunctionCallComponents() )
+       {
+         dataverse = functionCallComponents.first == null ? defaultDataverse : functionCallComponents.first;
+         libraryName = functionCallComponents.second;
+         functionName = functionCallComponents.third;
+         if(libraryName != null){
+          functionName = libraryName + ":" + functionName;
+         }
+       }
+     )
+     
   ("@" <INTEGER_LITERAL> 
      {
         arity = Integer.parseInt(token.image);
@@ -2051,15 +2060,30 @@
   List<Expression> argList = new ArrayList<Expression>();
   Expression tmp;
   int arity = 0;
-  String funcName;
-  String dataverse;
+  String funcName=null;
+  String dataverse=null;
+  String libraryName=null;
   String hint=null;
   String id1=null;
   String id2=null;
+  String first = null;
+  String second = null;
+  String third = null;
+  Triple<String,String,String> functionCallComponents = null;
 }
 {  
-    
-    <IDENTIFIER> { dataverse = defaultDataverse; funcName = token.image;} ("." <IDENTIFIER> { dataverse = funcName; funcName = token.image;})?
+    (
+      ( functionCallComponents = getFunctionCallComponents() )
+       {
+         dataverse = functionCallComponents.first == null ? defaultDataverse : functionCallComponents.first;
+         libraryName = functionCallComponents.second;
+         funcName = functionCallComponents.third;
+         if(libraryName != null){
+          funcName = libraryName + ":" + funcName;
+         }
+       } 
+    )
+
     {
        hint = getHint(token);
     }
@@ -2070,10 +2094,10 @@
      } ("," tmp = Expression() { argList.add(tmp); arity++; })*)? <RIGHTPAREN>
 
      {
-       FunctionSignature signature = lookupFunctionSignature(dataverse, funcName.toString(), arity);
+       FunctionSignature signature = lookupFunctionSignature(dataverse, funcName, arity);
              if(signature == null)
              {
-                signature = new FunctionSignature(dataverse, funcName.toString(), arity);
+                signature = new FunctionSignature(dataverse, funcName, arity);
              }
        callExpr = new CallExpr(signature,argList);
        if (hint != null && hint.startsWith(INDEXED_NESTED_LOOP_JOIN_HINT)) {
@@ -2083,6 +2107,43 @@
      }
 }
 
+Triple<String,String,String> getFunctionCallComponents() throws ParseException:
+{
+   String first = null;
+   String second = null;
+   String third = null;
+}
+{
+   <IDENTIFIER>{
+     first = token.image;
+   }
+   (
+    ("." <IDENTIFIER> {
+      second = token.image;
+    }
+    )? 
+    ( ":" <IDENTIFIER> {
+            third = token.image;
+      }
+    )?
+   )
+   {
+     if(second == null) {
+       if(third!=null){
+         second="" + first;
+       } else {
+       third = "" + first;
+       }
+       first = null;
+     } else if (third == null) {
+       third = "" + second;
+       second = null;
+     }
+     return new Triple<String,String,String>(first,second,third);
+   }
+
+}
+
 Expression DatasetAccessExpression() throws ParseException:
 {
   CallExpr callExpr;
diff --git a/asterix-common/pom.xml b/asterix-common/pom.xml
index 0d5c506..5930ea5 100644
--- a/asterix-common/pom.xml
+++ b/asterix-common/pom.xml
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<artifactId>asterix</artifactId>
@@ -18,11 +19,38 @@
 					<fork>true</fork>
 				</configuration>
 			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<version>2.2</version>
+				<configuration>
+					<includes>
+						<include>**/*.class</include>
+					</includes>
+				</configuration>
+				<executions>
+					<execution>
+						<goals>
+							<goal>test-jar</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
 		</plugins>
 	</build>
 
 	<dependencies>
 		<dependency>
+			<groupId>commons-io</groupId>
+			<artifactId>commons-io</artifactId>
+			<version>1.4</version>
+		</dependency>
+		<dependency>
+			<groupId>commons-httpclient</groupId>
+			<artifactId>commons-httpclient</artifactId>
+			<version>3.0.1</version>
+		</dependency>
+		<dependency>
 			<groupId>edu.uci.ics.hyracks</groupId>
 			<artifactId>algebricks-compiler</artifactId>
 		</dependency>
@@ -38,6 +66,19 @@
 			<scope>compile</scope>
 		</dependency>
 		<dependency>
+			<groupId>edu.uci.ics.asterix</groupId>
+			<artifactId>asterix-test-framework</artifactId>
+			<version>0.0.6-SNAPSHOT</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.8.1</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
 			<groupId>edu.uci.ics.hyracks</groupId>
 			<artifactId>hyracks-storage-am-lsm-common</artifactId>
 		</dependency>
diff --git a/asterix-common/src/test/java/edu/uci/ics/asterix/test/aql/TestHelper.java b/asterix-common/src/test/java/edu/uci/ics/asterix/test/aql/TestHelper.java
new file mode 100644
index 0000000..5777d0a
--- /dev/null
+++ b/asterix-common/src/test/java/edu/uci/ics/asterix/test/aql/TestHelper.java
@@ -0,0 +1,16 @@
+package edu.uci.ics.asterix.test.aql;
+
+import java.util.List;
+
+public final class TestHelper {
+
+    public static boolean isInPrefixList(List<String> prefixList, String s) {
+        for (String s2 : prefixList) {
+            if (s.startsWith(s2)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/asterix-common/src/test/java/edu/uci/ics/asterix/test/aql/TestsUtils.java b/asterix-common/src/test/java/edu/uci/ics/asterix/test/aql/TestsUtils.java
new file mode 100644
index 0000000..7e9b08f
--- /dev/null
+++ b/asterix-common/src/test/java/edu/uci/ics/asterix/test/aql/TestsUtils.java
@@ -0,0 +1,428 @@
+package edu.uci.ics.asterix.test.aql;
+
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.logging.Logger;
+
+import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import edu.uci.ics.asterix.testframework.context.TestCaseContext;
+import edu.uci.ics.asterix.testframework.context.TestFileContext;
+import edu.uci.ics.asterix.testframework.xml.TestCase.CompilationUnit;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+
+public class TestsUtils {
+
+	private static final String EXTENSION_AQL_RESULT = "adm";
+	private static final Logger LOGGER = Logger.getLogger(TestsUtils.class
+			.getName());
+	private static Method managixExecuteMethod = null;
+
+	/**
+	 * Probably does not work well with symlinks.
+	 */
+	public static boolean deleteRec(File path) {
+		if (path.isDirectory()) {
+			for (File f : path.listFiles()) {
+				if (!deleteRec(f)) {
+					return false;
+				}
+			}
+		}
+		return path.delete();
+	}
+
+	public static void runScriptAndCompareWithResult(File scriptFile,
+			PrintWriter print, File expectedFile, File actualFile)
+			throws Exception {
+		BufferedReader readerExpected = new BufferedReader(
+				new InputStreamReader(new FileInputStream(expectedFile),
+						"UTF-8"));
+		BufferedReader readerActual = new BufferedReader(new InputStreamReader(
+				new FileInputStream(actualFile), "UTF-8"));
+		String lineExpected, lineActual;
+		int num = 1;
+		try {
+			while ((lineExpected = readerExpected.readLine()) != null) {
+				lineActual = readerActual.readLine();
+				// Assert.assertEquals(lineExpected, lineActual);
+				if (lineActual == null) {
+					if (lineExpected.isEmpty()) {
+						continue;
+					}
+					throw new Exception("Result for " + scriptFile
+							+ " changed at line " + num + ":\n< "
+							+ lineExpected + "\n> ");
+				}
+
+				if (!equalStrings(lineExpected.split("Timestamp")[0],
+						lineActual.split("Timestamp")[0])) {
+					fail("Result for " + scriptFile + " changed at line " + num
+							+ ":\n< " + lineExpected + "\n> " + lineActual);
+				}
+
+				++num;
+			}
+			lineActual = readerActual.readLine();
+			// Assert.assertEquals(null, lineActual);
+			if (lineActual != null) {
+				throw new Exception("Result for " + scriptFile
+						+ " changed at line " + num + ":\n< \n> " + lineActual);
+			}
+			// actualFile.delete();
+		} finally {
+			readerExpected.close();
+			readerActual.close();
+		}
+
+	}
+
+	private static boolean equalStrings(String s1, String s2) {
+		String[] rowsOne = s1.split("\n");
+		String[] rowsTwo = s2.split("\n");
+
+		for (int i = 0; i < rowsOne.length; i++) {
+			String row1 = rowsOne[i];
+			String row2 = rowsTwo[i];
+
+			if (row1.equals(row2))
+				continue;
+
+			String[] fields1 = row1.split(" ");
+			String[] fields2 = row2.split(" ");
+
+			for (int j = 0; j < fields1.length; j++) {
+				if (fields1[j].equals(fields2[j])) {
+					continue;
+				} else if (fields1[j].indexOf('.') < 0) {
+					return false;
+				} else {
+					fields1[j] = fields1[j].split(",")[0];
+					fields2[j] = fields2[j].split(",")[0];
+					Double double1 = Double.parseDouble(fields1[j]);
+					Double double2 = Double.parseDouble(fields2[j]);
+					float float1 = (float) double1.doubleValue();
+					float float2 = (float) double2.doubleValue();
+
+					if (Math.abs(float1 - float2) == 0)
+						continue;
+					else {
+						return false;
+					}
+				}
+			}
+		}
+		return true;
+	}
+
+	public static String aqlExtToResExt(String fname) {
+		int dot = fname.lastIndexOf('.');
+		return fname.substring(0, dot + 1) + EXTENSION_AQL_RESULT;
+	}
+
+	public static void writeResultsToFile(File actualFile, JSONObject result)
+			throws IOException, JSONException {
+		BufferedWriter writer = new BufferedWriter(new FileWriter(actualFile));
+		Results res = new Results(result);
+		for (String line : res) {
+			writer.write(line);
+			writer.newLine();
+		}
+		writer.close();
+	}
+
+	public static class Results implements Iterable<String> {
+		private final JSONArray chunks;
+
+		public Results(JSONObject result) throws JSONException {
+			chunks = result.getJSONArray("results");
+		}
+
+		public Iterator<String> iterator() {
+			return new ResultIterator(chunks);
+		}
+	}
+
+	public static class ResultIterator implements Iterator<String> {
+		private final JSONArray chunks;
+
+		private int chunkCounter = 0;
+		private int recordCounter = 0;
+
+		public ResultIterator(JSONArray chunks) {
+			this.chunks = chunks;
+		}
+
+		@Override
+		public boolean hasNext() {
+			JSONArray resultArray;
+			try {
+				resultArray = chunks.getJSONArray(chunkCounter);
+				if (resultArray.getString(recordCounter) != null) {
+					return true;
+				}
+			} catch (JSONException e) {
+				return false;
+			}
+			return false;
+		}
+
+		@Override
+		public String next() throws NoSuchElementException {
+			JSONArray resultArray;
+			String item = "";
+
+			try {
+				resultArray = chunks.getJSONArray(chunkCounter);
+				item = resultArray.getString(recordCounter);
+				if (item == null) {
+					throw new NoSuchElementException();
+				}
+				item = item.trim();
+
+				recordCounter++;
+				if (recordCounter >= resultArray.length()) {
+					chunkCounter++;
+					recordCounter = 0;
+				}
+			} catch (JSONException e) {
+				throw new NoSuchElementException(e.getMessage());
+			}
+			return item;
+		}
+
+		@Override
+		public void remove() {
+			throw new NotImplementedException();
+		}
+	}
+
+	// Executes Query and returns results as JSONArray
+	public static JSONObject executeQuery(String str) throws Exception {
+
+		final String url = "http://localhost:19101/query";
+
+		// Create an instance of HttpClient.
+		HttpClient client = new HttpClient();
+
+		// Create a method instance.
+		GetMethod method = new GetMethod(url);
+
+		method.setQueryString(new NameValuePair[] { new NameValuePair("query",
+				str) });
+
+		// Provide custom retry handler is necessary
+		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+				new DefaultHttpMethodRetryHandler(3, false));
+
+		JSONObject result = null;
+
+		try {
+			// Execute the method.
+			int statusCode = client.executeMethod(method);
+
+			// Check if the method was executed successfully.
+			if (statusCode != HttpStatus.SC_OK) {
+				System.err.println("Method failed: " + method.getStatusLine());
+			}
+
+			// Read the response body as String.
+			String responseBody = method.getResponseBodyAsString();
+
+			result = new JSONObject(responseBody);
+		} catch (Exception e) {
+			System.out.println(e.getMessage());
+			e.printStackTrace();
+		}
+		return result;
+	}
+
+	// To execute Update statements
+	// Insert and Delete statements are executed here
+	public static void executeUpdate(String str) throws Exception {
+		final String url = "http://localhost:19101/update";
+
+		// Create an instance of HttpClient.
+		HttpClient client = new HttpClient();
+
+		// Create a method instance.
+		GetMethod method = new GetMethod(url);
+
+		method.setQueryString(new NameValuePair[] { new NameValuePair(
+				"statements", str) });
+
+		// Provide custom retry handler is necessary
+		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+				new DefaultHttpMethodRetryHandler(3, false));
+
+		// Execute the method.
+		int statusCode = client.executeMethod(method);
+
+		// Check if the method was executed successfully.
+		if (statusCode != HttpStatus.SC_OK) {
+			System.err.println("Method failed: " + method.getStatusLine());
+		}
+	}
+
+	// To execute DDL and Update statements
+	// create type statement
+	// create dataset statement
+	// create index statement
+	// create dataverse statement
+	// create function statement
+	public static void executeDDL(String str) throws Exception {
+		final String url = "http://localhost:19101/ddl";
+
+		// Create an instance of HttpClient.
+		HttpClient client = new HttpClient();
+
+		// Create a method instance.
+		GetMethod method = new GetMethod(url);
+
+		method.setQueryString(new NameValuePair[] { new NameValuePair("ddl",
+				str) });
+
+		// Provide custom retry handler is necessary
+		method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+				new DefaultHttpMethodRetryHandler(3, false));
+
+		// Execute the method.
+		int statusCode = client.executeMethod(method);
+
+		// Check if the method was executed successfully.
+		if (statusCode != HttpStatus.SC_OK) {
+			System.err.println("Method failed: " + method.getStatusLine());
+		}
+	}
+
+	// Method that reads a DDL/Update/Query File
+	// and returns the contents as a string
+	// This string is later passed to REST API for execution.
+	public static String readTestFile(File testFile) throws Exception {
+		BufferedReader reader = new BufferedReader(new FileReader(testFile));
+		String line = null;
+		StringBuilder stringBuilder = new StringBuilder();
+		String ls = System.getProperty("line.separator");
+
+		while ((line = reader.readLine()) != null) {
+			stringBuilder.append(line);
+			stringBuilder.append(ls);
+		}
+
+		return stringBuilder.toString();
+	}
+
+	public static void executeManagixCommand(String command)
+			throws ClassNotFoundException, NoSuchMethodException,
+			SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+		if (managixExecuteMethod == null) {
+			Class clazz = Class
+					.forName("edu.uci.ics.asterix.installer.test.AsterixInstallerIntegrationUtil");
+			managixExecuteMethod = clazz.getMethod("executeCommand",
+					String.class);
+		}
+		managixExecuteMethod.invoke(null, command);
+	}
+
+	public static void executeTest(String actualPath,
+			TestCaseContext testCaseCtx) throws Exception {
+
+		File testFile;
+		File expectedResultFile;
+		String statement;
+		List<TestFileContext> expectedResultFileCtxs;
+		List<TestFileContext> testFileCtxs;
+
+		int queryCount = 0;
+		JSONObject result;
+
+		List<CompilationUnit> cUnits = testCaseCtx.getTestCase()
+				.getCompilationUnit();
+		for (CompilationUnit cUnit : cUnits) {
+			LOGGER.info("[TEST]: " + testCaseCtx.getTestCase().getFilePath()
+					+ "/" + cUnit.getName());
+
+			testFileCtxs = testCaseCtx.getTestFiles(cUnit);
+			expectedResultFileCtxs = testCaseCtx.getExpectedResultFiles(cUnit);
+
+			for (TestFileContext ctx : testFileCtxs) {
+				testFile = ctx.getFile();
+				statement = TestsUtils.readTestFile(testFile);
+				try {
+					switch (ctx.getType()) {
+					case "ddl":
+						TestsUtils.executeDDL(statement);
+						break;
+					case "update":
+						TestsUtils.executeUpdate(statement);
+						break;
+					case "query":
+						result = TestsUtils.executeQuery(statement);
+						if (!cUnit.getExpectedError().isEmpty()) {
+							if (!result.has("error")) {
+								throw new Exception("Test \"" + testFile
+										+ "\" FAILED!");
+							}
+						} else {
+							expectedResultFile = expectedResultFileCtxs.get(
+									queryCount).getFile();
+
+							File actualFile = new File(actualPath
+									+ File.separator
+									+ testCaseCtx.getTestCase().getFilePath()
+											.replace(File.separator, "_") + "_"
+									+ cUnit.getName() + ".adm");
+
+							File actualResultFile = testCaseCtx
+									.getActualResultFile(cUnit, new File(
+											actualPath));
+							actualResultFile.getParentFile().mkdirs();
+
+							TestsUtils.writeResultsToFile(actualFile, result);
+
+							TestsUtils.runScriptAndCompareWithResult(testFile,
+									new PrintWriter(System.err),
+									expectedResultFile, actualFile);
+						}
+						queryCount++;
+						break;
+					case "mgx":
+						executeManagixCommand(statement);
+						break;
+					default:
+						throw new IllegalArgumentException(
+								"No statements of type " + ctx.getType());
+					}
+				} catch (Exception e) {
+					if (cUnit.getExpectedError().isEmpty()) {
+						throw new Exception(
+								"Test \"" + testFile + "\" FAILED!", e);
+					}
+				}
+			}
+		}
+
+	}
+}
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
index 1721666..9b0a41a 100644
--- a/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/driver/EventDriver.java
@@ -156,4 +156,5 @@
         }
         EventUtil.executeLocalScript(clientNode, eventsDir + "/" + "events" + "/" + "cleanup.sh", args);
     }
+
 }
diff --git a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
index 0761c7f..1c51022 100644
--- a/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
+++ b/asterix-events/src/main/java/edu/uci/ics/asterix/event/management/EventUtil.java
@@ -36,251 +36,233 @@
 
 public class EventUtil {
 
-	public static final String EVENTS_DIR = "events";
-	public static final String CLUSTER_CONF = "config/cluster.xml";
-	public static final String PATTERN_CONF = "config/pattern.xml";
-	public static final DateFormat dateFormat = new SimpleDateFormat(
-			"yyyy/MM/dd HH:mm:ss");
+    public static final String EVENTS_DIR = "events";
+    public static final String CLUSTER_CONF = "config/cluster.xml";
+    public static final String PATTERN_CONF = "config/pattern.xml";
+    public static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
 
-	private static final String IP_LOCATION = "IP_LOCATION";
-	private static final String CLUSTER_ENV = "ENV";
-	private static final String SCRIPT = "SCRIPT";
-	private static final String ARGS = "ARGS";
-	private static final String EXECUTE_SCRIPT = "events/execute.sh";
-	private static final String LOCALHOST = "localhost";
-	private static final String LOCALHOST_IP = "127.0.0.1";
+    private static final String IP_LOCATION = "IP_LOCATION";
+    private static final String CLUSTER_ENV = "ENV";
+    private static final String SCRIPT = "SCRIPT";
+    private static final String ARGS = "ARGS";
+    private static final String EXECUTE_SCRIPT = "events/execute.sh";
+    private static final String LOCALHOST = "localhost";
+    private static final String LOCALHOST_IP = "127.0.0.1";
 
-    public static Cluster getCluster(String clusterConfigurationPath)
-			throws JAXBException {
-		File file = new File(clusterConfigurationPath);
-		JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
-		Unmarshaller unmarshaller = ctx.createUnmarshaller();
-		Cluster cluster = (Cluster) unmarshaller.unmarshal(file);
-		if (cluster.getMasterNode().getClusterIp().equals(LOCALHOST)) {
-			cluster.getMasterNode().setClusterIp(LOCALHOST_IP);
-		}
-		for (Node node : cluster.getNode()) {
-			if (node.getClusterIp().equals(LOCALHOST)) {
-				node.setClusterIp(LOCALHOST_IP);
-			}
-		}
-		return cluster;
-	}
+    public static Cluster getCluster(String clusterConfigurationPath) throws JAXBException {
+        File file = new File(clusterConfigurationPath);
+        JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
+        Unmarshaller unmarshaller = ctx.createUnmarshaller();
+        Cluster cluster = (Cluster) unmarshaller.unmarshal(file);
+        if (cluster.getMasterNode().getClusterIp().equals(LOCALHOST)) {
+            cluster.getMasterNode().setClusterIp(LOCALHOST_IP);
+        }
+        for (Node node : cluster.getNode()) {
+            if (node.getClusterIp().equals(LOCALHOST)) {
+                node.setClusterIp(LOCALHOST_IP);
+            }
+        }
+        return cluster;
+    }
 
-	public static long parseTimeInterval(ValueType v, String unit)
-			throws IllegalArgumentException {
-		int val = 0;
-		switch (v.getType()) {
-		case ABS:
-			val = Integer.parseInt(v.getAbsoluteValue());
-			break;
-		case RANDOM_MIN_MAX:
-			val = Randomizer.getInstance().getRandomInt(v.getMin(), v.getMax());
-			break;
-		case RANDOM_RANGE:
-			String[] values = v.getRangeSet();
-			val = Integer.parseInt(values[Randomizer.getInstance()
-					.getRandomInt(0, values.length - 1)]);
-			break;
-		}
-		return computeInterval(val, unit);
-	}
+    public static long parseTimeInterval(ValueType v, String unit) throws IllegalArgumentException {
+        int val = 0;
+        switch (v.getType()) {
+            case ABS:
+                val = Integer.parseInt(v.getAbsoluteValue());
+                break;
+            case RANDOM_MIN_MAX:
+                val = Randomizer.getInstance().getRandomInt(v.getMin(), v.getMax());
+                break;
+            case RANDOM_RANGE:
+                String[] values = v.getRangeSet();
+                val = Integer.parseInt(values[Randomizer.getInstance().getRandomInt(0, values.length - 1)]);
+                break;
+        }
+        return computeInterval(val, unit);
+    }
 
-	public static long parseTimeInterval(String v, String unit)
-			throws IllegalArgumentException {
-		int value = Integer.parseInt(v);
-		return computeInterval(value, unit);
-	}
+    public static long parseTimeInterval(String v, String unit) throws IllegalArgumentException {
+        int value = Integer.parseInt(v);
+        return computeInterval(value, unit);
+    }
 
-	private static long computeInterval(int val, String unit) {
-		int vmult = 1;
-		if ("hr".equalsIgnoreCase(unit)) {
-			vmult = 3600 * 1000;
-		} else if ("min".equalsIgnoreCase(unit)) {
-			vmult = 60 * 1000;
-		} else if ("sec".equalsIgnoreCase(unit)) {
-			vmult = 1000;
-		} else
-			throw new IllegalArgumentException(
-					" invalid unit value specified for frequency (hr,min,sec)");
-		return val * vmult;
+    private static long computeInterval(int val, String unit) {
+        int vmult = 1;
+        if ("hr".equalsIgnoreCase(unit)) {
+            vmult = 3600 * 1000;
+        } else if ("min".equalsIgnoreCase(unit)) {
+            vmult = 60 * 1000;
+        } else if ("sec".equalsIgnoreCase(unit)) {
+            vmult = 1000;
+        } else
+            throw new IllegalArgumentException(" invalid unit value specified for frequency (hr,min,sec)");
+        return val * vmult;
 
-	}
+    }
 
-	public static Event getEvent(Pattern pattern, Events events) {
-		for (Event event : events.getEvent()) {
-			if (event.getType().equals(pattern.getEvent().getType())) {
-				return event;
-			}
-		}
-		throw new IllegalArgumentException(" Unknown event type"
-				+ pattern.getEvent().getType());
-	}
+    public static Event getEvent(Pattern pattern, Events events) {
+        for (Event event : events.getEvent()) {
+            if (event.getType().equals(pattern.getEvent().getType())) {
+                return event;
+            }
+        }
+        throw new IllegalArgumentException(" Unknown event type" + pattern.getEvent().getType());
+    }
 
-	public static Node getEventLocation(Pattern pattern,
-			List<Node> candidateLocations, Cluster cluster) {
-		ValueType value = new ValueType(pattern.getEvent().getNodeid()
-				.getValue());
-		Node location = null;
-		Type vtype = value.getType();
+    public static Node getEventLocation(Pattern pattern, List<Node> candidateLocations, Cluster cluster) {
+        ValueType value = new ValueType(pattern.getEvent().getNodeid().getValue());
+        Node location = null;
+        Type vtype = value.getType();
 
-		switch (vtype) {
-		case ABS:
-			location = getNodeFromId(value.getAbsoluteValue(), cluster);
-			break;
-		case RANDOM_RANGE:
-			int nodeIndex = Randomizer.getInstance().getRandomInt(0,
-					candidateLocations.size() - 1);
-			location = candidateLocations.get(nodeIndex);
-			break;
-		case RANDOM_MIN_MAX:
-			throw new IllegalStateException(
-					" Canont configure a min max value range for location");
-		}
-		return location;
+        switch (vtype) {
+            case ABS:
+                location = getNodeFromId(value.getAbsoluteValue(), cluster);
+                break;
+            case RANDOM_RANGE:
+                int nodeIndex = Randomizer.getInstance().getRandomInt(0, candidateLocations.size() - 1);
+                location = candidateLocations.get(nodeIndex);
+                break;
+            case RANDOM_MIN_MAX:
+                throw new IllegalStateException(" Canont configure a min max value range for location");
+        }
+        return location;
 
-	}
+    }
 
-	public static List<Node> getCandidateLocations(Pattern pattern,
-			Cluster cluster) {
-		ValueType value = new ValueType(pattern.getEvent().getNodeid()
-				.getValue());
-		List<Node> candidateList = new ArrayList<Node>();
-		switch (value.getType()) {
-		case ABS:
-			candidateList.add(getNodeFromId(value.getAbsoluteValue(), cluster));
-			break;
-		case RANDOM_RANGE:
-			boolean anyOption = false;
-			String[] values = value.getRangeSet();
-			for (String v : values) {
-				if (v.equalsIgnoreCase("ANY")) {
-					anyOption = true;
-				}
-			}
-			if (anyOption) {
-				for (Node node : cluster.getNode()) {
-					candidateList.add(node);
-				}
-			} else {
-				boolean found = false;
-				for (String v : values) {
-					for (Node node : cluster.getNode()) {
-						if (node.getId().equals(v)) {
-							candidateList.add(node);
-							found = true;
-							break;
-						}
-					}
-					if (!found) {
-						throw new IllegalStateException("Unknonw nodeId : " + v);
-					}
-					found = false;
-				}
+    public static List<Node> getCandidateLocations(Pattern pattern, Cluster cluster) {
+        ValueType value = new ValueType(pattern.getEvent().getNodeid().getValue());
+        List<Node> candidateList = new ArrayList<Node>();
+        switch (value.getType()) {
+            case ABS:
+                candidateList.add(getNodeFromId(value.getAbsoluteValue(), cluster));
+                break;
+            case RANDOM_RANGE:
+                boolean anyOption = false;
+                String[] values = value.getRangeSet();
+                for (String v : values) {
+                    if (v.equalsIgnoreCase("ANY")) {
+                        anyOption = true;
+                    }
+                }
+                if (anyOption) {
+                    for (Node node : cluster.getNode()) {
+                        candidateList.add(node);
+                    }
+                } else {
+                    boolean found = false;
+                    for (String v : values) {
+                        for (Node node : cluster.getNode()) {
+                            if (node.getId().equals(v)) {
+                                candidateList.add(node);
+                                found = true;
+                                break;
+                            }
+                        }
+                        if (!found) {
+                            throw new IllegalStateException("Unknonw nodeId : " + v);
+                        }
+                        found = false;
+                    }
 
-			}
-			String[] excluded = value.getRangeExcluded();
-			if (excluded != null && excluded.length > 0) {
-				List<Node> markedForRemoval = new ArrayList<Node>();
-				for (String exclusion : excluded) {
-					for (Node node : candidateList) {
-						if (node.getId().equals(exclusion)) {
-							markedForRemoval.add(node);
-						}
-					}
-				}
-				candidateList.removeAll(markedForRemoval);
-			}
-			break;
-		case RANDOM_MIN_MAX:
-			throw new IllegalStateException(
-					" Invalid value configured for location");
-		}
-		return candidateList;
-	}
+                }
+                String[] excluded = value.getRangeExcluded();
+                if (excluded != null && excluded.length > 0) {
+                    List<Node> markedForRemoval = new ArrayList<Node>();
+                    for (String exclusion : excluded) {
+                        for (Node node : candidateList) {
+                            if (node.getId().equals(exclusion)) {
+                                markedForRemoval.add(node);
+                            }
+                        }
+                    }
+                    candidateList.removeAll(markedForRemoval);
+                }
+                break;
+            case RANDOM_MIN_MAX:
+                throw new IllegalStateException(" Invalid value configured for location");
+        }
+        return candidateList;
+    }
 
-	private static Node getNodeFromId(String nodeid, Cluster cluster) {
-		if (nodeid.equals(EventDriver.CLIENT_NODE.getId())) {
-			return EventDriver.CLIENT_NODE;
-		}
+    private static Node getNodeFromId(String nodeid, Cluster cluster) {
+        if (nodeid.equals(EventDriver.CLIENT_NODE.getId())) {
+            return EventDriver.CLIENT_NODE;
+        }
 
-		if (nodeid.equals(cluster.getMasterNode().getId())) {
-			String javaOpts = cluster.getMasterNode().getJavaOpts() == null ? cluster
-					.getJavaOpts() : cluster.getMasterNode().getJavaOpts();
-			String logDir = cluster.getMasterNode().getLogdir() == null ? cluster
-					.getLogdir() : cluster.getMasterNode().getLogdir();
-			String javaHome = cluster.getMasterNode().getJavaHome() == null ? cluster
-					.getJavaHome() : cluster.getMasterNode().getJavaHome();
-			BigInteger debug = cluster.getMasterNode().getDebug();
-			return new Node(cluster.getMasterNode().getId(), cluster
-					.getMasterNode().getClusterIp(), javaHome, javaOpts,
-					logDir, null, null, debug);
-		}
+        if (nodeid.equals(cluster.getMasterNode().getId())) {
+            String javaOpts = cluster.getMasterNode().getJavaOpts() == null ? cluster.getJavaOpts() : cluster
+                    .getMasterNode().getJavaOpts();
+            String logDir = cluster.getMasterNode().getLogdir() == null ? cluster.getLogdir() : cluster.getMasterNode()
+                    .getLogdir();
+            String javaHome = cluster.getMasterNode().getJavaHome() == null ? cluster.getJavaHome() : cluster
+                    .getMasterNode().getJavaHome();
+            BigInteger debug = cluster.getMasterNode().getDebug();
+            return new Node(cluster.getMasterNode().getId(), cluster.getMasterNode().getClusterIp(), javaHome,
+                    javaOpts, logDir, null, null, debug);
+        }
 
-		List<Node> nodeList = cluster.getNode();
-		for (Node node : nodeList) {
-			if (node.getId().equals(nodeid)) {
-				return node;
-			}
-		}
-		StringBuffer buffer = new StringBuffer();
-		buffer.append(EventDriver.CLIENT_NODE.getId() + ",");
-		buffer.append(cluster.getMasterNode().getId() + ",");
-		for (Node v : cluster.getNode()) {
-			buffer.append(v.getId() + ",");
-		}
-		buffer.deleteCharAt(buffer.length() - 1);
-		throw new IllegalArgumentException("Unknown node id :" + nodeid
-				+ " valid ids:" + buffer);
-	}
+        List<Node> nodeList = cluster.getNode();
+        for (Node node : nodeList) {
+            if (node.getId().equals(nodeid)) {
+                return node;
+            }
+        }
+        StringBuffer buffer = new StringBuffer();
+        buffer.append(EventDriver.CLIENT_NODE.getId() + ",");
+        buffer.append(cluster.getMasterNode().getId() + ",");
+        for (Node v : cluster.getNode()) {
+            buffer.append(v.getId() + ",");
+        }
+        buffer.deleteCharAt(buffer.length() - 1);
+        throw new IllegalArgumentException("Unknown node id :" + nodeid + " valid ids:" + buffer);
+    }
 
-	public static void executeEventScript(Node node, String script,
-			List<String> args, Cluster cluster) throws IOException,
-			InterruptedException {
-		List<String> pargs = new ArrayList<String>();
-		pargs.add("/bin/bash");
-		pargs.add(EventDriver.getEventsDir() + "/" + EXECUTE_SCRIPT);
-		StringBuffer argBuffer = new StringBuffer();
-		String env = EventDriver.getStringifiedEnv(cluster) + " " + IP_LOCATION
-				+ "=" + node.getClusterIp();
-		if (args != null) {
-			for (String arg : args) {
-				argBuffer.append(arg + " ");
-			}
-		}
-		ProcessBuilder pb = new ProcessBuilder(pargs);
-		pb.environment().putAll(EventDriver.getEnvironment());
-		pb.environment().put(IP_LOCATION, node.getClusterIp());
-		pb.environment().put(CLUSTER_ENV, env);
-		pb.environment().put(SCRIPT, script);
-		pb.environment().put(ARGS, argBuffer.toString());
-		pb.start();
-	}
+    public static void executeEventScript(Node node, String script, List<String> args, Cluster cluster)
+            throws IOException, InterruptedException {
+        List<String> pargs = new ArrayList<String>();
+        pargs.add("/bin/bash");
+        pargs.add(EventDriver.getEventsDir() + "/" + EXECUTE_SCRIPT);
+        StringBuffer argBuffer = new StringBuffer();
+        String env = EventDriver.getStringifiedEnv(cluster) + " " + IP_LOCATION + "=" + node.getClusterIp();
+        if (args != null) {
+            for (String arg : args) {
+                argBuffer.append(arg + " ");
+            }
+        }
+        ProcessBuilder pb = new ProcessBuilder(pargs);
+        pb.environment().putAll(EventDriver.getEnvironment());
+        pb.environment().put(IP_LOCATION, node.getClusterIp());
+        pb.environment().put(CLUSTER_ENV, env);
+        pb.environment().put(SCRIPT, script);
+        pb.environment().put(ARGS, argBuffer.toString());
+        pb.start();
+    }
 
-	public static void executeLocalScript(Node node, String script,
-			List<String> args) throws IOException, InterruptedException {
-		List<String> pargs = new ArrayList<String>();
-		pargs.add("/bin/bash");
-		pargs.add(script);
-		if (args != null) {
-			pargs.addAll(args);
-		}
-		ProcessBuilder pb = new ProcessBuilder(pargs);
-		pb.environment().putAll(EventDriver.getEnvironment());
-		pb.environment().put(IP_LOCATION, node.getClusterIp());
-		pb.start();
-	}
+    public static void executeLocalScript(Node node, String script, List<String> args) throws IOException,
+            InterruptedException {
+        List<String> pargs = new ArrayList<String>();
+        pargs.add("/bin/bash");
+        pargs.add(script);
+        if (args != null) {
+            pargs.addAll(args);
+        }
+        ProcessBuilder pb = new ProcessBuilder(pargs);
+        pb.environment().putAll(EventDriver.getEnvironment());
+        pb.environment().put(IP_LOCATION, node.getClusterIp());
+        pb.start();
+    }
 
-	public static List<String> getEventArgs(Pattern pattern) {
-		List<String> pargs = new ArrayList<String>();
-		if (pattern.getEvent().getPargs() == null) {
-			return pargs;
-		}
-		String[] args = pattern.getEvent().getPargs().split(" ");
-		for (String arg : args) {
-			pargs.add(arg.trim());
-		}
-		return pargs;
-	}
+    public static List<String> getEventArgs(Pattern pattern) {
+        List<String> pargs = new ArrayList<String>();
+        if (pattern.getEvent().getPargs() == null) {
+            return pargs;
+        }
+        String[] args = pattern.getEvent().getPargs().split(" ");
+        for (String arg : args) {
+            pargs.add(arg.trim());
+        }
+        return pargs;
+    }
 
 }
diff --git a/asterix-events/src/main/resources/events/events.xml b/asterix-events/src/main/resources/events/events.xml
index f85e3ea1..392afe9 100644
--- a/asterix-events/src/main/resources/events/events.xml
+++ b/asterix-events/src/main/resources/events/events.xml
@@ -73,7 +73,14 @@
     <type>file_delete</type>
     <script>file/delete.sh</script>
     <description>Deletes a file on the local file system to a remote node</description>
-    <args>local_source_path destination_node destination_path</args>
+    <args>destination_node destination_path</args>
+    <daemon>false</daemon>
+  </event>
+  <event>
+    <type>file_create</type>
+    <script>file/create_file.sh</script>
+    <description>Creates a file on the local file system to a remote node</description>
+    <args>destination_node destination_path</args>
     <daemon>false</daemon>
   </event>
   <event>
diff --git a/asterix-events/src/main/resources/events/file/create_file.sh b/asterix-events/src/main/resources/events/file/create_file.sh
new file mode 100644
index 0000000..762a2d3
--- /dev/null
+++ b/asterix-events/src/main/resources/events/file/create_file.sh
@@ -0,0 +1,3 @@
+mkdir -p $1
+echo "touch $1/$2" >> ~/file_create.log
+touch $1/$2
diff --git a/asterix-events/src/main/resources/events/node_join/nc_join.sh b/asterix-events/src/main/resources/events/node_join/nc_join.sh
index d8bbbd2..d89c32f 100755
--- a/asterix-events/src/main/resources/events/node_join/nc_join.sh
+++ b/asterix-events/src/main/resources/events/node_join/nc_join.sh
@@ -5,5 +5,7 @@
 then 
   mkdir -p $LOG_DIR
 fi
+
 cd $WORKING_DIR
 $ASTERIX_HOME/bin/asterixnc -node-id $NC_ID -cc-host $CC_HOST -cc-port 1099 -cluster-net-ip-address $IP_LOCATION  -data-ip-address $IP_LOCATION -iodevices $IO_DEVICES -result-ip-address $IP_LOCATION &> $LOG_DIR/${NC_ID}.log
+
diff --git a/asterix-external-data/pom.xml b/asterix-external-data/pom.xml
index 2e99b7c..714642e 100644
--- a/asterix-external-data/pom.xml
+++ b/asterix-external-data/pom.xml
@@ -1,4 +1,5 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<artifactId>asterix</artifactId>
@@ -20,53 +21,62 @@
 				</configuration>
 			</plugin>
 			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>appassembler-maven-plugin</artifactId>
-				<version>1.0</version>
+				<groupId>org.jvnet.jaxb2.maven2</groupId>
+				<artifactId>maven-jaxb2-plugin</artifactId>
 				<executions>
 					<execution>
-						<configuration>
-							<programs>
-								<program>
-									<mainClass>edu.uci.ics.asterix.drivers.AsterixWebServer</mainClass>
-									<name>asterix-web</name>
-								</program>
-								<program>
-									<mainClass>edu.uci.ics.asterix.drivers.AsterixClientDriver</mainClass>
-									<name>asterix-cmd</name>
-								</program>
-							</programs>
-							<repositoryLayout>flat</repositoryLayout>
-							<repositoryName>lib</repositoryName>
-						</configuration>
-						<phase>package</phase>
+						<id>configuration</id>
 						<goals>
-							<goal>assemble</goal>
+							<goal>generate</goal>
 						</goals>
+						<configuration>
+							<schemaDirectory>src/main/resources/schema</schemaDirectory>
+							<schemaIncludes>
+								<include>library.xsd</include>
+							</schemaIncludes>
+							<generatePackage>edu.uci.ics.asterix.external.library</generatePackage>
+							<generateDirectory>${project.build.directory}/generated-sources/configuration</generateDirectory>
+						</configuration>
 					</execution>
 				</executions>
 			</plugin>
 			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-surefire-plugin</artifactId>
-				<version>2.7.2</version>
+                                <groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<version>2.2</version>
 				<configuration>
-					<!-- doesn't work from m2eclipse, currently <additionalClasspathElements> 
-						<additionalClasspathElement>${basedir}/src/main/resources</additionalClasspathElement> 
-						</additionalClasspathElements> -->
-					<forkMode>pertest</forkMode>
-					<argLine>-enableassertions -Xmx${test.heap.size}m
-						-Dfile.encoding=UTF-8
-						-Djava.util.logging.config.file=src/test/resources/logging.properties</argLine>
-					<includes>
-						<include>**/*TestSuite.java</include>
-						<include>**/*Test.java</include>
-					</includes>
+                                    <includes>
+                                        <include>**/*.class</include>
+                                        <include>**/*.txt</include>
+                                    </includes>
 				</configuration>
+				<executions>
+					<execution>
+						<goals>
+						     <goal>test-jar</goal>
+						</goals>
+						<phase>package</phase>
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.2-beta-5</version>
+				<executions>
+					<execution>
+						<configuration>
+							<descriptor>src/main/assembly/binary-assembly-libzip.xml</descriptor>
+							<finalName>testlib-zip</finalName>
+						</configuration>
+						<phase>package</phase>
+						<goals>
+							<goal>attached</goal>
+						</goals>
+					</execution>
+				</executions>
 			</plugin>
 		</plugins>
 	</build>
-
 	<dependencies>
 		<dependency>
 			<groupId>javax.servlet</groupId>
@@ -96,6 +106,10 @@
 			<scope>compile</scope>
 		</dependency>
 		<dependency>
+			<groupId>edu.uci.ics.hyracks</groupId>
+			<artifactId>algebricks-compiler</artifactId>
+		</dependency>
+		<dependency>
 			<groupId>com.kenai.nbpwr</groupId>
 			<artifactId>org-apache-commons-io</artifactId>
 			<version>1.3.1-201002241208</version>
@@ -135,5 +149,4 @@
 			<version>1.0</version>
 		</dependency>
 	</dependencies>
-
-</project>
+</project> 
diff --git a/asterix-external-data/src/main/assembly/binary-assembly-libjar.xml b/asterix-external-data/src/main/assembly/binary-assembly-libjar.xml
new file mode 100644
index 0000000..d76174a
--- /dev/null
+++ b/asterix-external-data/src/main/assembly/binary-assembly-libjar.xml
@@ -0,0 +1,19 @@
+<assembly>
+  <id>binary-assembly</id>
+  <formats>
+    <format>jar</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>target/test-classes</directory>
+      <outputDirectory></outputDirectory>
+      <includes>
+        <include>**</include>
+      </includes>
+      <excludes>
+        <exclude>**.xml</exclude>
+      </excludes>
+    </fileSet>
+  </fileSets>
+</assembly>
diff --git a/asterix-external-data/src/main/assembly/binary-assembly-libzip.xml b/asterix-external-data/src/main/assembly/binary-assembly-libzip.xml
new file mode 100644
index 0000000..bec6e32
--- /dev/null
+++ b/asterix-external-data/src/main/assembly/binary-assembly-libzip.xml
@@ -0,0 +1,23 @@
+<assembly>
+  <id>binary-assembly</id>
+  <formats>
+    <format>zip</format>
+  </formats>
+  <includeBaseDirectory>false</includeBaseDirectory>
+  <fileSets>
+    <fileSet>
+      <directory>target</directory>
+      <outputDirectory></outputDirectory>
+      <includes>
+        <include>*test*.jar</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>src/test/resources</directory>
+      <outputDirectory></outputDirectory>
+      <includes>
+        <include>*.xml</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</assembly>
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/NCFileSystemAdapter.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/NCFileSystemAdapter.java
index ef39d45..7d378a8 100644
--- a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/NCFileSystemAdapter.java
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/NCFileSystemAdapter.java
@@ -36,30 +36,30 @@
  */
 public class NCFileSystemAdapter extends FileSystemBasedAdapter {
 
-    private static final long serialVersionUID = 1L;
-    private FileSplit[] fileSplits;
+	private static final long serialVersionUID = 1L;
+	private FileSplit[] fileSplits;
 
-    public NCFileSystemAdapter(IAType atype) {
-        super(atype);
-    }
+	public NCFileSystemAdapter(IAType atype) {
+		super(atype);
+	}
 
-    @Override
-    public void configure(Map<String, String> arguments) throws Exception {
-        this.configuration = arguments;
-        String[] splits = arguments.get(KEY_PATH).split(",");
-        configureFileSplits(splits);
-        configureFormat();
-    }
+	@Override
+	public void configure(Map<String, String> arguments) throws Exception {
+		this.configuration = arguments;
+		String[] splits = arguments.get(KEY_PATH).split(",");
+		configureFileSplits(splits);
+		configureFormat();
+	}
 
-    @Override
-    public void initialize(IHyracksTaskContext ctx) throws Exception {
-        this.ctx = ctx;
-    }
+	@Override
+	public void initialize(IHyracksTaskContext ctx) throws Exception {
+		this.ctx = ctx;
+	}
 
-    @Override
-    public AdapterType getAdapterType() {
-        return AdapterType.READ;
-    }
+	@Override
+	public AdapterType getAdapterType() {
+		return AdapterType.READ;
+	}
 
     private void configureFileSplits(String[] splits) throws AsterixException {
         if (fileSplits == null) {
@@ -92,24 +92,25 @@
         partitionConstraint = new AlgebricksAbsolutePartitionConstraint(locs);
     }
 
-    @Override
-    public InputStream getInputStream(int partition) throws IOException {
-        FileSplit split = fileSplits[partition];
-        File inputFile = split.getLocalFile().getFile();
-        InputStream in;
-        try {
-            in = new FileInputStream(inputFile);
-            return in;
-        } catch (FileNotFoundException e) {
-            throw new IOException(e);
-        }
-    }
+	@Override
+	public InputStream getInputStream(int partition) throws IOException {
+		FileSplit split = fileSplits[partition];
+		File inputFile = split.getLocalFile().getFile();
+		InputStream in;
+		try {
+			in = new FileInputStream(inputFile);
+			return in;
+		} catch (FileNotFoundException e) {
+			throw new IOException(e);
+		}
+	}
 
-    @Override
-    public AlgebricksPartitionConstraint getPartitionConstraint() throws Exception {
-        if (partitionConstraint == null) {
-            configurePartitionConstraint();
-        }
+	@Override
+	public AlgebricksPartitionConstraint getPartitionConstraint()
+			throws Exception {
+		if (partitionConstraint == null) {
+			configurePartitionConstraint();
+		}
         return partitionConstraint;
     }
 }
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/PullBasedTwitterFeedClient.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/PullBasedTwitterFeedClient.java
index 2a07472..2550be6 100644
--- a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/PullBasedTwitterFeedClient.java
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/dataset/adapter/PullBasedTwitterFeedClient.java
@@ -14,9 +14,10 @@
  */
 package edu.uci.ics.asterix.external.dataset.adapter;
 
-import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
-import java.util.Queue;
+import java.util.UUID;
+import java.util.logging.Logger;
 
 import twitter4j.Query;
 import twitter4j.QueryResult;
@@ -41,15 +42,17 @@
 
     private String keywords;
     private Query query;
-    private long id = 0;
     private String id_prefix;
     private Twitter twitter;
     private int requestInterval = 10; // seconds
-    private Queue<Tweet> tweetBuffer = new LinkedList<Tweet>();
+    private QueryResult result;
 
-    IAObject[] mutableFields;
-    String[] tupleFieldValues;
+    private IAObject[] mutableFields;
+    private String[] tupleFieldValues;
     private ARecordType recordType;
+    private int nextTweetIndex = 0;
+
+    private static final Logger LOGGER = Logger.getLogger(PullBasedTwitterFeedClient.class.getName());
 
     public PullBasedTwitterFeedClient(IHyracksTaskContext ctx, PullBasedTwitterAdapter adapter) {
         this.id_prefix = ctx.getJobletContext().getApplicationContext().getNodeId();
@@ -59,32 +62,8 @@
         recordType = adapter.getAdapterOutputType();
         recordSerDe = new ARecordSerializerDeserializer(recordType);
         mutableRecord = new AMutableRecord(recordType, mutableFields);
-        initialize(adapter.getConfiguration());
         tupleFieldValues = new String[recordType.getFieldNames().length];
-    }
-
-    public void initialize(Map<String, String> params) {
-        this.keywords = params.get(PullBasedTwitterAdapter.QUERY);
-        this.query = new Query(keywords);
-        query.setRpp(100);
-    }
-
-    private Tweet getNextTweet() throws TwitterException, InterruptedException {
-        if (tweetBuffer.isEmpty()) {
-            QueryResult result;
-            Thread.sleep(1000 * requestInterval);
-            result = twitter.search(query);
-            tweetBuffer.addAll(result.getTweets());
-        }
-        return tweetBuffer.remove();
-    }
-
-    public ARecordType getRecordType() {
-        return recordType;
-    }
-
-    public AMutableRecord getMutableRecord() {
-        return mutableRecord;
+        initialize(adapter.getConfiguration());
     }
 
     @Override
@@ -95,8 +74,7 @@
             return false;
         }
         int numFields = recordType.getFieldNames().length;
-
-        tupleFieldValues[0] = id_prefix + ":" + id;
+        tupleFieldValues[0] = UUID.randomUUID().toString();
         tupleFieldValues[1] = tweet.getFromUser();
         tupleFieldValues[2] = tweet.getLocation() == null ? "" : tweet.getLocation();
         tupleFieldValues[3] = tweet.getText();
@@ -105,7 +83,6 @@
             ((AMutableString) mutableFields[i]).setValue(tupleFieldValues[i]);
             mutableRecord.setValueAtPos(i, mutableFields[i]);
         }
-        id++;
         return true;
     }
 
@@ -114,4 +91,29 @@
         // TOOO: implement resetting logic for Twitter
     }
 
+    public ARecordType getRecordType() {
+        return recordType;
+    }
+
+    public AMutableRecord getMutableRecord() {
+        return mutableRecord;
+    }
+
+    private void initialize(Map<String, String> params) {
+        this.keywords = params.get(PullBasedTwitterAdapter.QUERY);
+        this.requestInterval = Integer.parseInt(params.get(PullBasedTwitterAdapter.INTERVAL));
+        this.query = new Query(keywords);
+        query.setRpp(100);
+    }
+
+    private Tweet getNextTweet() throws TwitterException, InterruptedException {
+        if (result == null || nextTweetIndex >= result.getTweets().size()) {
+            Thread.sleep(1000 * requestInterval);
+            result = twitter.search(query);
+            nextTweetIndex = 0;
+        }
+        List<Tweet> tw = result.getTweets();
+        return tw.get(nextTweetIndex++);
+    }
+
 }
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/AsterixExternalScalarFunctionInfo.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/AsterixExternalScalarFunctionInfo.java
new file mode 100644
index 0000000..f133d91
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/AsterixExternalScalarFunctionInfo.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2009-2012 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.external.library;
+
+import java.util.List;
+
+import edu.uci.ics.asterix.om.functions.AsterixExternalFunctionInfo;
+import edu.uci.ics.asterix.om.functions.AsterixFunction;
+import edu.uci.ics.asterix.om.typecomputer.base.IResultTypeComputer;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
+
+public class AsterixExternalScalarFunctionInfo extends AsterixExternalFunctionInfo {
+
+    private static final long serialVersionUID = 1L;
+
+    public AsterixExternalScalarFunctionInfo(String namespace, AsterixFunction asterixFunction, IAType returnType,
+            String body, String language, List<IAType> argumentTypes, IResultTypeComputer rtc) {
+        super(namespace, asterixFunction, FunctionKind.SCALAR, argumentTypes, returnType, rtc, body, language);
+    }
+
+    public AsterixExternalScalarFunctionInfo() {
+        super();
+    }
+
+    
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunction.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunction.java
new file mode 100755
index 0000000..aaa5403
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunction.java
@@ -0,0 +1,75 @@
+package edu.uci.ics.asterix.external.library;
+
+import java.io.IOException;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+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.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public abstract class ExternalFunction implements IExternalFunction {
+
+    protected final IExternalFunctionInfo finfo;
+    protected final IFunctionFactory externalFunctionFactory;
+    protected final IExternalFunction externalFunction;
+    protected final ICopyEvaluatorFactory[] evaluatorFactories;
+    protected final IDataOutputProvider out;
+    protected final ArrayBackedValueStorage inputVal = new ArrayBackedValueStorage();
+    protected final ICopyEvaluator[] argumentEvaluators;
+    protected final JavaFunctionHelper functionHelper;
+
+    public ExternalFunction(IExternalFunctionInfo finfo, ICopyEvaluatorFactory args[],
+            IDataOutputProvider outputProvider) throws AlgebricksException {
+        this.finfo = finfo;
+        this.evaluatorFactories = args;
+        this.out = outputProvider;
+        argumentEvaluators = new ICopyEvaluator[args.length];
+        for (int i = 0; i < args.length; i++) {
+            argumentEvaluators[i] = args[i].createEvaluator(inputVal);
+        }
+        functionHelper = new JavaFunctionHelper(finfo, outputProvider);
+
+        String[] fnameComponents = finfo.getFunctionIdentifier().getName().split(":");
+        String functionLibary = fnameComponents[0];
+        String dataverse = finfo.getFunctionIdentifier().getNamespace();
+        ClassLoader libraryClassLoader = ExternalLibraryManager.getLibraryClassLoader(dataverse, functionLibary);
+        String classname = finfo.getFunctionBody().trim();
+        Class clazz;
+        try {
+            clazz = Class.forName(classname, true, libraryClassLoader);
+            externalFunctionFactory = (IFunctionFactory) clazz.newInstance();
+            externalFunction = externalFunctionFactory.getExternalFunction();
+        } catch (Exception e) {
+            throw new AlgebricksException(" Unable to load/instantiate class " + classname, e);
+        }
+    }
+
+    public static ISerializerDeserializer getSerDe(Object typeInfo) {
+        return AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(typeInfo);
+    }
+
+    public IExternalFunctionInfo getFinfo() {
+        return finfo;
+    }
+
+    public void setArguments(IFrameTupleReference tuple) throws AlgebricksException, IOException, AsterixException {
+        for (int i = 0; i < evaluatorFactories.length; i++) {
+            inputVal.reset();
+            argumentEvaluators[i].evaluate(tuple);
+            functionHelper.setArgument(i, inputVal.getByteArray());
+        }
+    }
+
+    @Override
+    public void deinitialize() {
+        externalFunction.deinitialize();
+    }
+
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunctionDescriptorProvider.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunctionDescriptorProvider.java
new file mode 100755
index 0000000..b5888a6
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunctionDescriptorProvider.java
@@ -0,0 +1,51 @@
+package edu.uci.ics.asterix.external.library;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+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.core.algebra.functions.IFunctionInfo;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+
+public class ExternalFunctionDescriptorProvider {
+
+    public static IFunctionDescriptor getExternalFunctionDescriptor(IExternalFunctionInfo finfo) throws AsterixException {
+        switch (finfo.getKind()) {
+            case SCALAR:
+                return new ExternalScalarFunctionDescriptor(finfo);
+            case AGGREGATE:
+            case UNNEST:
+                throw new AsterixException("Unsupported function kind :" + finfo.getKind());
+            default:
+                break;
+        }
+        return null;
+    }
+
+}
+
+class ExternalScalarFunctionDescriptor extends AbstractScalarFunctionDynamicDescriptor implements IFunctionDescriptor {
+
+    private final IFunctionInfo finfo;
+    private ICopyEvaluatorFactory evaluatorFactory;
+    private ICopyEvaluatorFactory[] args;
+
+    @Override
+    public ICopyEvaluatorFactory createEvaluatorFactory(ICopyEvaluatorFactory[] args) throws AlgebricksException {
+        evaluatorFactory = new ExternalScalarFunctionEvaluatorFactory((IExternalFunctionInfo) finfo, args);
+        return evaluatorFactory;
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return finfo.getFunctionIdentifier();
+    }
+
+    public ExternalScalarFunctionDescriptor(IFunctionInfo finfo) {
+        this.finfo = finfo;
+    }
+
+}
+
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunctionProvider.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunctionProvider.java
new file mode 100755
index 0000000..db6c224
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalFunctionProvider.java
@@ -0,0 +1,65 @@
+package edu.uci.ics.asterix.external.library;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class ExternalFunctionProvider {
+
+    private static Map<IExternalFunctionInfo, ExternalScalarFunction> functionRepo = new HashMap<IExternalFunctionInfo, ExternalScalarFunction>();
+
+    public static IExternalFunction getExternalFunctionEvaluator(IExternalFunctionInfo finfo,
+            ICopyEvaluatorFactory args[], IDataOutputProvider outputProvider) throws AlgebricksException {
+        switch (finfo.getKind()) {
+            case SCALAR:
+                ExternalScalarFunction function = functionRepo.get(finfo);
+                function = new ExternalScalarFunction(finfo, args, outputProvider);
+                // functionRepo.put(finfo, function);
+                return function;
+            case AGGREGATE:
+            case UNNEST:
+                throw new IllegalArgumentException(" not supported function kind" + finfo.getKind());
+            default:
+                throw new IllegalArgumentException(" unknown function kind" + finfo.getKind());
+        }
+    }
+}
+
+class ExternalScalarFunction extends ExternalFunction implements IExternalScalarFunction, ICopyEvaluator {
+
+    public ExternalScalarFunction(IExternalFunctionInfo finfo, ICopyEvaluatorFactory args[],
+            IDataOutputProvider outputProvider) throws AlgebricksException {
+        super(finfo, args, outputProvider);
+        try {
+            initialize(functionHelper);
+        } catch (Exception e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    @Override
+    public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {
+        try {
+            setArguments(tuple);
+            evaluate(functionHelper);
+        } catch (Exception e) {
+            throw new AlgebricksException(e);
+        }
+    }
+
+    public void evaluate(IFunctionHelper argumentProvider) throws Exception {
+        ((IExternalScalarFunction) externalFunction).evaluate(argumentProvider);
+    }
+
+    @Override
+    public void initialize(IFunctionHelper functionHelper) throws Exception {
+        ((IExternalScalarFunction) externalFunction).initialize(functionHelper);
+    }
+
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalLibraryManager.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalLibraryManager.java
new file mode 100755
index 0000000..520020d
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalLibraryManager.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009-2012 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.external.library;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ExternalLibraryManager {
+
+    private static Map<String, ClassLoader> libraryClassLoaders = new HashMap<String, ClassLoader>();
+
+    public static void registerLibraryClassLoader(String dataverseName, String libraryName, ClassLoader classLoader) {
+        String key = dataverseName + "." + libraryName;
+        synchronized (libraryClassLoaders) {
+            if (libraryClassLoaders.get(dataverseName) != null) {
+                throw new IllegalStateException("library class loader already registered!");
+            }
+            libraryClassLoaders.put(key, classLoader);
+        }
+    }
+
+    public static void deregisterLibraryClassLoader(String dataverseName, String libraryName) {
+        String key = dataverseName + "." + libraryName;
+        synchronized (libraryClassLoaders) {
+            if (libraryClassLoaders.get(dataverseName) != null) {
+                libraryClassLoaders.remove(key);
+            }
+        }
+    }
+
+    public static ClassLoader getLibraryClassLoader(String dataverseName, String libraryName) {
+        String key = dataverseName + "." + libraryName;
+        synchronized (libraryClassLoaders) {
+            return libraryClassLoaders.get(key);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalScalarFunctionEvaluatorFactory.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalScalarFunctionEvaluatorFactory.java
new file mode 100755
index 0000000..a185000
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ExternalScalarFunctionEvaluatorFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2009-2012 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.external.library;
+
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluator;
+import edu.uci.ics.hyracks.algebricks.runtime.base.ICopyEvaluatorFactory;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class ExternalScalarFunctionEvaluatorFactory implements ICopyEvaluatorFactory {
+
+    private final IExternalFunctionInfo finfo;
+    private final ICopyEvaluatorFactory[] args;
+
+    public ExternalScalarFunctionEvaluatorFactory(IExternalFunctionInfo finfo, ICopyEvaluatorFactory[] args)
+            throws AlgebricksException {
+        this.finfo = finfo;
+        this.args = args;
+    }
+
+    @Override
+    public ICopyEvaluator createEvaluator(IDataOutputProvider output) throws AlgebricksException {
+        return (ExternalScalarFunction) ExternalFunctionProvider.getExternalFunctionEvaluator(finfo, args, output);
+    }
+
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IExternalFunction.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IExternalFunction.java
new file mode 100755
index 0000000..e667828
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IExternalFunction.java
@@ -0,0 +1,7 @@
+package edu.uci.ics.asterix.external.library;
+
+public interface IExternalFunction {
+
+    public void deinitialize();
+
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IExternalScalarFunction.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IExternalScalarFunction.java
new file mode 100755
index 0000000..09451d8
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IExternalScalarFunction.java
@@ -0,0 +1,9 @@
+package edu.uci.ics.asterix.external.library;
+
+public interface IExternalScalarFunction extends IExternalFunction {
+
+    public void initialize(IFunctionHelper functionHelper) throws Exception;
+
+    public void evaluate(IFunctionHelper functionHelper) throws Exception;
+
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IFunctionFactory.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IFunctionFactory.java
new file mode 100755
index 0000000..f67957d
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IFunctionFactory.java
@@ -0,0 +1,7 @@
+package edu.uci.ics.asterix.external.library;
+
+public interface IFunctionFactory {
+
+    public IExternalFunction getExternalFunction();
+
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IFunctionHelper.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IFunctionHelper.java
new file mode 100755
index 0000000..0192e33
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IFunctionHelper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009-2012 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.external.library;
+
+import java.io.IOException;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.external.library.java.IJObject;
+import edu.uci.ics.asterix.external.library.java.JTypeTag;
+
+public interface IFunctionHelper {
+
+    public IJObject getArgument(int index);
+
+    public IJObject getResultObject();
+
+    public void setResult(IJObject result) throws IOException, AsterixException;
+    
+    public IJObject getObject(JTypeTag jtypeTag);
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IResultCollector.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IResultCollector.java
new file mode 100755
index 0000000..fee002e
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/IResultCollector.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2009-2012 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.external.library;
+
+import java.io.DataOutput;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.base.AOrderedList;
+import edu.uci.ics.asterix.om.base.ARecord;
+import edu.uci.ics.asterix.om.base.IAObject;
+
+public interface IResultCollector {
+
+    public void writeIntResult(int result) throws AsterixException;
+
+    public void writeFloatResult(float result) throws AsterixException;
+
+    public void writeDoubleResult(double result) throws AsterixException;
+
+    public void writeStringResult(String result) throws AsterixException;
+
+    public void writeRecordResult(ARecord result) throws AsterixException;
+
+    public void writeListResult(AOrderedList list) throws AsterixException;
+
+    public IAObject getComplexTypeResultHolder();
+    
+    public DataOutput getDataOutput();
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/JTypeObjectFactory.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/JTypeObjectFactory.java
new file mode 100644
index 0000000..ad56981
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/JTypeObjectFactory.java
@@ -0,0 +1,115 @@
+package edu.uci.ics.asterix.external.library;
+
+import java.util.ArrayList;
+
+import edu.uci.ics.asterix.external.library.java.IJObject;
+import edu.uci.ics.asterix.external.library.java.JObjects.JBoolean;
+import edu.uci.ics.asterix.external.library.java.JObjects.JCircle;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDate;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDateTime;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDouble;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDuration;
+import edu.uci.ics.asterix.external.library.java.JObjects.JFloat;
+import edu.uci.ics.asterix.external.library.java.JObjects.JInt;
+import edu.uci.ics.asterix.external.library.java.JObjects.JInterval;
+import edu.uci.ics.asterix.external.library.java.JObjects.JLine;
+import edu.uci.ics.asterix.external.library.java.JObjects.JLong;
+import edu.uci.ics.asterix.external.library.java.JObjects.JOrderedList;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPoint;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPoint3D;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPolygon;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRectangle;
+import edu.uci.ics.asterix.external.library.java.JObjects.JString;
+import edu.uci.ics.asterix.external.library.java.JObjects.JTime;
+import edu.uci.ics.asterix.external.library.java.JObjects.JUnorderedList;
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.AUnorderedListType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.container.IObjectFactory;
+
+public class JTypeObjectFactory implements IObjectFactory<IJObject, IAType> {
+
+    @Override
+    public IJObject create(IAType type) {
+        IJObject retValue = null;
+        switch (type.getTypeTag()) {
+            case INT32:
+                retValue = new JInt(0);
+                break;
+            case STRING:
+                retValue = new JString("");
+                break;
+            case FLOAT:
+                retValue = new JFloat(0);
+                break;
+            case DOUBLE:
+                retValue = new JDouble(0);
+                break;
+            case BOOLEAN:
+                retValue = new JBoolean(false);
+                break;
+            case CIRCLE:
+                retValue = new JCircle(new JPoint(0, 0), 0);
+                break;
+            case POINT:
+                retValue = new JPoint(0, 0);
+                break;
+            case POINT3D:
+                retValue = new JPoint3D(0, 0, 0);
+                break;
+            case POLYGON:
+                retValue = new JPolygon(new ArrayList<JPoint>());
+                break;
+            case LINE:
+                retValue = new JLine(new JPoint(0, 0), new JPoint(0, 0));
+                break;
+            case RECTANGLE:
+                retValue = new JRectangle(new JPoint(0, 0), new JPoint(1, 1));
+                break;
+            case DATE:
+                retValue = new JDate(0);
+                break;
+            case DATETIME:
+                retValue = new JDateTime(0);
+                break;
+            case DURATION:
+                retValue = new JDuration(0, 0);
+                break;
+            case INTERVAL:
+                retValue = new JInterval(0, 0);
+                break;
+            case TIME:
+                retValue = new JTime(0);
+                break;
+            case INT64:
+                retValue = new JLong(0);
+                break;
+            case ORDEREDLIST:
+                AOrderedListType ot = (AOrderedListType) type;
+                IAType orderedItemType = ot.getItemType();
+                IJObject orderedItemObject = create(orderedItemType);
+                retValue = new JOrderedList(orderedItemObject);
+                break;
+            case UNORDEREDLIST:
+                AUnorderedListType ut = (AUnorderedListType) type;
+                IAType unorderedItemType = ut.getItemType();
+                IJObject unorderedItemObject = create(unorderedItemType);
+                retValue = new JUnorderedList(unorderedItemObject);
+                break;
+            case RECORD:
+                IAType[] fieldTypes = ((ARecordType) type).getFieldTypes();
+                IJObject[] fieldObjects = new IJObject[fieldTypes.length];
+                int index = 0;
+                for (IAType fieldType : fieldTypes) {
+                    fieldObjects[index] = create(fieldType);
+                    index++;
+                }
+                retValue = new JRecord((ARecordType) type, fieldObjects);
+
+                break;
+        }
+        return retValue;
+    }
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/JavaFunctionHelper.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/JavaFunctionHelper.java
new file mode 100644
index 0000000..8aed123
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/JavaFunctionHelper.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2009-2012 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.external.library;
+
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.List;
+
+import edu.uci.ics.asterix.builders.RecordBuilder;
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.external.library.java.IJObject;
+import edu.uci.ics.asterix.external.library.java.JObjectUtil;
+import edu.uci.ics.asterix.external.library.java.JObjects.ByteArrayAccessibleDataInputStream;
+import edu.uci.ics.asterix.external.library.java.JObjects.ByteArrayAccessibleInputStream;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
+import edu.uci.ics.asterix.external.library.java.JTypeTag;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.ARecord;
+import edu.uci.ics.asterix.om.base.AString;
+import edu.uci.ics.asterix.om.base.IAObject;
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.container.IObjectPool;
+import edu.uci.ics.asterix.om.util.container.ListObjectPool;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+
+public class JavaFunctionHelper implements IFunctionHelper {
+
+    private final IExternalFunctionInfo finfo;
+    private final IDataOutputProvider outputProvider;
+    private IJObject[] arguments;
+    private IJObject resultHolder;
+    private IAObject innerResult;
+    private ISerializerDeserializer resultSerde;
+    private IObjectPool<IJObject, IAType> objectPool = new ListObjectPool<IJObject, IAType>(new JTypeObjectFactory());
+    byte[] buffer = new byte[32768];
+    ByteArrayAccessibleInputStream bis = new ByteArrayAccessibleInputStream(buffer, 0, buffer.length);
+    ByteArrayAccessibleDataInputStream dis = new ByteArrayAccessibleDataInputStream(bis);
+
+    public JavaFunctionHelper(IExternalFunctionInfo finfo, IDataOutputProvider outputProvider)
+            throws AlgebricksException {
+        this.finfo = finfo;
+        this.outputProvider = outputProvider;
+        List<IAType> params = finfo.getParamList();
+        arguments = new IJObject[params.size()];
+        int index = 0;
+        for (IAType param : params) {
+            this.arguments[index] = objectPool.allocate(param);
+            index++;
+        }
+        resultHolder = objectPool.allocate(finfo.getReturnType());
+    }
+
+    @Override
+    public IJObject getArgument(int index) {
+        return arguments[index];
+    }
+
+    @Override
+    public void setResult(IJObject result) throws IOException, AsterixException {
+        IAObject obj = result.getIAObject();
+        try {
+            outputProvider.getDataOutput().writeByte(obj.getType().getTypeTag().serialize());
+        } catch (IOException e) {
+            throw new HyracksDataException(e);
+        }
+
+        if (obj.getType().getTypeTag().equals(ATypeTag.RECORD)) {
+            ARecordType recType = (ARecordType) obj.getType();
+            if (recType.isOpen()) {
+                writeOpenRecord((JRecord) result, outputProvider.getDataOutput());
+            } else {
+                resultSerde = AqlSerializerDeserializerProvider.INSTANCE.getNonTaggedSerializerDeserializer(recType);
+                resultSerde.serialize(obj, outputProvider.getDataOutput());
+            }
+        } else {
+            resultSerde = AqlSerializerDeserializerProvider.INSTANCE.getNonTaggedSerializerDeserializer(obj.getType());
+            resultSerde.serialize(obj, outputProvider.getDataOutput());
+        }
+        reset();
+    }
+
+    private void writeOpenRecord(JRecord jRecord, DataOutput dataOutput) throws AsterixException, IOException {
+        ARecord aRecord = (ARecord) jRecord.getIAObject();
+        RecordBuilder recordBuilder = new RecordBuilder();
+        ARecordType recordType = aRecord.getType();
+        recordBuilder.reset(recordType);
+        ArrayBackedValueStorage fieldName = new ArrayBackedValueStorage();
+        ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
+        List<Boolean> openField = jRecord.getOpenField();
+
+        int fieldIndex = 0;
+        int closedFieldId = 0;
+        for (IJObject field : jRecord.getFields()) {
+            fieldValue.reset();
+            switch (field.getTypeTag()) {
+                case RECORD:
+                    ARecordType recType = (ARecordType) field.getIAObject().getType();
+                    if (recType.isOpen()) {
+                        fieldValue.getDataOutput().writeByte(recType.getTypeTag().serialize());
+                        writeOpenRecord((JRecord) field, fieldValue.getDataOutput());
+                    } else {
+                        AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(
+                                field.getIAObject().getType()).serialize(field.getIAObject(),
+                                fieldValue.getDataOutput());
+                    }
+                    break;
+                default:
+                    AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(field.getIAObject().getType())
+                            .serialize(field.getIAObject(), fieldValue.getDataOutput());
+                    break;
+            }
+            if (openField.get(fieldIndex)) {
+                String fName = jRecord.getFieldNames().get(fieldIndex);
+                fieldName.reset();
+                AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ASTRING).serialize(
+                        new AString(fName), fieldName.getDataOutput());
+                recordBuilder.addField(fieldName, fieldValue);
+            } else {
+                recordBuilder.addField(closedFieldId, fieldValue);
+                closedFieldId++;
+            }
+            fieldIndex++;
+        }
+
+        recordBuilder.write(dataOutput, false);
+
+    }
+
+    private void reset() {
+        for (IJObject jObject : arguments) {
+            switch (jObject.getTypeTag()) {
+                case RECORD:
+                    reset((JRecord) jObject);
+                    break;
+            }
+        }
+        switch (resultHolder.getTypeTag()) {
+            case RECORD:
+                reset((JRecord) resultHolder);
+                break;
+        }
+    }
+
+    private void reset(JRecord jRecord) {
+        List<IJObject> fields = ((JRecord) jRecord).getFields();
+        for (IJObject field : fields) {
+            switch (field.getTypeTag()) {
+                case RECORD:
+                    reset((JRecord) field);
+                    break;
+            }
+        }
+        jRecord.close();
+    }
+
+    public void setArgument(int index, byte[] argument) throws IOException, AsterixException {
+        bis.setContent(argument, 1, argument.length);
+        IAType type = finfo.getParamList().get(index);
+        arguments[index] = JObjectUtil.getJType(type.getTypeTag(), type, dis, objectPool);
+    }
+
+    @Override
+    public IJObject getResultObject() {
+        return resultHolder;
+    }
+
+    @Override
+    public IJObject getObject(JTypeTag jtypeTag) {
+        IJObject retValue = null;
+        switch (jtypeTag) {
+            case INT:
+                retValue = objectPool.allocate(BuiltinType.AINT32);
+                break;
+            case STRING:
+                retValue = objectPool.allocate(BuiltinType.ASTRING);
+                break;
+        }
+        return retValue;
+    }
+
+}
\ No newline at end of file
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ResultCollector.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ResultCollector.java
new file mode 100755
index 0000000..d53b044
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/ResultCollector.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2009-2012 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.external.library;
+
+import java.io.DataOutput;
+import java.nio.ByteBuffer;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.om.base.AMutableDouble;
+import edu.uci.ics.asterix.om.base.AMutableFloat;
+import edu.uci.ics.asterix.om.base.AMutableInt32;
+import edu.uci.ics.asterix.om.base.AMutableOrderedList;
+import edu.uci.ics.asterix.om.base.AMutableRecord;
+import edu.uci.ics.asterix.om.base.AMutableString;
+import edu.uci.ics.asterix.om.base.AOrderedList;
+import edu.uci.ics.asterix.om.base.ARecord;
+import edu.uci.ics.asterix.om.base.IAObject;
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
+import edu.uci.ics.hyracks.data.std.api.IDataOutputProvider;
+
+public class ResultCollector implements IResultCollector {
+
+    private IAObject reusableResultObjectHolder;
+    private ByteBuffer reusableResultBinaryHolder;
+    private IDataOutputProvider outputProvider;
+    private IExternalFunctionInfo finfo;
+
+    public ResultCollector(IExternalFunctionInfo finfo, IDataOutputProvider outputProvider) {
+        this.finfo = finfo;
+        IAType returnType = finfo.getReturnType();
+        reusableResultObjectHolder = allocateResultObjectHolder(returnType);
+        reusableResultBinaryHolder = allocateResultBinaryHolder(returnType);
+        this.outputProvider = outputProvider;
+    }
+
+    private IAObject allocateResultObjectHolder(IAType type) {
+        switch (type.getTypeTag()) {
+            case INT32:
+                return new AMutableInt32(0);
+            case FLOAT:
+                return new AMutableFloat(0f);
+            case DOUBLE:
+                return new AMutableDouble(0);
+            case STRING:
+                return new AMutableString("");
+            case ORDEREDLIST:
+                return new AMutableOrderedList((AOrderedListType) type);
+            case RECORD:
+                IAType[] fieldType = ((ARecordType) type).getFieldTypes();
+                IAObject[] fieldObjects = new IAObject[fieldType.length];
+                for (int i = 0; i < fieldType.length; i++) {
+                    fieldObjects[i] = allocateResultObjectHolder(fieldType[i]);
+                }
+                return new AMutableRecord((ARecordType) type, fieldObjects);
+        }
+        return null;
+    }
+
+    private ByteBuffer allocateResultBinaryHolder(IAType type) {
+        switch (type.getTypeTag()) {
+            case INT32:
+                return ByteBuffer.allocate(4);
+            case FLOAT:
+                return ByteBuffer.allocate(4);
+            case DOUBLE:
+                return ByteBuffer.allocate(8);
+            case STRING:
+                return ByteBuffer.allocate(32 * 1024);
+            case ORDEREDLIST:
+                return ByteBuffer.allocate(32 * 1024);
+            case RECORD:
+                return ByteBuffer.allocate(32 * 1024);
+        }
+        return null;
+    }
+
+    @Override
+    public void writeDoubleResult(double result) throws AsterixException {
+        ((AMutableDouble) reusableResultObjectHolder).setValue(result);
+        serializeResult(reusableResultObjectHolder);
+    }
+
+    @Override
+    public void writeFloatResult(float result) throws AsterixException {
+        ((AMutableDouble) reusableResultObjectHolder).setValue(result);
+        serializeResult(reusableResultObjectHolder);
+    }
+
+    @Override
+    public void writeIntResult(int result) throws AsterixException {
+        ((AMutableInt32) reusableResultObjectHolder).setValue(result);
+        serializeResult(reusableResultObjectHolder);
+    }
+
+    @Override
+    public void writeStringResult(String result) throws AsterixException {
+        ((AMutableString) reusableResultObjectHolder).setValue(result);
+        serializeResult(reusableResultObjectHolder);
+
+    }
+
+    @Override
+    public void writeRecordResult(ARecord result) throws AsterixException {
+        serializeResult(result);
+    }
+
+    @Override
+    public void writeListResult(AOrderedList list) throws AsterixException {
+        serializeResult(list);
+    }
+
+    public IAObject getComplexTypeResultHolder() {
+        return reusableResultObjectHolder;
+    }
+
+    private void serializeResult(IAObject object) throws AsterixException {
+        try {
+            AqlSerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(finfo.getReturnType()).serialize(
+                    reusableResultObjectHolder, outputProvider.getDataOutput());
+        } catch (HyracksDataException hde) {
+            throw new AsterixException(hde);
+        }
+    }
+
+    @Override
+    public DataOutput getDataOutput() {
+        return outputProvider.getDataOutput();
+    }
+
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/RuntimeExternalFunctionUtil.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/RuntimeExternalFunctionUtil.java
new file mode 100755
index 0000000..0c6713d
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/RuntimeExternalFunctionUtil.java
@@ -0,0 +1,100 @@
+package edu.uci.ics.asterix.external.library;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+
+import edu.uci.ics.asterix.om.base.AMutableInt32;
+import edu.uci.ics.asterix.om.base.AMutableRecord;
+import edu.uci.ics.asterix.om.base.AMutableString;
+import edu.uci.ics.asterix.om.base.IAObject;
+import edu.uci.ics.asterix.om.functions.IExternalFunctionInfo;
+import edu.uci.ics.asterix.om.functions.IFunctionDescriptor;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
+
+public class RuntimeExternalFunctionUtil {
+
+    private static Map<String, ClassLoader> libraryClassLoaders = new HashMap<String, ClassLoader>();
+
+    public static void registerLibraryClassLoader(String dataverseName, String libraryName, ClassLoader classLoader) {
+        String key = dataverseName + "." + libraryName;
+        synchronized (libraryClassLoaders) {
+            if (libraryClassLoaders.get(dataverseName) != null) {
+                throw new IllegalStateException("library class loader already registered!");
+            }
+            libraryClassLoaders.put(key, classLoader);
+        }
+    }
+
+    public static ClassLoader getLibraryClassLoader(String dataverseName, String libraryName) {
+        String key = dataverseName + "." + libraryName;
+        synchronized (libraryClassLoaders) {
+            return libraryClassLoaders.get(key);
+        }
+    }
+
+    public static IFunctionDescriptor getFunctionDescriptor(IFunctionInfo finfo) {
+        switch (((IExternalFunctionInfo) finfo).getKind()) {
+            case SCALAR:
+                return getScalarFunctionDescriptor(finfo);
+            case AGGREGATE:
+            case UNNEST:
+            case STATEFUL:
+                throw new NotImplementedException("External " + finfo.getFunctionIdentifier().getName()
+                        + " not supported");
+        }
+        return null;
+    }
+
+    private static AbstractScalarFunctionDynamicDescriptor getScalarFunctionDescriptor(IFunctionInfo finfo) {
+        return new ExternalScalarFunctionDescriptor(finfo);
+    }
+
+    public static ByteBuffer allocateArgumentBuffers(IAType type) {
+        switch (type.getTypeTag()) {
+            case INT32:
+                return ByteBuffer.allocate(4);
+            case STRING:
+                return ByteBuffer.allocate(32 * 1024);
+            default:
+                return ByteBuffer.allocate(32 * 1024);
+        }
+    }
+
+    public static IAObject allocateArgumentObjects(IAType type) {
+        switch (type.getTypeTag()) {
+            case INT32:
+                return new AMutableInt32(0);
+            case STRING:
+                return new AMutableString("");
+            default:
+                return null;
+                /*
+                ARecordType recordType = (ARecordType) type;
+                IAType[] fieldTypes = recordType.getFieldTypes();
+                IAObject[] fields = new IAObject[fieldTypes.length];
+                for (int i = 0; i < fields.length; i++) {
+                    fields[i] = allocateArgumentObjects(fieldTypes[i]);
+                }
+                return new AMutableRecord((ARecordType) type, fields);
+                */
+        }
+    }
+
+    public static File getExternalLibraryDeployDir(String nodeId) {
+        String filePath = null;
+        if (nodeId != null) {
+            filePath = "edu.uci.ics.hyracks.control.nc.NodeControllerService" + "/" + nodeId + "/"
+                    + "applications/asterix/expanded/external-lib/libraries";
+        } else {
+            filePath = "ClusterControllerService" + "/" + "applications/asterix/expanded/external-lib/libraries";
+
+        }
+        return new File(filePath);
+    }
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/IJObject.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/IJObject.java
new file mode 100644
index 0000000..1561c42
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/IJObject.java
@@ -0,0 +1,11 @@
+package edu.uci.ics.asterix.external.library.java;
+
+import edu.uci.ics.asterix.om.base.IAObject;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+
+public interface IJObject {
+
+    public ATypeTag getTypeTag();
+
+    public IAObject getIAObject();
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/IJType.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/IJType.java
new file mode 100644
index 0000000..fcc35eb
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/IJType.java
@@ -0,0 +1,11 @@
+package edu.uci.ics.asterix.external.library.java;
+
+import edu.uci.ics.asterix.om.base.IAObject;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+
+public interface IJType {
+
+      public ATypeTag getTypeTag();
+      
+      public IAObject getIAObject();
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JObjectUtil.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JObjectUtil.java
new file mode 100644
index 0000000..52071af
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JObjectUtil.java
@@ -0,0 +1,399 @@
+package edu.uci.ics.asterix.external.library.java;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AStringSerializerDeserializer;
+import edu.uci.ics.asterix.dataflow.data.nontagged.serde.SerializerDeserializerUtil;
+import edu.uci.ics.asterix.external.library.java.JObjects.ByteArrayAccessibleDataInputStream;
+import edu.uci.ics.asterix.external.library.java.JObjects.JBoolean;
+import edu.uci.ics.asterix.external.library.java.JObjects.JCircle;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDate;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDateTime;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDouble;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDuration;
+import edu.uci.ics.asterix.external.library.java.JObjects.JFloat;
+import edu.uci.ics.asterix.external.library.java.JObjects.JInt;
+import edu.uci.ics.asterix.external.library.java.JObjects.JInterval;
+import edu.uci.ics.asterix.external.library.java.JObjects.JLine;
+import edu.uci.ics.asterix.external.library.java.JObjects.JOrderedList;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPoint;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPoint3D;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPolygon;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRectangle;
+import edu.uci.ics.asterix.external.library.java.JObjects.JString;
+import edu.uci.ics.asterix.external.library.java.JObjects.JTime;
+import edu.uci.ics.asterix.external.library.java.JObjects.JUnorderedList;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnionType;
+import edu.uci.ics.asterix.om.types.AUnorderedListType;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.asterix.om.types.EnumDeserializer;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
+import edu.uci.ics.asterix.om.util.container.IObjectPool;
+
+public class JObjectUtil {
+
+    public static IJObject getJType(ATypeTag typeTag, IAType type, ByteArrayAccessibleDataInputStream dis,
+            IObjectPool<IJObject, IAType> objectPool) throws IOException, AsterixException {
+        IJObject jObject;
+
+        switch (typeTag) {
+
+            case INT32: {
+                int v = dis.readInt();
+                jObject = objectPool.allocate(BuiltinType.AINT32);
+                ((JInt) jObject).setValue(v);
+                break;
+            }
+
+            case FLOAT: {
+                float v = dis.readFloat();
+                jObject = objectPool.allocate(BuiltinType.AFLOAT);
+                ((JFloat) jObject).setValue(v);
+                break;
+            }
+
+            case DOUBLE: {
+                double value = dis.readDouble();
+                jObject = objectPool.allocate(BuiltinType.ADOUBLE);
+                ((JDouble) jObject).setValue(value);
+                break;
+            }
+
+            case STRING: {
+                String v = dis.readUTF();
+                jObject = objectPool.allocate(BuiltinType.ASTRING);
+                ((JString) jObject).setValue(v);
+                break;
+            }
+
+            case BOOLEAN:
+                jObject = objectPool.allocate(BuiltinType.ABOOLEAN);
+                ((JBoolean) jObject).setValue(dis.readBoolean());
+                break;
+
+            case DATE: {
+                int d = dis.readInt();
+                jObject = objectPool.allocate(BuiltinType.ADATE);
+                ((JDate) jObject).setValue(d);
+                break;
+            }
+
+            case DATETIME: {
+                jObject = objectPool.allocate(BuiltinType.ADATETIME);
+                long value = dis.readLong();
+                ((JDateTime) jObject).setValue(value);
+                break;
+            }
+
+            case DURATION: {
+                jObject = objectPool.allocate(BuiltinType.ADURATION);
+                int months = dis.readInt();
+                long msecs = dis.readLong();
+                ((JDuration) jObject).setValue(months, msecs);
+                break;
+            }
+
+            case TIME: {
+                jObject = objectPool.allocate(BuiltinType.ATIME);
+                int time = dis.readInt();
+                ((JTime) jObject).setValue(time);
+                break;
+            }
+
+            case INTERVAL: {
+                jObject = objectPool.allocate(BuiltinType.AINTERVAL);
+                long start = dis.readLong();
+                long end = dis.readLong();
+                byte intervalType = dis.readByte();
+                ((JInterval) jObject).setValue(start, end, intervalType);
+                break;
+            }
+
+            case CIRCLE: {
+                jObject = objectPool.allocate(BuiltinType.ACIRCLE);
+                double x = dis.readDouble();
+                double y = dis.readDouble();
+                double radius = dis.readDouble();
+                JPoint jpoint = (JPoint) objectPool.allocate(BuiltinType.APOINT);
+                jpoint.setValue(x, y);
+                ((JCircle) jObject).setValue(jpoint, radius);
+                break;
+            }
+
+            case POINT: {
+                jObject = objectPool.allocate(BuiltinType.APOINT);
+                double x = dis.readDouble();
+                double y = dis.readDouble();
+                ((JPoint) jObject).setValue(x, y);
+                break;
+            }
+
+            case POINT3D: {
+                jObject = objectPool.allocate(BuiltinType.APOINT3D);
+                double x = dis.readDouble();
+                double y = dis.readDouble();
+                double z = dis.readDouble();
+                ((JPoint3D) jObject).setValue(x, y, z);
+                break;
+            }
+
+            case LINE: {
+                jObject = objectPool.allocate(BuiltinType.ALINE);
+                double x1 = dis.readDouble();
+                double y1 = dis.readDouble();
+                double x2 = dis.readDouble();
+                double y2 = dis.readDouble();
+                JPoint jpoint1 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
+                jpoint1.setValue(x1, y1);
+                JPoint jpoint2 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
+                jpoint2.setValue(x2, y2);
+                ((JLine) jObject).setValue(jpoint1, jpoint2);
+                break;
+            }
+
+            case POLYGON: {
+                jObject = objectPool.allocate(BuiltinType.APOLYGON);
+                short numberOfPoints = dis.readShort();
+                List<JPoint> points = new ArrayList<JPoint>();
+                for (int i = 0; i < numberOfPoints; i++) {
+                    JPoint p1 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
+                    p1.setValue(dis.readDouble(), dis.readDouble());
+                    points.add(p1);
+                }
+                ((JPolygon) jObject).setValue(points);
+                break;
+            }
+
+            case RECTANGLE: {
+                jObject = objectPool.allocate(BuiltinType.ARECTANGLE);
+                double x1 = dis.readDouble();
+                double y1 = dis.readDouble();
+                double x2 = dis.readDouble();
+                double y2 = dis.readDouble();
+                JPoint jpoint1 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
+                jpoint1.setValue(x1, y1);
+                JPoint jpoint2 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
+                jpoint2.setValue(x2, y2);
+                ((JRectangle) jObject).setValue(jpoint1, jpoint2);
+                break;
+            }
+
+            case UNORDEREDLIST: {
+                AUnorderedListType listType = (AUnorderedListType) type;
+                IAType elementType = listType.getItemType();
+                jObject = objectPool.allocate(listType);
+
+                boolean fixedSize = false;
+                ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(dis.readByte());
+                switch (tag) {
+                    case STRING:
+                    case RECORD:
+                    case ORDEREDLIST:
+                    case UNORDEREDLIST:
+                    case ANY:
+                        fixedSize = false;
+                        break;
+                    default:
+                        fixedSize = true;
+                        break;
+                }
+                dis.readInt(); // list size
+                int numberOfitems;
+                numberOfitems = dis.readInt();
+                if (numberOfitems > 0) {
+                    if (!fixedSize) {
+                        for (int i = 0; i < numberOfitems; i++)
+                            dis.readInt();
+                    }
+                    for (int i = 0; i < numberOfitems; i++) {
+                        IJObject v = (IJObject) getJType(elementType.getTypeTag(), elementType, dis, objectPool);
+                        ((JUnorderedList) jObject).add(v);
+                    }
+                }
+
+                break;
+            }
+            case ORDEREDLIST: {
+                AOrderedListType listType = (AOrderedListType) type;
+                IAType elementType = listType.getItemType();
+                jObject = objectPool.allocate(listType);
+                boolean fixedSize = false;
+                ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(dis.readByte());
+                switch (tag) {
+                    case STRING:
+                    case RECORD:
+                    case ORDEREDLIST:
+                    case UNORDEREDLIST:
+                    case ANY:
+                        fixedSize = false;
+                        break;
+                    default:
+                        fixedSize = true;
+                        break;
+                }
+
+                dis.readInt(); // list size
+                int numberOfitems;
+                numberOfitems = dis.readInt();
+                if (numberOfitems > 0) {
+                    if (!fixedSize) {
+                        for (int i = 0; i < numberOfitems; i++)
+                            dis.readInt();
+                    }
+                    for (int i = 0; i < numberOfitems; i++) {
+                        IJObject v = (IJObject) getJType(elementType.getTypeTag(), elementType, dis, objectPool);
+                        ((JOrderedList) jObject).add(v);
+                    }
+                }
+
+                break;
+            }
+            case RECORD:
+                ARecordType recordType = (ARecordType) type;
+                int numberOfSchemaFields = recordType.getFieldTypes().length;
+                byte[] recordBits = dis.getInputStream().getArray();
+                boolean isExpanded = false;
+                int s = dis.getInputStream().getPosition();
+                int recordOffset = s;
+                int openPartOffset = 0;
+                int offsetArrayOffset = 0;
+                int[] fieldOffsets = new int[numberOfSchemaFields];
+                IJObject[] closedFields = new IJObject[numberOfSchemaFields];
+
+                if (recordType == null) {
+                    openPartOffset = s + AInt32SerializerDeserializer.getInt(recordBits, s + 6);
+                    s += 8;
+                    isExpanded = true;
+                } else {
+                    dis.skip(4); // reading length is not required.
+                    if (recordType.isOpen()) {
+                        isExpanded = dis.readBoolean();
+                        if (isExpanded) {
+                            openPartOffset = s + dis.readInt(); // AInt32SerializerDeserializer.getInt(recordBits, s + 6);
+                        } else {
+                            // do nothing s += 6;
+                        }
+                    } else {
+                        // do nothing s += 5;
+                    }
+                }
+
+                if (numberOfSchemaFields > 0) {
+                    int numOfSchemaFields = dis.readInt(); //s += 4;
+                    int nullBitMapOffset = 0;
+                    boolean hasNullableFields = NonTaggedFormatUtil.hasNullableField(recordType);
+                    if (hasNullableFields) {
+                        nullBitMapOffset = dis.getInputStream().getPosition();//s
+                        offsetArrayOffset = dis.getInputStream().getPosition() //s
+                                + (numberOfSchemaFields % 8 == 0 ? numberOfSchemaFields / 8
+                                        : numberOfSchemaFields / 8 + 1);
+                    } else {
+                        offsetArrayOffset = dis.getInputStream().getPosition();
+                    }
+                    for (int i = 0; i < numberOfSchemaFields; i++) {
+                        fieldOffsets[i] = dis.readInt(); // AInt32SerializerDeserializer.getInt(recordBits, offsetArrayOffset) + recordOffset;
+                        // offsetArrayOffset += 4;
+                    }
+                    for (int fieldNumber = 0; fieldNumber < numberOfSchemaFields; fieldNumber++) {
+                        if (hasNullableFields) {
+                            byte b1 = recordBits[nullBitMapOffset + fieldNumber / 8];
+                            int p = 1 << (7 - (fieldNumber % 8));
+                            if ((b1 & p) == 0) {
+                                // set null value (including type tag inside)
+                                //fieldValues.add(nullReference);
+                                continue;
+                            }
+                        }
+                        IAType[] fieldTypes = recordType.getFieldTypes();
+                        ATypeTag fieldValueTypeTag = null;
+
+                        IAType fieldType = fieldTypes[fieldNumber];
+                        if (fieldTypes[fieldNumber].getTypeTag() == ATypeTag.UNION) {
+                            if (NonTaggedFormatUtil.isOptionalField((AUnionType) fieldTypes[fieldNumber])) {
+                                fieldType = ((AUnionType) fieldTypes[fieldNumber]).getUnionList().get(
+                                        NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
+                                fieldValueTypeTag = fieldType.getTypeTag();
+                                //                      fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(recordBits,
+                                //                              fieldOffsets[fieldNumber], typeTag, false);
+                            }
+                        } else {
+                            fieldValueTypeTag = fieldTypes[fieldNumber].getTypeTag();
+                        }
+                        closedFields[fieldNumber] = getJType(fieldValueTypeTag, fieldType, dis, objectPool);
+                    }
+                }
+                if (isExpanded) {
+                    int numberOfOpenFields = dis.readInt();
+                    String[] fieldNames = new String[numberOfOpenFields];
+                    IAType[] fieldTypes = new IAType[numberOfOpenFields];
+                    IJObject[] openFields = new IJObject[numberOfOpenFields];
+                    for (int i = 0; i < numberOfOpenFields; i++) {
+                        dis.readInt();
+                        dis.readInt();
+                    }
+                    for (int i = 0; i < numberOfOpenFields; i++) {
+                        fieldNames[i] = AStringSerializerDeserializer.INSTANCE.deserialize(dis).getStringValue();
+                        ATypeTag openFieldTypeTag = SerializerDeserializerUtil.deserializeTag(dis);
+                        openFields[i] = getJType(openFieldTypeTag, null, dis, objectPool);
+                        fieldTypes[i] = openFields[i].getIAObject().getType();
+                    }
+                    ARecordType openPartRecType = new ARecordType(null, fieldNames, fieldTypes, true);
+                    if (numberOfSchemaFields > 0) {
+                        ARecordType mergedRecordType = mergeRecordTypes(recordType, openPartRecType);
+                        IJObject[] mergedFields = mergeFields(closedFields, openFields);
+                        jObject = objectPool.allocate(recordType);
+                        return new JRecord(mergedRecordType, mergedFields);
+                    } else {
+                        return new JRecord(recordType, openFields);
+                    }
+                } else {
+                    return new JRecord(recordType, closedFields);
+                }
+
+            default:
+                throw new IllegalStateException("Argument type: " + typeTag);
+        }
+        return jObject;
+    }
+
+    private static IJObject[] mergeFields(IJObject[] closedFields, IJObject[] openFields) {
+        IJObject[] fields = new IJObject[closedFields.length + openFields.length];
+        int i = 0;
+        for (; i < closedFields.length; i++) {
+            fields[i] = closedFields[i];
+        }
+        for (int j = 0; j < openFields.length; j++) {
+            fields[closedFields.length + j] = openFields[j];
+        }
+        return fields;
+    }
+
+    private static ARecordType mergeRecordTypes(ARecordType recType1, ARecordType recType2) throws AsterixException {
+
+        String[] fieldNames = new String[recType1.getFieldNames().length + recType2.getFieldNames().length];
+        IAType[] fieldTypes = new IAType[recType1.getFieldTypes().length + recType2.getFieldTypes().length];
+
+        int i = 0;
+        for (; i < recType1.getFieldNames().length; i++) {
+            fieldNames[i] = recType1.getFieldNames()[i];
+            fieldTypes[i] = recType1.getFieldTypes()[i];
+        }
+
+        for (int j = 0; j < recType2.getFieldNames().length; i++, j++) {
+            fieldNames[i] = recType2.getFieldNames()[j];
+            fieldTypes[i] = recType2.getFieldTypes()[j];
+        }
+        return new ARecordType(null, fieldNames, fieldTypes, true);
+    }
+}
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JObjects.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JObjects.java
new file mode 100644
index 0000000..2fae902
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JObjects.java
@@ -0,0 +1,875 @@
+package edu.uci.ics.asterix.external.library.java;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.om.base.ABoolean;
+import edu.uci.ics.asterix.om.base.AMutableCircle;
+import edu.uci.ics.asterix.om.base.AMutableDate;
+import edu.uci.ics.asterix.om.base.AMutableDateTime;
+import edu.uci.ics.asterix.om.base.AMutableDouble;
+import edu.uci.ics.asterix.om.base.AMutableDuration;
+import edu.uci.ics.asterix.om.base.AMutableFloat;
+import edu.uci.ics.asterix.om.base.AMutableInt32;
+import edu.uci.ics.asterix.om.base.AMutableInt64;
+import edu.uci.ics.asterix.om.base.AMutableInterval;
+import edu.uci.ics.asterix.om.base.AMutableLine;
+import edu.uci.ics.asterix.om.base.AMutableOrderedList;
+import edu.uci.ics.asterix.om.base.AMutablePoint;
+import edu.uci.ics.asterix.om.base.AMutablePoint3D;
+import edu.uci.ics.asterix.om.base.AMutablePolygon;
+import edu.uci.ics.asterix.om.base.AMutableRecord;
+import edu.uci.ics.asterix.om.base.AMutableRectangle;
+import edu.uci.ics.asterix.om.base.AMutableString;
+import edu.uci.ics.asterix.om.base.AMutableTime;
+import edu.uci.ics.asterix.om.base.AMutableUnorderedList;
+import edu.uci.ics.asterix.om.base.APoint;
+import edu.uci.ics.asterix.om.base.IAObject;
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.ARecordType;
+import edu.uci.ics.asterix.om.types.ATypeTag;
+import edu.uci.ics.asterix.om.types.AUnorderedListType;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.asterix.om.types.IAType;
+
+public class JObjects {
+
+    public static abstract class JObject implements IJObject {
+
+        protected IAObject value;
+        protected byte[] bytes;
+
+        protected JObject(IAObject value) {
+            this.value = value;
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return value.getType().getTypeTag();
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return value;
+        }
+    }
+
+    public static final class JInt implements IJObject {
+
+        private AMutableInt32 value;
+
+        public JInt(int value) {
+            this.value = new AMutableInt32(value);
+        }
+
+        public void setValue(int v) {
+            if (value == null) {
+                value = new AMutableInt32(v);
+            } else {
+                ((AMutableInt32) value).setValue(v);
+            }
+        }
+
+        public void setValue(AMutableInt32 v) {
+            value = v;
+        }
+
+        public int getValue() {
+            return ((AMutableInt32) value).getIntegerValue().intValue();
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return BuiltinType.AINT32.getTypeTag();
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return value;
+        }
+
+    }
+
+    public static final class JBoolean implements IJObject {
+
+        private boolean value;
+
+        public JBoolean(boolean value) {
+            this.value = value;
+        }
+
+        public void setValue(boolean value) {
+            this.value = value;
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.BOOLEAN;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return value ? ABoolean.TRUE : ABoolean.FALSE;
+        }
+
+    }
+
+    public static final class JLong extends JObject {
+
+        public JLong(long v) {
+            super(new AMutableInt64(v));
+        }
+
+        public void setValue(long v) {
+            ((AMutableInt64) value).setValue(v);
+        }
+
+        public long getValue() {
+            return ((AMutableInt64) value).getLongValue();
+        }
+
+    }
+
+    public static final class JDouble extends JObject {
+
+        public JDouble(double v) {
+            super(new AMutableDouble(v));
+        }
+
+        public void setValue(double v) {
+            ((AMutableDouble) value).setValue(v);
+        }
+
+        public double getValue() {
+            return ((AMutableDouble) value).getDoubleValue();
+        }
+
+    }
+
+    public static final class JString extends JObject {
+
+        public JString(String v) {
+            super(new AMutableString(v));
+        }
+
+        public void setValue(String v) {
+            ((AMutableString) value).setValue(v);
+        }
+
+        public String getValue() {
+            return ((AMutableString) value).getStringValue();
+        }
+
+    }
+
+    public static final class JFloat implements IJObject {
+
+        private AMutableFloat value;
+
+        public JFloat(float v) {
+            value = new AMutableFloat(v);
+        }
+
+        public void setValue(float v) {
+            ((AMutableFloat) value).setValue(v);
+        }
+
+        public float getValue() {
+            return ((AMutableFloat) value).getFloatValue();
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return BuiltinType.AFLOAT.getTypeTag();
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return value;
+        }
+
+    }
+
+    public static final class JPoint extends JObject {
+
+        public JPoint(double x, double y) {
+            super(new AMutablePoint(x, y));
+        }
+
+        public void setValue(double x, double y) {
+            ((AMutablePoint) value).setValue(x, y);
+        }
+
+        public double getXValue() {
+            return ((AMutablePoint) value).getX();
+        }
+
+        public double getYValue() {
+            return ((AMutablePoint) value).getY();
+        }
+
+        public IAObject getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return value.toString();
+        }
+    }
+
+    public static final class JRectangle implements IJObject {
+
+        private AMutableRectangle rect;
+
+        public JRectangle(JPoint p1, JPoint p2) {
+            rect = new AMutableRectangle((APoint) p1.getValue(), (APoint) p2.getValue());
+        }
+
+        public void setValue(JPoint p1, JPoint p2) {
+            this.rect.setValue((APoint) p1.getValue(), (APoint) p2.getValue());
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.RECTANGLE;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return rect;
+        }
+
+        @Override
+        public String toString() {
+            return rect.toString();
+        }
+
+    }
+
+    public static final class JTime implements IJObject {
+
+        private AMutableTime time;
+
+        public JTime(int timeInMillsec) {
+            time = new AMutableTime(timeInMillsec);
+        }
+
+        public void setValue(int timeInMillsec) {
+            time.setValue(timeInMillsec);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.TIME;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return time;
+        }
+
+        @Override
+        public String toString() {
+            return time.toString();
+        }
+
+    }
+
+    public static final class JInterval implements IJObject {
+
+        private AMutableInterval interval;
+
+        public JInterval(long intervalStart, long intervalEnd) {
+            interval = new AMutableInterval(intervalStart, intervalEnd, (byte) 0);
+        }
+
+        public void setValue(long intervalStart, long intervalEnd, byte typetag) {
+            interval.setValue(intervalStart, intervalEnd, typetag);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.INTERVAL;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return interval;
+        }
+
+        @Override
+        public String toString() {
+            return interval.toString();
+        }
+
+        public long getIntervalStart() {
+            return interval.getIntervalStart();
+        }
+
+        public long getIntervalEnd() {
+            return interval.getIntervalEnd();
+        }
+
+        public short getIntervalType() {
+            return interval.getIntervalType();
+        }
+
+    }
+
+    public static final class JDate implements IJObject {
+
+        private AMutableDate date;
+
+        public JDate(int chrononTimeInDays) {
+            date = new AMutableDate(chrononTimeInDays);
+        }
+
+        public void setValue(int chrononTimeInDays) {
+            date.setValue(chrononTimeInDays);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.DATE;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return date;
+        }
+
+        @Override
+        public String toString() {
+            return date.toString();
+        }
+
+    }
+
+    public static final class JDateTime implements IJObject {
+
+        private AMutableDateTime dateTime;
+
+        public JDateTime(long chrononTime) {
+            dateTime = new AMutableDateTime(chrononTime);
+        }
+
+        public void setValue(long chrononTime) {
+            dateTime.setValue(chrononTime);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.DATETIME;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return dateTime;
+        }
+
+        @Override
+        public String toString() {
+            return dateTime.toString();
+        }
+
+    }
+
+    public static final class JDuration implements IJObject {
+
+        private AMutableDuration duration;
+
+        public JDuration(int months, long milliseconds) {
+            duration = new AMutableDuration(months, milliseconds);
+        }
+
+        public void setValue(int months, long milliseconds) {
+            duration.setValue(months, milliseconds);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.DURATION;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return duration;
+        }
+
+        @Override
+        public String toString() {
+            return duration.toString();
+        }
+
+    }
+
+    public static final class JPolygon implements IJObject {
+
+        private AMutablePolygon polygon;
+        private List<JPoint> points;
+
+        public JPolygon(List<JPoint> points) {
+            this.points = points;
+        }
+
+        public void setValue(List<JPoint> points) {
+            this.points = points;
+            polygon = null;
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.POLYGON;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            if (polygon == null) {
+                APoint[] pts = new APoint[points.size()];
+                int index = 0;
+                for (JPoint p : points) {
+                    pts[index++] = (APoint) p.getIAObject();
+                }
+                polygon = new AMutablePolygon(pts);
+            }
+            return polygon;
+        }
+
+        @Override
+        public String toString() {
+            return getIAObject().toString();
+        }
+
+    }
+
+    public static final class JCircle implements IJObject {
+
+        private AMutableCircle circle;
+
+        public JCircle(JPoint center, double radius) {
+            circle = new AMutableCircle((APoint) center.getIAObject(), radius);
+        }
+
+        public void setValue(JPoint center, double radius) {
+            circle.setValue((APoint) center.getIAObject(), radius);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.CIRCLE;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return circle;
+        }
+
+        @Override
+        public String toString() {
+            return circle.toString();
+        }
+
+    }
+
+    public static final class JLine implements IJObject {
+
+        private AMutableLine line;
+
+        public JLine(JPoint p1, JPoint p2) {
+            line = new AMutableLine((APoint) p1.getIAObject(), (APoint) p2.getIAObject());
+        }
+
+        public void setValue(JPoint p1, JPoint p2) {
+            line.setValue((APoint) p1.getIAObject(), (APoint) p2.getIAObject());
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.LINE;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return line;
+        }
+
+        @Override
+        public String toString() {
+            return line.toString();
+        }
+
+    }
+
+    public static final class JPoint3D implements IJObject {
+
+        private AMutablePoint3D value;
+
+        public JPoint3D(double x, double y, double z) {
+            value = new AMutablePoint3D(x, y, z);
+        }
+
+        public void setValue(double x, double y, double z) {
+            value.setValue(x, y, z);
+        }
+
+        public double getXValue() {
+            return ((AMutablePoint3D) value).getX();
+        }
+
+        public double getYValue() {
+            return ((AMutablePoint3D) value).getY();
+        }
+
+        public double getZValue() {
+            return ((AMutablePoint3D) value).getZ();
+        }
+
+        public IAObject getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return value.toString();
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.POINT3D;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            return value;
+        }
+    }
+
+    public static final class JOrderedList implements IJObject {
+
+        private AOrderedListType listType;
+        private List<IJObject> jObjects;
+
+        public JOrderedList(IJObject jObject) {
+            this.listType = new AOrderedListType(jObject.getIAObject().getType(), null);
+            this.jObjects = new ArrayList<IJObject>();
+        }
+
+        public void add(IJObject jObject) {
+            jObjects.add(jObject);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.ORDEREDLIST;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            AMutableOrderedList v = new AMutableOrderedList(listType);
+            for (IJObject jObj : jObjects) {
+                v.add(jObj.getIAObject());
+            }
+            return v;
+        }
+
+        public AOrderedListType getListType() {
+            return listType;
+        }
+
+        public void addAll(Collection<IJObject> jObjectCollection) {
+            jObjects.addAll(jObjectCollection);
+        }
+
+        public void clear() {
+            jObjects.clear();
+        }
+
+        public IJObject getElement(int index) {
+            return jObjects.get(index);
+        }
+
+        public int size() {
+            return jObjects.size();
+        }
+
+    }
+
+    public static final class JUnorderedList implements IJObject {
+
+        private AUnorderedListType listType;
+        private List<IJObject> jObjects;
+
+        public JUnorderedList(IJObject jObject) {
+            this.listType = new AUnorderedListType(jObject.getIAObject().getType(), null);
+            this.jObjects = new ArrayList<IJObject>();
+        }
+
+        public void add(IJObject jObject) {
+            jObjects.add(jObject);
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return ATypeTag.UNORDEREDLIST;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            AMutableUnorderedList v = new AMutableUnorderedList(listType);
+            for (IJObject jObj : jObjects) {
+                v.add(jObj.getIAObject());
+            }
+            return v;
+        }
+
+        public AUnorderedListType getListType() {
+            return listType;
+        }
+
+        public boolean isEmpty() {
+            return jObjects.isEmpty();
+        }
+
+        public void addAll(Collection<IJObject> jObjectCollection) {
+            jObjects.addAll(jObjectCollection);
+        }
+
+        public void clear() {
+            jObjects.clear();
+        }
+
+        public IJObject getElement(int index) {
+            return jObjects.get(index);
+        }
+
+        public int size() {
+            return jObjects.size();
+        }
+
+    }
+
+    public static final class JRecord implements IJObject {
+
+        private AMutableRecord value;
+        private ARecordType recordType;
+        private List<IJObject> fields;
+        private List<String> fieldNames;
+        private List<IAType> fieldTypes;
+        private int numFieldsAdded = 0;
+        private List<Boolean> openField;
+
+        public JRecord(ARecordType recordType) {
+            this.recordType = recordType;
+            this.fields = new ArrayList<IJObject>();
+            initFieldInfo();
+        }
+
+        public JRecord(ARecordType recordType, IJObject[] fields) {
+            this.recordType = recordType;
+            this.fields = new ArrayList<IJObject>();
+            for (IJObject jObject : fields) {
+                this.fields.add(jObject);
+            }
+            initFieldInfo();
+        }
+
+        public JRecord(String[] fieldNames, IJObject[] fields) throws AsterixException {
+            this.recordType = getARecordType(fieldNames, fields);
+            this.fields = new ArrayList<IJObject>();
+            for (IJObject jObject : fields) {
+                this.fields.add(jObject);
+            }
+            initFieldInfo();
+        }
+
+        private ARecordType getARecordType(String[] fieldNames, IJObject[] fields) throws AsterixException {
+            IAType[] fieldTypes = new IAType[fields.length];
+            int index = 0;
+            for (IJObject jObj : fields) {
+                fieldTypes[index++] = jObj.getIAObject().getType();
+            }
+            ARecordType recordType = new ARecordType(null, fieldNames, fieldTypes, false);
+            return recordType;
+        }
+
+        private void initFieldInfo() {
+            this.openField = new ArrayList<Boolean>();
+            fieldNames = new ArrayList<String>();
+            for (String name : recordType.getFieldNames()) {
+                fieldNames.add(name);
+                openField.add(false);
+            }
+            fieldTypes = new ArrayList<IAType>();
+            for (IAType type : recordType.getFieldTypes()) {
+                fieldTypes.add(type);
+            }
+
+        }
+
+        private IAObject[] getIAObjectArray(List<IJObject> fields) {
+            IAObject[] retValue = new IAObject[fields.size()];
+            int index = 0;
+            for (IJObject jObject : fields) {
+                retValue[index++] = getIAObject(jObject);
+            }
+            return retValue;
+        }
+
+        private IAObject getIAObject(IJObject jObject) {
+            IAObject retVal = null;
+            switch (jObject.getTypeTag()) {
+                case RECORD:
+                    ARecordType recType = ((JRecord) jObject).getRecordType();
+                    IAObject[] fields = new IAObject[((JRecord) jObject).getFields().size()];
+                    int index = 0;
+                    for (IJObject field : ((JRecord) jObject).getFields()) {
+                        fields[index++] = getIAObject(field);
+                    }
+                    retVal = new AMutableRecord(recType, fields);
+                default:
+                    retVal = jObject.getIAObject();
+                    break;
+            }
+            return retVal;
+        }
+
+        public void addField(String fieldName, IJObject fieldValue) {
+            int pos = getFieldPosByName(fieldName);
+            if (pos >= 0) {
+                throw new IllegalArgumentException("field already defined");
+            }
+            numFieldsAdded++;
+            fields.add(fieldValue);
+            fieldNames.add(fieldName);
+            fieldTypes.add(fieldValue.getIAObject().getType());
+            openField.add(true);
+        }
+
+        public IJObject getValueByName(String fieldName) throws AsterixException, IOException {
+            int fieldPos = getFieldPosByName(fieldName);
+            if (fieldPos < 0) {
+                throw new AsterixException("unknown field: " + fieldName);
+            }
+            return fields.get(fieldPos);
+        }
+
+        public void setValueAtPos(int pos, IJObject jtype) {
+            fields.set(pos, jtype);
+        }
+
+        public void setValue(AMutableRecord mutableRecord) {
+            this.value = mutableRecord;
+            this.recordType = mutableRecord.getType();
+        }
+
+        @Override
+        public ATypeTag getTypeTag() {
+            return recordType.getTypeTag();
+        }
+
+        public void setField(String fieldName, IJObject fieldValue) {
+            int pos = getFieldPosByName(fieldName);
+            fields.set(pos, fieldValue);
+            if (value != null) {
+                value.setValueAtPos(pos, fieldValue.getIAObject());
+            }
+        }
+
+        private int getFieldPosByName(String fieldName) {
+            int index = 0;
+            for (String name : fieldNames) {
+                if (name.equals(fieldName)) {
+                    return index;
+                }
+                index++;
+            }
+            return -1;
+        }
+
+        public ARecordType getRecordType() {
+            return recordType;
+        }
+
+        public List<IJObject> getFields() {
+            return fields;
+        }
+
+        @Override
+        public IAObject getIAObject() {
+            if (value == null || numFieldsAdded > 0) {
+                value = new AMutableRecord(recordType, getIAObjectArray(fields));
+            }
+            return value;
+        }
+
+        public void close() {
+            if (numFieldsAdded > 0) {
+                int totalFields = fieldNames.size();
+                for (int i = 0; i < numFieldsAdded; i++) {
+                    fieldNames.remove(totalFields - 1 - i);
+                    fieldTypes.remove(totalFields - 1 - i);
+                    fields.remove(totalFields - 1 - i);
+                }
+                numFieldsAdded = 0;
+            }
+        }
+
+        public List<Boolean> getOpenField() {
+            return openField;
+        }
+
+        public List<String> getFieldNames() {
+            return fieldNames;
+        }
+
+        public List<IAType> getFieldTypes() {
+            return fieldTypes;
+        }
+
+    }
+
+    public static class ByteArrayAccessibleInputStream extends ByteArrayInputStream {
+
+        public ByteArrayAccessibleInputStream(byte[] buf, int offset, int length) {
+            super(buf, offset, length);
+        }
+
+        public void setContent(byte[] buf, int offset, int length) {
+            this.buf = buf;
+            this.pos = offset;
+            this.count = Math.min(offset + length, buf.length);
+            this.mark = offset;
+        }
+
+        public byte[] getArray() {
+            return buf;
+        }
+
+        public int getPosition() {
+            return pos;
+        }
+
+        public int getCount() {
+            return count;
+        }
+
+    }
+
+    public static class ByteArrayAccessibleDataInputStream extends DataInputStream {
+
+        public ByteArrayAccessibleDataInputStream(ByteArrayAccessibleInputStream in) {
+            super(in);
+        }
+
+        public ByteArrayAccessibleInputStream getInputStream() {
+            return (ByteArrayAccessibleInputStream) in;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JTypeTag.java b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JTypeTag.java
new file mode 100644
index 0000000..3b686f6
--- /dev/null
+++ b/asterix-external-data/src/main/java/edu/uci/ics/asterix/external/library/java/JTypeTag.java
@@ -0,0 +1,12 @@
+package edu.uci.ics.asterix.external.library.java;
+
+public enum JTypeTag {
+
+    INT,
+    STRING,
+    LONG,
+    DOUBLE,
+    FLOAT,
+    LIST,
+    OBJECT
+}
diff --git a/asterix-external-data/src/main/resources/schema/library.xsd b/asterix-external-data/src/main/resources/schema/library.xsd
new file mode 100644
index 0000000..3dc4659
--- /dev/null
+++ b/asterix-external-data/src/main/resources/schema/library.xsd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:lib="library" targetNamespace="library" elementFormDefault="qualified">
+
+<!-- definition of simple types --> 
+<xs:element name="language" type="xs:string"/>
+<xs:element name="name" type="xs:string"/>
+<xs:element name="arguments" type="xs:string"/>
+<xs:element name="return_type" type="xs:string"/>
+<xs:element name="function_type" type="xs:string"/>
+<xs:element name="definition" type="xs:string"/>
+
+<!-- definition of complex elements -->
+<xs:element name="function">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="lib:name"/>
+      <xs:element ref="lib:function_type"/>
+      <xs:element ref="lib:arguments"/>
+      <xs:element ref="lib:return_type"/>
+      <xs:element ref="lib:definition"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="functions">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="lib:function" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+<xs:element name="library">
+  <xs:complexType>
+    <xs:sequence>
+      <xs:element ref="lib:language"/>
+      <xs:element ref="lib:functions" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+</xs:element>
+
+</xs:schema>     
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/AllTypesFactory.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/AllTypesFactory.java
new file mode 100644
index 0000000..f095321
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/AllTypesFactory.java
@@ -0,0 +1,27 @@
+/*
+ * 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.external.library;
+
+import edu.uci.ics.asterix.external.library.IExternalFunction;
+import edu.uci.ics.asterix.external.library.IFunctionFactory;
+
+public class AllTypesFactory implements IFunctionFactory {
+
+    @Override
+    public IExternalFunction getExternalFunction() {
+        return new AllTypesFunction();
+    }
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/AllTypesFunction.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/AllTypesFunction.java
new file mode 100644
index 0000000..c5063db
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/AllTypesFunction.java
@@ -0,0 +1,115 @@
+/*
+ * 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.external.library;
+
+import edu.uci.ics.asterix.external.library.IExternalScalarFunction;
+import edu.uci.ics.asterix.external.library.IFunctionHelper;
+import edu.uci.ics.asterix.external.library.java.JObjects.JBoolean;
+import edu.uci.ics.asterix.external.library.java.JObjects.JCircle;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDate;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDateTime;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDouble;
+import edu.uci.ics.asterix.external.library.java.JObjects.JDuration;
+import edu.uci.ics.asterix.external.library.java.JObjects.JFloat;
+import edu.uci.ics.asterix.external.library.java.JObjects.JInt;
+import edu.uci.ics.asterix.external.library.java.JObjects.JLine;
+import edu.uci.ics.asterix.external.library.java.JObjects.JOrderedList;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPoint;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPoint3D;
+import edu.uci.ics.asterix.external.library.java.JObjects.JPolygon;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
+import edu.uci.ics.asterix.external.library.java.JObjects.JString;
+import edu.uci.ics.asterix.external.library.java.JObjects.JTime;
+import edu.uci.ics.asterix.external.library.java.JObjects.JUnorderedList;
+import edu.uci.ics.asterix.external.library.java.JTypeTag;
+
+public class AllTypesFunction implements IExternalScalarFunction {
+
+	private JOrderedList newFieldList;
+
+	@Override
+	public void initialize(IFunctionHelper functionHelper) {
+		newFieldList = new JOrderedList(functionHelper.getObject(JTypeTag.INT));
+	}
+
+	@Override
+	public void deinitialize() {
+	}
+
+	@Override
+	public void evaluate(IFunctionHelper functionHelper) throws Exception {
+		newFieldList.clear();
+		JRecord inputRecord = (JRecord) functionHelper.getArgument(0);
+		JInt id = (JInt) inputRecord.getValueByName("id");
+		JString name = (JString) inputRecord.getValueByName("name");
+		JFloat age = (JFloat) inputRecord.getValueByName("age");
+		JDouble salary = (JDouble) inputRecord.getValueByName("salary");
+		JBoolean married = (JBoolean) inputRecord.getValueByName("married");
+		JUnorderedList interest = (JUnorderedList) inputRecord
+				.getValueByName("interests");
+		JOrderedList children = (JOrderedList) inputRecord
+				.getValueByName("children");
+		JRecord address = (JRecord) inputRecord.getValueByName("address");
+		JDate dob = (JDate) inputRecord.getValueByName("dob");
+		JTime time = (JTime) inputRecord.getValueByName("time");
+		JDateTime dateTime = (JDateTime) inputRecord.getValueByName("datetime");
+		JDuration duration = (JDuration) inputRecord.getValueByName("duration");
+		JPoint location2d = (JPoint) inputRecord.getValueByName("location2d");
+		JPoint3D location3d = (JPoint3D) inputRecord
+				.getValueByName("location3d");
+		JLine line = (JLine) inputRecord.getValueByName("line");
+		JPolygon polygon = (JPolygon) inputRecord.getValueByName("polygon");
+		JCircle circle = (JCircle) inputRecord.getValueByName("circle");
+
+		JRecord result = (JRecord) functionHelper.getResultObject();
+		result.setField("id", id);
+		result.setField("name", name);
+		result.setField("age", age);
+		result.setField("salary", salary);
+		result.setField("married", married);
+		result.setField("interests", interest);
+		result.setField("children", children);
+		JInt zipCode = (JInt) functionHelper.getObject(JTypeTag.INT);
+		zipCode.setValue(92841);
+		address.addField("Zipcode", zipCode);
+		result.setField("address", address);
+		result.setField("dob", dob);
+		result.setField("time", time);
+		result.setField("datetime", dateTime);
+		result.setField("duration", duration);
+		result.setField("location2d", location2d);
+		result.setField("location3d", location3d);
+		result.setField("line", line);
+		result.setField("polygon", polygon);
+		result.setField("circle", circle);
+
+		JString newFieldString = (JString) functionHelper
+				.getObject(JTypeTag.STRING);
+		newFieldString.setValue("processed");
+		result.addField("status", newFieldString);
+
+		/*
+		 * JString element = (JString)
+		 * functionHelper.getObject(JTypeTag.STRING); element.setValue("raman");
+		 * newFieldList.add(element); result.addField("mylist", newFieldList);
+		 */
+
+		JString newFieldString2 = (JString) functionHelper
+				.getObject(JTypeTag.STRING);
+		newFieldString2.setValue("this is working");
+		result.addField("working", newFieldString);
+		functionHelper.setResult(result);
+	}
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/CapitalFinderFactory.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/CapitalFinderFactory.java
new file mode 100644
index 0000000..872b542
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/CapitalFinderFactory.java
@@ -0,0 +1,27 @@
+/*
+ * 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.external.library;
+
+import edu.uci.ics.asterix.external.library.IExternalScalarFunction;
+import edu.uci.ics.asterix.external.library.IFunctionFactory;
+
+public class CapitalFinderFactory implements IFunctionFactory {
+
+    @Override
+    public IExternalScalarFunction getExternalFunction() {
+        return new CapitalFinderFunction();
+    }
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/CapitalFinderFunction.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/CapitalFinderFunction.java
new file mode 100644
index 0000000..7953b62
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/CapitalFinderFunction.java
@@ -0,0 +1,57 @@
+/*
+ * 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.external.library;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
+import edu.uci.ics.asterix.external.library.java.JObjects.JString;
+import edu.uci.ics.asterix.external.library.java.JTypeTag;
+
+public class CapitalFinderFunction implements IExternalScalarFunction {
+
+    private static Properties capitalList;
+    private static final String NOT_FOUND = "NOT_FOUND";
+    private JString capital;
+
+    @Override
+    public void deinitialize() {
+        System.out.println(" De Initialized");
+    }
+
+    @Override
+    public void evaluate(IFunctionHelper functionHelper) throws Exception {
+        JString country = ((JString) functionHelper.getArgument(0));
+        JRecord record = (JRecord) functionHelper.getResultObject();
+        //     ((JString) record.getValueByName("country")).setValue(country.getValue());
+        String capitalCity = capitalList.getProperty(country.getValue(), NOT_FOUND);
+        //      ((JString) record.getValueByName("capital")).setValue(capitalCity);
+        capital.setValue(capitalCity);
+
+        record.setField("country", country);
+        record.setField("capital", capital);
+        functionHelper.setResult(record);
+    }
+
+    @Override
+    public void initialize(IFunctionHelper functionHelper) throws Exception {
+        InputStream in = CapitalFinderFunction.class.getClassLoader().getResourceAsStream("data/countriesCapitals.txt");
+        capitalList = new Properties();
+        capitalList.load(in);
+        capital = (JString) functionHelper.getObject(JTypeTag.STRING);
+    }
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/ParseTweetFactory.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/ParseTweetFactory.java
new file mode 100644
index 0000000..d868f20
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/ParseTweetFactory.java
@@ -0,0 +1,27 @@
+/*
+ * 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.external.library;
+
+import edu.uci.ics.asterix.external.library.IExternalScalarFunction;
+import edu.uci.ics.asterix.external.library.IFunctionFactory;
+
+public class ParseTweetFactory implements IFunctionFactory {
+
+    @Override
+    public IExternalScalarFunction getExternalFunction() {
+        return new ParseTweetFunction();
+    }
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/ParseTweetFunction.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/ParseTweetFunction.java
new file mode 100644
index 0000000..de13e59
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/ParseTweetFunction.java
@@ -0,0 +1,60 @@
+/*
+ * 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.external.library;
+
+import edu.uci.ics.asterix.external.library.java.JObjects.JOrderedList;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
+import edu.uci.ics.asterix.external.library.java.JObjects.JString;
+import edu.uci.ics.asterix.external.library.java.JTypeTag;
+
+public class ParseTweetFunction implements IExternalScalarFunction {
+
+    private JOrderedList list = null;
+
+    @Override
+    public void initialize(IFunctionHelper functionHelper) {
+        list = new JOrderedList(functionHelper.getObject(JTypeTag.STRING));
+    }
+
+    @Override
+    public void deinitialize() {
+    }
+
+    @Override
+    public void evaluate(IFunctionHelper functionHelper) throws Exception {
+        list.clear();
+        JRecord inputRecord = (JRecord) functionHelper.getArgument(0);
+        JString id = (JString) inputRecord.getValueByName("id");
+        JString text = (JString) inputRecord.getValueByName("text");
+
+        String[] tokens = text.getValue().split(" ");
+        for (String tk : tokens) {
+            if (tk.startsWith("#")) {
+                JString newField = (JString) functionHelper.getObject(JTypeTag.STRING);
+                newField.setValue(tk);
+                list.add(newField);
+            }
+        }
+        JRecord result = (JRecord) functionHelper.getResultObject();
+        result.setField("id", id);
+        result.setField("username", inputRecord.getValueByName("username"));
+        result.setField("location", inputRecord.getValueByName("location"));
+        result.setField("text", text);
+        result.setField("timestamp", inputRecord.getValueByName("timestamp"));
+        result.setField("topics", list);
+        functionHelper.setResult(result);
+    }
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/SumFactory.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/SumFactory.java
new file mode 100644
index 0000000..eabc6b5
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/SumFactory.java
@@ -0,0 +1,27 @@
+/*
+ * 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.external.library;
+        
+import edu.uci.ics.asterix.external.library.IExternalScalarFunction;
+import edu.uci.ics.asterix.external.library.IFunctionFactory;
+
+public class SumFactory implements IFunctionFactory {
+
+	@Override
+	public IExternalScalarFunction getExternalFunction() {
+		return new SumFunction();
+	}
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/SumFunction.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/SumFunction.java
new file mode 100644
index 0000000..0a4eca6
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/SumFunction.java
@@ -0,0 +1,43 @@
+/*
+ * 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.external.library;
+
+import edu.uci.ics.asterix.external.library.IExternalScalarFunction;
+import edu.uci.ics.asterix.external.library.IFunctionHelper;
+import edu.uci.ics.asterix.external.library.java.JObjects.JInt;
+
+public class SumFunction implements IExternalScalarFunction {
+
+    private JInt result;
+
+    @Override
+    public void deinitialize() {
+        System.out.println(" De Initialized");
+    }
+
+    @Override
+    public void evaluate(IFunctionHelper functionHelper) throws Exception {
+        int arg0 = ((JInt) functionHelper.getArgument(0)).getValue();
+        int arg1 = ((JInt) functionHelper.getArgument(1)).getValue();
+        result.setValue(arg0 + arg1);
+        functionHelper.setResult(result);
+    }
+
+    @Override
+    public void initialize(IFunctionHelper functionHelper) {
+        result = (JInt) functionHelper.getResultObject();
+    }
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/UpperCaseFactory.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/UpperCaseFactory.java
new file mode 100644
index 0000000..2c5f607
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/UpperCaseFactory.java
@@ -0,0 +1,27 @@
+/*
+ * 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.external.library;
+
+import edu.uci.ics.asterix.external.library.IExternalFunction;
+import edu.uci.ics.asterix.external.library.IFunctionFactory;
+
+public class UpperCaseFactory implements IFunctionFactory {
+
+    @Override
+    public IExternalFunction getExternalFunction() {
+        return new UpperCaseFunction();
+    }
+
+}
diff --git a/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/UpperCaseFunction.java b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/UpperCaseFunction.java
new file mode 100644
index 0000000..e3d1c9c
--- /dev/null
+++ b/asterix-external-data/src/test/java/edu/uci/ics/asterix/external/library/UpperCaseFunction.java
@@ -0,0 +1,67 @@
+/*
+ * 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.external.library;
+
+import java.util.Random;
+
+import edu.uci.ics.asterix.external.library.IExternalScalarFunction;
+import edu.uci.ics.asterix.external.library.IFunctionHelper;
+import edu.uci.ics.asterix.external.library.java.JTypeTag;
+import edu.uci.ics.asterix.external.library.java.JObjects.JInt;
+import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
+import edu.uci.ics.asterix.external.library.java.JObjects.JString;
+
+/**
+ * Accepts an input record of type Open{ id: int32, text: string }
+ * 
+ * Converts the text field into upper case and appends an additional field -
+ * "substring" with value as a random substring of the text field.
+ * 
+ * Return Type Open{ id: int32, text: string }
+ * 
+ */
+public class UpperCaseFunction implements IExternalScalarFunction {
+
+	private Random random;
+
+	@Override
+	public void initialize(IFunctionHelper functionHelper) {
+		random = new Random();
+	}
+
+	@Override
+	public void deinitialize() {
+	}
+
+	@Override
+	public void evaluate(IFunctionHelper functionHelper) throws Exception {
+		JRecord inputRecord = (JRecord) functionHelper.getArgument(0);
+		JInt id = (JInt) inputRecord.getValueByName("id");
+		id.setValue(id.getValue() * -1); // for maintaining uniqueness
+											// constraint in the case when
+											// output is re-inserted into source
+											// dataset
+		JString text = (JString) inputRecord.getValueByName("text");
+		text.setValue(text.getValue().toUpperCase());
+		JRecord result = (JRecord) functionHelper.getResultObject();
+		result.setField("id", id);
+		result.setField("text", text);
+		JString newField = (JString) functionHelper.getObject(JTypeTag.STRING);
+		newField.setValue(text.getValue().substring(
+				random.nextInt(text.getValue().length())));
+		result.addField("substring", newField);
+		functionHelper.setResult(result);
+	}
+}
diff --git a/asterix-external-data/src/test/resources/data/countriesCapitals.txt b/asterix-external-data/src/test/resources/data/countriesCapitals.txt
new file mode 100644
index 0000000..def17ed
--- /dev/null
+++ b/asterix-external-data/src/test/resources/data/countriesCapitals.txt
@@ -0,0 +1,189 @@
+United\ Arab\ Emirates=Abu Dhabi
+Nigeria=Abuja
+Ghana=Accra
+Ethiopia=Addis Ababa
+Algeria=Algiers
+Niue=Alofi
+Jordan=Amman
+Netherlands=Amsterdam 
+Andorra=Andorra la Vella
+Turkey=Ankara
+Madagascar=Antananarivo
+Samoa=Apia
+Turkmenistan=Ashgabat
+Eritrea=Asmara
+Kazakhstan=Astana
+Paraguay=Asunción
+Greece=Athens
+Iraq=Baghdad
+Azerbaijan=Baku
+Mali=Bamako
+Brunei=Bandar Seri Begawan
+Thailand=Bangkok
+Gambia=Banjul
+China=Beijing
+Lebanon=Beirut
+Serbia=Belgrade
+Belize=Belmopan
+Germany=Berlin
+Switzerland=Bern
+Kyrgyzstan=Bishkek
+Guinea-Bissau=Bissau
+Colombia=Bogotá
+Brazil=Brasília
+Slovakia=Bratislava
+Barbados=Bridgetown
+Belgium=Brussels
+Romania=Bucharest
+Hungary=Budapest
+Argentina=Buenos Aires
+Burundi=Bujumbura
+Egypt=Cairo
+Australia=Canberra
+Venezuela=Caracas
+Wales=Cardiff
+Moldova=Chisinau
+Guinea=Conakry
+Denmark=Copenhagen
+Senegal=Dakar
+Syria=Damascus
+Bangladesh=Dhaka
+Djibouti=Djibouti
+Qatar=Doha
+Ireland=Dublin
+Tajikistan=Dushanbe
+Scotland=Edinburgh
+Botswana=Gaborone
+Guyana=Georgetown
+Gibraltar=Gibraltar
+Guatemala=Guatemala City
+Guam=Hagåtña
+Bermuda=Hamilton
+Vietnam=Hanoi
+Zimbabwe=Harare
+Cuba=Havana
+Finland=Helsinki
+Pakistan=Islamabad
+Indonesia=Jakarta
+Afghanistan=Kabul
+Uganda=Kampala
+Nepal=Kathmandu
+Sudan=Khartoum
+Ukraine=Kiev
+Rwanda=Kigali
+Jamaica=Kingston
+Malaysia=Kuala Lumpur
+Kuwait=Kuwait City
+Gabon=Libreville
+Malawi=Lilongwe
+Peru=Lima
+Portugal=Lisbon
+Slovenia=Ljubljana
+Togo=Lome
+England=London
+Angola=Luanda
+Zambia=Lusaka
+Luxembourg=Luxembourg
+Spain=Madrid
+Marshall Islands=Majuro
+Equatorial Guinea=Malabo
+Maldives=Malé
+Nicaragua=Managua
+Bahrain=Manama
+Philippines=Manila
+Mozambique=Maputo
+Saint Martin=Marigot
+Lesotho=Maseru
+Wallis and Futuna=Mata-Utu
+Palau=Melekeok
+Mexico=Mexico City
+Belarus=Minsk
+Somalia=Mogadishu
+Monaco=Monaco
+Liberia=Monrovia
+Uruguay=Montevideo
+Comoros=Moroni
+Russia=Moscow
+Oman=Muscat
+Kenya=Nairobi
+Bahamas=Nassau
+Myanmar=Naypyidaw
+Chad=NDjamena
+India=New Delhi
+Niger=Niamey
+Cyprus=Nicosia
+Mauritania=Nouakchott
+Greenland=Nuuk
+Aruba=Oranjestad
+Norway=Oslo
+Canada=Ottawa
+Panama=Panama City
+Suriname=Paramaribo
+France=Paris
+Cambodia=Phnom Penh
+Montserrat=Brades Estate (de facto)
+Montenegro=Podgorica
+Mauritius=Port Louis
+Vanuatu=Port Vila
+Haiti=Port-au-Prince
+Benin=Cotonou (de facto)
+Czech Republic=Prague
+Cape Verde=Praia
+South\ Africa=Cape Town
+North\ Korea=Pyongyang
+Ecuador=Quito
+Morocco=Rabat
+Iceland=Reykjavík
+Latvia=Riga
+Saudi\ Arabia=Riyadh
+Italy=Rome
+Dominica=Roseau
+Costa\ Rica=San José
+Puerto\ Rico=San Juan
+San\ Marino=San Marino
+El\ Salvador=San Salvador
+Yemen=Sanaa
+Chile=Santiago
+Dominican\ Republic=Santo Domingo
+Bosnia\ and\ Herzegovina=Sarajevo
+South\ Korea=Seoul
+Singapore=Singapore
+Macedonia=Skopje
+Bulgaria=Sofia
+Sri\ Lanka=Colombo
+Grenada=St. George's
+Jersey=St. Helier
+Guernsey=St. Peter Port
+Sweden=Stockholm
+Bolivia=La Paz
+Abkhazia=Sukhumi
+Fiji=Suva
+Taiwan=Taipei
+Estonia=Tallinn
+Kiribati=Tarawa
+Uzbekistan=Tashkent
+Georgia=Tbilisi
+Honduras=Tegucigalpa
+Iran=Tehran
+Bhutan=Thimphu
+Albania=Tirana
+Transnistria=Tiraspol
+Japan=Tokyo
+Libya=Tripoli
+Tunisia=Tunis
+Mongolia=Ulan Bator
+Liechtenstein=Vaduz
+Malta=Valletta
+Anguilla=The Valley
+Vatican\ City=Vatican City
+Seychelles=Victoria
+Austria=Vienna
+Laos=Vientiane
+Lithuania=Vilnius
+Poland=Warsaw
+United\ States=Washington D.C.
+New\ Zealand=Wellington
+Namibia=Windhoek
+Nauru=Yaren (de facto)
+Armenia=Yerevan
+Croatia=Zagreb
diff --git a/asterix-external-data/src/test/resources/text_functions.xml b/asterix-external-data/src/test/resources/text_functions.xml
new file mode 100644
index 0000000..bee6604
--- /dev/null
+++ b/asterix-external-data/src/test/resources/text_functions.xml
@@ -0,0 +1,45 @@
+<library xmlns="library">
+	<language>JAVA</language>
+	<functions>
+		<function>
+			<function_type>SCALAR</function_type>
+			<name>parseTweet</name>
+			<arguments>TweetType</arguments>
+			<return_type>TweetType</return_type>
+			<definition>edu.uci.ics.asterix.external.library.ParseTweetFactory
+			</definition>
+		</function>
+		<function>
+			<function_type>SCALAR</function_type>
+			<name>mysum</name>
+			<arguments>AINT32,AINT32</arguments>
+			<return_type>AINT32</return_type>
+			<definition>edu.uci.ics.asterix.external.library.SumFactory
+			</definition>
+		</function>
+		<function>
+			<function_type>SCALAR</function_type>
+			<name>getCapital</name>
+			<arguments>ASTRING</arguments>
+			<return_type>CountryCapitalType</return_type>
+			<definition>edu.uci.ics.asterix.external.library.CapitalFinderFactory
+			</definition>
+		</function>
+		<function>
+			<function_type>SCALAR</function_type>
+			<name>toUpper</name>
+			<arguments>TextType</arguments>
+			<return_type>TextType</return_type>
+			<definition>edu.uci.ics.asterix.external.library.UpperCaseFactory
+			</definition>
+		</function>
+		<function>
+			<function_type>SCALAR</function_type>
+			<name>allTypes</name>
+			<arguments>AllType</arguments>
+			<return_type>AllType</return_type>
+			<definition>edu.uci.ics.asterix.external.library.AllTypesFactory
+			</definition>
+		</function>
+	</functions>
+</library>
diff --git a/asterix-installer/pom.xml b/asterix-installer/pom.xml
index 60ae2ce..5b3b7ff 100644
--- a/asterix-installer/pom.xml
+++ b/asterix-installer/pom.xml
@@ -1,151 +1,178 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-          <artifactId>asterix</artifactId>
-          <groupId>edu.uci.ics.asterix</groupId>
-          <version>0.0.6-SNAPSHOT</version>
-  </parent>
-  <artifactId>asterix-installer</artifactId>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+        <modelVersion>4.0.0</modelVersion>
+        <parent>
+                <artifactId>asterix</artifactId>
+                <groupId>edu.uci.ics.asterix</groupId>
+                <version>0.0.6-SNAPSHOT</version>
+        </parent>
+        <artifactId>asterix-installer</artifactId>
 
-  <properties>
-    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-  </properties>
+        <properties>
+                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        </properties>
 
-  <build>
-    <plugins>
-       <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <version>2.0.2</version>
-          <configuration>
-             <source>1.6</source>
-             <target>1.6</target>
-          </configuration>
-       </plugin>
-
-       <plugin>
-          <groupId>org.jvnet.jaxb2.maven2</groupId>
-          <artifactId>maven-jaxb2-plugin</artifactId>
-          <executions>
-            <execution>
-              <id>configuration</id>
-              <goals>
-                <goal>generate</goal>
-              </goals>
-              <configuration>
-                <args>
-                  <arg>-Xsetters</arg>
-                  <arg>-Xvalue-constructor</arg>
-                </args>
+        <build>
                 <plugins>
-                  <plugin>
-                    <groupId>org.jvnet.jaxb2_commons</groupId>
-                    <artifactId>jaxb2-basics</artifactId>
-                    <version>0.6.2</version>
-                  </plugin>
-                  <plugin>
-                    <groupId>org.jvnet.jaxb2_commons</groupId>
-                    <artifactId>jaxb2-value-constructor</artifactId>
-                    <version>3.0</version>
-                  </plugin>
-                </plugins>
-                <schemaDirectory>src/main/resources/schema</schemaDirectory>
-                <schemaIncludes>
-                  <include>installer-conf.xsd</include>
-                </schemaIncludes>
-                <generatePackage>edu.uci.ics.asterix.installer.schema.conf</generatePackage>
-                <generateDirectory>${project.build.directory}/generated-sources/configuration</generateDirectory>
-              </configuration>
-            </execution>
-            <execution>
-              <id>cluster</id>
-              <goals>
-                <goal>generate</goal>
-              </goals>
-              <configuration>
-                <schemaDirectory>src/main/resources/schema</schemaDirectory>
-                <schemaIncludes>
-                  <include>cluster.xsd</include>
-                </schemaIncludes>
-                <generatePackage>edu.uci.ics.asterix.installer.schema.cluster</generatePackage>
-                <bindingDirectory>src/main/resources/schema</bindingDirectory>
-                <bindingIncludes>
-                  <bindingInclude>jaxb-bindings.xjb</bindingInclude>
-                </bindingIncludes>
-                <generateDirectory>${project.build.directory}/generated-sources/cluster</generateDirectory>
-              </configuration>
-            </execution>
-          </executions>
-       </plugin>
-       <plugin>
-         <artifactId>maven-assembly-plugin</artifactId>
-         <version>2.2-beta-2</version>
-         <executions>
-           <execution>
-             <configuration>
-               <descriptor>src/main/assembly/binary-assembly.xml</descriptor>
-             </configuration>
-             <phase>package</phase>
-             <goals>
-               <goal>attached</goal>
-             </goals>
-           </execution>
-         </executions>
-       </plugin>
-    </plugins> 
-  </build>
+                        <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-compiler-plugin</artifactId>
+                                <version>2.0.2</version>
+                                <configuration>
+                                        <source>1.7</source>
+                                        <target>1.7</target>
+                                </configuration>
+                        </plugin>
 
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>args4j</groupId>
-      <artifactId>args4j</artifactId>
-      <version>2.0.12</version>
-      <type>jar</type>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.zookeeper</groupId>
-      <artifactId>zookeeper</artifactId>
-      <version>3.4.5</version>
-      <exclusions>
-            <exclusion>
-                <groupId>com.sun.jmx</groupId>
-                <artifactId>jmxri</artifactId>
-            </exclusion>
-            <exclusion>
-                <groupId>com.sun.jdmk</groupId>
-                <artifactId>jmxtools</artifactId>
-            </exclusion>
-            <exclusion>
-                <groupId>javax.jms</groupId>
-                <artifactId>jms</artifactId>
-            </exclusion>
-        </exclusions>
-    </dependency>
-    <dependency>
-        <groupId>commons-io</groupId>
-        <artifactId>commons-io</artifactId>
-        <version>1.4</version>
-    </dependency>
-    <dependency>
-        <groupId>edu.uci.ics.asterix</groupId>
-        <artifactId>asterix-events</artifactId>
-        <version>0.0.6-SNAPSHOT</version>
-        <type>jar</type>
-        <scope>compile</scope>
-    </dependency>
-    <dependency>
-        <groupId>edu.uci.ics.asterix</groupId>
-        <artifactId>asterix-server</artifactId>
-        <version>0.0.6-SNAPSHOT</version>
-        <type>zip</type>
-        <classifier>binary-assembly</classifier>
-    </dependency>
-  </dependencies>
-</project>
+                        <plugin>
+                                <groupId>org.jvnet.jaxb2.maven2</groupId>
+                                <artifactId>maven-jaxb2-plugin</artifactId>
+                                <executions>
+                                        <execution>
+                                                <id>configuration</id>
+                                                <goals>
+                                                        <goal>generate</goal>
+                                                </goals>
+                                                <configuration>
+                                                        <args>
+                                                                <arg>-Xsetters</arg>
+                                                                <arg>-Xvalue-constructor</arg>
+                                                        </args>
+                                                        <plugins>
+                                                                <plugin>
+                                                                        <groupId>org.jvnet.jaxb2_commons</groupId>
+                                                                        <artifactId>jaxb2-basics</artifactId>
+                                                                        <version>0.6.2</version>
+                                                                </plugin>
+                                                                <plugin>
+                                                                        <groupId>org.jvnet.jaxb2_commons</groupId>
+                                                                        <artifactId>jaxb2-value-constructor</artifactId>
+                                                                        <version>3.0</version>
+                                                                </plugin>
+                                                        </plugins>
+                                                        <schemaDirectory>src/main/resources/schema</schemaDirectory>
+                                                        <schemaIncludes>
+                                                                <include>installer-conf.xsd</include>
+                                                        </schemaIncludes>
+                                                        <generatePackage>edu.uci.ics.asterix.installer.schema.conf</generatePackage>
+                                                        <generateDirectory>${project.build.directory}/generated-sources/configuration</generateDirectory>
+                                                </configuration>
+                                        </execution>
+                                        <execution>
+                                                <id>cluster</id>
+                                                <goals>
+                                                        <goal>generate</goal>
+                                                </goals>
+                                                <configuration>
+                                                        <schemaDirectory>src/main/resources/schema</schemaDirectory>
+                                                        <schemaIncludes>
+                                                                <include>cluster.xsd</include>
+                                                        </schemaIncludes>
+                                                        <generatePackage>edu.uci.ics.asterix.installer.schema.cluster</generatePackage>
+                                                        <bindingDirectory>src/main/resources/schema</bindingDirectory>
+                                                        <bindingIncludes>
+                                                                <bindingInclude>jaxb-bindings.xjb</bindingInclude>
+                                                        </bindingIncludes>
+                                                        <generateDirectory>${project.build.directory}/generated-sources/cluster</generateDirectory>
+                                                </configuration>
+                                        </execution>
+                                </executions>
+                        </plugin>
+                        <plugin>
+                                <artifactId>maven-assembly-plugin</artifactId>
+                                <version>2.2-beta-5</version>
+                                <executions>
+                                        <execution>
+                                                <configuration>
+                                                        <descriptor>src/main/assembly/binary-assembly.xml</descriptor>
+                                                </configuration>
+                                                <phase>package</phase>
+                                                <goals>
+                                                        <goal>attached</goal>
+                                                </goals>
+                                        </execution>
+                                </executions>
+                        </plugin>
+                        <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-failsafe-plugin</artifactId>
+                                <version>2.6</version>
+                                <executions>
+                                        <execution>
+                                                <goals>
+                                                        <goal>integration-test</goal>
+                                                        <goal>verify</goal>
+                                                </goals>
+                                        </execution>
+                                </executions>
+                        </plugin>
+                </plugins>
+        </build>
+
+        <dependencies>
+                <dependency>
+                        <groupId>junit</groupId>
+                        <artifactId>junit</artifactId>
+                        <version>4.8.1</version>
+                        <scope>test</scope>
+                </dependency>
+                <dependency>
+                        <groupId>args4j</groupId>
+                        <artifactId>args4j</artifactId>
+                        <version>2.0.12</version>
+                        <type>jar</type>
+                        <scope>compile</scope>
+                </dependency>
+                <dependency>
+                        <groupId>org.apache.zookeeper</groupId>
+                        <artifactId>zookeeper</artifactId>
+                        <version>3.4.5</version>
+                        <exclusions>
+                                <exclusion>
+                                        <groupId>com.sun.jmx</groupId>
+                                        <artifactId>jmxri</artifactId>
+                                </exclusion>
+                                <exclusion>
+                                        <groupId>com.sun.jdmk</groupId>
+                                        <artifactId>jmxtools</artifactId>
+                                </exclusion>
+                                <exclusion>
+                                        <groupId>javax.jms</groupId>
+                                        <artifactId>jms</artifactId>
+                                </exclusion>
+                        </exclusions>
+                </dependency>
+                <dependency>
+                        <groupId>commons-io</groupId>
+                        <artifactId>commons-io</artifactId>
+                        <version>1.4</version>
+                </dependency>
+                <dependency>
+                        <groupId>edu.uci.ics.asterix</groupId>
+                        <artifactId>asterix-events</artifactId>
+                        <version>0.0.6-SNAPSHOT</version>
+                        <type>jar</type>
+                        <scope>compile</scope>
+                </dependency>
+                <dependency>
+                        <groupId>edu.uci.ics.asterix</groupId>
+                        <artifactId>asterix-common</artifactId>
+                        <version>0.0.6-SNAPSHOT</version>
+                        <type>test-jar</type>
+                        <scope>test</scope>
+                </dependency>
+                <dependency>
+                        <groupId>edu.uci.ics.asterix</groupId>
+                        <artifactId>asterix-server</artifactId>
+                        <version>0.0.6-SNAPSHOT</version>
+                        <type>zip</type>
+                        <classifier>binary-assembly</classifier>
+                </dependency>
+                <dependency>
+                        <groupId>edu.uci.ics.asterix</groupId>
+                        <artifactId>asterix-test-framework</artifactId>
+                        <version>0.0.6-SNAPSHOT</version>
+                        <scope>test</scope>
+                </dependency>
+        </dependencies>
+</project>
\ No newline at end of file
diff --git a/asterix-installer/src/main/assembly/binary-assembly.xml b/asterix-installer/src/main/assembly/binary-assembly.xml
index 6a0c130..739b444 100644
--- a/asterix-installer/src/main/assembly/binary-assembly.xml
+++ b/asterix-installer/src/main/assembly/binary-assembly.xml
@@ -1,6 +1,7 @@
 <assembly>
   <id>binary-assembly</id>
   <formats>
+    <format>dir</format>
     <format>zip</format>
   </formats>
   <includeBaseDirectory>false</includeBaseDirectory>
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java
index 7fc3884..21cec69 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CommandHandler.java
@@ -52,6 +52,12 @@
             case CONFIGURE:
                 cmd = new ConfigureCommand();
                 break;
+            case INSTALL:
+                cmd = new InstallCommand();
+                break;
+            case UNINSTALL:
+                cmd = new UninstallCommand();
+                break;
             case SHUTDOWN:
                 cmd = new ShutdownCommand();
                 break;
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java
index e742c4e..7f12f01 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ConfigureCommand.java
@@ -27,7 +27,7 @@
         cluster.setIodevices(workingDir);
         cluster.setStore("storage");
         cluster.setLogdir(workingDir + File.separator + "logs");
-        cluster.setJavaHome(System.getenv("JAVA_HOME"));
+        cluster.setJavaHome(System.getProperty("java.home"));
         cluster.setJavaOpts("-Xmx1024m");
 
         JAXBContext ctx = JAXBContext.newInstance(Cluster.class);
@@ -44,7 +44,7 @@
         configuration.getZookeeper().setHomeDir(
                 InstallerDriver.getManagixHome() + File.separator + InstallerDriver.MANAGIX_INTERNAL_DIR
                         + File.separator + "zookeeper_home");
-        configuration.getZookeeper().getServers().setJavaHome(System.getenv("JAVA_HOME"));
+        configuration.getZookeeper().getServers().setJavaHome(System.getProperty("java.home"));
 
         marshaller = ctx.createMarshaller();
         marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java
index 2de8e53..81d6481 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/CreateCommand.java
@@ -18,6 +18,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+
 import org.kohsuke.args4j.Option;
 
 import edu.uci.ics.asterix.event.management.EventUtil;
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/HelpCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/HelpCommand.java
index a9864a3..f0e2fcc 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/HelpCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/HelpCommand.java
@@ -55,6 +55,12 @@
             case VALIDATE:
                 helpMessage = new ValidateCommand().getUsageDescription();
                 break;
+            case INSTALL:
+                helpMessage = new InstallCommand().getUsageDescription();
+                break;
+            case UNINSTALL:
+                helpMessage = new UninstallCommand().getUsageDescription();
+                break;
             default:
                 helpMessage = "Unknown command " + command;
         }
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java
index 979c414..be64aa4 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ICommand.java
@@ -27,6 +27,8 @@
         ALTER,
         VALIDATE,
         CONFIGURE,
+        INSTALL,
+        UNINSTALL,
         SHUTDOWN,
         HELP
     }
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/InstallCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/InstallCommand.java
new file mode 100644
index 0000000..936efcb
--- /dev/null
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/InstallCommand.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2009-2012 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.installer.command;
+
+import org.kohsuke.args4j.Option;
+
+import edu.uci.ics.asterix.event.schema.pattern.Patterns;
+import edu.uci.ics.asterix.installer.driver.InstallerDriver;
+import edu.uci.ics.asterix.installer.driver.InstallerUtil;
+import edu.uci.ics.asterix.installer.events.PatternCreator;
+import edu.uci.ics.asterix.installer.model.AsterixInstance;
+import edu.uci.ics.asterix.installer.model.AsterixInstance.State;
+
+public class InstallCommand extends AbstractCommand {
+
+    @Override
+    protected void execCommand() throws Exception {
+        InstallerDriver.initConfig();
+        InstallConfig installConfig = ((InstallConfig) config);
+        String instanceName = installConfig.name;
+        AsterixInstance instance = InstallerUtil.validateAsterixInstanceExists(instanceName, State.INACTIVE);
+        PatternCreator pc = new PatternCreator();
+        Patterns patterns = pc.getLibraryInstallPattern(instance, installConfig.dataverseName,
+                installConfig.libraryName, installConfig.libraryPath);
+        InstallerUtil.getEventrixClient(instance.getCluster()).submit(patterns);
+        LOGGER.info("Installed library " + installConfig.libraryName);
+    }
+
+    @Override
+    protected CommandConfig getCommandConfig() {
+        return new InstallConfig();
+    }
+
+    @Override
+    protected String getUsageDescription() {
+        return "Installs a library to an asterix instance." + "\n" + "Arguments/Options\n"
+                + "-n  Name of Asterix Instance\n"
+                + "-d  Name of the dataverse under which the library will be installed\n" + "-l  Name of the library\n"
+                + "-p  Path to library zip bundle";
+
+    }
+
+}
+
+class InstallConfig extends CommandConfig {
+
+    @Option(name = "-n", required = true, usage = "Name of Asterix Instance")
+    public String name;
+
+    @Option(name = "-d", required = true, usage = "Name of the dataverse under which the library will be installed")
+    public String dataverseName;
+
+    @Option(name = "-l", required = true, usage = "Name of the library")
+    public String libraryName;
+
+    @Option(name = "-p", required = true, usage = "Path to library zip bundle")
+    public String libraryPath;
+
+}
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/UninstallCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/UninstallCommand.java
new file mode 100644
index 0000000..70b4d8c
--- /dev/null
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/UninstallCommand.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2009-2012 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.installer.command;
+
+import org.kohsuke.args4j.Option;
+
+import edu.uci.ics.asterix.event.schema.pattern.Patterns;
+import edu.uci.ics.asterix.installer.driver.InstallerDriver;
+import edu.uci.ics.asterix.installer.driver.InstallerUtil;
+import edu.uci.ics.asterix.installer.events.PatternCreator;
+import edu.uci.ics.asterix.installer.model.AsterixInstance;
+import edu.uci.ics.asterix.installer.model.AsterixInstance.State;
+import edu.uci.ics.asterix.installer.service.ILookupService;
+import edu.uci.ics.asterix.installer.service.ServiceProvider;
+
+public class UninstallCommand extends AbstractCommand {
+
+    @Override
+    protected void execCommand() throws Exception {
+        InstallerDriver.initConfig();
+        UninstallConfig uninstallConfig = ((UninstallConfig) config);
+        String instanceName = uninstallConfig.name;
+        InstallerUtil.validateAsterixInstanceExists(instanceName, State.INACTIVE);
+        ILookupService lookupService = ServiceProvider.INSTANCE.getLookupService();
+        AsterixInstance instance = lookupService.getAsterixInstance(instanceName);
+        PatternCreator pc = new PatternCreator();
+        Patterns patterns = pc.getLibraryUninstallPattern(instance, uninstallConfig.dataverseName,
+                uninstallConfig.libraryName);
+        InstallerUtil.getEventrixClient(instance.getCluster()).submit(patterns);
+        LOGGER.info("Uninstalled library " + uninstallConfig.libraryName);
+    }
+
+    @Override
+    protected CommandConfig getCommandConfig() {
+        return new UninstallConfig();
+    }
+
+    @Override
+    protected String getUsageDescription() {
+        return "Uninstalls a library from an asterix instance." + "\n" + "Arguments/Options\n"
+                + "-n  Name of Asterix Instance\n"
+                + "-d  Name of the dataverse under which the library will be installed\n" + "-l  Name of the library\n"
+                + "-l  Name of the library";
+    }
+
+}
+
+class UninstallConfig extends CommandConfig {
+
+    @Option(name = "-n", required = true, usage = "Name of Asterix Instance")
+    public String name;
+
+    @Option(name = "-d", required = true, usage = "Name of the dataverse under which the library will be installed")
+    public String dataverseName;
+
+    @Option(name = "-l", required = true, usage = "Name of the library")
+    public String libraryName;
+
+}
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java
index 4e6460b..dcc63df 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/command/ValidateCommand.java
@@ -32,7 +32,6 @@
 import edu.uci.ics.asterix.event.schema.cluster.Node;
 import edu.uci.ics.asterix.installer.driver.InstallerDriver;
 import edu.uci.ics.asterix.installer.driver.InstallerUtil;
-import edu.uci.ics.asterix.installer.model.ProcessInfo;
 import edu.uci.ics.asterix.installer.schema.conf.Configuration;
 import edu.uci.ics.asterix.installer.schema.conf.Zookeeper;
 
@@ -76,17 +75,10 @@
 
     public boolean validateEnvironment() throws Exception {
         boolean valid = true;
-        String managixHome = System.getenv(InstallerDriver.ENV_MANAGIX_HOME);
-        if (managixHome == null) {
+        File home = new File(InstallerDriver.getManagixHome());
+        if (!home.exists()) {
             valid = false;
-            LOGGER.fatal(InstallerDriver.ENV_MANAGIX_HOME + " not set " + ERROR);
-        } else {
-            File home = new File(managixHome);
-            if (!home.exists()) {
-                valid = false;
-                LOGGER.fatal(InstallerDriver.ENV_MANAGIX_HOME + ": " + home.getAbsolutePath() + " does not exist!"
-                        + ERROR);
-            }
+            LOGGER.fatal(InstallerDriver.ENV_MANAGIX_HOME + ": " + home.getAbsolutePath() + " does not exist!" + ERROR);
         }
         return valid;
 
@@ -256,9 +248,8 @@
             valid = valid && checkNodeReachability(server);
         }
 
-        if (valid)
+        if (valid) {
             valid = valid & checkPasswordLessSSHLogin(System.getProperty("user.name"), zk.getServers().getServer());
-        {
         }
 
         return valid;
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/driver/InstallerDriver.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/driver/InstallerDriver.java
index 3596032..9d95b4a 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/driver/InstallerDriver.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/driver/InstallerDriver.java
@@ -129,9 +129,15 @@
         buffer.append("validate " + ":" + " Validates the installer/cluster configuration" + "\n");
         buffer.append("configure" + ":" + " Auto-generate configuration for local psedu-distributed Asterix instance"
                 + "\n");
+        buffer.append("install  " + ":" + " Installs a library to an asterix instance" + "\n");
+        buffer.append("uninstall" + ":" + " Uninstalls a library from an asterix instance" + "\n");
         buffer.append("shutdown " + ":" + " Shutdown the installer service" + "\n");
         buffer.append("help     " + ":" + " Provides usage description of a command" + "\n");
 
         LOGGER.info(buffer.toString());
     }
+
+    public static void setManagixHome(String managixHome) {
+        InstallerDriver.managixHome = managixHome;
+    }
 }
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/events/PatternCreator.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/events/PatternCreator.java
index 0d50bbf..0068c08 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/events/PatternCreator.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/events/PatternCreator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2012 by The Regents of the University of California
+ * 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
@@ -17,6 +17,7 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -385,6 +386,85 @@
         return patterns;
     }
 
+    public Patterns getLibraryInstallPattern(AsterixInstance instance, String dataverse, String libraryName,
+            String libraryPath) throws Exception {
+        List<Pattern> patternList = new ArrayList<Pattern>();
+        Cluster cluster = instance.getCluster();
+        Nodeid nodeid = new Nodeid(new Value(null, EventDriver.CLIENT_NODE.getId()));
+        String username = cluster.getUsername() != null ? cluster.getUsername() : System.getProperty("user.name");
+        String workingDir = cluster.getWorkingDir().getDir();
+        String destDir = workingDir + File.separator + "library" + File.separator + dataverse + File.separator
+                + libraryName;
+        String fileToTransfer = new File(libraryPath).getAbsolutePath();
+
+        Iterator<Node> installTargets = cluster.getNode().iterator();
+        Node installNode = installTargets.next();
+        String destinationIp = installNode.getClusterIp();
+        String pargs = username + " " + fileToTransfer + " " + destinationIp + " " + destDir + " " + "unpack";
+        Event event = new Event("file_transfer", nodeid, pargs);
+        Pattern p = new Pattern(null, 1, null, event);
+        patternList.add(p);
+
+        if (!cluster.getWorkingDir().isNFS()) {
+            while (installTargets.hasNext()) {
+                Node node = installTargets.next();
+                pargs = username + " " + fileToTransfer + " " + node.getClusterIp() + " " + destDir + " " + "unpack";
+                event = new Event("file_transfer", nodeid, pargs);
+                p = new Pattern(null, 1, null, event);
+                patternList.add(p);
+            }
+
+            pargs = username + " " + fileToTransfer + " " + cluster.getMasterNode().getClusterIp() + " " + destDir
+                    + " " + "unpack";
+            event = new Event("file_transfer", nodeid, pargs);
+            p = new Pattern(null, 1, null, event);
+            patternList.add(p);
+        }
+        return new Patterns(patternList);
+    }
+
+    public Patterns getLibraryUninstallPattern(AsterixInstance instance, String dataverse, String libraryName)
+            throws Exception {
+        List<Pattern> patternList = new ArrayList<Pattern>();
+        Cluster cluster = instance.getCluster();
+        String workingDir = cluster.getWorkingDir().getDir();
+        String destFile = dataverse + "." + libraryName;
+        String pargs = workingDir + File.separator + "uninstall" + " " + destFile;
+
+        String metadataNodeId = instance.getMetadataNodeId();
+        Nodeid nodeid = new Nodeid(new Value(null, metadataNodeId));
+        Event event = new Event("file_create", nodeid, pargs);
+        Pattern p = new Pattern(null, 1, null, event);
+        patternList.add(p);
+
+        Iterator<Node> uninstallTargets = cluster.getNode().iterator();
+        String libDir = workingDir + File.separator + "library" + File.separator + dataverse + File.separator
+                + libraryName;
+        Node uninstallNode = uninstallTargets.next();
+        nodeid = new Nodeid(new Value(null, uninstallNode.getId()));
+        event = new Event("file_delete", nodeid, libDir);
+        p = new Pattern(null, 1, null, event);
+        patternList.add(p);
+        pargs = libDir;
+
+        if (!cluster.getWorkingDir().isNFS()) {
+            while (uninstallTargets.hasNext()) {
+                uninstallNode = uninstallTargets.next();
+                nodeid = new Nodeid(new Value(null, uninstallNode.getId()));
+                event = new Event("file_delete", nodeid, pargs);
+                p = new Pattern(null, 1, null, event);
+                patternList.add(p);
+            }
+
+            nodeid = new Nodeid(new Value(null, cluster.getMasterNode().getId()));
+            event = new Event("file_delete", nodeid, pargs);
+            p = new Pattern(null, 1, null, event);
+            patternList.add(p);
+
+        }
+        return new Patterns(patternList);
+    }
+
     private Patterns createRemoveAsterixRootMetadata(AsterixInstance instance) throws Exception {
         List<Pattern> patternList = new ArrayList<Pattern>();
         Cluster cluster = instance.getCluster();
diff --git a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java
index b43fcdf..f09e4b6 100644
--- a/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java
+++ b/asterix-installer/src/main/java/edu/uci/ics/asterix/installer/service/ZooKeeperService.java
@@ -172,7 +172,7 @@
 
     public void removeAsterixInstance(String name) throws Exception {
         if (!exists(name)) {
-            throw new InstallerException("Asterix instance by name " + name + " does not exists.");
+			throw new InstallerException("Asterix instance by name " + name + " does not exists.");
         }
         zk.delete(ASTERIX_INSTANCE_BASE_PATH + File.separator + name, DEFAULT_NODE_VERSION);
     }
diff --git a/asterix-installer/src/main/resources/clusters/local/local.xml b/asterix-installer/src/main/resources/clusters/local/local.xml
index d397bcd..1cbcdfa 100644
--- a/asterix-installer/src/main/resources/clusters/local/local.xml
+++ b/asterix-installer/src/main/resources/clusters/local/local.xml
@@ -13,9 +13,11 @@
     <id>master</id>
     <client-ip>127.0.0.1</client-ip>
     <cluster-ip>127.0.0.1</cluster-ip>
+    <java_opts>-Xmx1024m -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8800</java_opts>
   </master-node>
   <node>
     <id>node1</id>
     <cluster-ip>127.0.0.1</cluster-ip>
+    <java_opts>-Xmx1024m -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8701</java_opts>
   </node>
 </cluster>
diff --git a/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixExternalLibraryIT.java b/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixExternalLibraryIT.java
new file mode 100644
index 0000000..06102b1
--- /dev/null
+++ b/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixExternalLibraryIT.java
@@ -0,0 +1,85 @@
+/*
+ * 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.installer.test;
+
+import java.io.File;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import edu.uci.ics.asterix.installer.model.AsterixInstance.State;
+import edu.uci.ics.asterix.test.aql.TestsUtils;
+import edu.uci.ics.asterix.testframework.context.TestCaseContext;
+
+public class AsterixExternalLibraryIT {
+
+	private static final String LIBRARY_NAME = "testlib";
+	private static final String LIBRARY_DATAVERSE = "externallibtest";
+	private static final String PATH_BASE = "src/test/resources/integrationts/library";
+	private static final String PATH_ACTUAL = "ittest/";
+	private static final String LIBRARY_PATH = "asterix-external-data"
+			+ File.separator + "target" + File.separator
+			+ "testlib-zip-binary-assembly.zip";
+	private static final Logger LOGGER = Logger
+			.getLogger(AsterixExternalLibraryIT.class.getName());
+	private static List<TestCaseContext> testCaseCollection;
+
+	@BeforeClass
+	public static void setUp() throws Exception {
+		AsterixInstallerIntegrationUtil.init();
+		File asterixInstallerProjectDir = new File(System
+				.getProperty("user.dir"));
+		String asterixExternalLibraryPath = asterixInstallerProjectDir
+				.getParentFile().getAbsolutePath()
+				+ File.separator + LIBRARY_PATH;
+		LOGGER.info("Installing library :" + LIBRARY_NAME + " located at "
+				+ asterixExternalLibraryPath + " in dataverse "
+				+ LIBRARY_DATAVERSE);
+		AsterixInstallerIntegrationUtil.installLibrary(LIBRARY_NAME,
+				LIBRARY_DATAVERSE, asterixExternalLibraryPath);
+		AsterixInstallerIntegrationUtil
+				.transformIntoRequiredState(State.ACTIVE);
+		TestCaseContext.Builder b = new TestCaseContext.Builder();
+		testCaseCollection = b.build(new File(PATH_BASE));
+	}
+
+	@AfterClass
+	public static void tearDown() throws Exception {
+		AsterixInstallerIntegrationUtil.deinit();
+	}
+
+	@Test
+	public void test() throws Exception {
+		for (TestCaseContext testCaseCtx : testCaseCollection) {
+			TestsUtils.executeTest(PATH_ACTUAL, testCaseCtx);
+		}
+	}
+
+	public static void main(String[] args) throws Exception {
+		try {
+			setUp();
+			new AsterixExternalLibraryIT().test();
+		} catch (Exception e) {
+		    e.printStackTrace();
+			LOGGER.info("TEST CASES FAILED");
+		} finally {
+			tearDown();
+		}
+	}
+
+}
diff --git a/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixInstallerIntegrationUtil.java b/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixInstallerIntegrationUtil.java
new file mode 100644
index 0000000..0a058ff
--- /dev/null
+++ b/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixInstallerIntegrationUtil.java
@@ -0,0 +1,214 @@
+/*
+ * 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.installer.test;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import edu.uci.ics.asterix.installer.command.CommandHandler;
+import edu.uci.ics.asterix.installer.driver.InstallerDriver;
+import edu.uci.ics.asterix.installer.error.VerificationUtil;
+import edu.uci.ics.asterix.installer.model.AsterixInstance;
+import edu.uci.ics.asterix.installer.model.AsterixInstance.State;
+import edu.uci.ics.asterix.installer.model.AsterixRuntimeState;
+import edu.uci.ics.asterix.installer.schema.conf.Configuration;
+import edu.uci.ics.asterix.installer.service.ServiceProvider;
+import edu.uci.ics.hyracks.api.client.HyracksConnection;
+import edu.uci.ics.hyracks.api.client.IHyracksClientConnection;
+
+public class AsterixInstallerIntegrationUtil {
+
+    private static String managixHome;
+    private static String clusterConfigurationPath;
+    private static final CommandHandler cmdHandler = new CommandHandler();
+    public static final String ASTERIX_INSTANCE_NAME = "asterix";
+    private static final String CC_IP_ADDRESS = "127.0.0.1";
+    private static final int DEFAULT_HYRACKS_CC_CLIENT_PORT = 1098;
+    private static IHyracksClientConnection hcc;
+
+    private static final Logger LOGGER = Logger.getLogger(AsterixInstallerIntegrationUtil.class.getName());
+
+    public static void deinit() throws Exception {
+        deleteInstance();
+        stopZookeeper();
+    }
+
+    public static void init() throws Exception {
+        File asterixProjectDir = new File(System.getProperty("user.dir"));
+        File installerTargetDir = new File(asterixProjectDir, "target");
+        String managixHomeDirName = installerTargetDir.list(new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                return new File(dir, name).isDirectory() && name.startsWith("asterix-installer")
+                        && name.endsWith("binary-assembly");
+            }
+
+        })[0];
+        managixHome = new File(installerTargetDir, managixHomeDirName).getAbsolutePath();
+        System.setProperty("log4j.configuration", managixHome + File.separator + "conf" + File.separator
+                + "log4j.properties");
+
+        managixHome = AsterixInstallerIntegrationUtil.getManagixHome();
+        clusterConfigurationPath = managixHome + File.separator + "clusters" + File.separator + "local"
+                + File.separator + "local.xml";
+
+        InstallerDriver.setManagixHome(managixHome);
+
+        String command = "configure";
+        cmdHandler.processCommand(command.split(" "));
+        command = "validate -c " + clusterConfigurationPath;
+        cmdHandler.processCommand(command.split(" "));
+
+        startZookeeper();
+        InstallerDriver.initConfig();
+        createInstance();
+        hcc = new HyracksConnection(CC_IP_ADDRESS, DEFAULT_HYRACKS_CC_CLIENT_PORT);
+    }
+
+    public static IHyracksClientConnection getHyracksConnection() {
+        return hcc;
+    }
+
+    private static void startZookeeper() throws IOException, JAXBException, InterruptedException {
+        initZookeeperTestConfiguration();
+        String script = managixHome + File.separator + "bin" + File.separator + "managix";
+
+        // shutdown zookeeper if running
+        ProcessBuilder pb = new ProcessBuilder(script, "shutdown");
+        Map<String, String> env = pb.environment();
+        env.put("MANAGIX_HOME", managixHome);
+        pb.start();
+        Thread.sleep(2000);
+
+        // start zookeeper 
+        ProcessBuilder pb2 = new ProcessBuilder(script, "describe");
+        Map<String, String> env2 = pb2.environment();
+        env2.put("MANAGIX_HOME", managixHome);
+        pb2.start();
+
+        Thread.sleep(2000);
+    }
+
+    public static void createInstance() throws Exception {
+
+        String command = null;
+        AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService()
+                .getAsterixInstance(ASTERIX_INSTANCE_NAME);
+        if (instance != null) {
+            transformIntoRequiredState(State.INACTIVE);
+            command = "delete -n " + ASTERIX_INSTANCE_NAME;
+            cmdHandler.processCommand(command.split(" "));
+        }
+
+        command = "create -n " + ASTERIX_INSTANCE_NAME + " " + "-c" + " " + clusterConfigurationPath;
+        cmdHandler.processCommand(command.split(" "));
+
+        instance = ServiceProvider.INSTANCE.getLookupService().getAsterixInstance(ASTERIX_INSTANCE_NAME);
+        AsterixRuntimeState state = VerificationUtil.getAsterixRuntimeState(instance);
+        assert (state.getFailedNCs().isEmpty() && state.isCcRunning());
+    }
+
+    private static void initZookeeperTestConfiguration() throws JAXBException, FileNotFoundException {
+        String installerConfPath = InstallerDriver.getManagixHome() + File.separator + InstallerDriver.MANAGIX_CONF_XML;
+        JAXBContext ctx = JAXBContext.newInstance(Configuration.class);
+        Unmarshaller unmarshaller = ctx.createUnmarshaller();
+        Configuration configuration = (Configuration) unmarshaller.unmarshal(new File(installerConfPath));
+        configuration.getZookeeper().setClientPort(new BigInteger("3945"));
+        Marshaller marshaller = ctx.createMarshaller();
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+        marshaller.marshal(configuration, new FileOutputStream(installerConfPath));
+    }
+
+    public static void transformIntoRequiredState(AsterixInstance.State state) throws Exception {
+        AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService()
+                .getAsterixInstance(ASTERIX_INSTANCE_NAME);
+        assert (instance != null);
+        if (instance.getState().equals(state)) {
+            return;
+        }
+        if (state.equals(AsterixInstance.State.UNUSABLE)) {
+            throw new IllegalArgumentException("Invalid desired state");
+        }
+
+        String command = null;
+        switch (instance.getState()) {
+            case ACTIVE:
+                command = "stop -n " + ASTERIX_INSTANCE_NAME;
+                break;
+            case INACTIVE:
+                command = "start -n " + ASTERIX_INSTANCE_NAME;
+                break;
+        }
+        cmdHandler.processCommand(command.split(" "));
+    }
+
+    private static void stopZookeeper() throws IOException, JAXBException {
+        String script = managixHome + File.separator + "bin" + File.separator + "managix";
+        // shutdown zookeeper if running
+        ProcessBuilder pb = new ProcessBuilder(script, "shutdown");
+        Map<String, String> env = pb.environment();
+        env.put("MANAGIX_HOME", managixHome);
+        pb.start();
+    }
+
+    private static void deleteInstance() throws Exception {
+        String command = null;
+        AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService()
+                .getAsterixInstance(ASTERIX_INSTANCE_NAME);
+
+        if (instance == null) {
+            return;
+        } else {
+            transformIntoRequiredState(State.INACTIVE);
+            command = "delete -n " + ASTERIX_INSTANCE_NAME;
+            cmdHandler.processCommand(command.split(" "));
+        }
+        instance = ServiceProvider.INSTANCE.getLookupService().getAsterixInstance(ASTERIX_INSTANCE_NAME);
+        assert (instance == null);
+    }
+
+    public static String getManagixHome() {
+        return managixHome;
+    }
+
+    public static void installLibrary(String libraryName, String libraryDataverse, String libraryPath) throws Exception {
+        transformIntoRequiredState(State.INACTIVE);
+        String command = "install -n " + ASTERIX_INSTANCE_NAME + " -d " + libraryDataverse + " -l " + libraryName
+                + " -p " + libraryPath;
+        cmdHandler.processCommand(command.split(" "));
+    }
+
+    public static void uninstallLibrary(String dataverseName, String libraryName) throws Exception {
+        transformIntoRequiredState(State.INACTIVE);
+        String command = "uninstall -n " + ASTERIX_INSTANCE_NAME + " -d " + dataverseName + " -l " + "libraryName";
+        cmdHandler.processCommand(command.split(" "));
+    }
+
+    public static void executeCommand(String command) throws Exception {
+        cmdHandler.processCommand(command.trim().split(" "));
+    }
+
+}
diff --git a/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixLifecycleIT.java b/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixLifecycleIT.java
new file mode 100644
index 0000000..4d9a62a
--- /dev/null
+++ b/asterix-installer/src/test/java/edu/uci/ics/asterix/installer/test/AsterixLifecycleIT.java
@@ -0,0 +1,121 @@
+package edu.uci.ics.asterix.installer.test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runners.Parameterized.Parameters;
+
+import edu.uci.ics.asterix.installer.command.CommandHandler;
+import edu.uci.ics.asterix.installer.error.VerificationUtil;
+import edu.uci.ics.asterix.installer.model.AsterixInstance;
+import edu.uci.ics.asterix.installer.model.AsterixInstance.State;
+import edu.uci.ics.asterix.installer.model.AsterixRuntimeState;
+import edu.uci.ics.asterix.installer.service.ServiceProvider;
+import edu.uci.ics.asterix.test.aql.TestsUtils;
+import edu.uci.ics.asterix.testframework.context.TestCaseContext;
+
+
+public class AsterixLifecycleIT {
+
+    private static final int NUM_NC = 1;
+    private static final CommandHandler cmdHandler = new CommandHandler();
+    private static final String PATH_BASE = "src/test/resources/integrationts/lifecycle";
+    private static final String PATH_ACTUAL = "ittest/";
+    private static final Logger LOGGER = Logger.getLogger(AsterixLifecycleIT.class.getName());
+    private static List<TestCaseContext> testCaseCollection;
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        AsterixInstallerIntegrationUtil.init();
+        TestCaseContext.Builder b = new TestCaseContext.Builder();
+        testCaseCollection = b.build(new File(PATH_BASE));
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception {
+        AsterixInstallerIntegrationUtil.deinit();
+    }
+
+    @Parameters
+    public static Collection<Object[]> tests() throws Exception {
+        Collection<Object[]> testArgs = new ArrayList<Object[]>();
+        return testArgs;
+    }
+
+    @Test
+    public void testStopActiveInstance() throws Exception {
+        try {
+            AsterixInstallerIntegrationUtil.transformIntoRequiredState(State.ACTIVE);
+            String command = "stop -n " + AsterixInstallerIntegrationUtil.ASTERIX_INSTANCE_NAME;
+            cmdHandler.processCommand(command.split(" "));
+            AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService().getAsterixInstance(
+                    AsterixInstallerIntegrationUtil.ASTERIX_INSTANCE_NAME);
+            AsterixRuntimeState state = VerificationUtil.getAsterixRuntimeState(instance);
+            assert (state.getFailedNCs().size() == NUM_NC && !state.isCcRunning());
+            System.out.println("Test stop active instance PASSED");
+        } catch (Exception e) {
+            throw new Exception("Test configure installer " + "\" FAILED!", e);
+        }
+    }
+
+    @Test
+    public void testStartActiveInstance() throws Exception {
+        try {
+            AsterixInstallerIntegrationUtil.transformIntoRequiredState(State.INACTIVE);
+            String command = "start -n " + AsterixInstallerIntegrationUtil.ASTERIX_INSTANCE_NAME;
+            cmdHandler.processCommand(command.split(" "));
+            AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService().getAsterixInstance(
+                    AsterixInstallerIntegrationUtil.ASTERIX_INSTANCE_NAME);
+            AsterixRuntimeState state = VerificationUtil.getAsterixRuntimeState(instance);
+            assert (state.getFailedNCs().size() == 0 && state.isCcRunning());
+            System.out.println("Test start active instance PASSED");
+        } catch (Exception e) {
+            throw new Exception("Test configure installer " + "\" FAILED!", e);
+        }
+    }
+
+    @Test
+    public void testDeleteActiveInstance() throws Exception {
+        try {
+            AsterixInstallerIntegrationUtil.transformIntoRequiredState(State.INACTIVE);
+            String command = "delete -n " + AsterixInstallerIntegrationUtil.ASTERIX_INSTANCE_NAME;
+            cmdHandler.processCommand(command.split(" "));
+            AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService().getAsterixInstance(
+                    AsterixInstallerIntegrationUtil.ASTERIX_INSTANCE_NAME);
+            assert (instance == null);
+            System.out.println("Test delete active instance PASSED");
+        } catch (Exception e) {
+            throw new Exception("Test delete active instance " + "\" FAILED!", e);
+        } finally {
+            // recreate instance
+            AsterixInstallerIntegrationUtil.createInstance();
+        }
+    }
+
+    @Test
+    public void test() throws Exception {
+        for (TestCaseContext testCaseCtx : testCaseCollection) {
+            TestsUtils.executeTest(PATH_ACTUAL, testCaseCtx);
+        }
+    }
+    
+    public static void main(String[] args) throws Exception {
+        try {
+            setUp();
+            new AsterixLifecycleIT().test();
+        } catch (Exception e) {
+            e.printStackTrace();
+            LOGGER.info("TEST CASES FAILED");
+        } finally {
+            tearDown();
+        }
+    }
+
+
+}
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.1.ddl.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.1.ddl.aql
new file mode 100644
index 0000000..56f3003
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.1.ddl.aql
@@ -0,0 +1,25 @@
+/*
+ * Description  : Create a feed dataset that uses the feed simulator adapter.
+                  The feed simulator simulates feed from a file in the local fs.
+                  Associate with the feed an external user-defined function. The UDF 
+                  finds topics in each tweet. A topic is identified by a #. 
+                  Begin ingestion and apply external user defined function
+ * Expected Res : Success
+ * Date         : 23rd Apr 2013
+ */
+use dataverse externallibtest;
+
+create type TweetType as closed {
+  id: string,
+  username : string,
+  location : string,
+  text : string,
+  timestamp : string,
+  topics : {{string}}?
+}
+
+create feed dataset TweetFeed(TweetType)
+using "edu.uci.ics.asterix.tools.external.data.RateControlledFileSystemBasedAdapterFactory"
+(("output-type-name"="TweetType"),("fs"="localfs"),("path"="nc1://../asterix-app/data/twitter/obamatweets.adm"),("format"="adm"),("tuple-interval"="10"))
+apply function testlib:parseTweet@1
+primary key id;
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.2.update.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.2.update.aql
new file mode 100644
index 0000000..b7e03ec
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.2.update.aql
@@ -0,0 +1,12 @@
+/*
+ * Description  : Create a feed dataset that uses the feed simulator adapter.
+                  The feed simulator simulates feed from a file in the local fs.
+                  Associate with the feed an external user-defined function. The UDF 
+                  finds topics in each tweet. A topic is identified by a #. 
+                  Begin ingestion and apply external user defined function
+ * Expected Res : Success
+ * Date         : 23rd Apr 2013
+ */
+use dataverse externallibtest;
+
+begin feed TweetFeed;
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.3.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.3.query.aql
new file mode 100644
index 0000000..fd36fbc
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/feed_ingest.3.query.aql
@@ -0,0 +1,13 @@
+/*
+ * Description  : Create a feed dataset that uses the feed simulator adapter.
+                  The feed simulator simulates feed from a file in the local fs.
+                  Associate with the feed an external user-defined function. The UDF 
+                  finds topics in each tweet. A topic is identified by a #. 
+                  Begin ingestion and apply external user defined function
+ * Expected Res : Success
+ * Date         : 23rd Apr 2013
+ */
+use dataverse externallibtest;
+
+for $x in dataset TweetFeed
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/ingest.2.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/ingest.2.query.aql
new file mode 100644
index 0000000..4f1bdc6
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-feeds/ingest_feed/ingest.2.query.aql
@@ -0,0 +1,4 @@
+use dataverse externallibtest;
+
+let $x:=testlib:mysum(3,4)
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/getCapital/getCapital.1.ddl.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/getCapital/getCapital.1.ddl.aql
new file mode 100644
index 0000000..e140d9a
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/getCapital/getCapital.1.ddl.aql
@@ -0,0 +1,6 @@
+use dataverse externallibtest;
+
+create type CountryCapitalType if not exists as closed {
+country: string,
+capital: string
+};
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/getCapital/getCapital.2.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/getCapital/getCapital.2.query.aql
new file mode 100644
index 0000000..916c37b
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/getCapital/getCapital.2.query.aql
@@ -0,0 +1,5 @@
+use dataverse externallibtest;
+
+let $input:=["England","Italy","China","United States","India","Jupiter"]
+for $country in $input
+return testlib:getCapital($country)
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.1.ddl.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.1.ddl.aql
new file mode 100644
index 0000000..11a5ddc
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.1.ddl.aql
@@ -0,0 +1,9 @@
+use dataverse externallibtest;
+
+create type TextType if not exists as closed {
+id: int32,
+text: string
+};
+
+create dataset Check(TextType)
+primary key id;
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.2.update.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.2.update.aql
new file mode 100644
index 0000000..8a14669
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.2.update.aql
@@ -0,0 +1,6 @@
+use dataverse externallibtest;
+
+insert into dataset Check (
+{"id": 1, "text":"university of california, irvine"}
+);
+
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.3.update.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.3.update.aql
new file mode 100644
index 0000000..e4d113b
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.3.update.aql
@@ -0,0 +1,7 @@
+use dataverse externallibtest;
+
+insert into dataset Check (
+  for $x in dataset Check
+  let $y:=testlib:toUpper($x)
+  return $y
+);
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.4.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.4.query.aql
new file mode 100644
index 0000000..997c333
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/insert-from-select/insert-from-select.4.query.aql
@@ -0,0 +1,6 @@
+use dataverse externallibtest;
+
+for $x in  dataset Check 
+where $x.id < 0
+order by $x.id
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/mysum/mysum.1.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/mysum/mysum.1.query.aql
new file mode 100644
index 0000000..4f1bdc6
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/mysum/mysum.1.query.aql
@@ -0,0 +1,4 @@
+use dataverse externallibtest;
+
+let $x:=testlib:mysum(3,4)
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/toUpper/toUpper.1.ddl.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/toUpper/toUpper.1.ddl.aql
new file mode 100644
index 0000000..67635f5
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/toUpper/toUpper.1.ddl.aql
@@ -0,0 +1,7 @@
+use dataverse externallibtest;
+
+create type TextType if not exists as closed {
+id: int32,
+text: string
+};
+
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/toUpper/toUpper.2.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/toUpper/toUpper.2.query.aql
new file mode 100644
index 0000000..ba33dcc
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-functions/toUpper/toUpper.2.query.aql
@@ -0,0 +1,5 @@
+use dataverse externallibtest;
+
+let $input:={"id": 1, "text":"university of california, irvine"}
+let $x:=testlib:toUpper($input)
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/dataverseDataset/dataverseDataset.1.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/dataverseDataset/dataverseDataset.1.query.aql
new file mode 100644
index 0000000..40316d8
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/dataverseDataset/dataverseDataset.1.query.aql
@@ -0,0 +1,3 @@
+for $x in dataset Metadata.Dataverse
+order by $x.DataverseName
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/functionDataset/functionDataset.1.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/functionDataset/functionDataset.1.query.aql
new file mode 100644
index 0000000..fc47972
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/functionDataset/functionDataset.1.query.aql
@@ -0,0 +1,3 @@
+for $x in dataset Metadata.Function
+order by $x.Name
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/libraryDataset/libraryDataset.1.query.aql b/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/libraryDataset/libraryDataset.1.query.aql
new file mode 100644
index 0000000..36a8a52
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/queries/library-metadata/libraryDataset/libraryDataset.1.query.aql
@@ -0,0 +1,3 @@
+for $x in dataset Metadata.Library
+order by $x.Name
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/library/results/library-functions/getCapital/getCapital.1.adm b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/getCapital/getCapital.1.adm
new file mode 100644
index 0000000..16e9591
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/getCapital/getCapital.1.adm
@@ -0,0 +1,6 @@
+{ "country": "England", "capital": "London" }
+{ "country": "Italy", "capital": "Rome" }
+{ "country": "China", "capital": "Beijing" }
+{ "country": "United States", "capital": "Washington D.C." }
+{ "country": "India", "capital": "New Delhi" }
+{ "country": "Jupiter", "capital": "NOT_FOUND" }
diff --git a/asterix-installer/src/test/resources/integrationts/library/results/library-functions/insert-from-select/insert-from-select.1.adm b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/insert-from-select/insert-from-select.1.adm
new file mode 100644
index 0000000..a839cbc
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/insert-from-select/insert-from-select.1.adm
@@ -0,0 +1 @@
+{ "id": -1, "text": "UNIVERSITY OF CALIFORNIA, IRVINE" }
diff --git a/asterix-installer/src/test/resources/integrationts/library/results/library-functions/mysum/mysum.1.adm b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/mysum/mysum.1.adm
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/mysum/mysum.1.adm
@@ -0,0 +1 @@
+7
diff --git a/asterix-installer/src/test/resources/integrationts/library/results/library-functions/toUpper/toUpper.1.adm b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/toUpper/toUpper.1.adm
new file mode 100644
index 0000000..a839cbc
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/results/library-functions/toUpper/toUpper.1.adm
@@ -0,0 +1 @@
+{ "id": -1, "text": "UNIVERSITY OF CALIFORNIA, IRVINE" }
diff --git a/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/dataverseDataset/dataverseDataset.1.adm b/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/dataverseDataset/dataverseDataset.1.adm
new file mode 100644
index 0000000..330c347
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/dataverseDataset/dataverseDataset.1.adm
@@ -0,0 +1,2 @@
+{ "DataverseName": "Metadata", "DataFormat": "edu.uci.ics.asterix.runtime.formats.NonTaggedDataFormat", "Timestamp": "Thu Apr 25 11:17:56 PDT 2013", "PendingOp": 0 }
+{ "DataverseName": "externallibtest", "DataFormat": "edu.uci.ics.asterix.runtime.formats.NonTaggedDataFormat", "Timestamp": "Thu Apr 25 11:18:12 PDT 2013", "PendingOp": 0 }
diff --git a/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/functionDataset/functionDataset.1.adm b/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/functionDataset/functionDataset.1.adm
new file mode 100644
index 0000000..27bfa28
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/functionDataset/functionDataset.1.adm
@@ -0,0 +1,10 @@
+{ "DataverseName": "externallibtest", "Name": "testlib:allTypes", "Arity": "1", "Params": [ "AllType" ], "ReturnType": "AllType", "Definition": "edu.uci.ics.asterix.external.library.AllTypesFactory
+			", "Language": "JAVA", "Kind": "SCALAR" }
+{ "DataverseName": "externallibtest", "Name": "testlib:getCapital", "Arity": "1", "Params": [ "ASTRING" ], "ReturnType": "CountryCapitalType", "Definition": "edu.uci.ics.asterix.external.library.CapitalFinderFactory
+			", "Language": "JAVA", "Kind": "SCALAR" }
+{ "DataverseName": "externallibtest", "Name": "testlib:mysum", "Arity": "2", "Params": [ "AINT32", "AINT32" ], "ReturnType": "AINT32", "Definition": "edu.uci.ics.asterix.external.library.SumFactory
+			", "Language": "JAVA", "Kind": "SCALAR" }
+{ "DataverseName": "externallibtest", "Name": "testlib:parseTweet", "Arity": "1", "Params": [ "TweetType" ], "ReturnType": "TweetType", "Definition": "edu.uci.ics.asterix.external.library.ParseTweetFactory
+			", "Language": "JAVA", "Kind": "SCALAR" }
+{ "DataverseName": "externallibtest", "Name": "testlib:toUpper", "Arity": "1", "Params": [ "TextType" ], "ReturnType": "TextType", "Definition": "edu.uci.ics.asterix.external.library.UpperCaseFactory
+			", "Language": "JAVA", "Kind": "SCALAR" }
diff --git a/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/libraryDataset/libraryDataset.1.adm b/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/libraryDataset/libraryDataset.1.adm
new file mode 100644
index 0000000..573db0c
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/results/library-metadata/libraryDataset/libraryDataset.1.adm
@@ -0,0 +1 @@
+{ "DataverseName": "externallibtest", "Name": "testlib", "Timestamp": "Mon Apr 22 23:36:55 PDT 2013" }
diff --git a/asterix-installer/src/test/resources/integrationts/library/testsuite.xml b/asterix-installer/src/test/resources/integrationts/library/testsuite.xml
new file mode 100644
index 0000000..f97c050
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/library/testsuite.xml
@@ -0,0 +1,42 @@
+<test-suite xmlns="urn:xml.testframework.asterix.ics.uci.edu" ResultOffsetPath="results" QueryOffsetPath="queries" QueryFileExtension=".aql">
+  <test-group name="library-functions">
+    <test-case FilePath="library-functions">
+      <compilation-unit name="mysum">
+        <output-dir compare="Text">mysum</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="library-functions">
+      <compilation-unit name="toUpper">
+        <output-dir compare="Text">toUpper</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="library-functions">
+      <compilation-unit name="insert-from-select">
+        <output-dir compare="Text">insert-from-select</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="library-functions">
+      <compilation-unit name="getCapital">
+        <output-dir compare="Text">getCapital</output-dir>
+      </compilation-unit>
+    </test-case>
+  </test-group>
+  <test-group name="library-metadata">
+    <test-case FilePath="library-metadata">
+      <compilation-unit name="functionDataset">
+        <output-dir compare="Text">functionDataset</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="library-metadata">
+      <compilation-unit name="libraryDataset">
+        <output-dir compare="Text">libraryDataset</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="library-metadata">
+      <compilation-unit name="dataverseDataset">
+        <output-dir compare="Text">dataverseDataset</output-dir>
+      </compilation-unit>
+    </test-case>
+  </test-group>
+</test-suite>
+
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.1.ddl.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.1.ddl.aql
new file mode 100644
index 0000000..87b762b
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.1.ddl.aql
@@ -0,0 +1 @@
+create dataverse backupDataverse;
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.2.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.2.mgx.aql
new file mode 100644
index 0000000..2d8a23e
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.2.mgx.aql
@@ -0,0 +1 @@
+stop -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.3.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.3.mgx.aql
new file mode 100644
index 0000000..baf9551
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.3.mgx.aql
@@ -0,0 +1 @@
+backup -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.4.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.4.mgx.aql
new file mode 100644
index 0000000..4e99f33
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.4.mgx.aql
@@ -0,0 +1 @@
+start -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.5.ddl.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.5.ddl.aql
new file mode 100644
index 0000000..3b6f51b
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.5.ddl.aql
@@ -0,0 +1,2 @@
+drop dataverse backupDataverse;
+
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.6.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.6.mgx.aql
new file mode 100644
index 0000000..2d8a23e
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.6.mgx.aql
@@ -0,0 +1 @@
+stop -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.7.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.7.mgx.aql
new file mode 100644
index 0000000..063616b
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.7.mgx.aql
@@ -0,0 +1 @@
+restore -n asterix -b 0
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.8.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.8.mgx.aql
new file mode 100644
index 0000000..4e99f33
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.8.mgx.aql
@@ -0,0 +1 @@
+start -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.9.query.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.9.query.aql
new file mode 100644
index 0000000..4833c1b
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/backupRestore/backupRestore.9.query.aql
@@ -0,0 +1,3 @@
+for $x in dataset Metadata.Dataverse
+where $x.DataverseName='backupDataverse'
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.1.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.1.mgx.aql
new file mode 100644
index 0000000..2d8a23e
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.1.mgx.aql
@@ -0,0 +1 @@
+stop -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.2.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.2.mgx.aql
new file mode 100644
index 0000000..97ad91e
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.2.mgx.aql
@@ -0,0 +1 @@
+install -n asterix -d externallibtest -l testlib -p ../asterix-external-data/target/testlib-zip-binary-assembly.zip
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.3.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.3.mgx.aql
new file mode 100644
index 0000000..4e99f33
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.3.mgx.aql
@@ -0,0 +1 @@
+start -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.4.query.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.4.query.aql
new file mode 100644
index 0000000..5a46092
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/installLibrary/installLibrary.4.query.aql
@@ -0,0 +1,2 @@
+for $x in dataset Metadata.Library
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.1.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.1.mgx.aql
new file mode 100644
index 0000000..2d8a23e
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.1.mgx.aql
@@ -0,0 +1 @@
+stop -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.2.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.2.mgx.aql
new file mode 100644
index 0000000..1b5ae40
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.2.mgx.aql
@@ -0,0 +1 @@
+uninstall -n asterix -d externallibtest -l testlib 
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.3.mgx.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.3.mgx.aql
new file mode 100644
index 0000000..4e99f33
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.3.mgx.aql
@@ -0,0 +1 @@
+start -n asterix
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.4.query.aql b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.4.query.aql
new file mode 100644
index 0000000..5a46092
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/queries/asterix-lifecycle/uninstallLibrary/uninstallLibrary.4.query.aql
@@ -0,0 +1,2 @@
+for $x in dataset Metadata.Library
+return $x
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/backupRestore/backupRestore.1.adm b/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/backupRestore/backupRestore.1.adm
new file mode 100644
index 0000000..722abfd
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/backupRestore/backupRestore.1.adm
@@ -0,0 +1 @@
+{ "DataverseName": "backupDataverse", "DataFormat": "edu.uci.ics.asterix.runtime.formats.NonTaggedDataFormat", "Timestamp": "Wed Apr 24 16:13:46 PDT 2013", "PendingOp": 0 }
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/installLibrary/installLibrary.1.adm b/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/installLibrary/installLibrary.1.adm
new file mode 100644
index 0000000..a5d5c9b
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/installLibrary/installLibrary.1.adm
@@ -0,0 +1 @@
+{ "DataverseName": "externallibtest", "Name": "testlib", "Timestamp": "Wed Apr 24 17:25:25 PDT 2013" }
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/uninstallLibrary/uninstallLibrary.1.adm b/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/uninstallLibrary/uninstallLibrary.1.adm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/results/asterix-lifecycle/uninstallLibrary/uninstallLibrary.1.adm
diff --git a/asterix-installer/src/test/resources/integrationts/lifecycle/testsuite.xml b/asterix-installer/src/test/resources/integrationts/lifecycle/testsuite.xml
new file mode 100644
index 0000000..44343cc
--- /dev/null
+++ b/asterix-installer/src/test/resources/integrationts/lifecycle/testsuite.xml
@@ -0,0 +1,20 @@
+<test-suite xmlns="urn:xml.testframework.asterix.ics.uci.edu" ResultOffsetPath="results" QueryOffsetPath="queries" QueryFileExtension=".aql">
+  <test-group name="lifecycle">
+    <test-case FilePath="asterix-lifecycle">
+      <compilation-unit name="backupRestore">
+        <output-dir compare="Text">backupRestore</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="asterix-lifecycle">
+      <compilation-unit name="installLibrary">
+        <output-dir compare="Text">installLibrary</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="asterix-lifecycle">
+      <compilation-unit name="uninstallLibrary">
+        <output-dir compare="Text">uninstallLibrary</output-dir>
+      </compilation-unit>
+    </test-case>
+  </test-group>
+</test-suite>
+
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataCache.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataCache.java
index 0382315..4a86bca 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataCache.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataCache.java
@@ -21,13 +21,15 @@
 import java.util.Map;
 
 import edu.uci.ics.asterix.common.functions.FunctionSignature;
+import edu.uci.ics.asterix.external.dataset.adapter.AdapterIdentifier;
 import edu.uci.ics.asterix.metadata.api.IMetadataEntity;
-import edu.uci.ics.asterix.metadata.entities.DatasourceAdapter;
 import edu.uci.ics.asterix.metadata.entities.Dataset;
+import edu.uci.ics.asterix.metadata.entities.DatasourceAdapter;
 import edu.uci.ics.asterix.metadata.entities.Datatype;
 import edu.uci.ics.asterix.metadata.entities.Dataverse;
 import edu.uci.ics.asterix.metadata.entities.Function;
 import edu.uci.ics.asterix.metadata.entities.Index;
+import edu.uci.ics.asterix.metadata.entities.Library;
 import edu.uci.ics.asterix.metadata.entities.NodeGroup;
 
 /**
@@ -37,368 +39,407 @@
  * simply ignored, i.e., updates are not not applied to the cache.
  */
 public class MetadataCache {
-    // Key is dataverse name.
-    protected final Map<String, Dataverse> dataverses = new HashMap<String, Dataverse>();
-    // Key is dataverse name. Key of value map is dataset name.
-    protected final Map<String, Map<String, Dataset>> datasets = new HashMap<String, Map<String, Dataset>>();
-    // Key is dataverse name. Key of value map is dataset name. Key of value map of value map is index name.
-    protected final Map<String, Map<String, Map<String, Index>>> indexes = new HashMap<String, Map<String, Map<String, Index>>>();
-    // Key is dataverse name. Key of value map is datatype name.
-    protected final Map<String, Map<String, Datatype>> datatypes = new HashMap<String, Map<String, Datatype>>();
-    // Key is dataverse name.
-    protected final Map<String, NodeGroup> nodeGroups = new HashMap<String, NodeGroup>();
-    // Key is function Identifier . Key of value map is function name.
-    protected final Map<FunctionSignature, Function> functions = new HashMap<FunctionSignature, Function>();
-    // Key is adapter dataverse. Key of value map is the adapter name  
-    protected final Map<String, Map<String, DatasourceAdapter>> adapters = new HashMap<String, Map<String, DatasourceAdapter>>();
+	// Key is dataverse name.
+	protected final Map<String, Dataverse> dataverses = new HashMap<String, Dataverse>();
+	// Key is dataverse name. Key of value map is dataset name.
+	protected final Map<String, Map<String, Dataset>> datasets = new HashMap<String, Map<String, Dataset>>();
+	// Key is dataverse name. Key of value map is dataset name. Key of value map
+	// of value map is index name.
+	protected final Map<String, Map<String, Map<String, Index>>> indexes = new HashMap<String, Map<String, Map<String, Index>>>();
+	// Key is dataverse name. Key of value map is datatype name.
+	protected final Map<String, Map<String, Datatype>> datatypes = new HashMap<String, Map<String, Datatype>>();
+	// Key is dataverse name.
+	protected final Map<String, NodeGroup> nodeGroups = new HashMap<String, NodeGroup>();
+	// Key is function Identifier . Key of value map is function name.
+	protected final Map<FunctionSignature, Function> functions = new HashMap<FunctionSignature, Function>();
+	// Key is adapter dataverse. Key of value map is the adapter name
+	protected final Map<AdapterIdentifier, DatasourceAdapter> adapters = new HashMap<AdapterIdentifier, DatasourceAdapter>();
+	// Key is library dataverse. Key of value map is the library name
+	protected final Map<String, Map<String, Library>> libraries = new HashMap<String, Map<String, Library>>();
 
-    // Atomically executes all metadata operations in ctx's log.
-    public void commit(MetadataTransactionContext ctx) {
-        // Forward roll the operations written in ctx's log.
-        int logIx = 0;
-        ArrayList<MetadataLogicalOperation> opLog = ctx.getOpLog();
-        try {
-            for (logIx = 0; logIx < opLog.size(); logIx++) {
-                doOperation(opLog.get(logIx));
-            }
-        } catch (Exception e) {
-            // Undo operations.
-            try {
-                for (int i = logIx - 1; i >= 0; i--) {
-                    undoOperation(opLog.get(i));
-                }
-            } catch (Exception e2) {
-                // We encountered an error in undo. This case should never
-                // happen. Our only remedy to ensure cache consistency
-                // is to clear everything.
-                clear();
-            }
-        } finally {
-            ctx.clear();
-        }
-    }
+	// Atomically executes all metadata operations in ctx's log.
+	public void commit(MetadataTransactionContext ctx) {
+		// Forward roll the operations written in ctx's log.
+		int logIx = 0;
+		ArrayList<MetadataLogicalOperation> opLog = ctx.getOpLog();
+		try {
+			for (logIx = 0; logIx < opLog.size(); logIx++) {
+				doOperation(opLog.get(logIx));
+			}
+		} catch (Exception e) {
+			// Undo operations.
+			try {
+				for (int i = logIx - 1; i >= 0; i--) {
+					undoOperation(opLog.get(i));
+				}
+			} catch (Exception e2) {
+				// We encountered an error in undo. This case should never
+				// happen. Our only remedy to ensure cache consistency
+				// is to clear everything.
+				clear();
+			}
+		} finally {
+			ctx.clear();
+		}
+	}
 
-    public void clear() {
-        synchronized (dataverses) {
-            synchronized (nodeGroups) {
-                synchronized (datasets) {
-                    synchronized (indexes) {
-                        synchronized (datatypes) {
-                            synchronized (functions) {
-                                synchronized (adapters) {
-                                    dataverses.clear();
-                                    nodeGroups.clear();
-                                    datasets.clear();
-                                    indexes.clear();
-                                    datatypes.clear();
-                                    functions.clear();
-                                    adapters.clear();
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
+	public void clear() {
+		synchronized (dataverses) {
+			synchronized (nodeGroups) {
+				synchronized (datasets) {
+					synchronized (datatypes) {
+						synchronized (functions) {
+							synchronized (adapters) {
+								synchronized (libraries) {
+									dataverses.clear();
+									nodeGroups.clear();
+									datasets.clear();
+									datatypes.clear();
+									functions.clear();
+									adapters.clear();
+									libraries.clear();
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
 
-    public Object addDataverseIfNotExists(Dataverse dataverse) {
-        synchronized (dataverses) {
-            synchronized (datasets) {
-                synchronized (datatypes) {
-                    if (!dataverses.containsKey(dataverse)) {
-                        datasets.put(dataverse.getDataverseName(), new HashMap<String, Dataset>());
-                        datatypes.put(dataverse.getDataverseName(), new HashMap<String, Datatype>());
-                        adapters.put(dataverse.getDataverseName(), new HashMap<String, DatasourceAdapter>());
-                        return dataverses.put(dataverse.getDataverseName(), dataverse);
-                    }
-                    return null;
-                }
-            }
-        }
-    }
+	public Object addDataverseIfNotExists(Dataverse dataverse) {
+		synchronized (dataverses) {
+			synchronized (datasets) {
+				synchronized (datatypes) {
+					if (!dataverses.containsKey(dataverse)) {
+						datasets.put(dataverse.getDataverseName(),
+								new HashMap<String, Dataset>());
+						datatypes.put(dataverse.getDataverseName(),
+								new HashMap<String, Datatype>());
+						return dataverses.put(dataverse.getDataverseName(),
+								dataverse);
+					}
+					return null;
+				}
+			}
+		}
+	}
 
-    public Object addDatasetIfNotExists(Dataset dataset) {
-        synchronized (datasets) {
-            Map<String, Dataset> m = datasets.get(dataset.getDataverseName());
-            if (m == null) {
-                m = new HashMap<String, Dataset>();
-                datasets.put(dataset.getDataverseName(), m);
-            }
-            if (!m.containsKey(dataset.getDatasetName())) {
-                return m.put(dataset.getDatasetName(), dataset);
-            }
-            return null;
-        }
-    }
+	public Object addDatasetIfNotExists(Dataset dataset) {
+		synchronized (datasets) {
+			Map<String, Dataset> m = datasets.get(dataset.getDataverseName());
+			if (m == null) {
+				m = new HashMap<String, Dataset>();
+				datasets.put(dataset.getDataverseName(), m);
+			}
+			if (!m.containsKey(dataset.getDatasetName())) {
+				return m.put(dataset.getDatasetName(), dataset);
+			}
+			return null;
+		}
+	}
 
-    public Object addIndexIfNotExists(Index index) {
-        synchronized (indexes) {
-            Map<String, Map<String, Index>> datasetMap = indexes.get(index.getDataverseName());
-            if (datasetMap == null) {
-                datasetMap = new HashMap<String, Map<String, Index>>();
-                indexes.put(index.getDataverseName(), datasetMap);
-            }
-            Map<String, Index> indexMap = datasetMap.get(index.getDatasetName());
-            if (indexMap == null) {
-                indexMap = new HashMap<String, Index>();
-                datasetMap.put(index.getDatasetName(), indexMap);
-            }
-            if (!indexMap.containsKey(index.getIndexName())) {
-                return indexMap.put(index.getIndexName(), index);
-            }
-            return null;
-        }
-    }
+	public Object addIndexIfNotExists(Index index) {
+		synchronized (indexes) {
+			Map<String, Map<String, Index>> datasetMap = indexes.get(index
+					.getDataverseName());
+			if (datasetMap == null) {
+				datasetMap = new HashMap<String, Map<String, Index>>();
+				indexes.put(index.getDataverseName(), datasetMap);
+			}
+			Map<String, Index> indexMap = datasetMap
+					.get(index.getDatasetName());
+			if (indexMap == null) {
+				indexMap = new HashMap<String, Index>();
+				datasetMap.put(index.getDatasetName(), indexMap);
+			}
+			if (!indexMap.containsKey(index.getIndexName())) {
+				return indexMap.put(index.getIndexName(), index);
+			}
+			return null;
+		}
+	}
 
-    public Object addDatatypeIfNotExists(Datatype datatype) {
-        synchronized (datatypes) {
-            Map<String, Datatype> m = datatypes.get(datatype.getDataverseName());
-            if (m == null) {
-                m = new HashMap<String, Datatype>();
-                datatypes.put(datatype.getDataverseName(), m);
-            }
-            if (!m.containsKey(datatype.getDatatypeName())) {
-                return m.put(datatype.getDatatypeName(), datatype);
-            }
-            return null;
-        }
-    }
+	public Object addDatatypeIfNotExists(Datatype datatype) {
+		synchronized (datatypes) {
+			Map<String, Datatype> m = datatypes
+					.get(datatype.getDataverseName());
+			if (m == null) {
+				m = new HashMap<String, Datatype>();
+				datatypes.put(datatype.getDataverseName(), m);
+			}
+			if (!m.containsKey(datatype.getDatatypeName())) {
+				return m.put(datatype.getDatatypeName(), datatype);
+			}
+			return null;
+		}
+	}
 
-    public Object addNodeGroupIfNotExists(NodeGroup nodeGroup) {
-        synchronized (nodeGroups) {
-            if (!nodeGroups.containsKey(nodeGroup.getNodeGroupName())) {
-                return nodeGroups.put(nodeGroup.getNodeGroupName(), nodeGroup);
-            }
-            return null;
-        }
-    }
+	public Object addNodeGroupIfNotExists(NodeGroup nodeGroup) {
+		synchronized (nodeGroups) {
+			if (!nodeGroups.containsKey(nodeGroup.getNodeGroupName())) {
+				return nodeGroups.put(nodeGroup.getNodeGroupName(), nodeGroup);
+			}
+			return null;
+		}
+	}
 
-    public Object dropDataverse(Dataverse dataverse) {
-        synchronized (dataverses) {
-            synchronized (datasets) {
-                synchronized (indexes) {
-                    synchronized (datatypes) {
-                        synchronized (functions) {
-                            datasets.remove(dataverse.getDataverseName());
-                            indexes.remove(dataverse.getDataverseName());
-                            datatypes.remove(dataverse.getDataverseName());
-                            adapters.remove(dataverse.getDataverseName());
-                            List<FunctionSignature> markedFunctionsForRemoval = new ArrayList<FunctionSignature>();
-                            for (FunctionSignature signature : functions.keySet()) {
-                                if (signature.getNamespace().equals(dataverse.getDataverseName())) {
-                                    markedFunctionsForRemoval.add(signature);
-                                }
-                            }
-                            for (FunctionSignature signature : markedFunctionsForRemoval) {
-                                functions.remove(signature);
-                            }
-                            return dataverses.remove(dataverse.getDataverseName());
-                        }
-                    }
-                }
-            }
-        }
-    }
+	public Object dropDataverse(Dataverse dataverse) {
+		synchronized (dataverses) {
+			synchronized (datasets) {
+				synchronized (indexes) {
+					synchronized (datatypes) {
+						synchronized (functions) {
+							datasets.remove(dataverse.getDataverseName());
+							indexes.remove(dataverse.getDataverseName());
+							datatypes.remove(dataverse.getDataverseName());
+							adapters.remove(dataverse.getDataverseName());
+							List<FunctionSignature> markedFunctionsForRemoval = new ArrayList<FunctionSignature>();
+							for (FunctionSignature signature : functions
+									.keySet()) {
+								if (signature.getNamespace().equals(
+										dataverse.getDataverseName())) {
+									markedFunctionsForRemoval.add(signature);
+								}
+							}
+							for (FunctionSignature signature : markedFunctionsForRemoval) {
+								functions.remove(signature);
+							}
+							return dataverses.remove(dataverse
+									.getDataverseName());
+						}
+					}
+				}
+			}
+		}
+	}
 
-    public Object dropDataset(Dataset dataset) {
-        synchronized (datasets) {
-            synchronized (indexes) {
+	public Object dropDataset(Dataset dataset) {
+		synchronized (datasets) {
+			synchronized (indexes) {
 
-                //remove the indexes of the dataset from indexes' cache
-                Map<String, Map<String, Index>> datasetMap = indexes.get(dataset.getDataverseName());
-                if (datasetMap != null) {
-                    datasetMap.remove(dataset.getDatasetName());
-                }
+				// remove the indexes of the dataset from indexes' cache
+				Map<String, Map<String, Index>> datasetMap = indexes
+						.get(dataset.getDataverseName());
+				if (datasetMap != null) {
+					datasetMap.remove(dataset.getDatasetName());
+				}
 
-                //remove the dataset from datasets' cache
-                Map<String, Dataset> m = datasets.get(dataset.getDataverseName());
-                if (m == null) {
-                    return null;
-                }
-                return m.remove(dataset.getDatasetName());
-            }
-        }
-    }
-    
-    public Object dropIndex(Index index) {
-        synchronized (indexes) {
-            Map<String, Map<String, Index>> datasetMap = indexes.get(index.getDataverseName());
-            if (datasetMap == null) {
-                return null;
-            }
-            
-            Map<String, Index> indexMap = datasetMap.get(index.getDatasetName());
-            if (indexMap == null) {
-                return null;
-            }
-            
-            return indexMap.remove(index.getIndexName());
-        }
-    }
+				// remove the dataset from datasets' cache
+				Map<String, Dataset> m = datasets.get(dataset
+						.getDataverseName());
+				if (m == null) {
+					return null;
+				}
+				return m.remove(dataset.getDatasetName());
+			}
+		}
+	}
 
-    public Object dropDatatype(Datatype datatype) {
-        synchronized (datatypes) {
-            Map<String, Datatype> m = datatypes.get(datatype.getDataverseName());
-            if (m == null) {
-                return null;
-            }
-            return m.remove(datatype.getDatatypeName());
-        }
-    }
+	public Object dropIndex(Index index) {
+		synchronized (indexes) {
+			Map<String, Map<String, Index>> datasetMap = indexes.get(index
+					.getDataverseName());
+			if (datasetMap == null) {
+				return null;
+			}
 
-    public Object dropNodeGroup(NodeGroup nodeGroup) {
-        synchronized (nodeGroups) {
-            return nodeGroups.remove(nodeGroup.getNodeGroupName());
-        }
-    }
+			Map<String, Index> indexMap = datasetMap
+					.get(index.getDatasetName());
+			if (indexMap == null) {
+				return null;
+			}
 
-    public Dataverse getDataverse(String dataverseName) {
-        synchronized (dataverses) {
-            return dataverses.get(dataverseName);
-        }
-    }
+			return indexMap.remove(index.getIndexName());
+		}
+	}
 
-    public Dataset getDataset(String dataverseName, String datasetName) {
-        synchronized (datasets) {
-            Map<String, Dataset> m = datasets.get(dataverseName);
-            if (m == null) {
-                return null;
-            }
-            return m.get(datasetName);
-        }
-    }
-    
-    public Index getIndex(String dataverseName, String datasetName, String indexName) {
-        synchronized (indexes) {
-            Map<String, Map<String, Index>> datasetMap = indexes.get(dataverseName);
-            if (datasetMap == null) {
-                return null;
-            }
-            Map<String, Index> indexMap = datasetMap.get(datasetName);
-            if (indexMap == null) {
-                return null;
-            }
-            return indexMap.get(indexName);
-        }
-    }
+	public Object dropDatatype(Datatype datatype) {
+		synchronized (datatypes) {
+			Map<String, Datatype> m = datatypes
+					.get(datatype.getDataverseName());
+			if (m == null) {
+				return null;
+			}
+			return m.remove(datatype.getDatatypeName());
+		}
+	}
 
-    public Datatype getDatatype(String dataverseName, String datatypeName) {
-        synchronized (datatypes) {
-            Map<String, Datatype> m = datatypes.get(dataverseName);
-            if (m == null) {
-                return null;
-            }
-            return m.get(datatypeName);
-        }
-    }
+	public Object dropNodeGroup(NodeGroup nodeGroup) {
+		synchronized (nodeGroups) {
+			return nodeGroups.remove(nodeGroup.getNodeGroupName());
+		}
+	}
 
-    public NodeGroup getNodeGroup(String nodeGroupName) {
-        synchronized (nodeGroups) {
-            return nodeGroups.get(nodeGroupName);
-        }
-    }
+	public Dataverse getDataverse(String dataverseName) {
+		synchronized (dataverses) {
+			return dataverses.get(dataverseName);
+		}
+	}
 
-    public Function getFunction(FunctionSignature functionSignature) {
-        synchronized (functions) {
-            return functions.get(functionSignature);
-        }
-    }
+	public Dataset getDataset(String dataverseName, String datasetName) {
+		synchronized (datasets) {
+			Map<String, Dataset> m = datasets.get(dataverseName);
+			if (m == null) {
+				return null;
+			}
+			return m.get(datasetName);
+		}
+	}
 
-    public List<Dataset> getDataverseDatasets(String dataverseName) {
-        List<Dataset> retDatasets = new ArrayList<Dataset>();
-        synchronized (datasets) {
-            Map<String, Dataset> m = datasets.get(dataverseName);
-            if (m == null) {
-                return retDatasets;
-            }
-            for (Map.Entry<String, Dataset> entry : m.entrySet()) {
-                retDatasets.add(entry.getValue());
-            }
-            return retDatasets;
-        }
-    }
+	public Index getIndex(String dataverseName, String datasetName,
+			String indexName) {
+		synchronized (indexes) {
+			Map<String, Map<String, Index>> datasetMap = indexes
+					.get(dataverseName);
+			if (datasetMap == null) {
+				return null;
+			}
+			Map<String, Index> indexMap = datasetMap.get(datasetName);
+			if (indexMap == null) {
+				return null;
+			}
+			return indexMap.get(indexName);
+		}
+	}
 
-    /**
-     * Represents a logical operation against the metadata.
-     */
-    protected class MetadataLogicalOperation {
-        // Entity to be added/dropped.
-        public final IMetadataEntity entity;
-        // True for add, false for drop.
-        public final boolean isAdd;
+	public Datatype getDatatype(String dataverseName, String datatypeName) {
+		synchronized (datatypes) {
+			Map<String, Datatype> m = datatypes.get(dataverseName);
+			if (m == null) {
+				return null;
+			}
+			return m.get(datatypeName);
+		}
+	}
 
-        public MetadataLogicalOperation(IMetadataEntity entity, boolean isAdd) {
-            this.entity = entity;
-            this.isAdd = isAdd;
-        }
-    };
+	public NodeGroup getNodeGroup(String nodeGroupName) {
+		synchronized (nodeGroups) {
+			return nodeGroups.get(nodeGroupName);
+		}
+	}
 
-    protected void doOperation(MetadataLogicalOperation op) {
-        if (op.isAdd) {
-            op.entity.addToCache(this);
-        } else {
-            op.entity.dropFromCache(this);
-        }
-    }
+	public Function getFunction(FunctionSignature functionSignature) {
+		synchronized (functions) {
+			return functions.get(functionSignature);
+		}
+	}
 
-    protected void undoOperation(MetadataLogicalOperation op) {
-        if (!op.isAdd) {
-            op.entity.addToCache(this);
-        } else {
-            op.entity.dropFromCache(this);
-        }
-    }
+	public List<Dataset> getDataverseDatasets(String dataverseName) {
+		List<Dataset> retDatasets = new ArrayList<Dataset>();
+		synchronized (datasets) {
+			Map<String, Dataset> m = datasets.get(dataverseName);
+			if (m == null) {
+				return retDatasets;
+			}
+			for (Map.Entry<String, Dataset> entry : m.entrySet()) {
+				retDatasets.add(entry.getValue());
+			}
+			return retDatasets;
+		}
+	}
 
-    public Object addFunctionIfNotExists(Function function) {
-        synchronized (functions) {
-            FunctionSignature signature = new FunctionSignature(function.getDataverseName(), function.getName(),
-                    function.getArity());
-            Function fun = functions.get(signature);
-            if (fun == null) {
-                return functions.put(signature, function);
-            }
-            return null;
-        }
-    }
+	/**
+	 * Represents a logical operation against the metadata.
+	 */
+	protected class MetadataLogicalOperation {
+		// Entity to be added/dropped.
+		public final IMetadataEntity entity;
+		// True for add, false for drop.
+		public final boolean isAdd;
 
-    public Object dropFunction(Function function) {
-        synchronized (functions) {
-            FunctionSignature signature = new FunctionSignature(function.getDataverseName(), function.getName(),
-                    function.getArity());
-            Function fun = functions.get(signature);
-            if (fun == null) {
-                return null;
-            }
-            return functions.remove(signature);
-        }
-    }
+		public MetadataLogicalOperation(IMetadataEntity entity, boolean isAdd) {
+			this.entity = entity;
+			this.isAdd = isAdd;
+		}
+	};
 
-    public Object addAdapterIfNotExists(DatasourceAdapter adapter) {
-        synchronized (adapters) {
-            DatasourceAdapter adapterObject = adapters.get(adapter.getAdapterIdentifier().getNamespace()).get(
-                    adapter.getAdapterIdentifier().getAdapterName());
-            if (adapterObject != null) {
-                Map<String, DatasourceAdapter> adaptersInDataverse = adapters.get(adapter.getAdapterIdentifier()
-                        .getNamespace());
-                if (adaptersInDataverse == null) {
-                    adaptersInDataverse = new HashMap<String, DatasourceAdapter>();
-                    adapters.put(adapter.getAdapterIdentifier().getNamespace(), adaptersInDataverse);
-                }
-                return adaptersInDataverse.put(adapter.getAdapterIdentifier().getAdapterName(), adapter);
-            }
-            return null;
-        }
-    }
+	protected void doOperation(MetadataLogicalOperation op) {
+		if (op.isAdd) {
+			op.entity.addToCache(this);
+		} else {
+			op.entity.dropFromCache(this);
+		}
+	}
 
-    public Object dropAdapter(DatasourceAdapter adapter) {
-        synchronized (adapters) {
-            Map<String, DatasourceAdapter> adaptersInDataverse = adapters.get(adapter.getAdapterIdentifier()
-                    .getNamespace());
-            if (adaptersInDataverse != null) {
-                return adaptersInDataverse.remove(adapter.getAdapterIdentifier().getAdapterName());
-            }
-            return null;
-        }
-    }
+	protected void undoOperation(MetadataLogicalOperation op) {
+		if (!op.isAdd) {
+			op.entity.addToCache(this);
+		} else {
+			op.entity.dropFromCache(this);
+		}
+	}
+
+	public Object addFunctionIfNotExists(Function function) {
+		synchronized (functions) {
+			FunctionSignature signature = new FunctionSignature(
+					function.getDataverseName(), function.getName(),
+					function.getArity());
+			Function fun = functions.get(signature);
+			if (fun == null) {
+				return functions.put(signature, function);
+			}
+			return null;
+		}
+	}
+
+	public Object dropFunction(Function function) {
+		synchronized (functions) {
+			FunctionSignature signature = new FunctionSignature(
+					function.getDataverseName(), function.getName(),
+					function.getArity());
+			Function fun = functions.get(signature);
+			if (fun == null) {
+				return null;
+			}
+			return functions.remove(signature);
+		}
+	}
+
+	public Object addAdapterIfNotExists(DatasourceAdapter adapter) {
+		synchronized (adapters) {
+			boolean needToAddd = adapters.get(adapter.getAdapterIdentifier()) == null;
+			if (needToAddd) {
+				return adapters.put(adapter.getAdapterIdentifier(), adapter);
+			}
+			return null;
+		}
+	}
+
+	public Object dropAdapter(DatasourceAdapter adapter) {
+		synchronized (adapters) {
+			if (adapters.get(adapter.getAdapterIdentifier()) != null) {
+				return adapters.remove(adapter.getAdapterIdentifier());
+			}
+			return null;
+		}
+	}
+
+	public Object addLibraryIfNotExists(Library library) {
+		synchronized (libraries) {
+			Map<String, Library> libsInDataverse = libraries.get(library
+					.getDataverseName());
+			boolean needToAddd = (libsInDataverse == null || libsInDataverse
+					.get(library.getName()) != null);
+			if (needToAddd) {
+				if (libsInDataverse == null) {
+					libsInDataverse = new HashMap<String, Library>();
+					libraries.put(library.getDataverseName(), libsInDataverse);
+				}
+				return libsInDataverse.put(library.getDataverseName(), library);
+			}
+			return null;
+		}
+	}
+
+	public Object dropLibrary(Library library) {
+		synchronized (libraries) {
+			Map<String, Library> librariesInDataverse = libraries.get(library
+					.getDataverseName());
+			if (librariesInDataverse != null) {
+				return librariesInDataverse.remove(library.getName());
+			}
+			return null;
+		}
+	}
 }
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataManager.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataManager.java
index ad106fe..a573ed1 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataManager.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataManager.java
@@ -31,6 +31,7 @@
 import edu.uci.ics.asterix.metadata.entities.Dataverse;
 import edu.uci.ics.asterix.metadata.entities.Function;
 import edu.uci.ics.asterix.metadata.entities.Index;
+import edu.uci.ics.asterix.metadata.entities.Library;
 import edu.uci.ics.asterix.metadata.entities.Node;
 import edu.uci.ics.asterix.metadata.entities.NodeGroup;
 import edu.uci.ics.asterix.transaction.management.exception.ACIDException;
@@ -43,563 +44,642 @@
  * received from the metadata node, to avoid contacting the metadata node
  * repeatedly. We assume that this metadata manager is the only metadata manager
  * in an Asterix cluster. Therefore, no separate cache-invalidation mechanism is
- * needed at this point.
- * Assumptions/Limitations:
- * The metadata subsystem is started during NC Bootstrap start, i.e., when
- * Asterix is deployed.
- * The metadata subsystem is destroyed in NC Bootstrap end, i.e., when Asterix
- * is undeployed.
- * The metadata subsystem consists of the MetadataManager and the MatadataNode.
- * The MetadataManager provides users access to the metadata.
- * The MetadataNode implements direct access to the storage layer on behalf of
- * the MetadataManager, and translates the binary representation of ADM into
- * Java objects for consumption by the MetadataManager's users.
- * There is exactly one instance of the MetadataManager and of the MetadataNode
- * in the cluster, which may or may not be co-located on the same machine (or in
- * the same JVM).
- * The MetadataManager exists in the same JVM as its user's (e.g., the query
- * compiler).
- * The MetadataNode exists in the same JVM as it's transactional components
- * (LockManager, LogManager, etc.)
- * Users shall access the metadata only through the MetadataManager, and never
- * via the MetadataNode directly.
+ * needed at this point. Assumptions/Limitations: The metadata subsystem is
+ * started during NC Bootstrap start, i.e., when Asterix is deployed. The
+ * metadata subsystem is destroyed in NC Bootstrap end, i.e., when Asterix is
+ * undeployed. The metadata subsystem consists of the MetadataManager and the
+ * MatadataNode. The MetadataManager provides users access to the metadata. The
+ * MetadataNode implements direct access to the storage layer on behalf of the
+ * MetadataManager, and translates the binary representation of ADM into Java
+ * objects for consumption by the MetadataManager's users. There is exactly one
+ * instance of the MetadataManager and of the MetadataNode in the cluster, which
+ * may or may not be co-located on the same machine (or in the same JVM). The
+ * MetadataManager exists in the same JVM as its user's (e.g., the query
+ * compiler). The MetadataNode exists in the same JVM as it's transactional
+ * components (LockManager, LogManager, etc.) Users shall access the metadata
+ * only through the MetadataManager, and never via the MetadataNode directly.
  * Multiple threads may issue requests to the MetadataManager concurrently. For
  * the sake of accessing metadata, we assume a transaction consists of one
- * thread.
- * Users are responsible for locking the metadata (using the MetadataManager
- * API) before issuing requests.
- * The MetadataNode is responsible for acquiring finer-grained locks on behalf
- * of requests from the MetadataManager. Currently, locks are acquired per
- * BTree, since the BTree does not acquire even finer-grained locks yet
- * internally.
- * The metadata can be queried with AQL DML like any other dataset, but can only
- * be changed with AQL DDL.
- * The transaction ids for metadata transactions must be unique across the
+ * thread. Users are responsible for locking the metadata (using the
+ * MetadataManager API) before issuing requests. The MetadataNode is responsible
+ * for acquiring finer-grained locks on behalf of requests from the
+ * MetadataManager. Currently, locks are acquired per BTree, since the BTree
+ * does not acquire even finer-grained locks yet internally. The metadata can be
+ * queried with AQL DML like any other dataset, but can only be changed with AQL
+ * DDL. The transaction ids for metadata transactions must be unique across the
  * cluster, i.e., metadata transaction ids shall never "accidentally" overlap
  * with transaction ids of regular jobs or other metadata transactions.
  */
 public class MetadataManager implements IMetadataManager {
-    // Set in init().
-    public static MetadataManager INSTANCE;
-    private final MetadataCache cache = new MetadataCache();
-    private IAsterixStateProxy proxy;
-    private IMetadataNode metadataNode;
-    private final ReadWriteLock metadataLatch;
+	// Set in init().
+	public static MetadataManager INSTANCE;
+	private final MetadataCache cache = new MetadataCache();
+	private IAsterixStateProxy proxy;
+	private IMetadataNode metadataNode;
+	private final ReadWriteLock metadataLatch;
 
-    public MetadataManager(IAsterixStateProxy proxy) {
-        if (proxy == null) {
-            throw new Error("Null proxy given to MetadataManager.");
-        }
-        this.proxy = proxy;
-        this.metadataNode = null;
-        this.metadataLatch = new ReentrantReadWriteLock(true);
-    }
+	public MetadataManager(IAsterixStateProxy proxy) {
+		if (proxy == null) {
+			throw new Error("Null proxy given to MetadataManager.");
+		}
+		this.proxy = proxy;
+		this.metadataNode = null;
+		this.metadataLatch = new ReentrantReadWriteLock(true);
+	}
 
-    @Override
-    public void init() throws RemoteException {
-        // Could be synchronized on any object. Arbitrarily chose proxy.
-        synchronized (proxy) {
-            if (metadataNode != null) {
-                return;
-            }
-            metadataNode = proxy.getMetadataNode();
-            if (metadataNode == null) {
-                throw new Error("Failed to get the MetadataNode.\n" + "The MetadataNode was configured to run on NC: "
-                        + proxy.getAsterixProperties().getMetadataNodeName());
-            }
-        }
-    }
+	@Override
+	public void init() throws RemoteException {
+		// Could be synchronized on any object. Arbitrarily chose proxy.
+		synchronized (proxy) {
+			if (metadataNode != null) {
+				return;
+			}
+			metadataNode = proxy.getMetadataNode();
+			if (metadataNode == null) {
+				throw new Error("Failed to get the MetadataNode.\n"
+						+ "The MetadataNode was configured to run on NC: "
+						+ proxy.getAsterixProperties().getMetadataNodeName());
+			}
+		}
+	}
 
-    @Override
-    public MetadataTransactionContext beginTransaction() throws RemoteException, ACIDException {
-        JobId jobId = JobIdFactory.generateJobId();
-        metadataNode.beginTransaction(jobId);
-        return new MetadataTransactionContext(jobId);
-    }
+	@Override
+	public MetadataTransactionContext beginTransaction()
+			throws RemoteException, ACIDException {
+		JobId jobId = JobIdFactory.generateJobId();
+		metadataNode.beginTransaction(jobId);
+		return new MetadataTransactionContext(jobId);
+	}
 
-    @Override
-    public void commitTransaction(MetadataTransactionContext ctx) throws RemoteException, ACIDException {
-        metadataNode.commitTransaction(ctx.getJobId());
-        cache.commit(ctx);
-    }
+	@Override
+	public void commitTransaction(MetadataTransactionContext ctx)
+			throws RemoteException, ACIDException {
+		metadataNode.commitTransaction(ctx.getJobId());
+		cache.commit(ctx);
+	}
 
-    @Override
-    public void abortTransaction(MetadataTransactionContext ctx) throws RemoteException, ACIDException {
-        metadataNode.abortTransaction(ctx.getJobId());
-    }
+	@Override
+	public void abortTransaction(MetadataTransactionContext ctx)
+			throws RemoteException, ACIDException {
+		metadataNode.abortTransaction(ctx.getJobId());
+	}
 
-    @Override
-    public void lock(MetadataTransactionContext ctx, byte lockMode) throws RemoteException, ACIDException {
-        metadataNode.lock(ctx.getJobId(), lockMode);
-    }
+	@Override
+	public void lock(MetadataTransactionContext ctx, byte lockMode)
+			throws RemoteException, ACIDException {
+		metadataNode.lock(ctx.getJobId(), lockMode);
+	}
 
-    @Override
-    public void unlock(MetadataTransactionContext ctx) throws RemoteException, ACIDException {
-        metadataNode.unlock(ctx.getJobId());
-    }
+	@Override
+	public void unlock(MetadataTransactionContext ctx) throws RemoteException,
+			ACIDException {
+		metadataNode.unlock(ctx.getJobId());
+	}
 
-    @Override
-    public void addDataverse(MetadataTransactionContext ctx, Dataverse dataverse) throws MetadataException {
-        try {
-            metadataNode.addDataverse(ctx.getJobId(), dataverse);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.addDataverse(dataverse);
-    }
+	@Override
+	public void addDataverse(MetadataTransactionContext ctx, Dataverse dataverse)
+			throws MetadataException {
+		try {
+			metadataNode.addDataverse(ctx.getJobId(), dataverse);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.addDataverse(dataverse);
+	}
 
-    @Override
-    public void dropDataverse(MetadataTransactionContext ctx, String dataverseName) throws MetadataException {
-        try {
-            metadataNode.dropDataverse(ctx.getJobId(), dataverseName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.dropDataverse(dataverseName);
-    }
+	@Override
+	public void dropDataverse(MetadataTransactionContext ctx,
+			String dataverseName) throws MetadataException {
+		try {
+			metadataNode.dropDataverse(ctx.getJobId(), dataverseName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.dropDataverse(dataverseName);
+	}
 
-    @Override
-    public List<Dataverse> getDataverses(MetadataTransactionContext ctx) throws MetadataException {
-        try {
-            return metadataNode.getDataverses(ctx.getJobId());
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-    }
+	@Override
+	public List<Dataverse> getDataverses(MetadataTransactionContext ctx)
+			throws MetadataException {
+		try {
+			return metadataNode.getDataverses(ctx.getJobId());
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+	}
 
-    @Override
-    public Dataverse getDataverse(MetadataTransactionContext ctx, String dataverseName) throws MetadataException {
-        // First look in the context to see if this transaction created the
-        // requested dataverse itself (but the dataverse is still uncommitted).
-        Dataverse dataverse = ctx.getDataverse(dataverseName);
-        if (dataverse != null) {
-            // Don't add this dataverse to the cache, since it is still
-            // uncommitted.
-            return dataverse;
-        }
-        if (ctx.dataverseIsDropped(dataverseName)) {
-            // Dataverse has been dropped by this transaction but could still be
-            // in the cache.
-            return null;
-        }
-        dataverse = cache.getDataverse(dataverseName);
-        if (dataverse != null) {
-            // Dataverse is already in the cache, don't add it again.
-            return dataverse;
-        }
-        try {
-            dataverse = metadataNode.getDataverse(ctx.getJobId(), dataverseName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // We fetched the dataverse from the MetadataNode. Add it to the cache
-        // when this transaction commits.
-        if (dataverse != null) {
-            ctx.addDataverse(dataverse);
-        }
-        return dataverse;
-    }
+	@Override
+	public Dataverse getDataverse(MetadataTransactionContext ctx,
+			String dataverseName) throws MetadataException {
+		// First look in the context to see if this transaction created the
+		// requested dataverse itself (but the dataverse is still uncommitted).
+		Dataverse dataverse = ctx.getDataverse(dataverseName);
+		if (dataverse != null) {
+			// Don't add this dataverse to the cache, since it is still
+			// uncommitted.
+			return dataverse;
+		}
+		if (ctx.dataverseIsDropped(dataverseName)) {
+			// Dataverse has been dropped by this transaction but could still be
+			// in the cache.
+			return null;
+		}
+		dataverse = cache.getDataverse(dataverseName);
+		if (dataverse != null) {
+			// Dataverse is already in the cache, don't add it again.
+			return dataverse;
+		}
+		try {
+			dataverse = metadataNode
+					.getDataverse(ctx.getJobId(), dataverseName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// We fetched the dataverse from the MetadataNode. Add it to the cache
+		// when this transaction commits.
+		if (dataverse != null) {
+			ctx.addDataverse(dataverse);
+		}
+		return dataverse;
+	}
 
-    @Override
-    public List<Dataset> getDataverseDatasets(MetadataTransactionContext ctx, String dataverseName)
-            throws MetadataException {
-        List<Dataset> dataverseDatasets;
-        try {
-            // Assuming that the transaction can read its own writes on the
-            // metadata node.
-            dataverseDatasets = metadataNode.getDataverseDatasets(ctx.getJobId(), dataverseName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // Don't update the cache to avoid checking against the transaction's
-        // uncommitted datasets.
-        return dataverseDatasets;
-    }
+	@Override
+	public List<Dataset> getDataverseDatasets(MetadataTransactionContext ctx,
+			String dataverseName) throws MetadataException {
+		List<Dataset> dataverseDatasets;
+		try {
+			// Assuming that the transaction can read its own writes on the
+			// metadata node.
+			dataverseDatasets = metadataNode.getDataverseDatasets(
+					ctx.getJobId(), dataverseName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// Don't update the cache to avoid checking against the transaction's
+		// uncommitted datasets.
+		return dataverseDatasets;
+	}
 
-    @Override
-    public void addDataset(MetadataTransactionContext ctx, Dataset dataset) throws MetadataException {
-        // add dataset into metadataNode 
-        try {
-            metadataNode.addDataset(ctx.getJobId(), dataset);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
+	@Override
+	public void addDataset(MetadataTransactionContext ctx, Dataset dataset)
+			throws MetadataException {
+		// add dataset into metadataNode
+		try {
+			metadataNode.addDataset(ctx.getJobId(), dataset);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
 
-        // reflect the dataset into the cache
-        ctx.addDataset(dataset);
-    }
+		// reflect the dataset into the cache
+		ctx.addDataset(dataset);
+	}
 
-    @Override
-    public void dropDataset(MetadataTransactionContext ctx, String dataverseName, String datasetName)
-            throws MetadataException {
-        try {
-            metadataNode.dropDataset(ctx.getJobId(), dataverseName, datasetName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.dropDataset(dataverseName, datasetName);
-    }
+	@Override
+	public void dropDataset(MetadataTransactionContext ctx,
+			String dataverseName, String datasetName) throws MetadataException {
+		try {
+			metadataNode
+					.dropDataset(ctx.getJobId(), dataverseName, datasetName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.dropDataset(dataverseName, datasetName);
+	}
 
-    @Override
-    public Dataset getDataset(MetadataTransactionContext ctx, String dataverseName, String datasetName)
-            throws MetadataException {
+	@Override
+	public Dataset getDataset(MetadataTransactionContext ctx,
+			String dataverseName, String datasetName) throws MetadataException {
 
-        // First look in the context to see if this transaction created the
-        // requested dataset itself (but the dataset is still uncommitted).
-        Dataset dataset = ctx.getDataset(dataverseName, datasetName);
-        if (dataset != null) {
-            // Don't add this dataverse to the cache, since it is still
-            // uncommitted.
-            return dataset;
-        }
-        if (ctx.datasetIsDropped(dataverseName, datasetName)) {
-            // Dataset has been dropped by this transaction but could still be
-            // in the cache.
-            return null;
-        }
+		// First look in the context to see if this transaction created the
+		// requested dataset itself (but the dataset is still uncommitted).
+		Dataset dataset = ctx.getDataset(dataverseName, datasetName);
+		if (dataset != null) {
+			// Don't add this dataverse to the cache, since it is still
+			// uncommitted.
+			return dataset;
+		}
+		if (ctx.datasetIsDropped(dataverseName, datasetName)) {
+			// Dataset has been dropped by this transaction but could still be
+			// in the cache.
+			return null;
+		}
 
-        dataset = cache.getDataset(dataverseName, datasetName);
-        if (dataset != null) {
-            // Dataset is already in the cache, don't add it again.
-            return dataset;
-        }
-        try {
-            dataset = metadataNode.getDataset(ctx.getJobId(), dataverseName, datasetName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // We fetched the dataset from the MetadataNode. Add it to the cache
-        // when this transaction commits.
-        if (dataset != null) {
-            ctx.addDataset(dataset);
-        }
-        return dataset;
-    }
+		dataset = cache.getDataset(dataverseName, datasetName);
+		if (dataset != null) {
+			// Dataset is already in the cache, don't add it again.
+			return dataset;
+		}
+		try {
+			dataset = metadataNode.getDataset(ctx.getJobId(), dataverseName,
+					datasetName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// We fetched the dataset from the MetadataNode. Add it to the cache
+		// when this transaction commits.
+		if (dataset != null) {
+			ctx.addDataset(dataset);
+		}
+		return dataset;
+	}
 
-    @Override
-    public List<Index> getDatasetIndexes(MetadataTransactionContext ctx, String dataverseName, String datasetName)
-            throws MetadataException {
-        List<Index> datsetIndexes;
-        try {
-            datsetIndexes = metadataNode.getDatasetIndexes(ctx.getJobId(), dataverseName, datasetName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        return datsetIndexes;
-    }
+	@Override
+	public List<Index> getDatasetIndexes(MetadataTransactionContext ctx,
+			String dataverseName, String datasetName) throws MetadataException {
+		List<Index> datsetIndexes;
+		try {
+			datsetIndexes = metadataNode.getDatasetIndexes(ctx.getJobId(),
+					dataverseName, datasetName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		return datsetIndexes;
+	}
 
-    @Override
-    public void addDatatype(MetadataTransactionContext ctx, Datatype datatype) throws MetadataException {
-        try {
-            metadataNode.addDatatype(ctx.getJobId(), datatype);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.addDatatype(datatype);
-    }
+	@Override
+	public void addDatatype(MetadataTransactionContext ctx, Datatype datatype)
+			throws MetadataException {
+		try {
+			metadataNode.addDatatype(ctx.getJobId(), datatype);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.addDatatype(datatype);
+	}
 
-    @Override
-    public void dropDatatype(MetadataTransactionContext ctx, String dataverseName, String datatypeName)
-            throws MetadataException {
-        try {
-            metadataNode.dropDatatype(ctx.getJobId(), dataverseName, datatypeName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.dropDataDatatype(dataverseName, datatypeName);
-    }
+	@Override
+	public void dropDatatype(MetadataTransactionContext ctx,
+			String dataverseName, String datatypeName) throws MetadataException {
+		try {
+			metadataNode.dropDatatype(ctx.getJobId(), dataverseName,
+					datatypeName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.dropDataDatatype(dataverseName, datatypeName);
+	}
 
-    @Override
-    public Datatype getDatatype(MetadataTransactionContext ctx, String dataverseName, String datatypeName)
-            throws MetadataException {
-        // First look in the context to see if this transaction created the
-        // requested datatype itself (but the datatype is still uncommitted).
-        Datatype datatype = ctx.getDatatype(dataverseName, datatypeName);
-        if (datatype != null) {
-            // Don't add this dataverse to the cache, since it is still
-            // uncommitted.
-            return datatype;
-        }
-        if (ctx.datatypeIsDropped(dataverseName, datatypeName)) {
-            // Datatype has been dropped by this transaction but could still be
-            // in the cache.
-            return null;
-        }
+	@Override
+	public Datatype getDatatype(MetadataTransactionContext ctx,
+			String dataverseName, String datatypeName) throws MetadataException {
+		// First look in the context to see if this transaction created the
+		// requested datatype itself (but the datatype is still uncommitted).
+		Datatype datatype = ctx.getDatatype(dataverseName, datatypeName);
+		if (datatype != null) {
+			// Don't add this dataverse to the cache, since it is still
+			// uncommitted.
+			return datatype;
+		}
+		if (ctx.datatypeIsDropped(dataverseName, datatypeName)) {
+			// Datatype has been dropped by this transaction but could still be
+			// in the cache.
+			return null;
+		}
 
-        datatype = cache.getDatatype(dataverseName, datatypeName);
-        if (datatype != null) {
-            // Datatype is already in the cache, don't add it again.
-            return datatype;
-        }
-        try {
-            datatype = metadataNode.getDatatype(ctx.getJobId(), dataverseName, datatypeName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // We fetched the datatype from the MetadataNode. Add it to the cache
-        // when this transaction commits.
-        if (datatype != null) {
-            ctx.addDatatype(datatype);
-        }
-        return datatype;
-    }
+		datatype = cache.getDatatype(dataverseName, datatypeName);
+		if (datatype != null) {
+			// Datatype is already in the cache, don't add it again.
+			return datatype;
+		}
+		try {
+			datatype = metadataNode.getDatatype(ctx.getJobId(), dataverseName,
+					datatypeName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// We fetched the datatype from the MetadataNode. Add it to the cache
+		// when this transaction commits.
+		if (datatype != null) {
+			ctx.addDatatype(datatype);
+		}
+		return datatype;
+	}
 
-    @Override
-    public void addIndex(MetadataTransactionContext ctx, Index index) throws MetadataException {
-        try {
-            metadataNode.addIndex(ctx.getJobId(), index);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.addIndex(index);
-    }
+	@Override
+	public void addIndex(MetadataTransactionContext ctx, Index index)
+			throws MetadataException {
+		try {
+			metadataNode.addIndex(ctx.getJobId(), index);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.addIndex(index);
+	}
 
-    @Override
-    public void addAdapter(MetadataTransactionContext mdTxnCtx, DatasourceAdapter adapter) throws MetadataException {
-        try {
-            metadataNode.addAdapter(mdTxnCtx.getJobId(), adapter);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        mdTxnCtx.addAdapter(adapter);
+	@Override
+	public void addAdapter(MetadataTransactionContext mdTxnCtx,
+			DatasourceAdapter adapter) throws MetadataException {
+		try {
+			metadataNode.addAdapter(mdTxnCtx.getJobId(), adapter);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		mdTxnCtx.addAdapter(adapter);
 
-    }
+	}
 
-    @Override
-    public void dropIndex(MetadataTransactionContext ctx, String dataverseName, String datasetName, String indexName)
-            throws MetadataException {
-        try {
-            metadataNode.dropIndex(ctx.getJobId(), dataverseName, datasetName, indexName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.dropIndex(dataverseName, datasetName, indexName);
-    }
+	@Override
+	public void dropIndex(MetadataTransactionContext ctx, String dataverseName,
+			String datasetName, String indexName) throws MetadataException {
+		try {
+			metadataNode.dropIndex(ctx.getJobId(), dataverseName, datasetName,
+					indexName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.dropIndex(dataverseName, datasetName, indexName);
+	}
 
-    @Override
-    public Index getIndex(MetadataTransactionContext ctx, String dataverseName, String datasetName, String indexName)
-            throws MetadataException {
+	@Override
+	public Index getIndex(MetadataTransactionContext ctx, String dataverseName,
+			String datasetName, String indexName) throws MetadataException {
 
-        // First look in the context to see if this transaction created the
-        // requested index itself (but the index is still uncommitted).
-        Index index = ctx.getIndex(dataverseName, datasetName, indexName);
-        if (index != null) {
-            // Don't add this index to the cache, since it is still
-            // uncommitted.
-            return index;
-        }
+		// First look in the context to see if this transaction created the
+		// requested index itself (but the index is still uncommitted).
+		Index index = ctx.getIndex(dataverseName, datasetName, indexName);
+		if (index != null) {
+			// Don't add this index to the cache, since it is still
+			// uncommitted.
+			return index;
+		}
 
-        if (ctx.indexIsDropped(dataverseName, datasetName, indexName)) {
-            // Index has been dropped by this transaction but could still be
-            // in the cache.
-            return null;
-        }
+		if (ctx.indexIsDropped(dataverseName, datasetName, indexName)) {
+			// Index has been dropped by this transaction but could still be
+			// in the cache.
+			return null;
+		}
 
-        index = cache.getIndex(dataverseName, datasetName, indexName);
-        if (index != null) {
-            // Index is already in the cache, don't add it again.
-            return index;
-        }
-        try {
-            index = metadataNode.getIndex(ctx.getJobId(), dataverseName, datasetName, indexName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // We fetched the index from the MetadataNode. Add it to the cache
-        // when this transaction commits.
-        if (index != null) {
-            ctx.addIndex(index);
-        }
-        return index;
-    }
+		index = cache.getIndex(dataverseName, datasetName, indexName);
+		if (index != null) {
+			// Index is already in the cache, don't add it again.
+			return index;
+		}
+		try {
+			index = metadataNode.getIndex(ctx.getJobId(), dataverseName,
+					datasetName, indexName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// We fetched the index from the MetadataNode. Add it to the cache
+		// when this transaction commits.
+		if (index != null) {
+			ctx.addIndex(index);
+		}
+		return index;
+	}
 
-    @Override
-    public void addNode(MetadataTransactionContext ctx, Node node) throws MetadataException {
-        try {
-            metadataNode.addNode(ctx.getJobId(), node);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-    }
+	@Override
+	public void addNode(MetadataTransactionContext ctx, Node node)
+			throws MetadataException {
+		try {
+			metadataNode.addNode(ctx.getJobId(), node);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+	}
 
-    @Override
-    public void addNodegroup(MetadataTransactionContext ctx, NodeGroup nodeGroup) throws MetadataException {
-        try {
-            metadataNode.addNodeGroup(ctx.getJobId(), nodeGroup);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.addNogeGroup(nodeGroup);
-    }
+	@Override
+	public void addNodegroup(MetadataTransactionContext ctx, NodeGroup nodeGroup)
+			throws MetadataException {
+		try {
+			metadataNode.addNodeGroup(ctx.getJobId(), nodeGroup);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.addNogeGroup(nodeGroup);
+	}
 
-    @Override
-    public void dropNodegroup(MetadataTransactionContext ctx, String nodeGroupName) throws MetadataException {
-        try {
-            metadataNode.dropNodegroup(ctx.getJobId(), nodeGroupName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.dropNodeGroup(nodeGroupName);
-    }
+	@Override
+	public void dropNodegroup(MetadataTransactionContext ctx,
+			String nodeGroupName) throws MetadataException {
+		try {
+			metadataNode.dropNodegroup(ctx.getJobId(), nodeGroupName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.dropNodeGroup(nodeGroupName);
+	}
 
-    @Override
-    public NodeGroup getNodegroup(MetadataTransactionContext ctx, String nodeGroupName) throws MetadataException {
-        // First look in the context to see if this transaction created the
-        // requested dataverse itself (but the dataverse is still uncommitted).
-        NodeGroup nodeGroup = ctx.getNodeGroup(nodeGroupName);
-        if (nodeGroup != null) {
-            // Don't add this dataverse to the cache, since it is still
-            // uncommitted.
-            return nodeGroup;
-        }
-        if (ctx.nodeGroupIsDropped(nodeGroupName)) {
-            // NodeGroup has been dropped by this transaction but could still be
-            // in the cache.
-            return null;
-        }
-        nodeGroup = cache.getNodeGroup(nodeGroupName);
-        if (nodeGroup != null) {
-            // NodeGroup is already in the cache, don't add it again.
-            return nodeGroup;
-        }
-        try {
-            nodeGroup = metadataNode.getNodeGroup(ctx.getJobId(), nodeGroupName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // We fetched the nodeGroup from the MetadataNode. Add it to the cache
-        // when this transaction commits.
-        if (nodeGroup != null) {
-            ctx.addNogeGroup(nodeGroup);
-        }
-        return nodeGroup;
-    }
+	@Override
+	public NodeGroup getNodegroup(MetadataTransactionContext ctx,
+			String nodeGroupName) throws MetadataException {
+		// First look in the context to see if this transaction created the
+		// requested dataverse itself (but the dataverse is still uncommitted).
+		NodeGroup nodeGroup = ctx.getNodeGroup(nodeGroupName);
+		if (nodeGroup != null) {
+			// Don't add this dataverse to the cache, since it is still
+			// uncommitted.
+			return nodeGroup;
+		}
+		if (ctx.nodeGroupIsDropped(nodeGroupName)) {
+			// NodeGroup has been dropped by this transaction but could still be
+			// in the cache.
+			return null;
+		}
+		nodeGroup = cache.getNodeGroup(nodeGroupName);
+		if (nodeGroup != null) {
+			// NodeGroup is already in the cache, don't add it again.
+			return nodeGroup;
+		}
+		try {
+			nodeGroup = metadataNode
+					.getNodeGroup(ctx.getJobId(), nodeGroupName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// We fetched the nodeGroup from the MetadataNode. Add it to the cache
+		// when this transaction commits.
+		if (nodeGroup != null) {
+			ctx.addNogeGroup(nodeGroup);
+		}
+		return nodeGroup;
+	}
 
-    @Override
-    public void addFunction(MetadataTransactionContext mdTxnCtx, Function function) throws MetadataException {
-        try {
-            metadataNode.addFunction(mdTxnCtx.getJobId(), function);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        mdTxnCtx.addFunction(function);
-    }
+	@Override
+	public void addFunction(MetadataTransactionContext mdTxnCtx,
+			Function function) throws MetadataException {
+		try {
+			metadataNode.addFunction(mdTxnCtx.getJobId(), function);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		mdTxnCtx.addFunction(function);
+	}
 
-    @Override
-    public void dropFunction(MetadataTransactionContext ctx, FunctionSignature functionSignature)
-            throws MetadataException {
-        try {
-            metadataNode.dropFunction(ctx.getJobId(), functionSignature);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        ctx.dropFunction(functionSignature);
-    }
+	@Override
+	public void dropFunction(MetadataTransactionContext ctx,
+			FunctionSignature functionSignature) throws MetadataException {
+		try {
+			metadataNode.dropFunction(ctx.getJobId(), functionSignature);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.dropFunction(functionSignature);
+	}
 
-    @Override
-    public Function getFunction(MetadataTransactionContext ctx, FunctionSignature functionSignature)
-            throws MetadataException {
-        // First look in the context to see if this transaction created the
-        // requested dataset itself (but the dataset is still uncommitted).
-        Function function = ctx.getFunction(functionSignature);
-        if (function != null) {
-            // Don't add this dataverse to the cache, since it is still
-            // uncommitted.
-            return function;
-        }
-        if (ctx.functionIsDropped(functionSignature)) {
-            // Function has been dropped by this transaction but could still be
-            // in the cache.
-            return null;
-        }
-        if (ctx.getDataverse(functionSignature.getNamespace()) != null) {
-            // This transaction has dropped and subsequently created the same
-            // dataverse.
-            return null;
-        }
-        function = cache.getFunction(functionSignature);
-        if (function != null) {
-            // Function is already in the cache, don't add it again.
-            return function;
-        }
-        try {
-            function = metadataNode.getFunction(ctx.getJobId(), functionSignature);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // We fetched the function from the MetadataNode. Add it to the cache
-        // when this transaction commits.
-        if (function != null) {
-            ctx.addFunction(function);
-        }
-        return function;
+	@Override
+	public Function getFunction(MetadataTransactionContext ctx,
+			FunctionSignature functionSignature) throws MetadataException {
+		// First look in the context to see if this transaction created the
+		// requested dataset itself (but the dataset is still uncommitted).
+		Function function = ctx.getFunction(functionSignature);
+		if (function != null) {
+			// Don't add this dataverse to the cache, since it is still
+			// uncommitted.
+			return function;
+		}
+		if (ctx.functionIsDropped(functionSignature)) {
+			// Function has been dropped by this transaction but could still be
+			// in the cache.
+			return null;
+		}
+		if (ctx.getDataverse(functionSignature.getNamespace()) != null) {
+			// This transaction has dropped and subsequently created the same
+			// dataverse.
+			return null;
+		}
+		function = cache.getFunction(functionSignature);
+		if (function != null) {
+			// Function is already in the cache, don't add it again.
+			return function;
+		}
+		try {
+			function = metadataNode.getFunction(ctx.getJobId(),
+					functionSignature);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// We fetched the function from the MetadataNode. Add it to the cache
+		// when this transaction commits.
+		if (function != null) {
+			ctx.addFunction(function);
+		}
+		return function;
 
-    }
+	}
 
-    @Override
-    public void initializeDatasetIdFactory(MetadataTransactionContext ctx) throws MetadataException {
-        try {
-            metadataNode.initializeDatasetIdFactory(ctx.getJobId());
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-    }
+	@Override
+	public void initializeDatasetIdFactory(MetadataTransactionContext ctx)
+			throws MetadataException {
+		try {
+			metadataNode.initializeDatasetIdFactory(ctx.getJobId());
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+	}
 
-    @Override
-    public List<Function> getDataverseFunctions(MetadataTransactionContext ctx, String dataverseName)
-            throws MetadataException {
-        List<Function> dataverseFunctions;
-        try {
-            // Assuming that the transaction can read its own writes on the
-            // metadata node.
-            dataverseFunctions = metadataNode.getDataverseFunctions(ctx.getJobId(), dataverseName);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        // Don't update the cache to avoid checking against the transaction's
-        // uncommitted functions.
-        return dataverseFunctions;
-    }
+	@Override
+	public List<Function> getDataverseFunctions(MetadataTransactionContext ctx,
+			String dataverseName) throws MetadataException {
+		List<Function> dataverseFunctions;
+		try {
+			// Assuming that the transaction can read its own writes on the
+			// metadata node.
+			dataverseFunctions = metadataNode.getDataverseFunctions(
+					ctx.getJobId(), dataverseName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// Don't update the cache to avoid checking against the transaction's
+		// uncommitted functions.
+		return dataverseFunctions;
+	}
 
-    @Override
-    public void dropAdapter(MetadataTransactionContext ctx, String dataverseName, String name) throws MetadataException {
-        try {
-            metadataNode.dropAdapter(ctx.getJobId(), dataverseName, name);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-    }
+	@Override
+	public void dropAdapter(MetadataTransactionContext ctx,
+			String dataverseName, String name) throws MetadataException {
+		try {
+			metadataNode.dropAdapter(ctx.getJobId(), dataverseName, name);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+	}
 
-    @Override
-    public DatasourceAdapter getAdapter(MetadataTransactionContext ctx, String dataverseName, String name)
-            throws MetadataException {
-        DatasourceAdapter adapter = null;
-        try {
-            adapter = metadataNode.getAdapter(ctx.getJobId(), dataverseName, name);
-        } catch (RemoteException e) {
-            throw new MetadataException(e);
-        }
-        return adapter;
-    }
+	@Override
+	public DatasourceAdapter getAdapter(MetadataTransactionContext ctx,
+			String dataverseName, String name) throws MetadataException {
+		DatasourceAdapter adapter = null;
+		try {
+			adapter = metadataNode.getAdapter(ctx.getJobId(), dataverseName,
+					name);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		return adapter;
+	}
 
-    @Override
-    public void acquireWriteLatch() {
-        metadataLatch.writeLock().lock();
-    }
+	@Override
+	public void dropLibrary(MetadataTransactionContext ctx,
+			String dataverseName, String libraryName) throws MetadataException {
+		try {
+			metadataNode
+					.dropLibrary(ctx.getJobId(), dataverseName, libraryName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.dropLibrary(dataverseName, libraryName);
+	}
 
-    @Override
-    public void releaseWriteLatch() {
-        metadataLatch.writeLock().unlock();
-    }
+	@Override
+	public List<Library> getDataverseLibraries(MetadataTransactionContext ctx,
+			String dataverseName) throws MetadataException {
+		List<Library> dataverseLibaries = null;
+		try {
+			// Assuming that the transaction can read its own writes on the
+			// metadata node.
+			dataverseLibaries = metadataNode.getDataverseLibraries(
+					ctx.getJobId(), dataverseName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		// Don't update the cache to avoid checking against the transaction's
+		// uncommitted functions.
+		return dataverseLibaries;
+	}
 
-    @Override
-    public void acquireReadLatch() {
-        metadataLatch.readLock().lock();
-    }
+	@Override
+	public void addLibrary(MetadataTransactionContext ctx, Library library)
+			throws MetadataException {
+		try {
+			metadataNode.addLibrary(ctx.getJobId(), library);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		ctx.addLibrary(library);
+	}
 
-    @Override
-    public void releaseReadLatch() {
-        metadataLatch.readLock().unlock();
-    }
+	@Override
+	public Library getLibrary(MetadataTransactionContext ctx,
+			String dataverseName, String libraryName) throws MetadataException,
+			RemoteException {
+		Library library = null;
+		try {
+			library = metadataNode.getLibrary(ctx.getJobId(), dataverseName,
+					libraryName);
+		} catch (RemoteException e) {
+			throw new MetadataException(e);
+		}
+		return library;
+	}
+
+	@Override
+	public void acquireWriteLatch() {
+		metadataLatch.writeLock().lock();
+	}
+
+	@Override
+	public void releaseWriteLatch() {
+		metadataLatch.writeLock().unlock();
+	}
+
+	@Override
+	public void acquireReadLatch() {
+		metadataLatch.readLock().lock();
+	}
+
+	@Override
+	public void releaseReadLatch() {
+		metadataLatch.readLock().unlock();
+	}
 
 }
\ No newline at end of file
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataNode.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataNode.java
index d9c6ed4..90b72a2 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataNode.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataNode.java
@@ -37,6 +37,7 @@
 import edu.uci.ics.asterix.metadata.entities.Function;
 import edu.uci.ics.asterix.metadata.entities.Index;
 import edu.uci.ics.asterix.metadata.entities.InternalDatasetDetails;
+import edu.uci.ics.asterix.metadata.entities.Library;
 import edu.uci.ics.asterix.metadata.entities.Node;
 import edu.uci.ics.asterix.metadata.entities.NodeGroup;
 import edu.uci.ics.asterix.metadata.entitytupletranslators.DatasetTupleTranslator;
@@ -45,6 +46,7 @@
 import edu.uci.ics.asterix.metadata.entitytupletranslators.DataverseTupleTranslator;
 import edu.uci.ics.asterix.metadata.entitytupletranslators.FunctionTupleTranslator;
 import edu.uci.ics.asterix.metadata.entitytupletranslators.IndexTupleTranslator;
+import edu.uci.ics.asterix.metadata.entitytupletranslators.LibraryTupleTranslator;
 import edu.uci.ics.asterix.metadata.entitytupletranslators.NodeGroupTupleTranslator;
 import edu.uci.ics.asterix.metadata.entitytupletranslators.NodeTupleTranslator;
 import edu.uci.ics.asterix.metadata.valueextractors.DatasetNameValueExtractor;
@@ -265,7 +267,7 @@
         ILSMIndex lsmIndex = (ILSMIndex) indexLifecycleManager.getIndex(resourceID);
         indexLifecycleManager.open(resourceID);
 
-        //prepare a Callback for logging
+        // prepare a Callback for logging
         IModificationOperationCallback modCallback = createIndexModificationCallback(jobId, resourceID, metadataIndex,
                 lsmIndex, IndexOperation.INSERT);
 
@@ -376,7 +378,8 @@
                         searchKey);
                 deleteTupleFromIndex(jobId, MetadataPrimaryIndexes.DATASET_DATASET, datasetTuple);
             } catch (TreeIndexException tie) {
-                //ignore this exception and continue deleting all relevant artifacts. 
+                // ignore this exception and continue deleting all relevant
+                // artifacts.
             }
 
             // Delete entry from secondary index 'group'.
@@ -390,7 +393,8 @@
                             MetadataSecondaryIndexes.GROUPNAME_ON_DATASET_INDEX, groupNameSearchKey);
                     deleteTupleFromIndex(jobId, MetadataSecondaryIndexes.GROUPNAME_ON_DATASET_INDEX, groupNameTuple);
                 } catch (TreeIndexException tie) {
-                    //ignore this exception and continue deleting all relevant artifacts.
+                    // ignore this exception and continue deleting all relevant
+                    // artifacts.
                 }
             }
             // Delete entry from secondary index 'type'.
@@ -402,7 +406,8 @@
                         MetadataSecondaryIndexes.DATATYPENAME_ON_DATASET_INDEX, dataTypeSearchKey);
                 deleteTupleFromIndex(jobId, MetadataSecondaryIndexes.DATATYPENAME_ON_DATASET_INDEX, dataTypeTuple);
             } catch (TreeIndexException tie) {
-                //ignore this exception and continue deleting all relevant artifacts.
+                // ignore this exception and continue deleting all relevant
+                // artifacts.
             }
 
             // Delete entry(s) from the 'indexes' dataset.
@@ -502,7 +507,8 @@
             // Searches the index for the tuple to be deleted. Acquires an S
             // lock on the 'datatype' dataset.
             ITupleReference tuple = getTupleToBeDeleted(jobId, MetadataPrimaryIndexes.DATATYPE_DATASET, searchKey);
-            // This call uses the secondary index on datatype. Get nested types before deleting entry from secondary index.
+            // This call uses the secondary index on datatype. Get nested types
+            // before deleting entry from secondary index.
             List<String> nestedTypes = getNestedDatatypeNames(jobId, dataverseName, datatypeName);
             deleteTupleFromIndex(jobId, MetadataPrimaryIndexes.DATATYPE_DATASET, tuple);
             deleteFromDatatypeSecondaryIndex(jobId, dataverseName, datatypeName);
@@ -568,7 +574,7 @@
         long resourceID = metadataIndex.getResourceID();
         ILSMIndex lsmIndex = (ILSMIndex) indexLifecycleManager.getIndex(resourceID);
         indexLifecycleManager.open(resourceID);
-        //prepare a Callback for logging
+        // prepare a Callback for logging
         IModificationOperationCallback modCallback = createIndexModificationCallback(jobId, resourceID, metadataIndex,
                 lsmIndex, IndexOperation.DELETE);
         IIndexAccessor indexAccessor = lsmIndex.createAccessor(modCallback, NoOpOperationCallback.INSTANCE);
@@ -631,6 +637,20 @@
         }
     }
 
+    public List<Library> getDataverseLibraries(JobId jobId, String dataverseName) throws MetadataException,
+            RemoteException {
+        try {
+            ITupleReference searchKey = createTuple(dataverseName);
+            LibraryTupleTranslator tupleReaderWriter = new LibraryTupleTranslator(false);
+            IValueExtractor<Library> valueExtractor = new MetadataEntityValueExtractor<Library>(tupleReaderWriter);
+            List<Library> results = new ArrayList<Library>();
+            searchIndex(jobId, MetadataPrimaryIndexes.LIBRARY_DATASET, searchKey, valueExtractor, results);
+            return results;
+        } catch (Exception e) {
+            throw new MetadataException(e);
+        }
+    }
+
     private List<Datatype> getDataverseDatatypes(JobId jobId, String dataverseName) throws MetadataException,
             RemoteException {
         try {
@@ -853,7 +873,7 @@
         return results.get(0);
     }
 
-    //Debugging Method
+    // Debugging Method
     public String printMetadata() {
 
         StringBuilder sb = new StringBuilder();
@@ -1121,4 +1141,70 @@
             throw new MetadataException(e);
         }
     }
+
+    @Override
+    public void addLibrary(JobId jobId, Library library) throws MetadataException, RemoteException {
+        try {
+            // Insert into the 'Library' dataset.
+            LibraryTupleTranslator tupleReaderWriter = new LibraryTupleTranslator(true);
+            ITupleReference libraryTuple = tupleReaderWriter.getTupleFromMetadataEntity(library);
+            insertTupleIntoIndex(jobId, MetadataPrimaryIndexes.LIBRARY_DATASET, libraryTuple);
+
+        } catch (BTreeDuplicateKeyException e) {
+            throw new MetadataException("A library with this name " + library.getDataverseName()
+                    + " already exists in dataverse '" + library.getDataverseName() + "'.", e);
+        } catch (Exception e) {
+            throw new MetadataException(e);
+        }
+
+    }
+
+    @Override
+    public void dropLibrary(JobId jobId, String dataverseName, String libraryName) throws MetadataException,
+            RemoteException {
+        Library library;
+        try {
+            library = getLibrary(jobId, dataverseName, libraryName);
+        } catch (Exception e) {
+            throw new MetadataException(e);
+        }
+        if (library == null) {
+            throw new MetadataException("Cannot drop library '" + library + "' because it doesn't exist.");
+        }
+        try {
+            // Delete entry from the 'Library' dataset.
+            ITupleReference searchKey = createTuple(dataverseName, libraryName);
+            // Searches the index for the tuple to be deleted. Acquires an S
+            // lock on the 'Adapter' dataset.
+            ITupleReference datasetTuple = getTupleToBeDeleted(jobId, MetadataPrimaryIndexes.LIBRARY_DATASET, searchKey);
+            deleteTupleFromIndex(jobId, MetadataPrimaryIndexes.LIBRARY_DATASET, datasetTuple);
+
+            // TODO: Change this to be a BTree specific exception, e.g.,
+            // BTreeKeyDoesNotExistException.
+        } catch (TreeIndexException e) {
+            throw new MetadataException("Cannot drop library '" + libraryName, e);
+        } catch (Exception e) {
+            throw new MetadataException(e);
+        }
+
+    }
+
+    @Override
+    public Library getLibrary(JobId jobId, String dataverseName, String libraryName) throws MetadataException,
+            RemoteException {
+        try {
+            ITupleReference searchKey = createTuple(dataverseName, libraryName);
+            LibraryTupleTranslator tupleReaderWriter = new LibraryTupleTranslator(false);
+            List<Library> results = new ArrayList<Library>();
+            IValueExtractor<Library> valueExtractor = new MetadataEntityValueExtractor<Library>(tupleReaderWriter);
+            searchIndex(jobId, MetadataPrimaryIndexes.LIBRARY_DATASET, searchKey, valueExtractor, results);
+            if (results.isEmpty()) {
+                return null;
+            }
+            return results.get(0);
+        } catch (Exception e) {
+            throw new MetadataException(e);
+        }
+    }
+
 }
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataTransactionContext.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataTransactionContext.java
index cbd37d6..bb0bb8a 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataTransactionContext.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/MetadataTransactionContext.java
@@ -26,6 +26,7 @@
 import edu.uci.ics.asterix.metadata.entities.Dataverse;
 import edu.uci.ics.asterix.metadata.entities.Function;
 import edu.uci.ics.asterix.metadata.entities.Index;
+import edu.uci.ics.asterix.metadata.entities.Library;
 import edu.uci.ics.asterix.metadata.entities.NodeGroup;
 import edu.uci.ics.asterix.transaction.management.service.transaction.JobId;
 
@@ -123,6 +124,11 @@
         logAndApply(new MetadataLogicalOperation(dataverse, false));
     }
 
+    public void addLibrary(Library library) {
+        droppedCache.dropLibrary(library);
+        logAndApply(new MetadataLogicalOperation(library, true));
+    }
+
     public void dropDataDatatype(String dataverseName, String datatypeName) {
         Datatype datatype = new Datatype(dataverseName, datatypeName, null, false);
         droppedCache.addDatatypeIfNotExists(datatype);
@@ -149,6 +155,12 @@
         logAndApply(new MetadataLogicalOperation(adapter, false));
     }
 
+    public void dropLibrary(String dataverseName, String libraryName) {
+        Library library = new Library(dataverseName, libraryName);
+        droppedCache.addLibraryIfNotExists(library);
+        logAndApply(new MetadataLogicalOperation(library, false));
+    }
+
     public void logAndApply(MetadataLogicalOperation op) {
         opLog.add(op);
         doOperation(op);
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataManager.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataManager.java
index fdf2d60..46b1f80 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataManager.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataManager.java
@@ -21,16 +21,16 @@
 import edu.uci.ics.asterix.common.functions.FunctionSignature;
 import edu.uci.ics.asterix.metadata.MetadataException;
 import edu.uci.ics.asterix.metadata.MetadataTransactionContext;
-import edu.uci.ics.asterix.metadata.entities.DatasourceAdapter;
 import edu.uci.ics.asterix.metadata.entities.Dataset;
+import edu.uci.ics.asterix.metadata.entities.DatasourceAdapter;
 import edu.uci.ics.asterix.metadata.entities.Datatype;
 import edu.uci.ics.asterix.metadata.entities.Dataverse;
 import edu.uci.ics.asterix.metadata.entities.Function;
 import edu.uci.ics.asterix.metadata.entities.Index;
+import edu.uci.ics.asterix.metadata.entities.Library;
 import edu.uci.ics.asterix.metadata.entities.Node;
 import edu.uci.ics.asterix.metadata.entities.NodeGroup;
 import edu.uci.ics.asterix.transaction.management.exception.ACIDException;
-import edu.uci.ics.asterix.transaction.management.service.transaction.JobId;
 
 /**
  * A metadata manager provides user access to Asterix metadata (e.g., types,
@@ -128,7 +128,7 @@
      * @throws MetadataException
      */
     List<Dataverse> getDataverses(MetadataTransactionContext ctx) throws MetadataException;
-    
+
     /**
      * Retrieves a dataverse with given name.
      * 
@@ -179,7 +179,7 @@
      *             For example, if the dataset already exists.
      */
     public void addDataset(MetadataTransactionContext ctx, Dataset dataset) throws MetadataException;
-    
+
     /**
      * Retrieves a dataset within a given dataverse.
      * 
@@ -441,9 +441,8 @@
     public List<Function> getDataverseFunctions(MetadataTransactionContext ctx, String dataverseName)
             throws MetadataException;
 
-	
     public void initializeDatasetIdFactory(MetadataTransactionContext ctx) throws MetadataException;
-    
+
     public void acquireWriteLatch();
 
     public void releaseWriteLatch();
@@ -452,5 +451,62 @@
 
     public void releaseReadLatch();
 
+    /**
+     * Removes a library , acquiring local locks on behalf of the given
+     * transaction id.
+     * 
+     * @param ctx
+     *            MetadataTransactionContext of an active metadata transaction.
+     * @param dataverseName
+     *            dataverse asociated with the adapter that is to be deleted.
+     * @param libraryName
+     *            Name of library to be deleted. MetadataException for example,
+     *            if the library does not exists.
+     * @throws RemoteException
+     */
+    public void dropLibrary(MetadataTransactionContext ctx, String dataverseName, String libraryName)
+            throws MetadataException;
+
+    /**
+     * Adds a library, acquiring local locks on behalf of the given
+     * transaction id.
+     * 
+     * @param ctx
+     *            MetadataTransactionContext of an active metadata transaction.
+     * @param library
+     *            Library to be added
+     * @throws MetadataException
+     *             for example, if the library is already added.
+     * @throws RemoteException
+     */
+    public void addLibrary(MetadataTransactionContext ctx, Library library) throws MetadataException;
+
+    /**
+     * @param ctx
+     *            MetadataTransactionContext of an active metadata transaction.
+     * @param dataverseName
+     *            dataverse asociated with the library that is to be retrieved.
+     * @param libraryName
+     *            name of the library that is to be retrieved
+     * @return Library
+     * @throws MetadataException
+     * @throws RemoteException
+     */
+    public Library getLibrary(MetadataTransactionContext ctx, String dataverseName, String libraryName)
+            throws MetadataException, RemoteException;
+
+    /**
+     * Retireve libraries installed in a given dataverse.
+     * 
+     * @param ctx
+     *            MetadataTransactionContext of an active metadata transaction.
+     * @param dataverseName
+     *            dataverse asociated with the library that is to be retrieved.
+     * @return Library
+     * @throws MetadataException
+     * @throws RemoteException
+     */
+    public List<Library> getDataverseLibraries(MetadataTransactionContext ctx, String dataverseName)
+            throws MetadataException;
 
 }
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataNode.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataNode.java
index 836d42f..a27dae2 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataNode.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/api/IMetadataNode.java
@@ -22,12 +22,13 @@
 
 import edu.uci.ics.asterix.common.functions.FunctionSignature;
 import edu.uci.ics.asterix.metadata.MetadataException;
-import edu.uci.ics.asterix.metadata.entities.DatasourceAdapter;
 import edu.uci.ics.asterix.metadata.entities.Dataset;
+import edu.uci.ics.asterix.metadata.entities.DatasourceAdapter;
 import edu.uci.ics.asterix.metadata.entities.Datatype;
 import edu.uci.ics.asterix.metadata.entities.Dataverse;
 import edu.uci.ics.asterix.metadata.entities.Function;
 import edu.uci.ics.asterix.metadata.entities.Index;
+import edu.uci.ics.asterix.metadata.entities.Library;
 import edu.uci.ics.asterix.metadata.entities.Node;
 import edu.uci.ics.asterix.metadata.entities.NodeGroup;
 import edu.uci.ics.asterix.transaction.management.exception.ACIDException;
@@ -383,7 +384,6 @@
     public void addNode(JobId jobId, Node node) throws MetadataException, RemoteException;
 
     /**
-
      * @param jobId
      *            A globally unique id for an active metadata transaction.
      * @param functionSignature
@@ -408,7 +408,8 @@
      *             group to be deleted.
      * @throws RemoteException
      */
-    public void dropFunction(JobId jobId, FunctionSignature functionSignature) throws MetadataException, RemoteException;
+    public void dropFunction(JobId jobId, FunctionSignature functionSignature) throws MetadataException,
+            RemoteException;
 
     /**
      * @param jobId
@@ -442,8 +443,8 @@
     public List<DatasourceAdapter> getDataverseAdapters(JobId jobId, String dataverseName) throws MetadataException,
             RemoteException;
 
-    public DatasourceAdapter getAdapter(JobId jobId, String dataverseName, String adapterName) throws MetadataException,
-            RemoteException;
+    public DatasourceAdapter getAdapter(JobId jobId, String dataverseName, String adapterName)
+            throws MetadataException, RemoteException;
 
     /**
      * Deletes a adapter , acquiring local locks on behalf of the given
@@ -474,4 +475,62 @@
 
     public void initializeDatasetIdFactory(JobId jobId) throws MetadataException, RemoteException;
 
+    /**
+     * Removes a library , acquiring local locks on behalf of the given
+     * transaction id.
+     * 
+     * @param txnId
+     *            A globally unique id for an active metadata transaction.
+     * @param dataverseName
+     *            dataverse asociated with the adapter that is to be deleted.
+     * @param libraryName
+     *            Name of library to be deleted. MetadataException for example,
+     *            if the library does not exists.
+     * @throws RemoteException
+     */
+    public void dropLibrary(JobId jobId, String dataverseName, String libraryName) throws MetadataException,
+            RemoteException;
+
+    /**
+     * Adds a library, acquiring local locks on behalf of the given
+     * transaction id.
+     * 
+     * @param txnId
+     *            A globally unique id for an active metadata transaction.
+     * @param library
+     *            Library to be added
+     * @throws MetadataException
+     *             for example, if the library is already added.
+     * @throws RemoteException
+     */
+    public void addLibrary(JobId jobId, Library library) throws MetadataException, RemoteException;
+
+    /**
+     * @param txnId
+     *            A globally unique id for an active metadata transaction.
+     * @param dataverseName
+     *            dataverse asociated with the library that is to be retrieved.
+     * @param libraryName
+     *            name of the library that is to be retrieved
+     * @return Library
+     * @throws MetadataException
+     * @throws RemoteException
+     */
+    public Library getLibrary(JobId jobId, String dataverseName, String libraryName) throws MetadataException,
+            RemoteException;
+
+    /**
+     * Retireve libraries installed in a given dataverse.
+     * 
+     * @param txnId
+     *            A globally unique id for an active metadata transaction.
+     * @param dataverseName
+     *            dataverse asociated with the library that is to be retrieved.
+     * @return Library
+     * @throws MetadataException
+     * @throws RemoteException
+     */
+    public List<Library> getDataverseLibraries(JobId jobId, String dataverseName) throws MetadataException,
+            RemoteException;
+
 }
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java
index 805a550..0bd2a46 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataBootstrap.java
@@ -119,14 +119,14 @@
                 MetadataPrimaryIndexes.DATASET_DATASET, MetadataPrimaryIndexes.DATATYPE_DATASET,
                 MetadataPrimaryIndexes.INDEX_DATASET, MetadataPrimaryIndexes.NODE_DATASET,
                 MetadataPrimaryIndexes.NODEGROUP_DATASET, MetadataPrimaryIndexes.FUNCTION_DATASET,
-                MetadataPrimaryIndexes.DATASOURCE_ADAPTER_DATASET };
+                MetadataPrimaryIndexes.DATASOURCE_ADAPTER_DATASET, MetadataPrimaryIndexes.LIBRARY_DATASET };
         secondaryIndexes = new IMetadataIndex[] { MetadataSecondaryIndexes.GROUPNAME_ON_DATASET_INDEX,
                 MetadataSecondaryIndexes.DATATYPENAME_ON_DATASET_INDEX,
                 MetadataSecondaryIndexes.DATATYPENAME_ON_DATATYPE_INDEX };
     }
 
-    public static void startUniverse(AsterixProperties asterixProperties, INCApplicationContext ncApplicationContext, boolean isNewUniverse)
-            throws Exception {
+    public static void startUniverse(AsterixProperties asterixProperties, INCApplicationContext ncApplicationContext,
+            boolean isNewUniverse) throws Exception {
         runtimeContext = (AsterixAppRuntimeContext) ncApplicationContext.getApplicationObject();
 
         // Initialize static metadata objects, such as record types and metadata
@@ -233,7 +233,8 @@
                     primaryIndexes[i].getNodeGroupName());
             MetadataManager.INSTANCE.addDataset(mdTxnCtx, new Dataset(primaryIndexes[i].getDataverseName(),
                     primaryIndexes[i].getIndexedDatasetName(), primaryIndexes[i].getPayloadRecordType().getTypeName(),
-                    id, new HashMap<String,String>(), DatasetType.INTERNAL, primaryIndexes[i].getDatasetId().getId(), IMetadataEntity.PENDING_NO_OP));
+                    id, new HashMap<String, String>(), DatasetType.INTERNAL, primaryIndexes[i].getDatasetId().getId(),
+                    IMetadataEntity.PENDING_NO_OP));
         }
     }
 
@@ -331,8 +332,8 @@
         LSMBTree lsmBtree = null;
         long resourceID = -1;
         if (create) {
-            lsmBtree = LSMBTreeUtils.createLSMTree(memBufferCache, memFreePageManager, ioManager, file,
-                    bufferCache, fileMapProvider, typeTraits, comparatorFactories, bloomFilterKeyFields,
+            lsmBtree = LSMBTreeUtils.createLSMTree(memBufferCache, memFreePageManager, ioManager, file, bufferCache,
+                    fileMapProvider, typeTraits, comparatorFactories, bloomFilterKeyFields,
                     runtimeContext.getLSMMergePolicy(), runtimeContext.getLSMBTreeOperationTrackerFactory(),
                     runtimeContext.getLSMIOScheduler(), AsterixRuntimeComponentsProvider.LSMBTREE_PROVIDER);
             lsmBtree.create();
@@ -358,13 +359,11 @@
                 indexLifecycleManager.register(resourceID, lsmBtree);
             }
         }
-        
+
         index.setResourceID(resourceID);
         index.setFile(file);
         indexLifecycleManager.open(resourceID);
     }
-    
-    
 
     public static String getOutputDir() {
         return outputDir;
@@ -381,9 +380,9 @@
         String datasetName = null;
         String indexName = null;
         MetadataTransactionContext mdTxnCtx = null;
-        
+
         MetadataManager.INSTANCE.acquireWriteLatch();
-        
+
         try {
             mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
 
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataConstants.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataConstants.java
index 83c147f..2a57b12 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataConstants.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataConstants.java
@@ -19,10 +19,10 @@
 
     // Name of the dataverse the metadata lives in.
     public final static String METADATA_DATAVERSE_NAME = "Metadata";
-    
+
     // Name of the node group where metadata is stored on.
     public final static String METADATA_NODEGROUP_NAME = "MetadataGroup";
-    
+
     // Name of the default nodegroup where internal/feed datasets will be partitioned
     // if an explicit nodegroup is not specified at the time of creation of a dataset
     public static final String METADATA_DEFAULT_NODEGROUP_NAME = "DEFAULT_NG_ALL_NODES";
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataPrimaryIndexes.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataPrimaryIndexes.java
index 2fc3e59..88cee5b 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataPrimaryIndexes.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataPrimaryIndexes.java
@@ -42,9 +42,12 @@
     public static final int NODEGROUP_DATASET_ID = 6;
     public static final int FUNCTION_DATASET_ID = 7;
     public static final int DATASOURCE_ADAPTER_DATASET_ID = 8;
+    public static final int LIBRARY_DATASET_ID = 9;
+
     public static final int FIRST_AVAILABLE_USER_DATASET_ID = 100;
 
     public static IMetadataIndex DATASOURCE_ADAPTER_DATASET;
+    public static IMetadataIndex LIBRARY_DATASET;
 
     /**
      * Create all metadata primary index descriptors. MetadataRecordTypes must
@@ -93,5 +96,10 @@
                 BuiltinType.ASTRING, BuiltinType.ASTRING }, new String[] { "DataverseName", "Name" }, 0,
                 MetadataRecordTypes.DATASOURCE_ADAPTER_RECORDTYPE, DATASOURCE_ADAPTER_DATASET_ID, true, new int[] { 0,
                         1 });
+
+        LIBRARY_DATASET = new MetadataIndex("Library", null, 3,
+                new IAType[] { BuiltinType.ASTRING, BuiltinType.ASTRING }, new String[] { "DataverseName", "Name" }, 0,
+                MetadataRecordTypes.LIBRARY_RECORDTYPE, LIBRARY_DATASET_ID, true, new int[] { 0, 1 });
+
     }
 }
\ No newline at end of file
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataRecordTypes.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataRecordTypes.java
index 50681ee..fd52aa3 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataRecordTypes.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/bootstrap/MetadataRecordTypes.java
@@ -47,6 +47,7 @@
     public static ARecordType NODEGROUP_RECORDTYPE;
     public static ARecordType FUNCTION_RECORDTYPE;
     public static ARecordType DATASOURCE_ADAPTER_RECORDTYPE;
+    public static ARecordType LIBRARY_RECORDTYPE;
 
     /**
      * Create all metadata record types.
@@ -76,6 +77,7 @@
             NODEGROUP_RECORDTYPE = createNodeGroupRecordType();
             FUNCTION_RECORDTYPE = createFunctionRecordType();
             DATASOURCE_ADAPTER_RECORDTYPE = createDatasourceAdapterRecordType();
+            LIBRARY_RECORDTYPE = createLibraryRecordType();
         } catch (AsterixException e) {
             throw new MetadataException(e);
         }
@@ -357,4 +359,13 @@
         return new ARecordType("DatasourceAdapterRecordType", fieldNames, fieldTypes, true);
     }
 
+    public static final int LIBRARY_ARECORD_DATAVERSENAME_FIELD_INDEX = 0;
+    public static final int LIBRARY_ARECORD_NAME_FIELD_INDEX = 1;
+    public static final int LIBRARY_ARECORD_TIMESTAMP_FIELD_INDEX = 2;
+
+    private static ARecordType createLibraryRecordType() throws AsterixException {
+        String[] fieldNames = { "DataverseName", "Name", "Timestamp" };
+        IAType[] fieldTypes = { BuiltinType.ASTRING, BuiltinType.ASTRING, BuiltinType.ASTRING };
+        return new ARecordType("LibraryRecordType", fieldNames, fieldTypes, true);
+    }
 }
\ No newline at end of file
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/DatasourceAdapter.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/DatasourceAdapter.java
index 2955a08..c360b9f 100644
--- a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/DatasourceAdapter.java
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/DatasourceAdapter.java
@@ -20,6 +20,8 @@
 
 public class DatasourceAdapter implements IMetadataEntity {
 
+    private static final long serialVersionUID = 1L;
+
     public enum AdapterType {
         INTERNAL,
         EXTERNAL
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Library.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Library.java
new file mode 100644
index 0000000..a341ba9
--- /dev/null
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entities/Library.java
@@ -0,0 +1,36 @@
+package edu.uci.ics.asterix.metadata.entities;
+
+import edu.uci.ics.asterix.metadata.MetadataCache;
+import edu.uci.ics.asterix.metadata.api.IMetadataEntity;
+
+public class Library implements IMetadataEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String dataverse;
+    private final String name;
+
+    public Library(String dataverseName, String libraryName) {
+        this.dataverse = dataverseName;
+        this.name = libraryName;
+    }
+
+    public String getDataverseName() {
+        return dataverse;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Object addToCache(MetadataCache cache) {
+        return cache.addLibraryIfNotExists(this);
+    }
+
+    @Override
+    public Object dropFromCache(MetadataCache cache) {
+        return cache.dropLibrary(this);
+    }
+
+}
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entitytupletranslators/LibraryTupleTranslator.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entitytupletranslators/LibraryTupleTranslator.java
new file mode 100644
index 0000000..4bd2366
--- /dev/null
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/entitytupletranslators/LibraryTupleTranslator.java
@@ -0,0 +1,120 @@
+/*
+ * 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.metadata.entitytupletranslators;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.Calendar;
+
+import edu.uci.ics.asterix.common.exceptions.AsterixException;
+import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
+import edu.uci.ics.asterix.metadata.MetadataException;
+import edu.uci.ics.asterix.metadata.bootstrap.MetadataPrimaryIndexes;
+import edu.uci.ics.asterix.metadata.bootstrap.MetadataRecordTypes;
+import edu.uci.ics.asterix.metadata.entities.Library;
+import edu.uci.ics.asterix.om.base.ARecord;
+import edu.uci.ics.asterix.om.base.AString;
+import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
+
+/**
+ * Translates a Library metadata entity to an ITupleReference and vice versa.
+ */
+public class LibraryTupleTranslator extends AbstractTupleTranslator<Library> {
+    // Field indexes of serialized Library in a tuple.
+    // First key field.
+    public static final int LIBRARY_DATAVERSENAME_TUPLE_FIELD_INDEX = 0;
+    // Second key field.
+    public static final int LIBRARY_NAME_TUPLE_FIELD_INDEX = 1;
+
+    // Payload field containing serialized Library.
+    public static final int LIBRARY_PAYLOAD_TUPLE_FIELD_INDEX = 2;
+
+    @SuppressWarnings("unchecked")
+    private ISerializerDeserializer<ARecord> recordSerDes = AqlSerializerDeserializerProvider.INSTANCE
+            .getSerializerDeserializer(MetadataRecordTypes.LIBRARY_RECORDTYPE);
+
+    public LibraryTupleTranslator(boolean getTuple) {
+        super(getTuple, MetadataPrimaryIndexes.LIBRARY_DATASET.getFieldCount());
+    }
+
+    @Override
+    public Library getMetadataEntytiFromTuple(ITupleReference frameTuple) throws IOException {
+        byte[] serRecord = frameTuple.getFieldData(LIBRARY_PAYLOAD_TUPLE_FIELD_INDEX);
+        int recordStartOffset = frameTuple.getFieldStart(LIBRARY_PAYLOAD_TUPLE_FIELD_INDEX);
+        int recordLength = frameTuple.getFieldLength(LIBRARY_PAYLOAD_TUPLE_FIELD_INDEX);
+        ByteArrayInputStream stream = new ByteArrayInputStream(serRecord, recordStartOffset, recordLength);
+        DataInput in = new DataInputStream(stream);
+        ARecord libraryRecord = (ARecord) recordSerDes.deserialize(in);
+        return createLibraryFromARecord(libraryRecord);
+    }
+
+    private Library createLibraryFromARecord(ARecord libraryRecord) {
+        String dataverseName = ((AString) libraryRecord
+                .getValueByPos(MetadataRecordTypes.LIBRARY_ARECORD_DATAVERSENAME_FIELD_INDEX)).getStringValue();
+        String libraryName = ((AString) libraryRecord
+                .getValueByPos(MetadataRecordTypes.LIBRARY_ARECORD_NAME_FIELD_INDEX)).getStringValue();
+
+        return new Library(dataverseName, libraryName);
+    }
+
+    @Override
+    public ITupleReference getTupleFromMetadataEntity(Library library) throws IOException, MetadataException {
+        // write the key in the first 2 fields of the tuple
+        tupleBuilder.reset();
+        aString.setValue(library.getDataverseName());
+        stringSerde.serialize(aString, tupleBuilder.getDataOutput());
+        tupleBuilder.addFieldEndOffset();
+        aString.setValue(library.getName());
+        stringSerde.serialize(aString, tupleBuilder.getDataOutput());
+        tupleBuilder.addFieldEndOffset();
+
+        // write the pay-load in the third field of the tuple
+
+        recordBuilder.reset(MetadataRecordTypes.LIBRARY_RECORDTYPE);
+
+        // write field 0
+        fieldValue.reset();
+        aString.setValue(library.getDataverseName());
+        stringSerde.serialize(aString, fieldValue.getDataOutput());
+        recordBuilder.addField(MetadataRecordTypes.LIBRARY_ARECORD_DATAVERSENAME_FIELD_INDEX, fieldValue);
+
+        // write field 1
+        fieldValue.reset();
+        aString.setValue(library.getName());
+        stringSerde.serialize(aString, fieldValue.getDataOutput());
+        recordBuilder.addField(MetadataRecordTypes.LIBRARY_ARECORD_NAME_FIELD_INDEX, fieldValue);
+
+        // write field 2
+        fieldValue.reset();
+        aString.setValue(Calendar.getInstance().getTime().toString());
+        stringSerde.serialize(aString, fieldValue.getDataOutput());
+        recordBuilder.addField(MetadataRecordTypes.LIBRARY_ARECORD_TIMESTAMP_FIELD_INDEX, fieldValue);
+
+        // write record
+        try {
+            recordBuilder.write(tupleBuilder.getDataOutput(), true);
+        } catch (AsterixException e) {
+            throw new MetadataException(e);
+        }
+        tupleBuilder.addFieldEndOffset();
+        tuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
+        return tuple;
+    }
+
+}
\ No newline at end of file
diff --git a/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/functions/ExternalFunctionCompilerUtil.java b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/functions/ExternalFunctionCompilerUtil.java
new file mode 100644
index 0000000..1ad791b
--- /dev/null
+++ b/asterix-metadata/src/main/java/edu/uci/ics/asterix/metadata/functions/ExternalFunctionCompilerUtil.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2009-2012 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.metadata.functions;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import edu.uci.ics.asterix.external.library.AsterixExternalScalarFunctionInfo;
+import edu.uci.ics.asterix.metadata.MetadataException;
+import edu.uci.ics.asterix.metadata.MetadataManager;
+import edu.uci.ics.asterix.metadata.MetadataTransactionContext;
+import edu.uci.ics.asterix.metadata.entities.Datatype;
+import edu.uci.ics.asterix.metadata.entities.Function;
+import edu.uci.ics.asterix.om.functions.AsterixFunction;
+import edu.uci.ics.asterix.om.typecomputer.base.IResultTypeComputer;
+import edu.uci.ics.asterix.om.typecomputer.impl.ADoubleTypeComputer;
+import edu.uci.ics.asterix.om.typecomputer.impl.AFloatTypeComputer;
+import edu.uci.ics.asterix.om.typecomputer.impl.AInt32TypeComputer;
+import edu.uci.ics.asterix.om.typecomputer.impl.AStringTypeComputer;
+import edu.uci.ics.asterix.om.types.AOrderedListType;
+import edu.uci.ics.asterix.om.types.AUnorderedListType;
+import edu.uci.ics.asterix.om.types.BuiltinType;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression.FunctionKind;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import edu.uci.ics.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
+import edu.uci.ics.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
+
+public class ExternalFunctionCompilerUtil implements Serializable {
+
+    private  static Pattern orderedListPattern = Pattern.compile("\\[*\\]");
+    private  static Pattern unorderedListPattern = Pattern.compile("[{{*}}]");
+
+  
+    public static IFunctionInfo getExternalFunctionInfo(MetadataTransactionContext txnCtx, Function function)
+            throws MetadataException {
+
+        String functionKind = function.getKind();
+        IFunctionInfo finfo = null;
+        if (FunctionKind.SCALAR.toString().equalsIgnoreCase(functionKind)) {
+            finfo = getScalarFunctionInfo(txnCtx, function);
+        } else if (FunctionKind.AGGREGATE.toString().equalsIgnoreCase(functionKind)) {
+            finfo = getAggregateFunctionInfo(txnCtx, function);
+        } else if (FunctionKind.STATEFUL.toString().equalsIgnoreCase(functionKind)) {
+            finfo = getStatefulFunctionInfo(txnCtx, function);
+        } else if (FunctionKind.UNNEST.toString().equalsIgnoreCase(functionKind)) {
+            finfo = getUnnestFunctionInfo(txnCtx, function);
+        }
+        return finfo;
+    }
+
+    private static IFunctionInfo getScalarFunctionInfo(MetadataTransactionContext txnCtx, Function function)
+            throws MetadataException {
+        FunctionIdentifier fid = new FunctionIdentifier(function.getDataverseName(), function.getName(),
+                function.getArity());
+        IResultTypeComputer typeComputer = getResultTypeComputer(txnCtx, function);
+        List<IAType> arguments = new ArrayList<IAType>();
+        IAType returnType = null;
+        List<String> paramTypes = function.getParams();
+        for (String paramType : paramTypes) {
+            arguments.add(getTypeInfo(paramType, txnCtx, function));
+        }
+
+        returnType = getTypeInfo(function.getReturnType(), txnCtx, function);
+
+        AsterixExternalScalarFunctionInfo scalarFunctionInfo = new AsterixExternalScalarFunctionInfo(
+                fid.getNamespace(), new AsterixFunction(fid.getName(), fid.getArity()), returnType,
+                function.getFunctionBody(), function.getLanguage(), arguments, typeComputer);
+        return scalarFunctionInfo;
+    }
+
+    private static IAType getTypeInfo(String paramType, MetadataTransactionContext txnCtx, Function function)
+            throws MetadataException {
+        if (paramType.equalsIgnoreCase(BuiltinType.AINT32.getDisplayName())) {
+            return (BuiltinType.AINT32);
+        } else if (paramType.equalsIgnoreCase(BuiltinType.AFLOAT.getDisplayName())) {
+            return (BuiltinType.AFLOAT);
+        } else if (paramType.equalsIgnoreCase(BuiltinType.ASTRING.getDisplayName())) {
+            return (BuiltinType.ASTRING);
+        } else if (paramType.equalsIgnoreCase(BuiltinType.ADOUBLE.getDisplayName())) {
+            return (BuiltinType.ADOUBLE);
+        } else {
+            IAType collection = getCollectionType(paramType, txnCtx, function);
+            if (collection != null) {
+                return collection;
+            } else {
+                Datatype datatype;
+                datatype = MetadataManager.INSTANCE.getDatatype(txnCtx, function.getDataverseName(), paramType);
+                if (datatype == null) {
+                    throw new MetadataException(" Type " + paramType + " not defined");
+                }
+                return (datatype.getDatatype());
+            }
+        }
+    }
+
+    private static IAType getCollectionType(String paramType, MetadataTransactionContext txnCtx, Function function)
+            throws MetadataException {
+
+        Matcher matcher = orderedListPattern.matcher(paramType);
+        if (matcher.find()) {
+            String subType = paramType.substring(paramType.indexOf('[') + 1, paramType.lastIndexOf(']'));
+            return new AOrderedListType(getTypeInfo(subType, txnCtx, function), "AOrderedList");
+        } else {
+            matcher = unorderedListPattern.matcher(paramType);
+            if (matcher.find()) {
+                String subType = paramType.substring(paramType.indexOf("{{") + 2, paramType.lastIndexOf("}}"));
+                return new AUnorderedListType(getTypeInfo(subType, txnCtx, function), "AUnorderedList");
+            }
+        }
+        return null;
+    }
+
+    private static IResultTypeComputer getResultTypeComputer(final MetadataTransactionContext txnCtx,
+            final Function function) throws MetadataException {
+
+        final IAType type = getTypeInfo(function.getReturnType(), txnCtx, function);
+        switch (type.getTypeTag()) {
+            case INT32:
+                return AInt32TypeComputer.INSTANCE;
+            case FLOAT:
+                return AFloatTypeComputer.INSTANCE;
+            case DOUBLE:
+                return ADoubleTypeComputer.INSTANCE;
+            case STRING:
+                return AStringTypeComputer.INSTANCE;
+            case ORDEREDLIST:
+                return new IResultTypeComputer() {
+                    @Override
+                    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+                            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
+
+                        return new AOrderedListType(((AOrderedListType) type).getItemType(), ((AOrderedListType) type)
+                                .getItemType().getTypeName());
+                    }
+
+                };
+            case UNORDEREDLIST:
+                return new IResultTypeComputer() {
+                    @Override
+                    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+                            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
+
+                        return new AUnorderedListType(type, type.getTypeName());
+                    }
+
+                };
+            default:
+                IResultTypeComputer typeComputer = new IResultTypeComputer() {
+                    @Override
+                    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+                            IMetadataProvider<?, ?> mp) throws AlgebricksException {
+                        return type;
+                    }
+                };
+                return typeComputer;
+        }
+
+    }
+
+    private static IAType getType(Function function, MetadataTransactionContext txnCtx) throws AlgebricksException {
+        IAType collectionType = null;
+        try {
+            collectionType = getCollectionType(function.getReturnType(), txnCtx, function);
+            if (collectionType != null) {
+                return collectionType;
+            } else {
+
+                Datatype datatype;
+                datatype = MetadataManager.INSTANCE.getDatatype(txnCtx, function.getDataverseName(),
+                        function.getReturnType());
+                return datatype.getDatatype();
+            }
+        } catch (MetadataException me) {
+            throw new AlgebricksException(me);
+        }
+    }
+
+    private static IFunctionInfo getUnnestFunctionInfo(MetadataTransactionContext txnCtx, Function function) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    private static IFunctionInfo getStatefulFunctionInfo(MetadataTransactionContext txnCtx, Function function) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    private static IFunctionInfo getAggregateFunctionInfo(MetadataTransactionContext txnCtx, Function function) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+    
+    public static void main(String args[]) throws FileNotFoundException, IOException {
+        ExternalFunctionCompilerUtil obj = new ExternalFunctionCompilerUtil();
+        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/tmp/ecu.obj"));
+        oos.writeObject(obj);
+    }
+
+}
\ No newline at end of file
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/common/AqlExpressionTypeComputer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/common/AqlExpressionTypeComputer.java
index 7448a9d..8ddbd99 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/common/AqlExpressionTypeComputer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/dataflow/data/common/AqlExpressionTypeComputer.java
@@ -5,6 +5,7 @@
 
 import edu.uci.ics.asterix.om.constants.AsterixConstantValue;
 import edu.uci.ics.asterix.om.functions.AsterixBuiltinFunctions;
+import edu.uci.ics.asterix.om.functions.AsterixExternalFunctionInfo;
 import edu.uci.ics.asterix.om.typecomputer.base.IResultTypeComputer;
 import edu.uci.ics.asterix.om.types.AUnionType;
 import edu.uci.ics.asterix.om.types.BuiltinType;
@@ -58,8 +59,13 @@
             unionList.add(BuiltinType.ABOOLEAN);
             return new AUnionType(unionList, "OptionalBoolean");
         }
-        // Note: only builtin functions, for now.
-        IResultTypeComputer rtc = AsterixBuiltinFunctions.getResultTypeComputer(fi);
+        // Note: built-in functions + udfs
+        IResultTypeComputer rtc = null;
+        if (AsterixBuiltinFunctions.isBuiltinCompilerFunction(fi)) {
+            rtc = AsterixBuiltinFunctions.getResultTypeComputer(fi);
+        } else {
+            rtc = ((AsterixExternalFunctionInfo) expr.getFunctionInfo()).getResultTypeComputer();
+        }
         if (rtc == null) {
             throw new AlgebricksException("Type computer missing for " + fi);
         }
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 3cad3be..cf00102 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
@@ -30,6 +30,7 @@
 import edu.uci.ics.asterix.om.typecomputer.impl.CastRecordResultTypeComputer;
 import edu.uci.ics.asterix.om.typecomputer.impl.ClosedRecordConstructorResultType;
 import edu.uci.ics.asterix.om.typecomputer.impl.FieldAccessByIndexResultType;
+import edu.uci.ics.asterix.om.typecomputer.impl.FlowRecordResultTypeComputer;
 import edu.uci.ics.asterix.om.typecomputer.impl.InjectFailureTypeComputer;
 import edu.uci.ics.asterix.om.typecomputer.impl.NonTaggedCollectionMemberResultType;
 import edu.uci.ics.asterix.om.typecomputer.impl.NonTaggedFieldAccessByNameResultType;
@@ -462,6 +463,8 @@
             "inject-failure", 2);
     public final static FunctionIdentifier CAST_RECORD = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
             "cast-record", 1);
+    public final static FunctionIdentifier FLOW_RECORD = new FunctionIdentifier(FunctionConstants.ASTERIX_NS,
+            "flow-record", 1);
 
     // Spatial and temporal type accessors
     public static final FunctionIdentifier ACCESSOR_TEMPORAL_YEAR = new FunctionIdentifier(
@@ -775,6 +778,7 @@
         add(REG_EXP, ABooleanTypeComputer.INSTANCE);
         add(INJECT_FAILURE, InjectFailureTypeComputer.INSTANCE);
         add(CAST_RECORD, CastRecordResultTypeComputer.INSTANCE);
+        add(FLOW_RECORD, FlowRecordResultTypeComputer.INSTANCE);
 
         add(TID, AInt32TypeComputer.INSTANCE);
         add(TIME_CONSTRUCTOR, OptionalATimeTypeComputer.INSTANCE);
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixFunctionInfo.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixFunctionInfo.java
index 4655c37..06d2c39 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixFunctionInfo.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/functions/AsterixFunctionInfo.java
@@ -14,11 +14,13 @@
  */
 package edu.uci.ics.asterix.om.functions;
 
+import java.io.Serializable;
+
 import edu.uci.ics.asterix.common.functions.FunctionSignature;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
 import edu.uci.ics.hyracks.algebricks.core.algebra.functions.IFunctionInfo;
 
-public class AsterixFunctionInfo implements IFunctionInfo {
+public class AsterixFunctionInfo implements IFunctionInfo, Serializable {
 
     private final FunctionIdentifier functionIdentifier;
 
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/base/IResultTypeComputer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/base/IResultTypeComputer.java
index e90da6b..d3f75d6 100644
--- a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/base/IResultTypeComputer.java
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/base/IResultTypeComputer.java
@@ -1,5 +1,6 @@
 package edu.uci.ics.asterix.om.typecomputer.base;
 
+import java.io.Serializable;
 
 import edu.uci.ics.asterix.om.types.IAType;
 import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
@@ -7,7 +8,7 @@
 import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
 import edu.uci.ics.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
 
-public interface IResultTypeComputer {
+public interface IResultTypeComputer extends Serializable {
     public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
             IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException;
 }
diff --git a/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java
new file mode 100644
index 0000000..a982a1f
--- /dev/null
+++ b/asterix-om/src/main/java/edu/uci/ics/asterix/om/typecomputer/impl/FlowRecordResultTypeComputer.java
@@ -0,0 +1,26 @@
+package edu.uci.ics.asterix.om.typecomputer.impl;
+
+import edu.uci.ics.asterix.om.typecomputer.base.IResultTypeComputer;
+import edu.uci.ics.asterix.om.typecomputer.base.TypeComputerUtilities;
+import edu.uci.ics.asterix.om.types.IAType;
+import edu.uci.ics.hyracks.algebricks.common.exceptions.AlgebricksException;
+import edu.uci.ics.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import edu.uci.ics.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
+import edu.uci.ics.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
+
+public class FlowRecordResultTypeComputer implements IResultTypeComputer {
+
+    public static final FlowRecordResultTypeComputer INSTANCE = new FlowRecordResultTypeComputer();
+
+    @Override
+    public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env,
+            IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException {
+        ScalarFunctionCallExpression funcExpr = (ScalarFunctionCallExpression) expression;
+        IAType type = TypeComputerUtilities.getRequiredType(funcExpr);
+        if (type == null) {
+            type = (IAType) env.getType(funcExpr.getArguments().get(0).getValue());
+        }
+        return type;
+    }
+}
diff --git a/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/FlowRecordDescriptor.java b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/FlowRecordDescriptor.java
new file mode 100644
index 0000000..81c23cd
--- /dev/null
+++ b/asterix-runtime/src/main/java/edu/uci/ics/asterix/runtime/evaluators/functions/FlowRecordDescriptor.java
@@ -0,0 +1,74 @@
+package edu.uci.ics.asterix.runtime.evaluators.functions;
+
+import java.io.DataOutput;
+
+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.pointables.PointableAllocator;
+import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
+import edu.uci.ics.asterix.om.types.ARecordType;
+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.data.std.api.IDataOutputProvider;
+import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
+import edu.uci.ics.hyracks.dataflow.common.data.accessors.IFrameTupleReference;
+
+public class FlowRecordDescriptor extends AbstractScalarFunctionDynamicDescriptor {
+
+    public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() {
+        public IFunctionDescriptor createFunctionDescriptor() {
+            return new FlowRecordDescriptor();
+        }
+    };
+
+    private static final long serialVersionUID = 1L;
+    private ARecordType inputType;
+
+    public void reset(ARecordType inputType) {
+        this.inputType = inputType;
+    }
+
+    @Override
+    public FunctionIdentifier getIdentifier() {
+        return AsterixBuiltinFunctions.FLOW_RECORD;
+    }
+
+    @Override
+    public ICopyEvaluatorFactory createEvaluatorFactory(final ICopyEvaluatorFactory[] args) {
+        final ICopyEvaluatorFactory recordEvalFactory = args[0];
+
+        return new ICopyEvaluatorFactory() {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public ICopyEvaluator createEvaluator(final IDataOutputProvider output) throws AlgebricksException {
+                final DataOutput out = output.getDataOutput();
+                final ArrayBackedValueStorage recordBuffer = new ArrayBackedValueStorage();
+                final ICopyEvaluator recEvaluator = recordEvalFactory.createEvaluator(recordBuffer);
+
+                return new ICopyEvaluator() {
+                    // pointable allocator
+                    private PointableAllocator allocator = new PointableAllocator();
+                    final IVisitablePointable recAccessor = allocator.allocateRecordValue(inputType);
+
+                    @Override
+                    public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {
+                        try {
+                            recordBuffer.reset();
+                            recEvaluator.evaluate(tuple);
+                            recAccessor.set(recordBuffer);
+                            out.write(recAccessor.getByteArray(), recAccessor.getStartOffset(), recAccessor.getLength());
+                        } catch (Exception ioe) {
+                            throw new AlgebricksException(ioe);
+                        }
+                    }
+                };
+            }
+        };
+    }
+
+}
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 84142be..6ec507b 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
@@ -67,6 +67,11 @@
 import edu.uci.ics.asterix.runtime.aggregates.std.SumAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.stream.EmptyStreamAggregateDescriptor;
 import edu.uci.ics.asterix.runtime.aggregates.stream.NonEmptyStreamAggregateDescriptor;
+import edu.uci.ics.asterix.runtime.evaluators.accessors.CircleCenterAccessor;
+import edu.uci.ics.asterix.runtime.evaluators.accessors.CircleRadiusAccessor;
+import edu.uci.ics.asterix.runtime.evaluators.accessors.LineRectanglePolygonAccessor;
+import edu.uci.ics.asterix.runtime.evaluators.accessors.PointXCoordinateAccessor;
+import edu.uci.ics.asterix.runtime.evaluators.accessors.PointYCoordinateAccessor;
 import edu.uci.ics.asterix.runtime.evaluators.accessors.TemporalDayAccessor;
 import edu.uci.ics.asterix.runtime.evaluators.accessors.TemporalHourAccessor;
 import edu.uci.ics.asterix.runtime.evaluators.accessors.TemporalIntervalEndAccessor;
@@ -76,11 +81,6 @@
 import edu.uci.ics.asterix.runtime.evaluators.accessors.TemporalMonthAccessor;
 import edu.uci.ics.asterix.runtime.evaluators.accessors.TemporalSecondAccessor;
 import edu.uci.ics.asterix.runtime.evaluators.accessors.TemporalYearAccessor;
-import edu.uci.ics.asterix.runtime.evaluators.accessors.CircleCenterAccessor;
-import edu.uci.ics.asterix.runtime.evaluators.accessors.CircleRadiusAccessor;
-import edu.uci.ics.asterix.runtime.evaluators.accessors.LineRectanglePolygonAccessor;
-import edu.uci.ics.asterix.runtime.evaluators.accessors.PointXCoordinateAccessor;
-import edu.uci.ics.asterix.runtime.evaluators.accessors.PointYCoordinateAccessor;
 import edu.uci.ics.asterix.runtime.evaluators.common.CreateMBREvalFactory;
 import edu.uci.ics.asterix.runtime.evaluators.common.FieldAccessByIndexEvalFactory;
 import edu.uci.ics.asterix.runtime.evaluators.common.FunctionManagerImpl;
@@ -131,6 +131,7 @@
 import edu.uci.ics.asterix.runtime.evaluators.functions.EndsWithDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.FieldAccessByIndexDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.FieldAccessByNameDescriptor;
+import edu.uci.ics.asterix.runtime.evaluators.functions.FlowRecordDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.FuzzyEqDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.GetItemDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.GramTokensDescriptor;
@@ -170,10 +171,6 @@
 import edu.uci.ics.asterix.runtime.evaluators.functions.SpatialDistanceDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.SpatialIntersectDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.StartsWithDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.functions.SubstringDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.functions.SwitchCaseDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.functions.UnorderedListConstructorDescriptor;
-import edu.uci.ics.asterix.runtime.evaluators.functions.WordTokensDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.StringConcatDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.StringEndWithDescrtiptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.StringEqualDescriptor;
@@ -189,6 +186,10 @@
 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;
+import edu.uci.ics.asterix.runtime.evaluators.functions.SubstringDescriptor;
+import edu.uci.ics.asterix.runtime.evaluators.functions.SwitchCaseDescriptor;
+import edu.uci.ics.asterix.runtime.evaluators.functions.UnorderedListConstructorDescriptor;
+import edu.uci.ics.asterix.runtime.evaluators.functions.WordTokensDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.AddDateDurationDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.AddDatetimeDurationDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.AddTimeDurationDescriptor;
@@ -222,6 +223,7 @@
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.IntervalOverlapsDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.IntervalStartedByDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.IntervalStartsDescriptor;
+import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.OverlapDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.SubtractDateDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.SubtractDatetimeDescriptor;
 import edu.uci.ics.asterix.runtime.evaluators.functions.temporal.SubtractTimeDescriptor;
@@ -463,6 +465,7 @@
         temp.add(RegExpDescriptor.FACTORY);
         temp.add(InjectFailureDescriptor.FACTORY);
         temp.add(CastRecordDescriptor.FACTORY);
+        temp.add(FlowRecordDescriptor.FACTORY);
         temp.add(NotNullDescriptor.FACTORY);
 
         // Spatial and temporal type accessors
@@ -693,6 +696,10 @@
             ARecordType it = (ARecordType) TypeComputerUtilities.getInputType((AbstractFunctionCallExpression) expr);
             ((CastRecordDescriptor) fd).reset(rt, it);
         }
+        if (fd.getIdentifier().equals(AsterixBuiltinFunctions.FLOW_RECORD)) {
+            ARecordType it = (ARecordType) TypeComputerUtilities.getInputType((AbstractFunctionCallExpression) expr);
+            ((FlowRecordDescriptor) fd).reset(it);
+        }
         if (fd.getIdentifier().equals(AsterixBuiltinFunctions.OPEN_RECORD_CONSTRUCTOR)) {
             ARecordType rt = (ARecordType) context.getType(expr);
             ((OpenRecordConstructorDescriptor) fd).reset(rt,