Skip to content

Commit b604a59

Browse files
authored
Merge pull request #14 from TechNinjaLabs/release/4.0.0
Release 4.0.0. - .Net 8.0 Upgrade.
2 parents 9f81e1b + 822283a commit b604a59

File tree

216 files changed

+7133
-181
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

216 files changed

+7133
-181
lines changed

.github/workflows/CI-Build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
Run-Lint:
1111
runs-on: ubuntu-latest
1212
env:
13-
github-token: '${{ secrets.GITHUB_TOKEN }}'
13+
github-token: '${{ secrets.GH_PACKAGES }}'
1414
steps:
1515
- name: Step-01 Checkout code
1616
uses: actions/checkout@v3
@@ -22,7 +22,7 @@ jobs:
2222
VALIDATE_ALL_CODEBASE: false
2323
FILTER_REGEX_INCLUDE: .*src/.*
2424
DEFAULT_BRANCH: master
25-
GITHUB_TOKEN: '${{ env.github-token }}'
25+
GITHUB_TOKEN: '${{ secrets.GH_PACKAGES }}'
2626
Build-Beta:
2727
if: ${{ !startsWith(github.head_ref, 'release/')}}
2828
runs-on: ubuntu-latest
@@ -131,7 +131,7 @@ jobs:
131131
outputs:
132132
semVersion: ${{ needs.Build-Release.outputs.semVersion }}
133133
env:
134-
github-token: '${{ secrets.GITHUB_TOKEN }}'
134+
github-token: '${{ secrets.GH_PACKAGES }}'
135135
nuget-token: '${{ secrets.NUGET_API_KEY }}'
136136
working-directory: /home/runner/work/FeatureOne/FeatureOne
137137
steps:

GitVersion.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
next-version: 3.0.0
1+
next-version: 4.0.0
22
tag-prefix: '[vV]'
33
mode: ContinuousDeployment
44
branches:

