-
Notifications
You must be signed in to change notification settings - Fork 174
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented missing conversion infrastructure for IFC4x3
- Loading branch information
1 parent
4112e60
commit a0908d5
Showing
3 changed files
with
313 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,260 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Collections.Specialized; | ||
using System.ComponentModel; | ||
using System.Linq; | ||
using Xbim.Common.Exceptions; | ||
|
||
namespace Xbim.Common.Collections | ||
{ | ||
public class ProxyNestedValueSet<TInner, TOuter> : IItemSet<IItemSet<TOuter>>, IList | ||
{ | ||
private readonly IItemSet<IItemSet<TInner>> _inner; | ||
private readonly Func<TInner, TOuter> _toOut; | ||
private readonly Func<TOuter, TInner> _toIn; | ||
|
||
public event NotifyCollectionChangedEventHandler CollectionChanged; | ||
public event PropertyChangedEventHandler PropertyChanged; | ||
|
||
private IList List { get { return _inner as IList; } } | ||
|
||
public int Count => _inner.Count; | ||
|
||
public bool IsReadOnly => false; | ||
|
||
public IPersistEntity OwningEntity => _inner.OwningEntity; | ||
|
||
public bool IsFixedSize => false; | ||
|
||
public object SyncRoot => _inner; | ||
|
||
public bool IsSynchronized => true; | ||
|
||
object IList.this[int index] { get => this[index]; set => this[index] = value as IItemSet<TOuter>; } | ||
|
||
public IItemSet<TOuter> this[int index] { | ||
get | ||
{ | ||
var iset = _inner[index]; | ||
return new ProxyValueSet<TInner, TOuter>(iset, _toOut, _toIn); | ||
} | ||
set | ||
{ | ||
if (value == null) | ||
{ | ||
_inner[index] = null; | ||
return; | ||
} | ||
|
||
var iset = _inner.GetAt(index); | ||
iset.AddRange(value.Select(v => _toIn(v))); | ||
} | ||
} | ||
|
||
public ProxyNestedValueSet(IItemSet<IItemSet<TInner>> inner, Func<TInner, TOuter> toOut, Func<TOuter, TInner> toIn) | ||
{ | ||
_inner = inner; | ||
_toOut = toOut; | ||
_toIn = toIn; | ||
|
||
if (List == null) | ||
throw new XbimException("Inner list must implement IList"); | ||
|
||
// forward notifications | ||
_inner.CollectionChanged += (s, a) => | ||
{ | ||
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(a.Action)); | ||
}; | ||
_inner.PropertyChanged += (s, a) => | ||
{ | ||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(a.PropertyName)); | ||
}; | ||
} | ||
|
||
public IItemSet<TOuter> GetAt(int index) | ||
{ | ||
var iset = _inner.GetAt(index); | ||
return new ProxyValueSet<TInner, TOuter>(iset, _toOut, _toIn); | ||
} | ||
|
||
public void AddRange(IEnumerable<IItemSet<TOuter>> values) | ||
{ | ||
var idx = _inner.Count; | ||
foreach (var set in values) | ||
{ | ||
_inner.GetAt(idx).AddRange(set.Select(v => _toIn(v))); | ||
idx++; | ||
} | ||
} | ||
|
||
public IItemSet<TOuter> FirstOrDefault(Func<IItemSet<TOuter>, bool> predicate) | ||
{ | ||
var set = _inner.FirstOrDefault(i => predicate(new ProxyValueSet<TInner, TOuter>(i, _toOut, _toIn))); | ||
if (set == null) | ||
return null; | ||
return new ProxyValueSet<TInner, TOuter>(set, _toOut, _toIn); | ||
} | ||
|
||
TF IItemSet<IItemSet<TOuter>>.FirstOrDefault<TF>(Func<TF, bool> predicate) | ||
{ | ||
return _inner | ||
.Select(i => new ProxyValueSet<TInner, TOuter>(i, _toOut, _toIn)) | ||
.OfType<TF>() | ||
.FirstOrDefault(predicate); | ||
} | ||
|
||
public IEnumerable<TW> Where<TW>(Func<TW, bool> predicate) where TW : IItemSet<TOuter> | ||
{ | ||
return _inner | ||
.Select(i => new ProxyValueSet<TInner, TOuter>(i, _toOut, _toIn)) | ||
.OfType<TW>() | ||
.Where(predicate); | ||
} | ||
|
||
public int IndexOf(IItemSet<TOuter> item) | ||
{ | ||
var inner = item.Select(i => _toIn(i)).ToList(); | ||
var find = _inner.FirstOrDefault(i => inner.SequenceEqual(i)); | ||
if (find == null) | ||
return -1; | ||
return _inner.IndexOf(find); | ||
} | ||
|
||
public void Insert(int index, IItemSet<TOuter> item) | ||
{ | ||
this[index] = item; | ||
} | ||
|
||
public void RemoveAt(int index) | ||
{ | ||
_inner.RemoveAt(index); | ||
} | ||
|
||
public void Add(IItemSet<TOuter> item) | ||
{ | ||
_inner.GetAt(_inner.Count).AddRange(item.Select(i => _toIn(i))); | ||
} | ||
|
||
public void Clear() | ||
{ | ||
_inner.Clear(); | ||
} | ||
|
||
public bool Contains(IItemSet<TOuter> item) | ||
{ | ||
return IndexOf(item) > -1; | ||
} | ||
|
||
public void CopyTo(IItemSet<TOuter>[] array, int arrayIndex) | ||
{ | ||
for (int i = 0; i < _inner.Count; i++) | ||
{ | ||
array[arrayIndex + i] = new ProxyValueSet<TInner, TOuter>(_inner[i], _toOut, _toIn); | ||
} | ||
} | ||
|
||
public bool Remove(IItemSet<TOuter> item) | ||
{ | ||
var idx = IndexOf(item); | ||
if (idx < 0) | ||
return false; | ||
|
||
RemoveAt(idx); | ||
return true; | ||
} | ||
|
||
public IEnumerator<IItemSet<TOuter>> GetEnumerator() | ||
{ | ||
return new ProxyEnumerator(this); | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() | ||
{ | ||
return GetEnumerator(); | ||
} | ||
|
||
public int Add(object value) | ||
{ | ||
if (!(value is IItemSet<TOuter> set)) | ||
throw new ArgumentException("Invalid type", nameof(value)); | ||
|
||
Add(set); | ||
return Count - 1; | ||
} | ||
|
||
public bool Contains(object value) | ||
{ | ||
if (!(value is IItemSet<TOuter> set)) | ||
throw new ArgumentException("Invalid type", nameof(value)); | ||
|
||
return Contains(set); | ||
} | ||
|
||
public int IndexOf(object value) | ||
{ | ||
if (!(value is IItemSet<TOuter> set)) | ||
throw new ArgumentException("Invalid type", nameof(value)); | ||
|
||
return IndexOf(set); | ||
} | ||
|
||
public void Insert(int index, object value) | ||
{ | ||
if (!(value is IItemSet<TOuter> set)) | ||
throw new ArgumentException("Invalid type", nameof(value)); | ||
|
||
Insert(index, set); | ||
} | ||
|
||
public void Remove(object value) | ||
{ | ||
if (!(value is IItemSet<TOuter> set)) | ||
throw new ArgumentException("Invalid type", nameof(value)); | ||
|
||
Remove(set); | ||
} | ||
|
||
public void CopyTo(Array array, int index) | ||
{ | ||
for (int i = 0; i < _inner.Count; i++) | ||
array.SetValue(new ProxyValueSet<TInner, TOuter>(_inner[i], _toOut, _toIn), index + i); | ||
} | ||
|
||
private class ProxyEnumerator : IEnumerator<IItemSet<TOuter>> | ||
{ | ||
private ProxyNestedValueSet<TInner, TOuter> inner; | ||
private IItemSet<TOuter> current; | ||
private int currentIdx = -1; | ||
|
||
public ProxyEnumerator(ProxyNestedValueSet<TInner, TOuter> inner) | ||
{ | ||
this.inner = inner; | ||
} | ||
|
||
public IItemSet<TOuter> Current => current; | ||
|
||
object IEnumerator.Current => current; | ||
|
||
public void Dispose() | ||
{ | ||
inner = null; | ||
} | ||
|
||
public bool MoveNext() | ||
{ | ||
currentIdx++; | ||
if (currentIdx > (inner.Count -1)) | ||
return false; | ||
|
||
current = inner[currentIdx]; | ||
return true; | ||
} | ||
|
||
public void Reset() | ||
{ | ||
currentIdx = -1; | ||
} | ||
} | ||
} | ||
} |
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,42 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Xbim.Common.Metadata; | ||
|
||
namespace Xbim.Ifc4.Interfaces | ||
{ | ||
/// <summary> | ||
/// This helper is using reflection because IfcValue types are identicla between IFC4 and IFC4x3 | ||
/// </summary> | ||
public static class IfcValueHelper | ||
{ | ||
|
||
private static ExpressMetaData _ifc4meta; | ||
private static ExpressMetaData _ifc4x3meta; | ||
|
||
private static ExpressMetaData Ifc4Meta => _ifc4meta ?? (_ifc4meta = ExpressMetaData.GetMetadata(typeof(Ifc4.Interfaces.IIfcValue).Module)); | ||
private static ExpressMetaData Ifc4x3Meta => _ifc4x3meta ?? (_ifc4x3meta = ExpressMetaData.GetMetadata(typeof(Ifc4x3.MeasureResource.IfcValue).Module)); | ||
|
||
public static Ifc4.Interfaces.IIfcValue ToIfc4(this Ifc4x3.MeasureResource.IfcValue value) | ||
{ | ||
if (value == null) | ||
return null; | ||
var name = value.GetType().Name.ToUpperInvariant(); | ||
if (!Ifc4Meta.TryGetExpressType(name, out ExpressType type)) | ||
throw new NotSupportedException(); | ||
return Activator.CreateInstance(type.Type, value.Value) as IIfcValue; | ||
} | ||
|
||
public static Ifc4x3.MeasureResource.IfcValue ToIfc3(this Ifc4.Interfaces.IIfcValue value) | ||
{ | ||
if (value == null) | ||
return null; | ||
var name = value.GetType().Name.ToUpperInvariant(); | ||
if (!Ifc4x3Meta.TryGetExpressType(name, out ExpressType type)) | ||
throw new NotSupportedException(); | ||
return Activator.CreateInstance(type.Type, value.Value) as Ifc4x3.MeasureResource.IfcValue; | ||
} | ||
} | ||
} |