Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions Tests/CultureSensitivityTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System.Globalization;
using Xbim.Ifc;
using Xbim.Ifc4;
using Xbim.Ifc4.Interfaces;
using Xbim.Ifc4.MeasureResource;
using Xbim.IO.Memory;
using Xunit;

Expand Down Expand Up @@ -32,5 +35,91 @@ public void Can_read_ifcxml_regardless_of_current_culture(string culture)
CultureInfo.CurrentCulture = previous;
}
}

[Theory]
[InlineData("en-US")]
[InlineData("tr-TR")]
public void Can_query_OfType_by_type_name_regardless_of_current_culture(string culture)
{
var previous = CultureInfo.CurrentCulture;
try
{
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(culture);

// a threshold of 0 forces the Esent database store rather than the memory model
using var store = IfcStore.Open(@"TestFiles\SampleHouse4.ifc", null, 0);

// the type name has to contain a lower case 'i' for the Turkish casing to bite:
// "IfcWall" upper-cases identically in every culture, "IfcBuilding" does not
Assert.NotEmpty(store.Instances.OfType("IfcBuilding", false));
}
finally
{
CultureInfo.CurrentCulture = previous;
}
}

[Theory]
[InlineData("en-US")]
[InlineData("tr-TR")]
public void Imperial_unit_symbol_is_detected_regardless_of_current_culture(string culture)
{
var previous = CultureInfo.CurrentCulture;
try
{
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(culture);

using var model = new MemoryModel(new EntityFactoryIfc4());
using var txn = model.BeginTransaction("unit");
var unit = model.Instances.New<IfcConversionBasedUnit>(u =>
{
u.Name = "inch";
u.UnitType = IfcUnitEnum.LENGTHUNIT;
u.Dimensions = model.Instances.New<IfcDimensionalExponents>(d =>
{
d.LengthExponent = 1;
d.MassExponent = 0;
d.TimeExponent = 0;
d.ElectricCurrentExponent = 0;
d.ThermodynamicTemperatureExponent = 0;
d.AmountOfSubstanceExponent = 0;
d.LuminousIntensityExponent = 0;
});
});

// "inch".ToUpper() is "İNCH" under tr-TR and does not contain "INCH"
Assert.Equal("in", unit.Symbol);
}
finally
{
CultureInfo.CurrentCulture = previous;
}
}