License.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023 Ninja Sha!4h
3+
Copyright (c) 2024 Tech Ninja Labs
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
# <img src="https://github.com/NinjaRocks/FeatureOne/blob/master/ninja-icon-16.png" alt="ninja" style="width:30px;"/> FeatureOne v3.0.0
1+
2+
# <img src="https://github.com/NinjaRocks/FeatureOne/blob/master/ninja-icon-16.png" alt="ninja" style="width:30px;"/> FeatureOne v4.0.0
23
[![NuGet version](https://badge.fury.io/nu/FeatureOne.svg)](https://badge.fury.io/nu/FeatureOne) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/NinjaRocks/FeatureOne/blob/master/License.md) [![build-master](https://github.com/NinjaRocks/FeatureOne/actions/workflows/Build-Master.yml/badge.svg)](https://github.com/NinjaRocks/FeatureOne/actions/workflows/Build-Master.yml) [![GitHub Release](https://img.shields.io/github/v/release/ninjarocks/FeatureOne?logo=github&sort=semver)](https://github.com/ninjarocks/FeatureOne/releases/latest)
3-
[![CodeQL](https://github.com/NinjaRocks/FeatureOne/actions/workflows/codeql.yml/badge.svg)](https://github.com/NinjaRocks/FeatureOne/actions/workflows/codeql.yml) [![.Net](https://img.shields.io/badge/.Net%206.0-blue)](https://dotnet.microsoft.com/en-us/download/dotnet/6)
4+
[![CodeQL](https://github.com/NinjaRocks/FeatureOne/actions/workflows/codeql.yml/badge.svg)](https://github.com/NinjaRocks/FeatureOne/actions/workflows/codeql.yml) [![.Net](https://img.shields.io/badge/.Net-8.0-blue)](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
45

56
.Net Library to implement feature toggles.
67
--
@@ -311,12 +312,24 @@ SQL support can easily be installed as a separate nuget package.
311312
```
312313
$ dotnet add package FeatureOne.SQL --version {latest}
313314
```
314-
Supports Db Providers `MSSQL: System.Data.SqlClient`, `ODBC: System.Data.Odbc`, `OLEDB: System.Data.OleDb`, `SQLite: System.Data.SQLite`, `MySQL: MySql.Data.MySqlClient` & `PostgreSQL: Npgsql`.
315+
### Step 1 - Configure Database Provider
316+
To register a database provider, You need to add the relevant db factory with a specific `ProviderName` to `DbProviderFactories` in the bootstrap code.
317+
ie.
318+
`DbProviderFactories.RegisterFactory("ProviderName", ProviderFactory)`
315319

320+
After adding the provider factory you need to pass the same provider in the `connection settings` of SQLConfiguration.
316321

322+
> Below is the list of most common provider factories yu could configure.
323+
>
324+
- MSSQL - DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance);
325+
- ODBC - DbProviderFactories.RegisterFactory("System.Data.Odbc", OdbcFactory.Instance);
326+
- OleDb - DbProviderFactories.RegisterFactory("System.Data.OleDb", OleDbFactory.Instance);
327+
- SQLite - DbProviderFactories.RegisterFactory("System.Data.SQLite", SQLiteFactory.Instance);
328+
- MySQL - DbProviderFactories.RegisterFactory("MySql.Data.MySqlClient", MySqlClientFactory.Instance);
329+
- PostgreSQL - DbProviderFactories.RegisterFactory("Npgsql", NpgsqlFactory.Instance);
330+
>
317331
318-
For any other SQL provider, You need to add provider factory to `DbProviderFactories.RegisterFactory("ProviderName", ProviderFactory)` and pass the provider specific `connection settings` in SQLConfiguration.
319-
### Database Setup
332+
### STEP 2 - Setup Feature Table (Database)
320333
> Requires creating a feature table with columns for feature name, toggle definition and feature archival.
321334
322335
SQL SCRIPT below.
@@ -329,7 +342,7 @@ CREATE TABLE TFeatures (
329342
);
330343
```
331344

332-
### Example Table Record
345+
#### Example Table Record
333346
> Feature toggles need to be `scripted` to backend database in JSON format.
334347
335348
Please see example entries below.
@@ -339,8 +352,8 @@ Please see example entries below.
339352
| dashboard_widget |{ "conditions":[{ "type":"Simple", "isEnabled": true }] } | false |
340353
|pen_test_dashboard| { "operator":"any", "conditions":[{ "type":"simple", "isEnabled":false}, { "type":"Regex", "claim":"email","expression":"^[a-zA-Z0-9_.+-][email protected]" }]} | false|
341354

342-
### Bootstrap initialization
343-
> See below bootstrap initialization for FeatureOne with SQL backend.
355+
### STEP 3 - Bootstrap initialization
356+
> See below bootstrap initialization for FeatureOne with MS SQL backend.
344357
345358

346359
#### SQL Configuration - Set connection string and other settings.
@@ -350,7 +363,7 @@ Please see example entries below.
350363
// provider specific connection settings.
351364
ConnectionSettings = new ConnectionSettings
352365
{
353-
Providername = DbProviderName.MSSql,
366+
Providername = "System.Data.SqlClient", -- same provider name as register with db factory.
354367
ConnectionString ="Data Source=Powerstation; Initial Catalog=Features; Integrated Security=SSPI;"
355368
},
356369
@@ -377,6 +390,9 @@ Please see example entries below.
377390
```
378391
i. With SQL configuration.
379392
```
393+
-- Register db factory
394+
DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance);
395+
380396
var storageProvider = new SQlStorageProvider(sqlConfiguration);
381397
Features.Initialize(() => new Features(new FeatureStore(storageProvider)));
382398
```

src/FeatureOne.File/FeatureOne.File.csproj

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<Nullable>disable</Nullable>
66
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
77
<GenerateAssemblyInfo>False</GenerateAssemblyInfo>
@@ -13,26 +13,28 @@
1313
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
1414
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
1515
<Title>FeatureOne.File</Title>
16-
<Authors>ninja.shayk</Authors>
17-
<Company>Ninja.Sha!4H</Company>
16+
<Authors>Tech Ninja Labs</Authors>
17+
<Company>Tech Ninja Labs</Company>
1818
<Product>FeatureOne</Product>
19-
<Description>.Net library to implement feature toggles using File system storage.</Description>
20-
<Copyright>Copyright (c) 2023 Ninja Sha!4h</Copyright>
19+
<Description>.Net library to implement feature toggles with File system storage.</Description>
20+
<Copyright>Copyright (c) 2024 Tech Ninja Labs</Copyright>
2121
<PackageReadmeFile>README.md</PackageReadmeFile>
22-
<RepositoryUrl>https://github.com/NinjaRocks/FeatureOne</RepositoryUrl>
22+
<RepositoryUrl>https://github.com/TechNinjaLabs/FeatureOne</RepositoryUrl>
2323
<RepositoryType>git</RepositoryType>
24-
<PackageTags>feature-toggle; feature-flag; feature-flags; feature-toggles; .netstandard2.1; featureOne; File-system; File-Backend; File-Toggles;</PackageTags>
25-
<Version>3.0.0</Version>
24+
<PackageTags>feature-toggle; feature-flag; feature-flags; feature-toggles; .net8.0; featureOne; File-system; File-Backend; File-Toggles;</PackageTags>
25+
<Version>4.0.0</Version>
2626
<PackageLicenseFile>License.md</PackageLicenseFile>
2727
<PackageIcon>ninja-icon-16.png</PackageIcon>
2828
<PackageReleaseNotes>
29-
Release Notes v3.0.0. - Targets .Net 6.0
30-
Adds support for File system storage provider for implementing Feature Toggles stored on file.
31-
- Provides memory caching enabled via configuration.
32-
- Added extensibility for Custom implementations-
33-
- Provides extension point to support more SQL providers.
34-
- Provides extenion point for custom caching.
35-
- Provides extension point for custom deserializer for Toggle Conditions.
29+
Release Notes v4.0.0. - Targets .Net 8.0
30+
Library to Implement Feature Toggles to hide/show program features with File system storage.
31+
- Provides Out of box Simple and Regex toggle conditions.
32+
- Provides Out of box support for File system storage provider to store toggles on disk file.
33+
- Provides the support for default memory caching via configuration.
34+
- Provides extensibility for custom implementations ie.
35+
-- Provides extensibility for implementing custom toggle conditions for bespoke use cases.
36+
-- Provides extensibility for implementing custom caching provider.
37+
-- Provides extensibility for implementing custom toggle deserializer for bespoke scenarios.
3638
</PackageReleaseNotes>
3739
</PropertyGroup>
3840

src/FeatureOne.SQL/FeatureOne.SQL.csproj

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<ImplicitUsings>disable</ImplicitUsings>
66
<Nullable>disable</Nullable>
77
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
@@ -14,27 +14,29 @@
1414
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
1515
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
1616
<Title>FeatureOne.SQL</Title>
17-
<Authors>ninja.shayk</Authors>
18-
<Company>Ninja.Sha!4H</Company>
17+
<Authors>Tech Ninja Labs</Authors>
18+
<Company>Tech Ninja Labs</Company>
1919
<Product>FeatureOne</Product>
20-
<Description>.Net library to implement feature toggles with SQL backend.</Description>
21-
<Copyright>Copyright (c) 2023 Ninja Sha!4h</Copyright>
20+
<Description>.Net library to implement feature toggles with SQL storage.</Description>
21+
<Copyright>Copyright (c) 2024 Tech Ninja Labs</Copyright>
2222
<PackageReadmeFile>README.md</PackageReadmeFile>
23-
<RepositoryUrl>https://github.com/NinjaRocks/FeatureOne</RepositoryUrl>
23+
<RepositoryUrl>https://github.com/TechNinjaLabs/FeatureOne</RepositoryUrl>
2424
<RepositoryType>git</RepositoryType>
25-
<PackageTags>feature-toggle; feature-flag; feature-flags; feature-toggles; .netstandard2.1; featureOne; SQL-Backend; SQL-Toggles; SQL</PackageTags>
26-
<Version>3.0.0</Version>
25+
<PackageTags>feature-toggle; feature-flag; feature-flags; feature-toggles; .net8.0; featureOne; SQL-Backend; SQL-Toggles; SQL</PackageTags>
26+
<Version>4.0.0</Version>
2727
<PackageLicenseFile>License.md</PackageLicenseFile>
2828
<PackageIcon>ninja-icon-16.png</PackageIcon>
2929
<PackageReleaseNotes>
30-
Release Notes v3.0.0. - Targets .Net 6.0
31-
Adds support for SQL storage provider for implementing Feature Toggles.
32-
- Supports MSSQL, SQLite, ODBC, OLEDB, MySQL, PostgreSQL Db providers.
33-
- Provides memory caching - enabled via configuration.
34-
- Added extensibility for Custom implementations-
35-
- Provides extension point to support more SQL providers.
36-
- Provides extenion point for custom caching.
37-
- Provides extension point for custom deserializer for Toggle Conditions.
30+
Release Notes v4.0.0. - Targets .Net 8.0
31+
Library to Implement Feature Toggles to hide/show program features with SQL storage.
32+
- Supports configuring all Db providers - MSSQL, SQLite, ODBC, OLEDB, MySQL, PostgreSQL.
33+
- Provides Out of box Simple and Regex toggle conditions.
34+
- Provides the support for default memory caching via configuration.
35+
- Provides extensibility for custom implementations ie.
36+
-- Provides extensibility for implementing custom toggle conditions for bespoke use cases.
37+
-- Provides extensibility to plugin other SQL providers.
38+
-- Provides extensibility for implementing custom caching providers.
39+
-- Provides extensibility for implementing custom toggle deserializer for bespoke scenarios.
3840
</PackageReleaseNotes>
3941
</PropertyGroup>
4042

@@ -54,14 +56,8 @@
5456
</ItemGroup>
5557

5658
<ItemGroup>
57-
<PackageReference Include="Npgsql" Version="7.0.4" />
5859
<PackageReference Include="System.Data.Common" Version="4.3.0" />
59-
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
60-
<PackageReference Include="System.Data.Odbc" Version="7.0.0" />
61-
<PackageReference Include="System.Data.OleDb" Version="7.0.0" />
62-
<PackageReference Include="System.Data.SQLite" Version="1.0.86" />
63-
<PackageReference Include="MySql.Data" Version="8.0.33" />
64-
<PackageReference Include="System.Text.Json" Version="7.0.1" />
60+
<PackageReference Include="System.Text.Json" Version="8.0.3" />
6561
</ItemGroup>
6662

6763
<ItemGroup>

src/FeatureOne.SQL/StorageProvider/DbRepository.cs

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,17 @@
22
using System.Collections.Generic;
33
using System.Data;
44
using System.Data.Common;
5-
using System.Data.Odbc;
6-
using System.Data.OleDb;
7-
using System.Data.SqlClient;
8-
using System.Data.SQLite;
9-
using System.Linq;
10-
using MySql.Data.MySqlClient;
11-
using Npgsql;
125

136
namespace FeatureOne.SQL.StorageProvider
147
{
158
internal class DbRepository : IDbRepository
169
{
1710
private readonly SQLConfiguration sqlConfiguration;
1811

19-
public DbRepository(SQLConfiguration configuration)
12+
public DbRepository(SQLConfiguration sqlConfiguration)
2013
{
21-
this.sqlConfiguration = configuration ?? throw new ArgumentNullException(nameof(SQLConfiguration));
22-
23-
var names = DbProviderFactories.GetProviderInvariantNames();
24-
25-
if (!names.Any(x => x.Equals("System.Data.SqlClient") && SqlClientFactory.Instance != null))
26-
DbProviderFactories.RegisterFactory("System.Data.SqlClient", SqlClientFactory.Instance);
27-
28-
if (!names.Any(x => x.Equals("System.Data.Odbc")) && OdbcFactory.Instance != null)
29-
DbProviderFactories.RegisterFactory("System.Data.Odbc", OdbcFactory.Instance);
30-
31-
if (!names.Any(x => x.Equals("System.Data.OleDb")) && OleDbFactory.Instance != null)
32-
DbProviderFactories.RegisterFactory("System.Data.OleDb", OleDbFactory.Instance);
33-
34-
if (!names.Any(x => x.Equals("System.Data.SQLite")) && SQLiteFactory.Instance != null)
35-
DbProviderFactories.RegisterFactory("System.Data.SQLite", SQLiteFactory.Instance);
36-
37-
if (!names.Any(x => x.Equals("MySql.Data.MySqlClient")) && MySqlClientFactory.Instance != null)
38-
DbProviderFactories.RegisterFactory("MySql.Data.MySqlClient", MySqlClientFactory.Instance);
39-
40-
if (!names.Any(x => x.Equals("Npgsql")) && NpgsqlFactory.Instance != null)
41-
DbProviderFactories.RegisterFactory("Npgsql", NpgsqlFactory.Instance);
14+
this.sqlConfiguration = sqlConfiguration ??
15+
throw new ArgumentNullException(nameof(SQLConfiguration));
4216
}
4317

4418
public DbRecord[] GetByName(string name)

src/FeatureOne/AssemblyInfo.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111
using System;
1212
using System.Reflection;
1313

14-
[assembly: System.Reflection.AssemblyCompanyAttribute("Ninja.Sha!4H")]
14+
[assembly: System.Reflection.AssemblyCompanyAttribute("Tech Ninja Labs")]
1515
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
16-
[assembly: System.Reflection.AssemblyCopyrightAttribute("2023")]
16+
[assembly: System.Reflection.AssemblyCopyrightAttribute("2024")]
1717
[assembly: System.Reflection.AssemblyDescriptionAttribute(".Net Library to implement feature toggles.")]
18-
[assembly: System.Reflection.AssemblyFileVersionAttribute("2.0.0.0")]
19-
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.7")]
18+
[assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.0.0")]
19+
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.0")]
2020
[assembly: System.Reflection.AssemblyProductAttribute("FeatureOne")]
2121
[assembly: System.Reflection.AssemblyTitleAttribute("FeatureOne")]
22-
[assembly: System.Reflection.AssemblyVersionAttribute("2.0.0.0")]
23-
[assembly: System.Reflection.AssemblyMetadataAttribute("RepositoryUrl", "https://github.com/NinjaRocks/FeatureOne")]
22+
[assembly: System.Reflection.AssemblyVersionAttribute("4.0.0.0")]
23+
[assembly: System.Reflection.AssemblyMetadataAttribute("RepositoryUrl", "https://github.com/TechNinjaLabs/FeatureOne")]
2424

2525
// Generated by the MSBuild WriteCodeFragment class.
2626

src/FeatureOne/FeatureOne.csproj

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<ImplicitUsings>disable</ImplicitUsings>
66
<Nullable>disable</Nullable>
77
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
@@ -14,31 +14,32 @@
1414
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
1515
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
1616
<Title>FeatureOne</Title>
17-
<Authors>ninja.shayk</Authors>
18-
<Company>Ninja.Sha!4H</Company>
17+
<Authors>Tech Ninja Labs</Authors>
18+
<Company>Tech Ninja Labs</Company>
1919
<Product>FeatureOne</Product>
20-
<Description>.Net library to implement feature toggles (Need to implement storage backend).</Description>
21-
<Copyright>Copyright (c) 2023 Ninja Sha!4h</Copyright>
20+
<Description>.Net library to implement feature toggles.</Description>
21+
<Copyright>Copyright (c) 2024 Tech Ninja Labs</Copyright>
2222
<PackageReadmeFile>README.md</PackageReadmeFile>
23-
<RepositoryUrl>https://github.com/NinjaRocks/FeatureOne</RepositoryUrl>
23+
<RepositoryUrl>https://github.com/TechNinjaLabs/FeatureOne</RepositoryUrl>
2424
<RepositoryType>git</RepositoryType>
25-
<PackageTags>feature-toggle; feature-flag; feature-flags; feature-toggles; .netstandard2.1; featureOne</PackageTags>
26-
<Version>3.0.0</Version>
25+
<PackageTags>feature-toggle; feature-flag; feature-flags; feature-toggles; net8.0; featureOne</PackageTags>
26+
<Version>4.0.0</Version>
2727
<PackageLicenseFile>LICENSE.md</PackageLicenseFile>
2828
<PackageIcon>ninja-icon-16.png</PackageIcon>
2929
<PackageReleaseNotes>
30-
Release Notes v3.0.0 Core Functionality :- Targets .Net 6.0
31-
- To Implement Feature Toggles to hide/show program features.
32-
- Provides Out of box Simple and Regex toggle conditions .
33-
- Provides extensibility for custom implementation
34-
- to implement custom toggle conditions for any bespoke use case.
35-
- to implement backend storage. No Backend storage exists by default.
30+
Release Notes v4.0.0 Core Functionality :- Targets .Net 8.0
31+
Library to Implement Feature Toggles to hide/show program features. Does not contain storage provider.
32+
- Provides Out of box Simple and Regex toggle conditions.
33+
- Provides extensibility for custom implementations ie.
34+
-- No storage exists by default. Requires `IStorageProvider` implementation to plugin in backend data store for stored features.
35+
-- Provides extensibility to implement custom toggle conditions for bespoke use cases.
36+
-- Provides extensibility for custom toggle deserializer for bespoke scenarios.
3637
</PackageReleaseNotes>
3738
</PropertyGroup>
3839

3940
<ItemGroup>
40-
<PackageReference Include="System.Runtime.Caching" Version="7.0.0" />
41-
<PackageReference Include="System.Text.Json" Version="7.0.1" />
41+
<PackageReference Include="System.Runtime.Caching" Version="8.0.0" />
42+
<PackageReference Include="System.Text.Json" Version="8.0.3" />
4243
</ItemGroup>
4344

4445
<ItemGroup>

0 commit comments

Comments
 (0)