Support for hints in create dataset statement. 

ASTERIX allows user to give additional information in form of hints. 
These hints can come handy in scenarios such as determining other parameters like the size of bloom filter to hold data. 

To begin with, the onyl hint supported by Asterix is the 'CARDINALITY' hint.
CARDINALITY gives the expected number of tuples in the dataset.

An example create dataset statement that provides hints is given below:-

create dataset X(TypeY)
partitioned by key id 
hints (CARDINALITY=2500);

Please note that hints are case-insensitive. 

Test Cases:-
Positive
asterix-app/src/test/resources/metadata/queries/basic/issue_251_dataset_hint_1.aql
asterix-app/src/test/resources/metadata/queries/basic/issue_251_dataset_hint_2.aql
asterix-app/src/test/resources/metadata/queries/basic/issue_251_dataset_hint_3.aql
asterix-app/src/test/resources/metadata/queries/basic/issue_251_dataset_hint_4.aql

Negative
asterix-app/src/test/resources/metadata/queries/exception/issue_251_dataset_hint_error_1.aql
asterix-app/src/test/resources/metadata/queries/exception/issue_251_dataset_hint_error_2.aql


git-svn-id: https://asterixdb.googlecode.com/svn/branches/asterix_stabilization_issue_251@1105 eaa15691-b419-025a-1212-ee371bd00084
diff --git a/asterix-aql/src/main/javacc/AQL.jj b/asterix-aql/src/main/javacc/AQL.jj
index 8672fd1..fd5aaaa 100644
--- a/asterix-aql/src/main/javacc/AQL.jj
+++ b/asterix-aql/src/main/javacc/AQL.jj
@@ -669,7 +669,8 @@
   String nameComponentSecond = null;
   boolean ifNotExists = false;
   IDatasetDetailsDecl datasetDetails = null;
-  Pair<Identifier,Identifier> nameComponents = null;	
+  Pair<Identifier,Identifier> nameComponents = null;
+  Map<String,String> hints = new HashMap<String,String>();	
 }
 {
   {
@@ -701,11 +702,19 @@
       else if(datasetType == DatasetType.FEED) {
       	datasetDetails = FeedDatasetDeclaration();
       }
-      dd = new DatasetDecl(dataverseName, datasetName, itemTypeName, datasetType, datasetDetails,ifNotExists);
-      
   }
+  
+  (
+  "hints"
   {
-    return dd;
+      initProperties(hints);
+  }
+  )?
+   ";"
+ 
+  {
+   dd = new DatasetDecl(dataverseName, datasetName, itemTypeName, hints, datasetType, datasetDetails,ifNotExists);
+   return dd;
   }
 }
 
@@ -733,7 +742,7 @@
         nodeGroupName = new Identifier(token.image);
     }
   )?
-  ";"
+  
   {
     idd = new InternalDetailsDecl(nodeGroupName, partitioningExprs);
     return idd;
@@ -767,7 +776,6 @@
 		  edd.setAdapter(adapterClassname);
    		  edd.setProperties(properties);
     } 
-  ";"
  
   {
     return edd;
@@ -833,7 +841,7 @@
     	nodeGroupName = new Identifier(token.image);
   }
   )?
-  ";"
+  
   {
     fdd = new FeedDetailsDecl(adapterFactoryClassname, properties, appliedFunction, nodeGroupName, partitioningExprs);
     return fdd;
@@ -923,6 +931,75 @@
      }
 }
 
+void initProperties(Map<String,String> properties)  throws ParseException :
+{
+	String key;
+	String value;
+}
+{
+    (
+      <LEFTPAREN>
+        (
+          <IDENTIFIER>
+          {
+            key = (new Identifier(token.image)).getValue();
+          }
+          "=" 
+          (
+            (<STRING_LITERAL>
+             {
+              value = removeQuotesAndEscapes(token.image);
+             }
+            ) |
+            (<INTEGER_LITERAL>
+             {
+             try{
+              value = "" + Integer.valueOf(token.image);
+              } catch (NumberFormatException nfe){
+                  throw new ParseException("inapproriate value: " + token.image); 
+              }
+             } 
+            )
+          )
+        {
+          properties.put(key, value);
+        }
+       ( 
+        "," 
+        (
+          <IDENTIFIER>
+          {
+            key = (new Identifier(token.image)).getValue();
+          }
+          "=" 
+          (
+           (<STRING_LITERAL>
+            {
+              value = removeQuotesAndEscapes(token.image);
+            }
+           ) |
+           (<INTEGER_LITERAL>
+            {
+              try{
+                value = "" + Integer.valueOf(token.image);
+              } catch (NumberFormatException nfe){
+              	throw new ParseException("inapproriate value: " + token.image); 
+              }
+            } 
+           )
+          ) 
+        )
+        {
+          properties.put(key, value);
+        }
+        
+       )*
+      )
+       <RIGHTPAREN>
+    )?
+}
+
+
 
 NodegroupDecl NodegroupDeclaration() throws ParseException :
 {