using System; using System.IO; using System.Collections.Generic; using System.Text; using ln.templates.streams; using ln.templates.elements; namespace ln.templates { public class Template { public TemplateProvider Provider { get; private set; } public String SourceFilename { get; private set; } public String PseudoFilename { get; private set; } public DateTime SourceTimeStamp { get; private set; } public Element RootElement { get; private set; } public Expression FrameExpression { get; private set; } public Template(String sourceFilename) { SourceFilename = sourceFilename; PseudoFilename = sourceFilename; LoadSource(null); } public Template(String sourceFilename, TemplateProvider provider) { Provider = provider; SourceFilename = sourceFilename; PseudoFilename = sourceFilename; LoadSource(null); } public Template(String source,String pseudoFilename,TemplateProvider provider) { Provider = provider; PseudoFilename = pseudoFilename; LoadSource(source); } private void LoadSource(String source) { if (source == null) { using (FileStream fileStream = new FileStream(SourceFilename, FileMode.Open)) { byte[] loadBuffer = new byte[fileStream.Length]; fileStream.Read(loadBuffer, 0, loadBuffer.Length); fileStream.Close(); source = Encoding.UTF8.GetString(loadBuffer); SourceTimeStamp = File.GetLastWriteTimeUtc(SourceFilename); } } TemplateReader templateReader = new TemplateReader(source); RootElement = templateReader.RootElement; FrameExpression = templateReader.FrameExpression; } public String Generate() { return Generate(false); } public String Generate(bool unframed) { Context context = new Context(this); return Generate(context); } public String Generate(Context context) { return Generate(context, false); } public String Generate(Context context,bool unframed) { if (SourceFilename != null) { DateTime ts = File.GetLastWriteTimeUtc(SourceFilename); if (ts > SourceTimeStamp) LoadSource(null); } StringWriter writer = new StringWriter(); RootElement.Generate(writer, context); if (!unframed && (FrameExpression != null)) { Template frame = context.Provider.FindTemplate(FrameExpression.Evaluate(context.ExpressionContext) as string); if (frame == null) { throw new NullReferenceException(String.Format("FindTemplate() returned null for {0}",FrameExpression.Source)); } return frame.Generate(new Context(context, writer.ToString())); } return writer.ToString(); } public class Context { public Context Parent { get; } public Template Template { get; } public TemplateProvider Provider => Template.Provider; public String FramedContent { get; } public Expression.Context ExpressionContext { get; } public Context(Template template) { Template = template; ExpressionContext = new Expression.Context(null, null); ExpressionContext.AddMappedValue("__template__", template.SourceFilename); ExpressionContext.AddMappedValue("__provider__", template.Provider); } public Context(Context parent,String framedContent) { Parent = parent; Template = parent.Template; FramedContent = framedContent; ExpressionContext = new Expression.Context(parent.ExpressionContext); if (framedContent != null) ExpressionContext.SetMappedValue("__frame__", framedContent); } } } }