diff --git a/Levante.sln b/Levante.sln
new file mode 100644
index 0000000..f677917
--- /dev/null
+++ b/Levante.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.30501.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Levante", "Levante\Levante.csproj", "{32A552B5-F2D0-4EB9-90E4-7A026C35AE67}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LevanteTestMVC", "LevanteTestMVC\LevanteTestMVC.csproj", "{0B7C0CC1-7750-4CCC-B12E-95DDF0136A0E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {32A552B5-F2D0-4EB9-90E4-7A026C35AE67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {32A552B5-F2D0-4EB9-90E4-7A026C35AE67}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {32A552B5-F2D0-4EB9-90E4-7A026C35AE67}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {32A552B5-F2D0-4EB9-90E4-7A026C35AE67}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0B7C0CC1-7750-4CCC-B12E-95DDF0136A0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0B7C0CC1-7750-4CCC-B12E-95DDF0136A0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0B7C0CC1-7750-4CCC-B12E-95DDF0136A0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0B7C0CC1-7750-4CCC-B12E-95DDF0136A0E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Levante.v12.suo b/Levante.v12.suo
new file mode 100644
index 0000000..2e73c8d
Binary files /dev/null and b/Levante.v12.suo differ
diff --git a/Levante/Calls.cs b/Levante/Calls.cs
new file mode 100644
index 0000000..fd8f66d
--- /dev/null
+++ b/Levante/Calls.cs
@@ -0,0 +1,501 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Reflection;
+using System.Text;
+
+namespace Levante
+{
+ ///
+ /// Class for the RESTful calls
+ /// All the methods are statics
+ ///
+ class Calls
+ {
+ // Name or IP Address of the Server to call
+ private static String _ServerName;
+ public String ServerName
+ {
+ get
+ {
+ return _ServerName;
+ }
+ set
+ {
+ _ServerName = value;
+ }
+ }
+
+ // Port Number of the Server to call
+ private static Int32? _ServerPort;
+ public Int32? ServerPort
+ {
+ get
+ {
+ return _ServerPort;
+ }
+ set
+ {
+ _ServerPort = value;
+ }
+ }
+
+ ///
+ /// Create a new connection to the database
+ ///
+ /// Datas for the connection to the database
+ /// Feedback of the operation
+ public static GenericResult ConnectToODB(parmConnection Connection)
+ {
+ try
+ {
+ GenericResult res = new GenericResult();
+ res.Code = ResultCode.OK;
+
+ try
+ {
+ String resStr = Utility.CallWS(Connection
+ , null
+ , "connect/" + Connection.DBName
+ , "GET") as String;
+ }
+ catch (Exception exc)
+ {
+ if (exc.Message.Contains("401"))
+ {
+ res.Code = ResultCode.AuthError;
+ res.Message = "Authentication Error: " + exc.Message;
+ }
+ else
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+ }
+
+ return res;
+ }
+ catch (Exception exc)
+ {
+ throw new Exception("ConnectToODB - " + exc.Message);
+ }
+ }
+
+ ///
+ /// Force disconnection from the database
+ ///
+ /// Datas for the connection to the database
+ /// Feedback of the operation
+ public static GenericResult DisconnectFromODB(parmConnection Connection)
+ {
+ try
+ {
+ GenericResult res = new GenericResult();
+ res.Code = ResultCode.OK;
+
+ // Disconnection doesn't need authentication
+ Connection.Authentication = null;
+
+ try
+ {
+ String resStr = Utility.CallWS(Connection
+ , null
+ , "disconnect"
+ , "GET") as String;
+ }
+ catch (Exception exc)
+ {
+ if (exc.Message.Contains("401"))
+ {
+ // I can expect a 401 error from certain browsers, I can ignore it
+ }
+ else
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+ }
+
+ return res;
+ }
+ catch (Exception exc)
+ {
+ throw new Exception("DisconnectFromODB - " + exc.Message);
+ }
+ }
+
+ ///
+ /// Get a document given its RID
+ ///
+ /// Expected class/type of the document
+ /// Datas for the connection to the database
+ /// Record Id
+ /// Document found
+ public static Object GetDocumentById(parmConnection Connection, String RID)
+ {
+ return Utility.CallWS(Connection
+ , null
+ , "document/" + Connection.DBName + "/" + RID
+ , "GET");
+ }
+
+ ///
+ /// Check if a document exists in the database
+ ///
+ /// Datas for the connection to the database
+ /// Record Id
+ /// True if the document exists
+ public static Boolean DocumentExists(parmConnection Connection, String RID)
+ {
+ // L'eccezione di record non trovato viene gestita ad un livello superiore
+ Utility.CallWS(Connection
+ , null
+ , "document/" + Connection.DBName + "/" + RID
+ , "HEAD");
+
+ return true;
+ }
+
+ ///
+ /// Given a Query (e.g.: SELECT) returns the result
+ ///
+ /// Expected class/type of the documents returned
+ /// Datas for the connection to the database
+ /// SQL command for the query
+ /// Limit number of the returned documents
+ /// Fetching level for the nested classes; N=maximum level specified, 0=current document, -1=all the levels, -2=excluded
+ /// List of the documents founded with the query
+ public static List Query(parmConnection Connection, String SqlQuery, Int32 Limit, Int32 FetchPlan)
+ {
+ QueryResult res = Utility.CallWS(Connection
+ , null
+ , "query/" + Connection.DBName + "/sql/" + SqlQuery + "/" + Limit + "/*:" + FetchPlan
+ , "GET") as QueryResult;
+
+ // I've to cast all the documents of the list
+ List listres = new List();
+ foreach (Object elem in res.Result)
+ {
+ T elem_casted = JsonHelper.DeserializeObjectFromString(elem.ToString());
+ listres.Add(elem_casted);
+ }
+
+ return listres;
+ }
+
+ ///
+ /// Execute a SQL Command (INSERT, UPDATE, DELETE)
+ ///
+ /// Expected class/type of the documents returned
+ /// Datas for the connection to the database
+ /// SQL command to execute
+ /// List of the documents affected by the command, or GenericResult of the exception
+ public static Object Command(parmConnection Connection, String SqlCommand)
+ {
+ GenericResult res = new GenericResult();
+ res.Code = ResultCode.OK;
+
+ try
+ {
+ QueryResult cmdres = Utility.CallWS(Connection
+ , SqlCommand
+ , "command/" + Connection.DBName + "/sql"
+ , "POST") as QueryResult;
+
+ // I've to cast all the documents of the list
+ List listres = new List();
+ foreach (Object elem in cmdres.Result)
+ {
+ T elem_casted = JsonHelper.DeserializeObjectFromString(elem.ToString());
+ listres.Add(elem_casted);
+ }
+
+ return listres;
+ }
+ catch (Exception exc)
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+
+ return res;
+ }
+
+ ///
+ /// Delete a document given its RID
+ ///
+ /// Datas for the connection to the database
+ /// Record Id
+ /// Feedback of the operation
+ public static GenericResult DeleteDocumentById(parmConnection Connection, String RID)
+ {
+ GenericResult res = new GenericResult();
+ res.Code = ResultCode.OK;
+
+ try
+ {
+ Utility.CallWS(Connection
+ , null
+ , "document/" + Connection.DBName + "/" + RID
+ , "DELETE");
+ }
+ catch (Exception exc)
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+
+ return res;
+ }
+
+ ///
+ /// Create a new document in the database for the specified class
+ ///
+ /// Expected class/type of the document to insert
+ /// Datas for the connection to the database
+ /// Document to insert in the database
+ /// Document created with its RID
+ /// Feedback of the operation
+ public static GenericResult InsertDocument(parmConnection Connection, T document, out T document_res)
+ {
+ GenericResult res = new GenericResult();
+ res.Code = ResultCode.OK;
+
+ document_res = document;
+
+ try
+ {
+ document_res = (T)Utility.CallWS(Connection
+ , JsonHelper.SerializeObjectToString(document)
+ , "document/" + Connection.DBName
+ , "POST");
+ }
+ catch (Exception exc)
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+
+ return res;
+ }
+ public static GenericResult InsertDocument(parmConnection Connection, T document)
+ {
+ T document_res = document;
+ return InsertDocument(Connection, document, out document_res);
+ }
+
+ ///
+ /// Update a specific document of the database
+ ///
+ /// Expected class/type of the document
+ /// Datas for the connection to the database
+ /// Document to update in the database with its RID
+ /// Document updated and returned
+ /// Could be a Full update or a Partial one
+ /// Feedback of the operation
+ public static GenericResult UpdateDocument(parmConnection Connection, T document, out T document_res, UpdateMode updatemode = UpdateMode.Full)
+ {
+ GenericResult res = new GenericResult();
+ res.Code = ResultCode.OK;
+
+ document_res = document;
+
+ try
+ {
+ // Reperisco l'Id dal parametro
+ PropertyInfo prop = document.GetType().GetProperty("Id");
+ if (prop == null)
+ {
+ res.Code = ResultCode.ParametersError;
+ res.Message = "'Id' property is missing";
+ return res;
+ }
+ String Id = prop.GetValue(document).ToString();
+ if (Id.StartsWith("#"))
+ Id = Id.Substring(1);
+
+ String updatemode_str = "full";
+ switch (updatemode)
+ {
+ case UpdateMode.Partial:
+ updatemode_str = "partial";
+ break;
+ }
+
+ document_res = (T)Utility.CallWS(Connection
+ , JsonHelper.SerializeObjectToString(document)
+ , "document/" + Connection.DBName + "/" + Id + "?updateMode=" + updatemode_str
+ , "PUT");
+ }
+ catch (Exception exc)
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+
+ return res;
+ }
+ public static GenericResult UpdateDocument(parmConnection Connection, T document, UpdateMode updatemode = UpdateMode.Full)
+ {
+ T document_res = document;
+ return UpdateDocument(Connection, document, out document_res, updatemode);
+ }
+
+ ///
+ /// Returns the list of the existing databases on the server specified
+ ///
+ /// Datas for the connection to the server
+ /// List of the databases names, or an error feedback
+ public static ListStringResult DatabasesList(parmConnection Connection)
+ {
+ ListStringResult res = new ListStringResult();
+ res.Code = ResultCode.OK;
+
+ try
+ {
+ DatabasesListResult dlres = Utility.CallWS(Connection
+ , null
+ , "listDatabases"
+ , "GET") as DatabasesListResult;
+ res.Result = dlres.Databases.ToList();
+ return res;
+ }
+ catch (Exception exc)
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+
+ return res;
+ }
+
+ ///
+ /// Returns the structure of the specified class
+ ///
+ /// Datas for the connection to the database
+ /// Name of the class
+ /// Structure of the class found, or an error feedback
+ public static ClassStructResult GetClass(parmConnection Connection, String Name)
+ {
+ ClassStructResult res = new ClassStructResult();
+ res.Code = ResultCode.OK;
+
+ try
+ {
+ res.Result = Utility.CallWS(Connection
+ , null
+ , "class/" + Connection.DBName + "/" + Name
+ , "GET") as ClassStruct;
+ }
+ catch (Exception exc)
+ {
+ res.Code = ResultCode.GenericError;
+ res.Message = exc.Message;
+ }
+
+ return res;
+ }
+
+ ///
+ /// SELECT statement of a DotQuery object
+ ///
+ /// Expected class/type of the documents returned
+ /// Datas for the connection to the database
+ /// Structures of the classes involved
+ /// SQL query for the FROM statement
+ /// SQL query for the WHERE statement
+ /// if 'true' returns all the field using the "*" char
+ /// List of documents returned from the query
+ public static List DotQuery_Select(Connection Connection, List ClassesStruct, String Qry_From, String Qry_Where = "", Boolean SelectAll = false)
+ {
+ String qry_select = "";
+
+ if (!SelectAll)
+ {
+ // Add to the SELECT query the RID of each class
+ foreach (ClassStruct classes_struct_elem in ClassesStruct)
+ {
+ if (qry_select != "")
+ qry_select += ", ";
+ qry_select += String.Format("@rid as {0}_rid", classes_struct_elem.Name);
+ }
+
+ // Get from the Type all the Properties of the Classes that are involved
+ foreach (PropertyInfo pi in (typeof(T)).GetProperties())
+ {
+ String qry_attrname = pi.Name;
+ if (pi.CustomAttributes.Any(ca => ca.AttributeType.Name == "JsonPropertyAttribute"))
+ {
+ CustomAttributeData attr = pi.CustomAttributes.First(ca => ca.AttributeType.Name == "JsonPropertyAttribute");
+ qry_attrname = attr.ConstructorArguments[0].Value.ToString();
+
+ // Check if the Class is involved and the Attribute exists, so I can add it to the SELECT statement
+ if (qry_attrname.Contains("."))
+ {
+ if (ClassesStruct.Any(cs => cs.Name == qry_attrname.Split('.')[0])
+ && ClassesStruct.Find(cs => cs.Name == qry_attrname.Split('.')[0])
+ .Properties.Any(p => p.Name == qry_attrname.Split('.')[1]))
+ {
+ if (qry_select != "")
+ qry_select += ", ";
+ qry_select += qry_attrname;
+ }
+ }
+ else
+ {
+ if (ClassesStruct.SelectMany(cs => cs.Properties).Any(p => p.Name == qry_attrname))
+ {
+ if (qry_select != "")
+ qry_select += ", ";
+ qry_select += qry_attrname;
+ }
+ }
+ }
+ }
+ }
+ else
+ qry_select = "*";
+ qry_select = "SELECT " + qry_select;
+
+ String qry_complete = qry_select + " " + Qry_From;
+ if (!String.IsNullOrEmpty(Qry_Where))
+ qry_complete += " " + Qry_Where;
+
+ return Connection.Query(qry_complete) as List;
+ }
+
+ ///
+ /// COUNT statement of a DotQuery object
+ ///
+ /// Datas for the connection to the database
+ /// SQL query for the FROM statement
+ /// SQL query for the WHERE statement
+ /// Total number of records returned from the complete query
+ public static Int32 DotQuery_Count(Connection Connection, String Qry_From, String Qry_Where = "")
+ {
+ String qry_complete = "SELECT COUNT(*) as Result " + Qry_From;
+ if (!String.IsNullOrEmpty(Qry_Where))
+ qry_complete += " " + Qry_Where;
+
+ List res = Connection.Query(qry_complete) as List;
+ return res[0].Result;
+ }
+
+ ///
+ /// Execute a transaction made of one or more operations
+ ///
+ /// Datas for the connection to the database
+ /// List of all the operations to execute with the transaction
+ public static void Transaction_Execute(Connection Connection, parmBatch ParmBatch)
+ {
+ if (ParmBatch != null && ParmBatch.Operations.Count > 0)
+ {
+ Utility.CallWS