using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Runtime;
using System.Collections;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Specialized;
using System.Configuration;
using System.Text.RegularExpressions;
using System.IO;
namespace SubSonic.CodeGenerator
{
[Serializable]
public class Template
{
private string projectDirectory = string.Empty;
public string ProjectDirectory
{
get
{
projectDirectory = String.IsNullOrEmpty(projectDirectory) ? Directory.GetCurrentDirectory() : projectDirectory;
return projectDirectory;
}
set { projectDirectory = value; }
}
private ICodeLanguage language = new CSharpCodeLanguage();
public ICodeLanguage Language
{
get { return language; }
set { language = value; }
}
//no empty templates :)
private Template()
{
}
public Template(string input)
{
Input = input;
Using_Libraries = GetUsings();
}
private string _Using_Libraries;
public string Using_Libraries
{
get { return _Using_Libraries; }
set { _Using_Libraries = value; }
}
public static ArrayList References
{
get { return GetReferences(); }
}
private bool _IsSuccessful;
public bool IsSuccessful
{
get { return _IsSuccessful; }
set { _IsSuccessful = value; }
}
private string _Input;
public string Input
{
get { return _Input; }
set { _Input = value; }
}
private string _GeneratedCode;
public string GeneratedCode
{
get { return _GeneratedCode; }
set { _GeneratedCode = value; }
}
private string _Output;
public string Output
{
get { return _Output; }
set { _Output = value; }
}
private string _Error;
public string Error
{
get { return _Error; }
set { _Error = value; }
}
private Exception _InnerException;
[XmlIgnore]
public Exception InnerException
{
get { return _InnerException; }
set { _InnerException = value; }
}
private static string GetUsings()
{
StringBuilder sbUsings = new StringBuilder();
sbUsings.AppendLine("using System;");
sbUsings.AppendLine("using System.Text.RegularExpressions;");
sbUsings.AppendLine("using System.Collections;");
sbUsings.AppendLine("using System.IO;");
sbUsings.AppendLine("using System.Text;");
sbUsings.AppendLine("using SubSonic;");
sbUsings.AppendLine("using SubSonic.CodeGenerator;");
sbUsings.AppendLine("using System.Data;");
sbUsings.AppendLine("using System.Configuration;");
sbUsings.AppendLine("using SubSonic.Utilities;");
return sbUsings.ToString();
}
private static ArrayList GetReferences()
{
ArrayList referenceList = new ArrayList();
referenceList.Add("System.dll");
referenceList.Add("System.Data.dll");
referenceList.Add("System.Drawing.dll");
referenceList.Add("System.Xml.dll");
referenceList.Add("System.Windows.Forms.dll");
referenceList.Add("System.Configuration.dll");
Utilities.Utility.WriteTrace("Setting references");
//find out where the dll is
string subSonicLoc = typeof(Template).Assembly.Location;
referenceList.Add(subSonicLoc);
Utilities.Utility.WriteTrace("Loading SubSonic.dll from " + subSonicLoc);
return referenceList;
}
#region Rendering
public string Render()
{
//parse it
Parse();
//compile it
return Generate();
}
#endregion
#region GenerateOutput specific functions
private string Generate()
{
//string result;
IsSuccessful = true;
ICodeLanguage iLanguage = new CSharpCodeLanguage();
//string entry = "Render";
string code = GeneratedCode.Trim();
if (String.IsNullOrEmpty(code))
{
return string.Empty;
}
CompileEngine engine = new CompileEngine(code, iLanguage, "Render");
engine.References = References;
engine.Run();
Output = engine.OutputText;
return Output;
//result = engine.OutputText;
//return result;
}
private void Parse()
{
Input = Input + "<%%>";
GeneratedCode = GetParsedResult();
IsSuccessful = true;
}
public static string LoadTextFromManifest(string templateFileName)
{
string templateText = null;
Assembly asm = Assembly.GetExecutingAssembly();
Stream stream = asm.GetManifestResourceStream("SubSonic.CodeGeneration.Templates." + templateFileName);
if (stream != null)
{
StreamReader sReader = new StreamReader(stream);
templateText = sReader.ReadToEnd();
sReader.Close();
}
return templateText;
}
private string GetParsedResult()
{
string modifiedcode = GetCodeWithoutAssemblyNameSpacePropertyAndOther();
StringBuilder finalcode = new StringBuilder(Using_Libraries);
//string finalcode = Using_Libraries +
finalcode.Append(
@"
namespace SubSonic.CodeGenerator
{
/// <summary>
/// Summary description for ParseManager.
/// </summary>
public class Parser
{
public Parser()
{
//
// TODO: Add constructor logic here
//
}
public static void Main()
{
}
public static string Render()
{
MemoryStream mStream = new MemoryStream();
StreamWriter writer = new StreamWriter(mStream,System.Text.Encoding.UTF8);
#:::#RenderMethod#:::#
//
StreamReader sr = new StreamReader(mStream);
writer.Flush();
mStream.Position = 0;
string returndata = sr.ReadToEnd();
return returndata;
}
}
}"
);
return Utilities.Utility.FastReplace(finalcode.ToString(), "#:::#RenderMethod#:::#", modifiedcode, StringComparison.InvariantCultureIgnoreCase);
//finalcode = Regex.Replace(finalcode, "#:::#RenderMethod#:::#", modifiedcode);
//return finalcode;
}
private string GetCodeWithoutAssemblyNameSpacePropertyAndOther()
{
string tempcode = Input;
//Modify this part if you want to read the <%@ tags also you can implement your own tags here.
tempcode = Regex.Replace(tempcode, "(?i)<%@\\s*Property.*?%>", string.Empty);
tempcode = Regex.Replace(tempcode, "(?i)<%@\\s*Assembly.*?%>", string.Empty);
tempcode = Regex.Replace(tempcode, "(?i)<%@\\s*Import.*?%>", string.Empty);
tempcode = Regex.Replace(tempcode, "(?i)<%@\\s*CodeTemplate.*?%>", string.Empty);
tempcode = ParseScript(tempcode);
tempcode = Regex.Replace(tempcode, @"<%=.*?%>", new MatchEvaluator(RefineCalls), RegexOptions.Singleline);
tempcode = Regex.Replace(tempcode, @"<%%>", string.Empty, RegexOptions.Singleline);
tempcode = Regex.Replace(tempcode, @"<%[^=|@].*?%>", new MatchEvaluator(RefineCodeTag), RegexOptions.Singleline);
//see if there's an @Page directive
Regex regLang = new Regex(@"<%@.*?Language=.*?%>");
Match pageDirMatch = regLang.Match(tempcode);
if (pageDirMatch != null)
{
//there's a language directive
string directive = pageDirMatch.Value;
if (directive.ToLower().Contains("vb"))
{
language = new VBCodeLanguage();
}
}
//strip the directive
tempcode = Regex.Replace(tempcode, "(?i)<%@\\s*Page.*?%>", string.Empty);
return tempcode;
}
private static string RefineCalls(Match m)
{
// Get the matched string.
string x = m.ToString();
// If the first char is lower case...
x = Regex.Replace(x, "<%=", "\t\t\twriter.Write(");
x = Regex.Replace(x, "%>", ");");
return x;
}
private static string RefineCodeTag(Match m)
{
// Get the matched string.
string x = m.ToString();
// If the first char is lower case...
x = x.Substring(2, x.Length - 4);
x = "\t\t\t" + x;
return x;
}
private static string ParseScript(string lcCode)
{
if (lcCode == null)
{
return "";
}
MemoryStream mStream = new MemoryStream();
StreamWriter writer = new StreamWriter(mStream, System.Text.Encoding.UTF8);
int lnLast = 0;
int lnAt = lcCode.IndexOf("<%", 0);
if (lnAt == -1)
{
return lcCode;
}
while (lnAt > -1)
{
if (lnAt > -1)
{
// *** Catch the plain text write out to the Response Stream as is - fix up for quotes
writer.Write("\t\t\twriter.Write(@\"" + lcCode.Substring(lnLast, lnAt - lnLast).Replace("\"", "\"\"") + "\" );");
}
//*** Find end tag
int lnAt2 = lcCode.IndexOf("%>", lnAt);
if (lnAt2 < 0)
{
break;
}
writer.Write(lcCode.Substring(lnAt, lnAt2 - lnAt + 2));
lnLast = lnAt2 + 2;
lnAt = lcCode.IndexOf("<%", lnLast);
if (lnAt < 0)
{
// *** Write out the final block of non-code text
writer.Write("\t\t\twriter.Write(@\"" + lcCode.Substring(lnLast, lcCode.Length - lnLast).Replace("\"", "\"\"") + "\" );");
}
}
writer.Flush();
mStream.Position = 0;
StreamReader sr = new StreamReader(mStream);
string returndata = sr.ReadToEnd();
return returndata;
}
#endregion
}
}