Skip to content

Commit bcebe39

Browse files
committed
Add support for inheritance (switched on by default, turn off by specifying the -i switch or by setting PocoSetting.Inherit to a non-null value)
1 parent 0588a28 commit bcebe39

File tree

8 files changed

+121
-15
lines changed

8 files changed

+121
-15
lines changed

OData2Poco.CommandLine.Test/ProgramTests.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Diagnostics;
3+
using System.Linq;
34
using CommandLine;
45
using Medallion.Shell;
56
using NUnit.Framework;
@@ -76,6 +77,70 @@ public void PocoSettingTest(string url, string version, int n)
7677
Assert.IsFalse(output.Contains("public class Product :")); // -i is not set
7778
}
7879

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+
79144
[Test]
80145
[TestCaseSource(typeof(TestSample), "UrlCases")]
81146
public void NullableDatatypeTest(string url, string version, int n)

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public PocoSetting()
8080
{
8181
Lang= Language.CS;
8282
NamespacePrefix = string.Empty;
83-
Inherit = string.Empty;
83+
Inherit = null;
8484
NameCase= CaseEnum.None;
8585
AddJsonAttribute= false;
8686

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(),

OData2Poco.Shared/V4/Poco.cs

Lines changed: 19 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,17 @@ 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+
174186
//fill keys
175187
var list = GetKeys(ent);
176188
if (list != null) classTemplate.Keys.AddRange(list);
@@ -232,6 +244,10 @@ private List<PropertyTemplate> GetClassProperties(IEdmSchemaType ent)
232244

233245
var structuredType = ent as IEdmStructuredType;
234246
var properties = structuredType.Properties();
247+
if (_setting.UseInheritance)
248+
{
249+
properties = properties.Where(x => x.DeclaringType.FullTypeName() == ent.FullTypeName());
250+
}
235251

236252
var list = properties.Select(property => new PropertyTemplate
237253
{

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ To install run the command:
4141
- Convert name of properties to camelCase or PasCase
4242
- Add nullable datatypes, e.g. int?.
4343
- Generate (or not) navigation properties.
44+
- Generated class follows inhertance hierarchy of OData feed (unless switched-off).
4445
- Generated class can inherit from a common BaseClass/interface.
4546
- Define namespace to overwrite the namespace of the model.
47+
4648
- Add primary key/mandatory comments to the properties of the class. .
4749
- Save metadata and generated code to a user defined file name.
4850
- Support .NET 4.5 or higher

0 commit comments

Comments
 (0)