Skip to content

Commit

Permalink
Added support for reference models with a relative uri (#183)
Browse files Browse the repository at this point in the history
* Added support for reference models with a relative uri

Fixes: #182
  • Loading branch information
Tiberriver256 authored Jan 20, 2021
1 parent fdcf18e commit ef08797
Show file tree
Hide file tree
Showing 8 changed files with 3,790 additions and 6 deletions.
17 changes: 15 additions & 2 deletions src/Templates/ODataT4CodeGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 16.0.0.0
Expand Down Expand Up @@ -906,6 +906,12 @@ public class CodeGenerationContext
/// Preconfigured WebProxy for fetching the metadata
/// </summary>
private WebProxy webProxy;

/// <summary>
/// The metadata uri used for the original source edmx
/// </summary>
private Uri metadataUri;

private IList<string> customHttpHeaders;
/// <summary>
/// Constructs an instance of <see cref="CodeGenerationContext"/>.
Expand All @@ -926,6 +932,7 @@ public CodeGenerationContext(Uri metadataUri, string namespacePrefix)
public CodeGenerationContext(Uri metadataUri, string namespacePrefix, WebProxy proxy, IList<string> CustomHttpHeaders)
: this(GetEdmxStringFromMetadataPath(metadataUri, proxy, CustomHttpHeaders), namespacePrefix)
{
this.metadataUri = metadataUri;
webProxy = proxy;
customHttpHeaders = CustomHttpHeaders;
}
Expand Down Expand Up @@ -1026,6 +1033,12 @@ public Func<Uri, XmlReader> GetReferencedModelReaderFuncWrapper
{
return (uri) =>
{
Uri originalUri = uri;
if(!uri.IsAbsoluteUri)
{
// In the case that the reference model uri is relative we should create an absolute uri using the metadataUri as the base
uri = new Uri(metadataUri, uri.ToString());
}
using (XmlReader reader = GetReferencedModelReaderFunc(uri, webProxy, customHttpHeaders))
{
if (reader == null)
Expand All @@ -1039,7 +1052,7 @@ public Func<Uri, XmlReader> GetReferencedModelReaderFuncWrapper
this.ReferencesMap = new Dictionary<Uri, XElement>();
}
this.ReferencesMap.Add(uri, element);
this.ReferencesMap.Add(originalUri, element);
return element.CreateReader(ReaderOptions.None);
}
};
Expand Down
17 changes: 15 additions & 2 deletions src/Templates/ODataT4CodeGenerator.ttinclude
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,12 @@ public class CodeGenerationContext
/// Preconfigured WebProxy for fetching the metadata
/// </summary>
private WebProxy webProxy;

/// <summary>
/// The metadata uri used for the original source edmx
/// </summary>
private Uri metadataUri;

private IList<string> customHttpHeaders;
/// <summary>
/// Constructs an instance of <see cref="CodeGenerationContext"/>.
Expand All @@ -780,6 +786,7 @@ public class CodeGenerationContext
public CodeGenerationContext(Uri metadataUri, string namespacePrefix, WebProxy proxy, IList<string> CustomHttpHeaders)
: this(GetEdmxStringFromMetadataPath(metadataUri, proxy, CustomHttpHeaders), namespacePrefix)
{
this.metadataUri = metadataUri;
webProxy = proxy;
customHttpHeaders = CustomHttpHeaders;
}
Expand Down Expand Up @@ -880,6 +887,12 @@ public class CodeGenerationContext
{
return (uri) =>
{
Uri originalUri = uri;
if(!uri.IsAbsoluteUri)
{
// In the case that the reference model uri is relative we should create an absolute uri using the metadataUri as the base
uri = new Uri(metadataUri, uri.ToString());
}
using (XmlReader reader = GetReferencedModelReaderFunc(uri, webProxy, customHttpHeaders))
{
if (reader == null)
Expand All @@ -893,7 +906,7 @@ public class CodeGenerationContext
this.ReferencesMap = new Dictionary<Uri, XElement>();
}

this.ReferencesMap.Add(uri, element);
this.ReferencesMap.Add(originalUri, element);
return element.CreateReader(ReaderOptions.None);
}
};
Expand Down Expand Up @@ -5822,4 +5835,4 @@ End Namespace
<#+
}
}
#>
#>

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
<edmx:Reference Uri="./MultiReferenceModelCoreTerms.xml">
<edmx:Include Alias="Core" Namespace="Microsoft.OData.SampleService.Models.ModelRefDemo.Core.V1"/>
</edmx:Reference>
<edmx:Reference Uri="./MultiReferenceModelDeviceModelTerms.xml">
<edmx:Include Namespace="Microsoft.OData.SampleService.Models.ModelRefDemo.Vocabulary.V1" Alias="IoTDeviceModel"/>
</edmx:Reference>
<edmx:Reference Uri="./MultiReferenceModelGPS.xml">
<edmx:Include Namespace="Microsoft.OData.SampleService.Models.ModelRefDemo.GPS" Alias="GPS"/>
</edmx:Reference>
<edmx:Reference Uri="./MultiReferenceModelLocation.xml">
<edmx:Include Namespace="Microsoft.OData.SampleService.Models.ModelRefDemo.Location" Alias="Location"/>
</edmx:Reference>
<edmx:Reference Uri="./MultiReferenceModelMap.xml">
<edmx:Include Namespace="Microsoft.OData.SampleService.Models.ModelRefDemo.Map" Alias="Map"/>
</edmx:Reference>
<edmx:DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Microsoft.OData.SampleService.Models.ModelRefDemo.TruckDemo" Alias="Self">
<ComplexType Name="LocationAndFuel">
<Property Name="FuelLevel" Type="Edm.Double"/>
<Property Name="Location" Type="Location.GeoLocation"/>
</ComplexType>
<ComplexType Name="TruckStoppedAlarmType">
<Property Name="Severity" Type="Edm.Int32" DefaultValue="3"/>
<Property Name="LocationAndFuel" Type="Self.LocationAndFuel"/>
<Annotation Term="Core.Description" String="Alarm: Truck Stopped!"/>
<Annotation Term="IoTDeviceModel.IsAlarm" Bool="true"/>
</ComplexType>
<EntityType Name="HeadUnitType">
<Key>
<PropertyRef Name="SerialNo"/>
</Key>
<Property Name="SerialNo" Type="Edm.String" Nullable="false"/>
<Property Name="DimmingLevel" Type="Edm.Double"/>
</EntityType>
<EntityType Name="TruckType">
<Key>
<PropertyRef Name="Key"/>
</Key>
<Property Name="Key" Type="Edm.String" Nullable="false"/>
<Property Name="VIN" Type="Edm.String"/>
<Property Name="FuelLevel" Type="Edm.Double"/>
<Property Name="ACState" Type="Edm.Boolean"/>
<Property Name="TruckIsHomeFuelLevel" Type="Edm.Double">
<Annotation Term="IoTDeviceModel.IsEvent" Bool="true"/>
</Property>
<Property Name="TruckStoppedAlarm" Type="Self.TruckStoppedAlarmType">
<Annotation Term="IoTDeviceModel.IsEvent" Bool="true"/>
</Property>
<Property Name="OutsideGeoFenceAlarm" Type="Location.OutsideGeoFenceAlarmType">
<Annotation Term="IoTDeviceModel.IsEvent" Bool="true"/>
</Property>
<NavigationProperty Name="HeadUnit" Type="Self.HeadUnitType" ContainsTarget="true"/>
<NavigationProperty Name="VehicleGPS" Type="GPS.VehicleGPSType" ContainsTarget="true"/>
</EntityType>
<EntityType Name="DerivedVehicleGPSType" BaseType="GPS.VehicleGPSType">
<Property Name="DisplayName" Type="Edm.String"/>
</EntityType>
<Action Name="SetACState" IsBound="true">
<Parameter Name="targetTruck" Type="Self.TruckType"/>
<Parameter Name="state" Type="Edm.Boolean">
<Annotation Term="Core.Description" String="The state of AC"/>
</Parameter>
<Annotation Term="Core.Description" String="Set the AC state"/>
</Action>
<Action Name="TurnOffAC" IsBound="true">
<Parameter Name="targetTruck" Type="Self.TruckType"/>
<Annotation Term="Core.Description" String="Turn off AC"/>
</Action>
<Function Name="GetDefaultOutsideGeoFenceAlarm" IsComposable="true">
<ReturnType Type="Location.OutsideGeoFenceAlarmType"/>
</Function>
<EntityContainer Name="TruckDemoService" Extends="GPS.GPSContainer">
<EntitySet Name="Trucks" EntityType="Microsoft.OData.SampleService.Models.ModelRefDemo.TruckDemo.TruckType">
<Annotation Term="Core.Description" String="Our Trucks"/>
</EntitySet>
<EntitySet Name="VehicleGPSSet" EntityType="Microsoft.OData.SampleService.Models.ModelRefDemo.GPS.VehicleGPSType"/>
<EntitySet Name="DerivedVehicleGPSSet" EntityType="Microsoft.OData.SampleService.Models.ModelRefDemo.TruckDemo.DerivedVehicleGPSType"/>
<FunctionImport Name="GetDefaultOutsideGeoFenceAlarm" Function="Microsoft.OData.SampleService.Models.ModelRefDemo.TruckDemo.GetDefaultOutsideGeoFenceAlarm"/>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,25 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CodeGenReferences\*.cs" />
<EmbeddedResource Include="CodeGenReferences\*.xml" />
<EmbeddedResource Include="CodeGenReferences\*.vb" />
<EmbeddedResource Include="CodeGenReferences\MultiReferenceModelCoreTerms.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeGenReferences\MultiReferenceModelDeviceModelTerms.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeGenReferences\MultiReferenceModelGPS.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeGenReferences\MultiReferenceModelLocation.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeGenReferences\MultiReferenceModelMap.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="CodeGenReferences\MultiReferenceModelRelativeUri.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\..\src\Templates\ODataT4CodeGenerator.ttinclude">
Expand All @@ -175,6 +192,33 @@
<Content Include="CodeGeneration\SampleServiceV2.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="CodeGenReferences\AbstractEntityTypeWithoutKey.xml" />
<EmbeddedResource Include="CodeGenReferences\DupNames.xml" />
<EmbeddedResource Include="CodeGenReferences\EmptySchema.xml" />
<EmbeddedResource Include="CodeGenReferences\EntitiesEnumsFunctions.xml" />
<EmbeddedResource Include="CodeGenReferences\EntityBooleanPropertyWithDefaultValue.xml" />
<EmbeddedResource Include="CodeGenReferences\EntityHierarchyWithIDAndId.xml" />
<EmbeddedResource Include="CodeGenReferences\KeywordsAsNames.xml" />
<EmbeddedResource Include="CodeGenReferences\MergedFunctionalTest.xml" />
<EmbeddedResource Include="CodeGenReferences\Multiplicity.xml" />
<EmbeddedResource Include="CodeGenReferences\MultiReferenceModel.xml" />
<EmbeddedResource Include="CodeGenReferences\NamespaceInKeywords.xml" />
<EmbeddedResource Include="CodeGenReferences\NamespaceInKeywordsWithRefModel.xml" />
<EmbeddedResource Include="CodeGenReferences\NamespaceInKeywordsWithRefModelReferenced.xml" />
<EmbeddedResource Include="CodeGenReferences\NamespacePrefixRepeatWithSchemaNameSpace.xml" />
<EmbeddedResource Include="CodeGenReferences\NamespacePrefixWithDoubleNamespaces.xml" />
<EmbeddedResource Include="CodeGenReferences\NamespacePrefixWithInheritence.xml" />
<EmbeddedResource Include="CodeGenReferences\NamespacePrefixWithSingleNamespace.xml" />
<EmbeddedResource Include="CodeGenReferences\OverrideOperations.xml" />
<EmbeddedResource Include="CodeGenReferences\PrefixConflict.xml" />
<EmbeddedResource Include="CodeGenReferences\Simple.xml" />
<EmbeddedResource Include="CodeGenReferences\SimpleMultipleFiles.xml" />
<EmbeddedResource Include="CodeGenReferences\SourceParameterOrKeysProperty.xml" />
<EmbeddedResource Include="CodeGenReferences\TempSimple.xml" />
<EmbeddedResource Include="CodeGenReferences\TypeDefinitions.xml" />
<EmbeddedResource Include="CodeGenReferences\UnexpectedElementsAndAttributes.xml" />
<EmbeddedResource Include="CodeGenReferences\UpperCamelCaseWithNamespacePrefix.xml" />
<EmbeddedResource Include="CodeGenReferences\UpperCamelCaseWithoutNamespacePrefix.xml" />
<Content Include="TestMetadataCsdl.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ internal static string GetFileContent(string fileName)
return LoadContentFromBaseline(fileName);
}

