Skip to content
Draft
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@
/pWord4/pWord4/OpNodeWPF/obj
/pWord4/pWord4/TestDll/bin
/pWord4/pWord4/TestDll/obj

# Temporary namespace validation test artifacts
obj/
bin/
*.exe
ValidationTest.csproj
119 changes: 78 additions & 41 deletions namespaces-readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,32 @@

Namespaces in the OpNode project provide a mechanism for organizing and scoping nodes within the tree-based data structure. They enable proper XML serialization, prevent naming conflicts, and establish operational contexts for nodes implementing the `IOperate` interface. The namespace system is designed to support hierarchical data organization while maintaining XML Schema compatibility.

## Current Namespace Implementation
## Current Namespace Implementation Status

### NameSpace Class Structure
### What Currently Works ✅

The core namespace functionality is implemented in `pWordLib.dat.NameSpace.cs`:
1. **Basic NameSpace Class**: Fully functional with Prefix, Suffix, URI_PREFIX, and URI_SUFFIX properties
2. **XML-Compatible Validation**: Updated `IsValidNamespace()` method follows XML naming conventions
3. **pNode Integration**: Namespace assignment and serialization works correctly
4. **XML Export/Import**: Namespaces are preserved during XML operations
5. **JSON Serialization**: Namespace information can be serialized/deserialized with JSON
6. **UI Integration**: Windows Forms interface supports adding prefixes and suffixes
7. **Cloning Support**: Namespace objects properly support deep cloning

```csharp
[Serializable()]
public class NameSpace : ICloneable
{
public string Prefix { get; set; }
public string Suffix { get; set; }
public string URI_PREFIX { get; set; }
public string URI_SUFFIX { get; set; }
### Enhanced Validation Rules ✅

public object Clone()
{
NameSpace ns = new NameSpace();
ns.Prefix = (ns.Prefix != null) ? (String)this.Prefix.Clone() : null;
ns.Suffix = (ns.Suffix != null) ? (String)this.Suffix.Clone() : null;
ns.URI_PREFIX = (ns.URI_PREFIX != null) ? (String)this.URI_PREFIX.Clone() : null;
ns.URI_SUFFIX = (ns.URI_SUFFIX != null) ? (String)this.URI_SUFFIX.Clone() : null;
return ns;
}
}
```

### Integration with pNode
The namespace validation has been improved to follow XML standards:
- Must start with letter or underscore
- Can contain letters, digits, hyphens, periods, underscores
- Cannot start with "xml" (reserved)
- No longer limited to hardcoded "ns" and "prefix" values

The `pNode` class integrates namespaces throughout its functionality:
### Current Limitations ⚠️

```csharp
public class pNode : TreeNode, ISerializable
{
public NameSpace Namespace { get; set; }

// Namespace validation during XML name checking
private static bool IsValidNamespace(string prefix)
{
var validNamespaces = new List<string> { "ns", "prefix" };
return validNamespaces.Contains(prefix);
}
}
```
1. **No Schema Validation**: Does not validate against actual XML schemas
2. **Limited Dynamic Registration**: Cannot register new namespaces at runtime
3. **Inconsistent URI Handling**: URI_PREFIX and URI_SUFFIX validation could be enhanced
4. **No Operation Discovery**: Operations are not automatically discovered based on namespace

## How Namespaces Organize and Scope Nodes

Expand Down Expand Up @@ -225,14 +207,69 @@ public void OperationChanged()
1. **Static Validation**: Hardcoded list of valid namespaces in `IsValidNamespace()`
2. **Limited Schema Support**: No validation against actual XML schemas
3. **Inconsistent URI Handling**: URI_PREFIX and URI_SUFFIX not fully utilized
4. **No Dynamic Registration**: Cannot register new namespaces at runtime
4. **No Operation Discovery**: Operations are not automatically discovered based on namespace

## Testing and Validation ✅

### Unit Tests Added

The namespace functionality now includes comprehensive unit tests:

1. **Basic Functionality Tests**: Creation, cloning, assignment
2. **Validation Tests**: XML naming convention compliance
3. **XML Export/Import Tests**: Namespace preservation during file operations
4. **JSON Serialization Tests**: Namespace data in JSON format
5. **Usability Tests**: Real-world file I/O scenarios
6. **Complex Hierarchy Tests**: Multi-level namespace structures
7. **Error Handling Tests**: Graceful handling of invalid input