[Theory]
[InlineData("en-US")]
[InlineData("tr-TR")]
public void Case_insensitive_property_set_lookup_works_regardless_of_current_culture(string culture)
{
var previous = CultureInfo.CurrentCulture;
try
{
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(culture);

using var model = new MemoryModel(new EntityFactoryIfc4());
using var txn = model.BeginTransaction("psets");
var pile = model.Instances.New<Xbim.Ifc4.StructuralElementsDomain.IfcPile>();
var pset = model.Instances.New<Xbim.Ifc4.Kernel.IfcPropertySet>(p => p.Name = "Pset_WindowCommon");
pile.AddPropertySet(pset);

// 'i' and 'I' are different letters under the Turkish casing rules, so a
// culture-sensitive case-insensitive comparison does not match here
Assert.NotNull(pile.GetPropertySet("PSET_WINDOWCOMMON", caseSensitive: false));
}
finally
{
CultureInfo.CurrentCulture = previous;
}
}
}
}
2 changes: 1 addition & 1 deletion Xbim.IO.Esent/Esent/PersistedEntityInstanceCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2536,7 +2536,7 @@ internal XbimGeometryHandle GetGeometryHandle(int geometryLabel)
internal IEnumerable<IPersistEntity> OfType(string stringType, bool activate)
{

var ot = Model.Metadata.ExpressType(stringType.ToUpper());
var ot = Model.Metadata.ExpressType(stringType.ToUpperInvariant());
if (ot == null)
{
// it could be that we're searching for an interface
Expand Down
14 changes: 12 additions & 2 deletions Xbim.Ifc2x3/Kernel/IfcObjectPartial.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,20 @@ public void AddPropertySet(IfcPropertySet pSet)
/// <param name="pSetName"></param>
/// <param name="caseSensitive"></param>
/// <returns></returns>

public IfcPropertySet GetPropertySet(string pSetName, bool caseSensitive = true)
{
return PropertySets.FirstOrDefault(ps=>string.Compare(ps.Name,pSetName,!caseSensitive)==0);
return PropertySets.FirstOrDefault(ps => string.Equals(ps.Name, pSetName, Comparison(caseSensitive)));
}

// Property set names are IFC identifiers, so a case-insensitive match must be ordinal:
// the culture-sensitive comparison treats 'i' and 'I' as different letters under tr-TR.
private static StringComparison Comparison(bool caseSensitive)
{
return caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
}


public IfcPropertySingleValue GetPropertySingleValue(string pSetName, string propertyName)
{
var pset = GetPropertySet(pSetName);
Expand Down Expand Up @@ -208,7 +217,7 @@ public Ifc4.Interfaces.IIfcElementQuantity GetElementQuantity(string pSetName, b
{
IfcRelDefinesByProperties rel = caseSensitive ?
IsDefinedByProperties.FirstOrDefault(r => r.RelatingPropertyDefinition.Name == pSetName && r.RelatingPropertyDefinition is Ifc4.Interfaces.IIfcElementQuantity)
: IsDefinedByProperties.FirstOrDefault(r => r.RelatingPropertyDefinition.Name.ToString().ToLower() == pSetName.ToLower() && r.RelatingPropertyDefinition is Ifc4.Interfaces.IIfcElementQuantity);
: IsDefinedByProperties.FirstOrDefault(r => string.Equals(r.RelatingPropertyDefinition.Name, pSetName, StringComparison.OrdinalIgnoreCase) && r.RelatingPropertyDefinition is Ifc4.Interfaces.IIfcElementQuantity);
if (rel != null) return rel.RelatingPropertyDefinition as Ifc4.Interfaces.IIfcElementQuantity;
return null;
}
Expand Down Expand Up @@ -399,6 +408,7 @@ public enum XbimQuantityTypeEnum
Count,
Weight,
Time

}

}
144 changes: 72 additions & 72 deletions Xbim.Ifc2x3/Kernel/IfcTypeObjectPartial.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Xbim.Ifc2x3.MeasureResource;
using Xbim.Ifc2x3.ProductExtension;
using Xbim.Ifc2x3.PropertyResource;
using Xbim.Ifc2x3.QuantityResource;

namespace Xbim.Ifc2x3.Kernel
{
public partial class IfcTypeObject
{
public void AddPropertySet(IfcPropertySetDefinition pSetDefinition)
{
HasPropertySets.Add(pSetDefinition);
}

/// <summary>
/// Returns the propertyset of the specified name, null if it does not exist
/// </summary>
/// <param name="pSetName"></param>
/// <param name="caseSensitive"></param>
/// <returns></returns>
public IfcPropertySet GetPropertySet(string pSetName, bool caseSensitive = true)
{
if (HasPropertySets == null) return null;
using System;
using System.Collections.Generic;
using System.Linq;
using Xbim.Ifc2x3.MeasureResource;
using Xbim.Ifc2x3.ProductExtension;
using Xbim.Ifc2x3.PropertyResource;
using Xbim.Ifc2x3.QuantityResource;
namespace Xbim.Ifc2x3.Kernel
{
public partial class IfcTypeObject
{
public void AddPropertySet(IfcPropertySetDefinition pSetDefinition)
{
HasPropertySets.Add(pSetDefinition);
}
/// <summary>
/// Returns the propertyset of the specified name, null if it does not exist
/// </summary>
/// <param name="pSetName"></param>
/// <param name="caseSensitive"></param>
/// <returns></returns>
public IfcPropertySet GetPropertySet(string pSetName, bool caseSensitive = true)
{
if (HasPropertySets == null) return null;
return caseSensitive ?
HasPropertySets.FirstOrDefault<IfcPropertySet>(r => r.Name == pSetName) :
HasPropertySets.FirstOrDefault<IfcPropertySet>(r => string.Equals(r.Name.ToString(), pSetName, StringComparison.CurrentCultureIgnoreCase));
}

HasPropertySets.FirstOrDefault<IfcPropertySet>(r => string.Equals(r.Name, pSetName, StringComparison.OrdinalIgnoreCase));
}
public IfcPropertySingleValue GetPropertySingleValue(string pSetName, string propertyName)
{
var pset = GetPropertySet(pSetName);
Expand All @@ -44,36 +44,36 @@ public IfcValue GetPropertySingleValueValue(string pSetName, string propertyName
}

public IEnumerable<IfcPropertySet> PropertySets
{
get
{
if (HasPropertySets != null) return HasPropertySets.OfType<IfcPropertySet>();
return Enumerable.Empty<IfcPropertySet>();
}
{
get
{
if (HasPropertySets != null) return HasPropertySets.OfType<IfcPropertySet>();
return Enumerable.Empty<IfcPropertySet>();
}
}

public IDictionary<IfcLabel, Dictionary<IfcIdentifier, IfcValue>> PropertySingleValues
{
get
{
var result = new Dictionary<IfcLabel, Dictionary<IfcIdentifier, IfcValue>>();
var pSets = HasPropertySets;
if (pSets == null) return result;
var pSetsPure = pSets.OfType<IfcPropertySet>();
foreach (var pSet in pSetsPure)
{
var value = new Dictionary<IfcIdentifier, IfcValue>();
IfcLabel psetName = pSet.Name ?? new IfcLabel("Undefined");
foreach (var prop in pSet.HasProperties)
{
var singleVal = prop as IfcPropertySingleValue;
if (singleVal == null) continue;
value.Add(prop.Name, singleVal.NominalValue);
}
result.Add(psetName, value);
}
return result;
}
{
get
{
var result = new Dictionary<IfcLabel, Dictionary<IfcIdentifier, IfcValue>>();
var pSets = HasPropertySets;
if (pSets == null) return result;
var pSetsPure = pSets.OfType<IfcPropertySet>();
foreach (var pSet in pSetsPure)
{
var value = new Dictionary<IfcIdentifier, IfcValue>();
IfcLabel psetName = pSet.Name ?? new IfcLabel("Undefined");
foreach (var prop in pSet.HasProperties)
{
var singleVal = prop as IfcPropertySingleValue;
if (singleVal == null) continue;
value.Add(prop.Name, singleVal.NominalValue);
}
result.Add(psetName, value);
}
return result;
}
}

public IfcPropertySingleValue SetPropertySingleValue(string pSetName, string propertyName, IfcValue value)
Expand Down Expand Up @@ -106,7 +106,7 @@ public IfcPropertySingleValue SetPropertySingleValue(string pSetName, string pro
public IfcPhysicalSimpleQuantity GetElementPhysicalSimpleQuantity(string pSetName, string qualityName)
{
var elementQuality = GetElementQuantity(pSetName);
return elementQuality != null ? elementQuality.Quantities.FirstOrDefault<IfcPhysicalSimpleQuantity>(sq => sq.Name == qualityName) : null;
return elementQuality != null ? elementQuality.Quantities.FirstOrDefault<IfcPhysicalSimpleQuantity>(sq => sq.Name == qualityName) : null;
}


Expand All @@ -115,24 +115,24 @@ public IfcPhysicalSimpleQuantity GetElementPhysicalSimpleQuantity(string pSetNam
/// </summary>
/// <returns>All physical simple quantities (like length, area, volume, count, etc.)</returns>
public IEnumerable<IfcPhysicalSimpleQuantity> PhysicalSimpleQuantities
{
get
{
return ElementQuantities.SelectMany(eq => eq.Quantities).OfType<IfcPhysicalSimpleQuantity>();
}
{
get
{
return ElementQuantities.SelectMany(eq => eq.Quantities).OfType<IfcPhysicalSimpleQuantity>();
}
}

/// <summary>
/// Use this method to get all element quantities related to this object
/// </summary>
/// <returns>All related element quantities</returns>
public IEnumerable<IfcElementQuantity> ElementQuantities
{
get
{
if (HasPropertySets != null) return HasPropertySets.OfType<IfcElementQuantity>();
return Enumerable.Empty<IfcElementQuantity>();
}
{
get
{
if (HasPropertySets != null) return HasPropertySets.OfType<IfcElementQuantity>();
return Enumerable.Empty<IfcElementQuantity>();
}
}

public IfcElementQuantity GetElementQuantity(string pSetName, bool caseSensitive = true)
Expand All @@ -141,10 +141,10 @@ public IfcElementQuantity GetElementQuantity(string pSetName, bool caseSensitiv

return caseSensitive ?
HasPropertySets.FirstOrDefault<IfcElementQuantity>(r => r.Name == pSetName) :
HasPropertySets.FirstOrDefault<IfcElementQuantity>(r => r.Name.ToString().ToLower() == pSetName.ToLower());
HasPropertySets.FirstOrDefault<IfcElementQuantity>(r => string.Equals(r.Name, pSetName, StringComparison.OrdinalIgnoreCase));
}



}
}
}
}
14 changes: 11 additions & 3 deletions Xbim.Ifc2x3/MeasureResource/IfcConversionBasedUnitPartial.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
namespace Xbim.Ifc2x3.MeasureResource
using System;
namespace Xbim.Ifc2x3.MeasureResource
{
public partial class IfcConversionBasedUnit
{
Expand All @@ -24,16 +25,23 @@ public partial class IfcConversionBasedUnit
if (Dimensions.LengthExponent == 3) //volume
pow += '\u00B3'; //((char)0x00B3)add ³

if ((name.ToUpper().Contains("FEET")) || (name.ToUpper().Contains("FOOT")))
if (Contains(name, "FEET") || Contains(name, "FOOT"))
return "ft" + pow;

if (name.ToUpper().Contains("INCH"))
if (Contains(name, "INCH"))
return "in" + pow;

return name + pow;
}
return name;
}
}

// Ordinal, case-insensitive: name.ToUpper() is culture sensitive, so under the Turkish
// casing rules "inch" upper-cases to "İNCH" and never contains "INCH".
private static bool Contains(string name, string token)
{
return name != null && name.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0;
}
}
}
Loading