internal static string GetAbsoluteUriOfFile(string fileName)
{
var outPutDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
var filePath = Path.Combine(outPutDirectory, $"CodeGenReferences\\{fileName}");
return filePath;
}

private const string BaseName = "ODataConnectedService.Tests.CodeGenReferences.";
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();

Expand Down Expand Up @@ -493,6 +500,25 @@ private static string LoadContentFromBaseline(string key)

#endregion

#region MultiReferenceModelRelativeUri

public static string EdmxWithMultiReferenceModelRelativeUriFilePath = GetAbsoluteUriOfFile("MultiReferenceModelRelativeUri.xml");

public static string MultiReferenceModelRelativeUriCSharp = LoadContentFromBaseline("MultiReferenceModelRelativeUri.cs");
public static string MultiReferenceModelRelativeUriVB = LoadContentFromBaseline("MultiReferenceModelRelativeUri.vb");

public static ODataT4CodeGeneratorTestsDescriptor MultiReferenceModelRelativeUri = new ODataT4CodeGeneratorTestsDescriptor()
{
ExpectedResults = new Dictionary<string, string>()
{
{ ExpectedCSharp, MultiReferenceModelRelativeUriCSharp },
{ ExpectedVB, MultiReferenceModelRelativeUriVB },
},
Verify = (code, isCSharp, useDSC) => VerifyGeneratedCode(code, MultiReferenceModelRelativeUri.ExpectedResults, isCSharp, useDSC, "MultiReferenceModelRelativeUri"),
};