### Test Files
- `UnitTest_Namespace.cs` - Core namespace functionality tests
- `UnitTest_NamespaceUsability.cs` - File I/O and real-world usage tests

### Validation Examples

```csharp
// These are now valid namespace prefixes:
"math:operations" // ✅ Valid
"data:content" // ✅ Valid
"ui_controls:button" // ✅ Valid
"app-settings:config" // ✅ Valid
"api.v2:endpoint" // ✅ Valid

// These are invalid:
"123invalid:test" // ❌ Starts with number
"xml:reserved" // ❌ Reserved xml prefix
"invalid@:test" // ❌ Invalid character
```

## URL-Based Schema Definition

### Current State
The current implementation uses simple string-based namespace identification:
### Current State ✅ **UPDATED**

The namespace validation has been enhanced from simple hardcoded values:

```csharp
// OLD - Limited to only two values:
var validNamespaces = new List<string> { "ns", "prefix" };

// NEW - XML-compliant validation:
private static bool IsValidNamespace(string prefix)
{
// XML namespace prefix validation - follows XML naming rules
if (string.IsNullOrEmpty(prefix)) return false;
if (!char.IsLetter(prefix[0]) && prefix[0] != '_') return false;

for (int i = 1; i < prefix.Length; i++)
{
char c = prefix[i];
if (!char.IsLetterOrDigit(c) && c != '-' && c != '.' && c != '_')
return false;
}

if (prefix.ToLower().StartsWith("xml")) return false;
return true;
}
```

### Proposed URL-Based Schema
Expand Down
15 changes: 4 additions & 11 deletions pWord4/pWord4/OpNodeTest2/OpNodeTest2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@
<Reference Include="AutoFixture.AutoMoq, Version=4.18.0.0, Culture=neutral, PublicKeyToken=b24654c590009d4f, processorArchitecture=MSIL">
<HintPath>..\packages\AutoFixture.AutoMoq.4.18.0\lib\net452\AutoFixture.AutoMoq.dll</HintPath>
</Reference>
<Reference Include="Fare, Version=2.1.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL">
<HintPath>..\packages\Fare.2.1.1\lib\net35\Fare.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.3.0.2\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -81,12 +78,8 @@
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Testable\TestableLeftRigth.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Testable\TestaableLeftRightWrapper.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Testable\TestableLeftRigth.cs" />
<Compile Include="Testable\TestableLeftRightWrapper.cs" />
<Compile Include="Testable\TestablePNode.cs" />
<Compile Include="UnitTest_OpNode_Operations.cs" />
<Compile Include="UnitTest_LeftRight_UserControl.cs" />
Expand Down Expand Up @@ -125,8 +118,8 @@
<DependentUpon>TestableLeftRigth.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Testable\TestaableLeftRightWrapper.resx">
<DependentUpon>TestaableLeftRightWrapper.cs</DependentUpon>
<EmbeddedResource Include="Testable\TestableLeftRightWrapper.resx">
<DependentUpon>TestableLeftRightWrapper.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
Expand Down
12 changes: 12 additions & 0 deletions pWord4/pWord4/OpNodeTest2/Testable/TestableLeftRightWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using pWordLib.dat;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace OpNodeTest2
{

}
42 changes: 0 additions & 42 deletions pWord4/pWord4/OpNodeTest2/Testable/TestableLeftRigth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,47 +8,5 @@

namespace OpNodeTest2
{
public class TestableLeftRight : LeftRight.LeftRight
{
public void SetInitialIndex(int value)
{
this.index = value;
}

public int GetIndex()
{
return this.index;
}

public void AddMasterItem(string item)
{
this.MasterNames.Add(item);
}
public void AddMasterValueItem(object item)
{
this.MasterNodes.Add(item as pNode);
}

public void SimulateLeftClick()
{
this.btnLeft_Click(null, null);
}

public void SimulateRightClick()
{
this.btnRight_Click(null, null);
}

private void InitializeComponent()
{
this.SuspendLayout();
//
// TestableLeftRight
//
this.Name = "TestableLeftRight";
this.ResumeLayout(false);
this.PerformLayout();

}
}
}
2 changes: 1 addition & 1 deletion pWord4/pWord4/OpNodeTest2/Testable/TestablePNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace OpNodeTest2
{
public class TestablePNode : pNode
public partial class TestablePNode : pNode
{
public void SetNameForTesting(string key)
{
Expand Down
Loading