-
Notifications
You must be signed in to change notification settings - Fork 343
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2918 from FirelyTeam/6.0/add-support-for-overflow
#2901 Add support for overflow to POCOs
- Loading branch information
Showing
530 changed files
with
56,478 additions
and
662 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Hl7.Fhir.Model; | ||
|
||
public abstract partial class Base: IReadOnlyDictionary<string,object>, IDictionary<string, object> | ||
{ | ||
private object get(string key) => | ||
this.TryGetValue(key, out var value) | ||
? value | ||
: throw new KeyNotFoundException($"Element '{key}' is not a known FHIR element or has no value."); | ||
|
||
public IReadOnlyDictionary<string, object> AsReadOnlyDictionary() => this; | ||
public IDictionary<string, object> AsDictionary() => this; | ||
|
||
#region IReadOnlyDictionary | ||
|
||
IEnumerable<string> IReadOnlyDictionary<string, object>.Keys => GetElementPairs().Select(kvp => kvp.Key); | ||
IEnumerable<object> IReadOnlyDictionary<string, object>.Values => GetElementPairs().Select(kvp => kvp.Value); | ||
int IReadOnlyCollection<KeyValuePair<string, object>>.Count => GetElementPairs().Count(); | ||
object IReadOnlyDictionary<string, object>.this[string key] => get(key); | ||
|
||
bool IReadOnlyDictionary<string, object>.TryGetValue(string key, out object value) => | ||
TryGetValue(key, out value!); | ||
|
||
bool IReadOnlyDictionary<string, object>.ContainsKey(string key) => TryGetValue(key, out _); | ||
|
||
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator() => | ||
GetElementPairs().GetEnumerator(); | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => GetElementPairs().GetEnumerator(); | ||
|
||
#endregion | ||
|
||
#region IDictionary | ||
|
||
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item) => | ||
AsDictionary().Add(item.Key, item.Value); | ||
|
||
void ICollection<KeyValuePair<string, object>>.Clear() | ||
{ | ||
// Slow.... | ||
foreach (var kvp in this) | ||
SetValue(kvp.Key, null); | ||
} | ||
|
||
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item) => | ||
TryGetValue(item.Key, out _); // we don't care about the item, we cannot have the same key twice. | ||
|
||
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) | ||
{ | ||
foreach (var kvp in this) | ||
array[arrayIndex++] = kvp; | ||
} | ||
|
||
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item) => | ||
AsDictionary().Remove(item.Key); | ||
|
||
int ICollection<KeyValuePair<string, object>>.Count => AsReadOnlyDictionary().Count; | ||
bool ICollection<KeyValuePair<string, object>>.IsReadOnly => false; | ||
ICollection<object> IDictionary<string, object>.Values => AsReadOnlyDictionary().Values.ToList(); | ||
ICollection<string> IDictionary<string, object>.Keys => AsReadOnlyDictionary().Keys.ToList(); | ||
bool IDictionary<string, object>.TryGetValue(string key, out object value) => TryGetValue(key, out value!); | ||
|
||
object IDictionary<string, object>.this[string key] | ||
{ | ||
get => this.AsReadOnlyDictionary()[key]; | ||
set => SetValue(key, value); | ||
} | ||
|
||
void IDictionary<string, object>.Add(string key, object value) | ||
{ | ||
if (TryGetValue(key, out _)) | ||
throw new ArgumentException($"An element with the key '{key}' already exists in the dictionary."); | ||
|
||
SetValue(key, value); | ||
} | ||
|
||
bool IDictionary<string, object>.ContainsKey(string key) => TryGetValue(key, out _); | ||
|
||
bool IDictionary<string, object>.Remove(string key) | ||
{ | ||
var existed = TryGetValue(key, out _); | ||
SetValue(key, null); | ||
return existed; | ||
} | ||
|
||
#endregion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,90 +1,134 @@ | ||
/* | ||
Copyright (c) 2011-2012, HL7, Inc | ||
All rights reserved. | ||
Redistribution and use in source and binary forms, with or without modification, | ||
Redistribution and use in source and binary forms, with or without modification, | ||
are permitted provided that the following conditions are met: | ||
* Redistributions of source code must retain the above copyright notice, this | ||
* Redistributions of source code must retain the above copyright notice, this | ||
list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
* Redistributions in binary form must reproduce the above copyright notice, | ||
this list of conditions and the following disclaimer in the documentation | ||
and/or other materials provided with the distribution. | ||
* Neither the name of HL7 nor the names of its contributors may be used to | ||
endorse or promote products derived from this software without specific | ||
* Neither the name of HL7 nor the names of its contributors may be used to | ||
endorse or promote products derived from this software without specific | ||
prior written permission. | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | ||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | ||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | ||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
using Hl7.Fhir.Introspection; | ||
#nullable enable | ||
|
||
using Hl7.Fhir.Model; | ||
using Hl7.Fhir.Utility; | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.ComponentModel; | ||
using System.ComponentModel.DataAnnotations; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Runtime.Serialization; | ||
using System.Threading; | ||
using DataType = System.ComponentModel.DataAnnotations.DataType; | ||
|
||
namespace Hl7.Fhir.Model; | ||
|
||
namespace Hl7.Fhir.Model | ||
public abstract partial class Base : IDeepCopyable, IDeepComparable, | ||
IAnnotated, IAnnotatable, IValidatableObject, INotifyPropertyChanged | ||
{ | ||
public abstract partial class Base : IDeepCopyable, IDeepComparable, | ||
IAnnotated, IAnnotatable, IValidatableObject, INotifyPropertyChanged, IReadOnlyDictionary<string, object> | ||
{ | ||
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) => Enumerable.Empty<ValidationResult>(); | ||
/// <summary> | ||
/// FHIR Type Name | ||
/// </summary> | ||
public virtual string TypeName => GetType().Name; | ||
|
||
|
||
private Dictionary<string, object>? _overflow = null; | ||
|
||
/// <summary> | ||
/// A dictionary containing all elements that are not explicitly defined in the class. | ||
/// </summary> | ||
protected Dictionary<string, object> Overflow => | ||
LazyInitializer.EnsureInitialized(ref _overflow, () => new Dictionary<string, object>())!; | ||
|
||
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) => []; | ||
|
||
#region << Annotations >> | ||
[NonSerialized] | ||
private AnnotationList _annotations = null; | ||
#region << Annotations >> | ||
|
||
private AnnotationList annotations => LazyInitializer.EnsureInitialized(ref _annotations, () => new()); | ||
[NonSerialized] private AnnotationList? _annotations = null; | ||
|
||
public IEnumerable<object> Annotations(Type type) => annotations.OfType(type); | ||
private AnnotationList annotations => LazyInitializer.EnsureInitialized(ref _annotations, () => [])!; | ||
|
||
public void AddAnnotation(object annotation) => annotations.AddAnnotation(annotation); | ||
public IEnumerable<object> Annotations(Type type) => annotations.OfType(type); | ||
|
||
public void RemoveAnnotations(Type type) => annotations.RemoveAnnotations(type); | ||
#endregion | ||
public void AddAnnotation(object annotation) => annotations.AddAnnotation(annotation); | ||
|
||
#region INotifyPropertyChanged | ||
public void RemoveAnnotations(Type type) => annotations.RemoveAnnotations(type); | ||
|
||
public event PropertyChangedEventHandler PropertyChanged; | ||
#endregion | ||
|
||
protected virtual void OnPropertyChanged(String property) => | ||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); | ||
#region INotifyPropertyChanged | ||
|
||
#endregion | ||
public event PropertyChangedEventHandler? PropertyChanged; | ||
|
||
public IReadOnlyDictionary<string, object> AsReadOnlyDictionary() => this; | ||
protected virtual void OnPropertyChanged(string property) => | ||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); | ||
|
||
#region IReadOnlyDictionary | ||
IEnumerable<string> IReadOnlyDictionary<string, object>.Keys => GetElementPairs().Select(kvp => kvp.Key); | ||
#endregion | ||
|
||
IEnumerable<object> IReadOnlyDictionary<string, object>.Values => GetElementPairs().Select(kvp => kvp.Value); | ||
protected virtual Base SetValue(string key, object? value) | ||
{ | ||
if (value is null) | ||
Overflow.Remove(key); | ||
else | ||
Overflow[key] = value; | ||
|
||
return this; | ||
} | ||
|
||
int IReadOnlyCollection<KeyValuePair<string, object>>.Count => GetElementPairs().Count(); | ||
protected virtual bool TryGetValue(string key, [NotNullWhen(true)] out object? value) => | ||
Overflow.TryGetValue(key, out value); | ||
|
||
object IReadOnlyDictionary<string, object>.this[string key] => TryGetValue(key, out var value) ? value : throw new KeyNotFoundException(); | ||
protected virtual IEnumerable<KeyValuePair<string, object>> GetElementPairs() => Overflow; | ||
|
||
bool IReadOnlyDictionary<string, object>.ContainsKey(string key) => TryGetValue(key, out _); | ||
// TODO bring Children + NamedChildren over as well. | ||
} | ||
|
||
IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator() => GetElementPairs().GetEnumerator(); | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => GetElementPairs().GetEnumerator(); | ||
/// <summary> | ||
/// A dynamic data type that can hold any element. | ||
/// </summary> | ||
public class DynamicDataType : DataType | ||
{ | ||
public void Add(string arg1, object arg2) => this.SetValue(arg1, arg2); | ||
|
||
bool IReadOnlyDictionary<string, object>.TryGetValue(string key, out object value) => TryGetValue(key, out value); | ||
#endregion | ||
public object this[string key] | ||
{ | ||
get => this.AsReadOnlyDictionary()[key]; | ||
set => SetValue(key, value); | ||
} | ||
} | ||
|
||
|
||
/// <summary> | ||
/// A dynamic resource that can hold any element. | ||
/// </summary> | ||
public class DynamicResource : Resource | ||
{ | ||
public void Add(string arg1, object arg2) => this.SetValue(arg1, arg2); | ||
|
||
public object this[string key] | ||
{ | ||
get => this.AsReadOnlyDictionary()[key]; | ||
set => SetValue(key, value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.