Skip to content

Commit e8cfb39

Browse files
authored
Merge pull request #6 from merijndejonge/master
Add support for inheritance
2 parents 6d538c9 + bcebe39 commit e8cfb39

File tree

13 files changed

+164
-34
lines changed

13 files changed

+164
-34
lines changed

OData2Poco.CommandLine.Test/OData2Poco.CommandLine.Test.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
<Prefer32Bit>false</Prefer32Bit>
3535
</PropertyGroup>
3636
<ItemGroup>
37+
<Reference Include="CommandLine, Version=1.9.71.2, Culture=neutral, PublicKeyToken=de6f01bd326f8c32, processorArchitecture=MSIL">
38+
<HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
39+
</Reference>
3740
<Reference Include="MedallionShell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
3841
<HintPath>..\packages\MedallionShell.1.1.0\lib\net45\MedallionShell.dll</HintPath>
3942
<Private>True</Private>
@@ -81,6 +84,10 @@
8184
<Project>{59c02b8c-7388-490a-801c-aea5244e3879}</Project>
8285
<Name>OData2Poco.CommandLine</Name>
8386
</ProjectReference>
87+
<ProjectReference Include="..\OData2PocoLib\OData2Poco.csproj">
88+
<Project>{bcc5139d-a1c0-46e7-aba7-72e9660607de}</Project>
89+
<Name>OData2Poco</Name>
90+
</ProjectReference>
8491
</ItemGroup>
8592
<ItemGroup>
8693
<None Include="packages.config" />

OData2Poco.CommandLine.Test/ProgramTests.cs

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.Diagnostics;
3+
using System.Linq;
4+
using CommandLine;
35
using Medallion.Shell;
46
using NUnit.Framework;
57

