blob: 243b2deb2c11ea2c8f5826c30afac2bdca26b96b [file] [log] [blame]
#if FEATURE_XSLT
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Xsl;
namespace Lucene.Net.QueryParsers.Xml
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 at
*
* 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.
*/
/// <summary>
/// Provides utilities for turning query form input (such as from a web page or Swing gui) into
/// Lucene XML queries by using XSL templates. This approach offers a convenient way of externalizing
/// and changing how user input is turned into Lucene queries.
/// Database applications often adopt similar practices by externalizing SQL in template files that can
/// be easily changed/optimized by a DBA.
/// The static methods can be used on their own or by creating an instance of this class you can store and
/// re-use compiled stylesheets for fast use (e.g. in a server environment)
///
/// LUCENENET (.NET Core): This is not compiled this because .NET Standard
/// does not currently support XSL Transform.
/// </summary>
public class QueryTemplateManager
{
IDictionary<string, XslCompiledTransform> compiledTemplatesCache = new Dictionary<string, XslCompiledTransform>();
XslCompiledTransform defaultCompiledTemplates = null;
public QueryTemplateManager()
{
}
public QueryTemplateManager(Stream xslIs)
{
AddDefaultQueryTemplate(xslIs);
}
public virtual void AddDefaultQueryTemplate(Stream xslIs)
{
defaultCompiledTemplates = GetTemplates(xslIs);
}
public virtual void AddQueryTemplate(string name, Stream xslIs)
{
compiledTemplatesCache[name] = GetTemplates(xslIs);
}
public virtual string GetQueryAsXmlString(IDictionary<string, string> formProperties, string queryTemplateName)
{
XslCompiledTransform ts = compiledTemplatesCache[queryTemplateName];
return GetQueryAsXmlString(formProperties, ts);
}
public virtual XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties, string queryTemplateName)
{
XslCompiledTransform ts = compiledTemplatesCache[queryTemplateName];
return GetQueryAsDOM(formProperties, ts);
}
public virtual string GetQueryAsXmlString(IDictionary<string, string> formProperties)
{
return GetQueryAsXmlString(formProperties, defaultCompiledTemplates);
}
public virtual XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties)
{
return GetQueryAsDOM(formProperties, defaultCompiledTemplates);
}
/// <summary>
/// Fast means of constructing query using a precompiled stylesheet
/// </summary>
public static string GetQueryAsXmlString(IDictionary<string, string> formProperties, XslCompiledTransform template)
{
// TODO: Suppress XML header with encoding (as Strings have no encoding)
using (var stream = new MemoryStream())
{
TransformCriteria(formProperties, template, stream);
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
/// <summary>
/// Slow means of constructing query parsing a stylesheet from an input stream
/// </summary>
public static string GetQueryAsXmlString(IDictionary<string, string> formProperties, Stream xslIs)
{
// TODO: Suppress XML header with encoding (as Strings have no encoding)
using (var stream = new MemoryStream())
{
TransformCriteria(formProperties, xslIs, stream);
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
/// <summary>
/// Fast means of constructing query using a cached,precompiled stylesheet
/// </summary>
public static XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties, XslCompiledTransform template)
{
XmlDocument result = new XmlDocument();
using (var stream = new MemoryStream())
{
TransformCriteria(formProperties, template, stream);
stream.Position = 0;
result.Load(stream);
}
return result;
}
/// <summary>
/// Slow means of constructing query - parses stylesheet from input stream
/// </summary>
public static XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties, Stream xslIs)
{
XmlDocument result = new XmlDocument();
using (var stream = new MemoryStream())
{
TransformCriteria(formProperties, xslIs, stream);
stream.Position = 0;
result.Load(stream);
}
return result;
}
/// <summary>
/// Slower transformation using an uncompiled stylesheet (suitable for development environment)
/// </summary>
public static void TransformCriteria(IDictionary<string, string> formProperties, Stream xslIs, Stream result)
{
XmlDocument xslDoc = new XmlDocument();
xslDoc.Load(xslIs);
XslCompiledTransform transformer = new XslCompiledTransform();
transformer.Load(xslDoc);
TransformCriteria(formProperties, transformer, result);
}
/// <summary>
/// Fast transformation using a pre-compiled stylesheet (suitable for production environments)
/// </summary>
public static void TransformCriteria(IDictionary<string, string> formProperties, XslCompiledTransform transformer, Stream result)
{
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("Document");
doc.AppendChild(root);
foreach (var prop in formProperties)
{
string propName = prop.Key;
string value = prop.Value;
if ((value != null) && (value.Length > 0))
{
DOMUtils.InsertChild(root, propName, value);
}
}
transformer.Transform(doc, null, result);
}
/// <summary>
/// Parses a query stylesheet for repeated use
/// </summary>
public static XslCompiledTransform GetTemplates(Stream xslIs)
{
using (var reader = XmlReader.Create(xslIs))
{
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(reader);
return xslt;
}
}
}
}
#endif