#endregion

#region UpperCamelCaseWithNamespacePrefix

public static string EdmxUpperCamelCaseWithNamespacePrefix = LoadContentFromBaseline("UpperCamelCaseWithNamespacePrefix.xml");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,16 @@ public void CodeGenWithMultiReferenceModel()
//ODataT4CodeGeneratorTestDescriptors.MultiReferenceModel.Verify(code, false/*isCSharp*/, true/*useDSC*/);
}

[TestMethod]
public void CodeGenWithMultiReferenceModelRelativeUri()
{
string code = CodeGenWithT4Template(ODataT4CodeGeneratorTestDescriptors.MultiReferenceModelRelativeUri.Metadata, null, true, false, metadataDocumentUri: ODataT4CodeGeneratorTestDescriptors.EdmxWithMultiReferenceModelRelativeUriFilePath );
ODataT4CodeGeneratorTestDescriptors.MultiReferenceModelRelativeUri.Verify(code, true /*isCSharp*/, false /*useDSC*/);

code = CodeGenWithT4Template(ODataT4CodeGeneratorTestDescriptors.MultiReferenceModelRelativeUri.Metadata, null, false, false, metadataDocumentUri: ODataT4CodeGeneratorTestDescriptors.EdmxWithMultiReferenceModelRelativeUriFilePath);
ODataT4CodeGeneratorTestDescriptors.MultiReferenceModelRelativeUri.Verify(code, false/*isCSharp*/, false/*useDSC*/);
}