@@ -15,7 +17,7 @@ public class ProgramTests
1517
{
1618
private const double Timeout = 3 * 60; //sec
1719
private const string appCommand = @"o2pgen";
18-
static Func<string, Command> TestCommand = (s => Command.Run(appCommand, s.Split(' '),
20+
static Func<string, Medallion.Shell.Command> TestCommand = (s => Medallion.Shell.Command.Run(appCommand, s.Split(' '),
1921
options => options.Timeout(TimeSpan.FromSeconds(Timeout))));
2022

2123
/// <summary>
@@ -28,7 +30,7 @@ public class ProgramTests
2830
/// </remarks>
2931
private Func<string, Tuple<int, string>> RunCommand = (s =>
3032
{
31-
var command = Command.Run(appCommand, s.Split(' '),
33+
var command = Medallion.Shell.Command.Run(appCommand, s.Split(' '),
3234
options => options.Timeout(TimeSpan.FromSeconds(Timeout)));
3335

3436
var outText = command.Result.StandardOutput;
@@ -75,6 +77,70 @@ public void PocoSettingTest(string url, string version, int n)
7577
Assert.IsFalse(output.Contains("public class Product :")); // -i is not set
7678
}
7779

80+
[Test]
81+
public void PocoWithInheritanceTest()
82+
{
83+
var url = "http://services.odata.org/V4/TripPinServiceRW/" ;
84+
var a = $"-r {url} -v";
85+
86+
var tuble = RunCommand(a);
87+
var output = tuble.Item2;
88+
89+
Assert.IsTrue(output.Contains("public class PublicTransportation : PlanItem"));
90+
}
91+
92+
[Test(Description = "If model inheritance is used (the default) check that the propterties of a base calsss are not duplicated inderived classes")]
93+
public void PropertyInheritenceTest()
94+
{
95+
var url = "http://services.odata.org/V4/TripPinServiceRW/";
96+
var a = $"-r {url} -v";
97+
98+
var tuble = RunCommand(a);
99+
var output = tuble.Item2;
100+
101+
var lines = output.Split('\n');
102+
var occurneces = lines.Count(l => l.Contains("public int PlanItemId"));
103+
104+
Assert.IsTrue(occurneces == 1); // For inheritance, check that PlanItemId property only occurs in the base class
105+
106+
}
107+
[Test]
108+
public void PocoWithBaseClassTest()
109+
{
110+
var url = "http://services.odata.org/V4/TripPinServiceRW/";
111+
const string myBaseClass = nameof(myBaseClass);
112+
113+
var a = $"-r {url} -v -i {myBaseClass}";
114+
115+
var tuble = RunCommand(a);
116+
var output = tuble.Item2;
117+
118+
Assert.IsTrue(output.Contains($"public class PublicTransportation : {myBaseClass}"));
119+
120+
var lines = output.Split('\n');
121+
var occurneces = lines.Count(l => l.Contains("public int PlanItemId"));
122+
123+
Assert.IsTrue(occurneces > 1);
124+
}
125+
126+
[Test(Description = "If model inheritance is not used, the properties from a base class should by duplicated in the derived classes.")]
127+
public void PropertyDuplicationTest()
128+
{
129+
var url = "http://services.odata.org/V4/TripPinServiceRW/";
130+
const string myBaseClass = nameof(myBaseClass);
131+
132+
var a = $"-r {url} -v -i {myBaseClass}";
133+
134+
var tuble = RunCommand(a);
135+
var output = tuble.Item2;
136+
137+
var lines = output.Split('\n');
138+
var occurneces = lines.Count(l => l.Contains("public int PlanItemId"));
139+
140+
Assert.IsTrue(occurneces > 1); // If not using model inheritance, check that the PlanItemId property is duplicated in derived classes
141+
142+
}
143+
78144
[Test]
79145
[TestCaseSource(typeof(TestSample), "UrlCases")]
80146
public void NullableDatatypeTest(string url, string version, int n)
@@ -183,7 +249,7 @@ public void PocoSettingNamespaceTest(string url, string version, int n)
183249
Assert.AreEqual(0, tuble.Item1);
184250
// Console.WriteLine(tuble.Item2);
185251

186-
Assert.IsTrue(output.Contains("MyNamespace1.MyNamespace2.")); //-i, -v
252+
Assert.IsTrue(output.Contains("MyNamespace1.MyNamespace2.")); //-m, -v
187253

188254
}
189255

@@ -287,6 +353,27 @@ public void InValidArgumentTest(string url, string version, int n)
287353
//}
288354

289355

356+
[Test]
357+
public void InheritanceEnabledByDefaultTest()
358+
{
359+
var a = new string[] {};
360+
361+
var options = new Options();
362+
Parser.Default.ParseArguments(a, options);
363+
var command = new Command(options);
290364

291-
}//
365+
Assert.IsTrue(command.PocoSettingOptions.UseInheritance);
366+
}
367+
[Test]
368+
public void InheritanceDisabledWithInheritSettingTest()
369+
{
370+
var a = new[] { "-i", "MyBaseClass" };
371+
372+
var options = new Options();
373+
Parser.Default.ParseArguments(a, options);
374+
var command = new Command(options);
375+
376+
Assert.IsFalse(command.PocoSettingOptions.UseInheritance);
377+
}
378+
}
292379
}//

OData2Poco.CommandLine.Test/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3+
<package id="CommandLineParser" version="1.9.71" targetFramework="net45" />
34
<package id="MedallionShell" version="1.1.0" targetFramework="net45" />
45
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
56
<package id="NUnit" version="2.6.4" targetFramework="net45" />

OData2Poco.CommandLine/Command.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public Command(Options options)
2626
AddNavigation = ArgOptions.Navigation,
2727
AddNullableDataType = ArgOptions.AddNullableDataType,
2828
AddEager = ArgOptions.Eager, //v2.1.0
29-
Inherit = string.IsNullOrWhiteSpace(ArgOptions.Inherit) ? string.Empty : ArgOptions.Inherit, //v2.1.0
29+
Inherit = string.IsNullOrWhiteSpace(ArgOptions.Inherit) ? null : ArgOptions.Inherit, //v2.1.0
3030
NamespacePrefix = string.IsNullOrEmpty(ArgOptions.Namespace) ? string.Empty : ArgOptions.Namespace,
3131
//v2.1.0
3232
AddJsonAttribute = ArgOptions.AddJsonAttribute, //v2.2

OData2Poco.CommandLine/Properties/AssemblyInfo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Reflection;
2+
using System.Runtime.CompilerServices;
23
using System.Runtime.InteropServices;
34

45
// General Information about an assembly is controlled through the following
@@ -13,6 +14,8 @@
1314
[assembly: AssemblyTrademark("")]
1415
[assembly: AssemblyCulture("")]
1516

17+
[assembly: InternalsVisibleTo("OData2Poco.CommandLine.Test")]
18+
1619
// Setting ComVisible to false makes the types in this assembly not visible
1720
// to COM components. If you need to access a type in this assembly from
1821
// COM, set the ComVisible attribute to true on that type.

OData2Poco.Shared/ClassTemplate.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace OData2Poco
88
public partial class ClassTemplate
99
{
1010
public string Name { get; set; }
11+
public string BaseType { get; set; }
1112
public string Comment { get; set; }
1213
public string ToDebugString { get; set; }
1314
public List<PropertyTemplate> Properties { get; set; }

OData2Poco.Shared/PocoClassGeneratorCs.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,9 @@ internal string ClassToString(ClassTemplate ent, bool includeNamespace = false)
153153
{
154154
csTemplate.PushIndent("\t").WriteLine(item).PopIndent();
155155
}
156+
var baseClass = ent.BaseType != null && PocoSetting.UseInheritance ? ent.BaseType : PocoSetting.Inherit;
156157

157-
csTemplate.StartClass(ent.Name, PocoSetting.Inherit);
158+
csTemplate.StartClass(ent.Name, baseClass);
158159
// csTemplate.StartClass(ent.Name, PocoSetting.Inherit, partial:true); //delayed to a future release to avoid change of most test cases
159160
foreach (var p in ent.Properties)
160161
{

OData2Poco.Shared/PocoFactory.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,35 @@ namespace OData2Poco
77
// factory class
88
internal class PocoFactory
99
{
10-
private static IPocoGenerator Create(MetaDataInfo metadata)
10+
private static IPocoGenerator Create(MetaDataInfo metadata, PocoSetting setting)
1111
{
1212
if (string.IsNullOrEmpty(metadata.MetaDataAsString)) throw new InvalidOperationException("No Metadata available");
1313

1414
var metaDataVersion = metadata.MetaDataVersion;
1515
switch (metaDataVersion)
1616
{
1717
case ODataVersion.V4:
18-
return new Poco(metadata);
18+
return new Poco(metadata, setting);
1919

2020
case ODataVersion.V1:
2121
case ODataVersion.V2:
2222
case ODataVersion.V3:
23-
return new V3.Poco(metadata);
23+
return new V3.Poco(metadata, setting);
2424
//throw new NotImplementedException();
2525

2626
default:
2727
throw new NotSupportedException(string.Format("OData Version '{0}' is not supported", metaDataVersion));
2828

2929
}
3030
}
31-
public static IPocoClassGenerator GeneratePoco(MetaDataInfo metadata,PocoSetting setting=null)
31+
32+
public static IPocoClassGenerator GeneratePoco(MetaDataInfo metadata, PocoSetting setting = null)
3233
{
33-
if(string.IsNullOrEmpty(metadata.MetaDataAsString))
34+
if (setting == null) setting = new PocoSetting();
35+
if (string.IsNullOrEmpty(metadata.MetaDataAsString))
3436
throw new XmlException("Metaddata is empty");
35-
var generator = Create(metadata);
36-
return new PocoClassGeneratorCs(generator, setting??new PocoSetting() );
37+
var generator = Create(metadata, setting);
38+
return new PocoClassGeneratorCs(generator, setting);
3739
}
3840
}
3941
}

OData2Poco.Shared/PocoSetting.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ public class PocoSetting
4646
/// Base class and/or interfaces to implement
4747
/// </value>
4848
public string Inherit { get; set; }
49-
49+
/// <summary>
50+
/// Indicates whether or not to generate classes that follow the inheritance hierarchy of the ODATA types. Default is true. Disable by setting Inherit to a non-null value.
51+
///
52+
/// </summary>
53+
public bool UseInheritance => Inherit == null;
5054
/// <summary>
5155
/// Gets or sets a namespace prefix.
5256
/// </summary>
@@ -76,7 +80,7 @@ public PocoSetting()
7680
{
7781
Lang= Language.CS;
7882
NamespacePrefix = string.Empty;
79-
Inherit = string.Empty;
83+
Inherit = null;
8084
NameCase= CaseEnum.None;
8185
AddJsonAttribute= false;
8286

OData2Poco.Shared/V3/Poco.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ namespace OData2Poco.V4
2525
/// </summary>
2626
internal partial class Poco : IPocoGenerator
2727
{
28-
28+
private readonly PocoSetting _setting;
29+
2930
public MetaDataInfo MetaData { get; set; }
3031

3132
public string MetaDataAsString
@@ -56,10 +57,10 @@ public string ServiceUrl
5657
// ServiceUrl = serviceUrl;
5758
// //MetaDataVersion = Helper.GetMetadataVersion(metaData);
5859
//}
59-
internal Poco(MetaDataInfo metaData)
60+
internal Poco(MetaDataInfo metaData, PocoSetting setting)
6061
{
62+
_setting = setting;
6163
MetaData = metaData;
62-
6364
}
6465
private IEnumerable<IEdmSchemaType> SchemaElements
6566
{
@@ -171,6 +172,19 @@ private ClassTemplate GeneratePocoClass(IEdmSchemaType ent)
171172
//v1.4
172173
classTemplate.EntitySetName = GetEntitySetName(ent.Name);
173174

175+
// Set base type if _setting.UseInheritance == true
176+
if (_setting.UseInheritance && ent is IEdmEntityType)
177+
{
178+
var entityType = (IEdmEntityType)ent;
179+
var baseEntityType = entityType.BaseEntityType();
180+
if (baseEntityType != null)
181+
{
182+
classTemplate.BaseType = baseEntityType.Name;
183+
}
184+
185+
}
186+
187+
174188
//fill keys
175189
var list = GetKeys(ent);
176190
if (list != null) classTemplate.Keys.AddRange(list);
@@ -233,6 +247,11 @@ private List<PropertyTemplate> GetClassProperties(IEdmSchemaType ent)
233247
var structuredType = ent as IEdmStructuredType;
234248
var properties = structuredType.Properties();
235249

250+
if (_setting.UseInheritance)
251+
{
252+
properties = properties.Where(x => ((IEdmSchemaType)x.DeclaringType).FullName() == ent.FullName());
253+
}
254+
236255
var list = properties.Select(property => new PropertyTemplate
237256
{
238257
//ToTrace = property.ToTraceString(),

0 commit comments

Comments
 (0)