/// /// 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 ); } } }