[TestMethod]
public void CodeGenWithUpperCamelCaseWithNamespacePrefix()
{
Expand Down Expand Up @@ -538,7 +548,7 @@ private static string CodeGenWithT4Template(string edmx, string namespacePrefix,
bool useDataServiceCollection, bool enableNamingAlias = false,
bool ignoreUnexpectedElementsAndAttributes = false,
Func<Uri, WebProxy, IList<string>, XmlReader> getReferencedModelReaderFunc = null,
bool appendDSCSuffix = false, string MetadataFilePath = null, bool generateMultipleFiles = false,
bool appendDSCSuffix = false, string MetadataFilePath = null, bool generateMultipleFiles = false, string metadataDocumentUri = null,
IEnumerable<string> excludedSchemaTypes = default(List<string>))

{
Expand Down Expand Up @@ -568,6 +578,11 @@ private static string CodeGenWithT4Template(string edmx, string namespacePrefix,
ExcludedSchemaTypes = excludedSchemaTypes
};

if (!String.IsNullOrEmpty(metadataDocumentUri))
{
t4CodeGenerator.MetadataDocumentUri = metadataDocumentUri;
}

if (!String.IsNullOrEmpty(MetadataFilePath))
{
t4CodeGenerator.MetadataFilePath = MetadataFilePath;
Expand Down

0 comments on commit ef08797

Please sign in to comment.