///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
namespace JetBrains.Omea.Tools.PropGen
{
class PropGen
{
private XmlDocument _doc = new XmlDocument();
private StreamWriter _writer;
private string _indent;
private string _prefix;
private string _defaultDataType;
private string _visibility;
private bool _ownerPlugin;
private int _indentLevel;
private readonly Dictionary _dataTypes = new Dictionary();
private readonly Dictionary _corePropTypes = new Dictionary();
///
/// The main entry point for the application.
///
[STAThread]
static void Main( string[] args )
{
if ( args.Length != 2 && args.Length != 3 )
{
Console.WriteLine( "Usage: PropGen [/interface] " );
return;
}
if ( args [0] == "/interface" )
{
new PropGen().GenerateInterface( args [1], args [2] );
}
else
{
new PropGen().Generate( args [0], args [1] );
}
}
public PropGen()
{
_dataTypes["Int"] = "int";
_dataTypes["String"] = "string";
_dataTypes["Date"] = "DateTime";
_dataTypes["Link"] = "IResource";
_dataTypes["Blob"] = "Stream";
_dataTypes["Double"] = "double";
_dataTypes["LongString"] = "string";
_dataTypes["Bool"] = "bool";
_corePropTypes["Name"] = "String";
_corePropTypes["Parent"] = "Link";
}
public void GenerateInterface( string xmlName, string csName )
{
_doc.Load( xmlName );
_writer = new StreamWriter( csName );
_writer.WriteLine("// DO NOT EDIT!!!");
_writer.WriteLine("// This file was autogenerated by the PropGen utility from the {0} schema file on {1}.", xmlName, DateTime.Now.ToString("s"));
_writer.WriteLine();
//_writer.WriteLine( "using System;" );
//_writer.WriteLine();
XmlElement interfaceElement = (XmlElement) _doc.SelectSingleNode( "/props/interface" );
string nameSpace = interfaceElement.GetAttribute( "namespace" );
if ( nameSpace != "JetBrains.Omea.OpenAPI" )
{
_writer.WriteLine( "using JetBrains.Omea.OpenAPI;" );
}
_writer.WriteLine( "" );
if ( nameSpace.Length > 0 )
{
_writer.WriteLine( "namespace " + nameSpace );
_writer.WriteLine( "{" );
}
_visibility = GetVisibility(_doc);
_indent = new string( ' ', 4 );
GenerateXmlDocComment( interfaceElement );
_writer.WriteLine( "{0}public interface {1}", _indent, interfaceElement.GetAttribute( "name" ) );
_writer.WriteLine( "{0}{{", _indent );
_indent = new string( ' ', 8 );
GenerateInterfaceProperties();
_indent = new string( ' ', 4 );
_writer.WriteLine( "{0}}}", _indent );
_writer.WriteLine( "}" );
_writer.Close();
}
public void Generate( string xmlName, string csName )
{
_doc.Load( xmlName );
_writer = new StreamWriter( csName );
_writer.WriteLine("// DO NOT EDIT!!!");
_writer.WriteLine("// This file was autogenerated by the PropGen utility from the {0} schema file on {1}.", xmlName, DateTime.Now.ToString("s"));
_writer.WriteLine();
//_writer.WriteLine( "using System;" );
_writer.WriteLine( "using JetBrains.Omea.OpenAPI;" );
_writer.WriteLine();
string nameSpace = _doc.DocumentElement.GetAttribute( "namespace" );
if ( nameSpace.Length > 0 )
{
_writer.WriteLine( "namespace " + nameSpace );
OpenBrace();
}
string className = _doc.DocumentElement.GetAttribute( "class" );
if ( className.Length == 0 )
{
className = "Props";
}
_visibility = GetVisibility( _doc );
_indent = new string( ' ', 4 );
GenerateXmlDocComment( _doc.DocumentElement );
string implements = "";
XmlElement interfaceNode = (XmlElement) _doc.SelectSingleNode( "/props/interface" );
if ( interfaceNode != null )
{
implements = ": " + interfaceNode.GetAttribute( "name" );
}
_writer.WriteLine( " {0} class {1}{2}", _visibility, className, implements );
OpenBrace();
_prefix = _doc.DocumentElement.GetAttribute( "prefix" );
if ( _prefix.Length > 0 )
{
_prefix += ".";
}
_defaultDataType = _doc.DocumentElement.GetAttribute( "defaultDataType" );
_ownerPlugin = _doc.DocumentElement.GetAttribute( "ownerPlugin" ) == "1";
GenerateClassNameConstants();
GeneratePropFields();
_writer.WriteLine( "" );
GeneratePropProperties();
_writer.WriteLine( "" );
if ( _doc.DocumentElement.GetAttribute( "static" ) == "1" )
{
string registerArgs = "";
if ( _ownerPlugin )
{
registerArgs = " IPlugin ownerPlugin ";
}
_writer.WriteLine( "{0}{1} static void Register({2})", _indent, GetVisibility( _doc ), registerArgs );
_writer.WriteLine( _indent + "{" );
_indent = new string( ' ', 12 );
_writer.WriteLine( "{0}IResourceStore store = Core.ResourceStore;", _indent );
}
else
{
string constructorVisibility = _doc.DocumentElement.GetAttribute( "constructor" );
if ( constructorVisibility.Length == 0 )
{
constructorVisibility = _visibility;
}
_writer.WriteLine( "{0}{1} {2}( IResourceStore store )",
_indent, constructorVisibility, className );
_writer.WriteLine( _indent + "{" );
_indent = new string( ' ', 12 );
}
GeneratePropTypeRegistration();
_writer.WriteLine( "" );
GenerateResourceTypeRegistration();
GenerateUniqueRestrictions();
GenerateLinkRestrictions();
_indent = new string( ' ', 8 );
_writer.WriteLine( _indent + "}" );
CloseBrace();
GenerateBusinessObjectClasses();
if (_doc.DocumentElement.GetAttribute("namespace").Length > 0)
{
CloseBrace();
}
_writer.Close();
}
private void OpenBrace()
{
_indentLevel += 4;
_writer.WriteLine("{0}{{", _indent);
_indent = new string(' ', _indentLevel);
}
private void CloseBrace()
{
_indentLevel -= 4;
_indent = new string(' ', _indentLevel);
_writer.WriteLine("{0}}}", _indent);
_writer.WriteLine("");
}
private void GenerateXmlDocComment( XmlElement element )
{
string summary = element.GetAttribute( "summary" );
if ( summary.Length > 0 )
{
_writer.WriteLine( "" );
_writer.WriteLine( "{0}/// ", _indent );
_writer.WriteLine( "{0}/// {1}", _indent, summary );
_writer.WriteLine( "{0}/// ", _indent );
}
string since = element.GetAttribute( "since" );
if ( since.Length > 0 )
{
_writer.WriteLine( "{0}/// {1}", _indent, since );
}
}
private void GenerateClassNameConstants()
{
XmlNodeList resourceTypeNodes = _doc.SelectNodes( "/props/resourcetype" );
foreach( XmlElement node in resourceTypeNodes )
{
string typeName = node.GetAttribute( "name" );
_writer.WriteLine( "{0}internal const string {1}Resource = \"{2}{1}\";",
_indent, typeName, _prefix );
}
if ( resourceTypeNodes.Count > 0 )
{
_writer.WriteLine( "" );
}
}
private void GeneratePropFields()
{
string prefix = GetStatic( _doc );
foreach( XmlElement node in _doc.SelectNodes( "/props/prop" ) )
{
_writer.WriteLine( "{0}private {1}PropId<{2}> _prop{3};", _indent, prefix,
GetPropIdType(node), GetPropName( node ) );
}
}
private string GetPropIdType(XmlElement node)
{
string dataType = node.GetAttribute("dataType");
return _dataTypes[dataType];
}
private void GenerateInterfaceProperties()
{
foreach( XmlElement node in _doc.SelectNodes( "/props/prop" ) )
{
GenerateXmlDocComment( node );
_writer.WriteLine( "{0}PropId<{1}> {2} {{ get; }}", _indent, GetPropIdType(node), GetPropName( node) );
}
}
private void GeneratePropProperties()
{
string visibility = GetVisibility( _doc );
string isStatic = GetStatic( _doc );
foreach( XmlElement node in _doc.SelectNodes( "/props/prop" ) )
{
GenerateXmlDocComment( node );
_writer.WriteLine( "{0}{1} {2}PropId<{3}> {4} {{ get {{ return _prop{4}; }} }}",
_indent, visibility, isStatic, GetPropIdType(node), GetPropName( node ) );
}
}
private void GenerateBusinessObjectClasses()
{
foreach (XmlElement node in _doc.SelectNodes("/props/resourcetype"))
{
XmlNodeList coreProps = node.GetElementsByTagName("coreProp");
XmlNodeList props = node.GetElementsByTagName("prop");
if (coreProps.Count > 0 || props.Count > 0)
{
string visibility = GetVisibility(_doc);
string name = node.GetAttribute("name");
_writer.WriteLine("{0}{1} partial class {2}: BusinessObject",
_indent, visibility, name);
OpenBrace();
GenerateResourceTypeId(name);
_writer.WriteLine("{0}public static {1}ResourceType ResourceType = {1}ResourceType.Instance;",
_indent, name);
_writer.WriteLine("");
_writer.WriteLine("{0}public static {1} Create()", _indent, name);
OpenBrace();
_writer.WriteLine("{0}return new {1}();", _indent, name);
CloseBrace();
_writer.WriteLine("{0}protected {1}(): base(Props.{1}Resource)", _indent, name);
OpenBrace();
CloseBrace();
_writer.WriteLine("{0}protected {1}(IResource res): base(res)", _indent, name);
OpenBrace();
CloseBrace();
foreach(XmlElement element in coreProps)
{
GenerateCoreBusinessObjectProp(element.GetAttribute("name"));
}
foreach(XmlElement element in props)
{
GenerateBusinessObjectProp(element.GetAttribute("name"));
}
CloseBrace();
}
}
}
private void GenerateResourceTypeId(string name)
{
_writer.WriteLine("{0}{1} class {2}ResourceType: ResourceTypeId<{2}>",
_indent, _visibility, name);
OpenBrace();
_writer.WriteLine("{0}private {1}ResourceType(): base(Props.{1}Resource)",
_indent, name);
OpenBrace();
CloseBrace();
_writer.WriteLine("{0}public override {1} CreateBusinessObject(IResource res)",
_indent, name);
OpenBrace();
_writer.WriteLine("{0}return new {1}(res);", _indent, name);
CloseBrace();
_writer.WriteLine("{0}{1} static {2}ResourceType Instance = new {2}ResourceType();",
_indent, _visibility, name);
CloseBrace();
}
private void GenerateCoreBusinessObjectProp(string name)
{
string propIdType = _dataTypes[_corePropTypes[name]];
GenerateWrapperProp(propIdType, name, "Core.PropIds");
}
private void GenerateWrapperProp(string propIdType, string name, string accessor)
{
_writer.WriteLine("{0}public {1} {2}", _indent, propIdType, name);
OpenBrace();
_writer.WriteLine("{0}get {{ return GetProp({1}.{2}); }}", _indent, accessor, name);
_writer.WriteLine("{0}set {{ SetProp({1}.{2}, value); }}", _indent, accessor, name);
CloseBrace();
}
private void GenerateBusinessObjectProp(string name)
{
XmlNode prop = _doc.SelectSingleNode("/props/prop[@name='" + name + "']");
string propIdType = _dataTypes[prop.Attributes["dataType"].Value];
GenerateWrapperProp(propIdType, name, "Props");
}
private void GeneratePropTypeRegistration()
{
foreach( XmlElement node in _doc.SelectNodes( "/props/prop" ) )
{
_writer.Write( "{0}_prop{1} = store.PropTypes.Register( ", _indent, GetPropName( node ) );
_writer.Write( "\"{0}{1}\", ", _prefix, node.GetAttribute( "name" ) );
string dataType = node.GetAttribute( "dataType" );
if ( dataType.Length == 0 )
{
dataType = _defaultDataType;
}
_writer.Write( "PropDataTypes." + dataType );
string flags = GetFlags( "PropTypeFlags", node );
if ( flags != "" )
{
_writer.WriteLine( "," );
_writer.Write( _indent + " " + flags );
}
_writer.WriteLine( " );" );
if ( node.GetAttribute( "internal" ) != "1" )
{
GenerateDisplayNameRegistration( node );
}
}
}
private void GenerateDisplayNameRegistration( XmlElement node )
{
string displayName = node.GetAttribute( "displayName" );
if ( displayName == "" )
{
displayName = SplitCamelCase( node.GetAttribute( "name" ) );
}
if ( node.GetAttribute( "directedLink" ) != "1" )
{
if ( displayName != node.GetAttribute( "name" ) )
{
_writer.WriteLine( "{0}store.PropTypes.RegisterDisplayName( _prop{1}, \"{2}\" );",
_indent, GetPropName( node ), displayName );
}
}
else
{
string reverseDisplayName = node.GetAttribute( "reverseDisplayName" );
if ( reverseDisplayName == "" )
{
reverseDisplayName = SplitCamelCase( node.GetAttribute( "name" ) );
}
_writer.WriteLine( "{0}store.PropTypes.RegisterDisplayName( _prop{1}, \"{2}\", \"{3}\" );",
_indent, GetPropName( node ), displayName, reverseDisplayName );
}
_writer.WriteLine( "" );
}
private void GenerateResourceTypeRegistration()
{
XmlNodeList resourceTypeNodes = _doc.SelectNodes( "/props/resourcetype" );
foreach( XmlElement node in resourceTypeNodes )
{
string name = node.GetAttribute( "name" );
string displayName = node.GetAttribute( "displayName" );
if ( displayName.Length == 0 && node.GetAttribute( "internal" ) != "1" )
{
displayName = SplitCamelCase( name );
}
string displayNameTemplate = node.GetAttribute( "dnTemplate" );
if ( displayNameTemplate.StartsWith( "Core." ) )
{
displayNameTemplate = "Core.ResourceStore.PropTypes [Core.Props." +
displayNameTemplate.Substring( 5 ) + "].Name";
}
else
{
displayNameTemplate = "\"" + displayNameTemplate + "\"";
}
_writer.Write( "{0}store.ResourceTypes.Register( {1}Resource, \"{2}\", {3}",
_indent, name, displayName, displayNameTemplate );
string flags = GetFlags( "ResourceTypeFlags", node );
if ( flags != "" )
{
_writer.WriteLine( "," );
_writer.Write( _indent + " " + flags );
}
else if ( _ownerPlugin )
{
_writer.Write( "ResourceTypeFlags.Normal" );
}
if ( _ownerPlugin )
{
_writer.Write( ", ownerPlugin" );
}
_writer.WriteLine( " );" );
}
if ( resourceTypeNodes.Count > 0 )
{
_writer.WriteLine( "" );
}
}
private void GenerateLinkRestrictions()
{
foreach( XmlElement node in _doc.SelectNodes( "/props/prop/linkRestriction" ) )
{
string fromType = GetClassName( node, "fromtype" );
string propName = GetPropName( (XmlElement) node.ParentNode );
string toType = GetClassName( node, "totype" );
if ( toType.Length == 0 )
{
toType = null;
}
string minCount = node.GetAttribute( "mincount" );
if ( minCount.Length == 0 )
{
minCount = "0";
}
string maxCount = node.GetAttribute( "maxcount" );
if ( maxCount.Length == 0 )
{
maxCount = "Int32.MaxValue";
}
_writer.WriteLine( "{0}store.RegisterLinkRestriction( {1}, _prop{2}, {3}, {4}, {5} );",
_indent, fromType, propName, toType, minCount, maxCount );
}
}
private void GenerateUniqueRestrictions()
{
foreach( XmlElement node in _doc.SelectNodes( "/props/prop/unique" ) )
{
string propName = GetPropName( (XmlElement) node.ParentNode );
string className = GetClassName( node, "resourcetype" );
_writer.WriteLine( "{0}store.RegisterUniqueRestriction( {1}, _prop{2} );",
_indent, className, propName );
}
}
private string GetClassName( XmlElement node, string attrName )
{
string className = node.GetAttribute( attrName );
if ( _doc.SelectSingleNode( "/props/resourcetype[@name='" + className + "']" ) != null )
{
className = className + "Resource";
}
else
{
className = "\"" + className + "\"";
}
return className;
}
private static string GetVisibility( XmlDocument doc )
{
string visibility = doc.DocumentElement.GetAttribute( "visibility" );
if ( visibility.Length == 0 )
{
visibility = "public";
}
return visibility;
}
private static string GetStatic( XmlDocument doc )
{
if ( doc.DocumentElement.GetAttribute( "static" ) == "1" )
{
return "static ";
}
return "";
}
private static string GetPropName( XmlElement node )
{
string propName = node.GetAttribute( "propName" );
if ( propName.Length == 0 )
{
propName = node.GetAttribute( "name" );
}
return propName;
}
private static string SplitCamelCase( string s )
{
StringBuilder result = new StringBuilder( s );
for( int i=result.Length-1; i > 0; i-- )
{
if ( Char.IsUpper( result [i] ) )
{
result.Insert( i, ' ' );
}
}
return result.ToString();
}
private string GetFlags( string prefix, XmlElement node )
{
ArrayList flags = new ArrayList();
foreach( XmlAttribute attr in node.Attributes )
{
if ( attr.Value == "1" )
{
string attrName = attr.Name;
flags.Add( prefix + "." + Char.ToUpper( attrName [0] ) + attrName.Substring( 1 ) );
}
}
string[] flagsArray = (string[]) flags.ToArray( typeof (string) );
return String.Join( " | ", flagsArray );
}
}
}