Skip to content

Commit

Permalink
Merge branch 'feature/Ternary_relationships' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Cédric L. Charlier committed Apr 21, 2016
2 parents 82ee6f5 + 09ee7b8 commit 1253bf8
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 14 deletions.
88 changes: 88 additions & 0 deletions ERMine.Core.UnitTesting/Parsing/ModelParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,94 @@ public void Parse_TwoEntitiesAndRelationship_Label()
var entityRelationships = ModelParser.EntityRelationships.Parse(input);

Assert.AreEqual(3, entityRelationships.Count());
Assert.AreEqual(2, entityRelationships.Count(e => e is Entity));
Assert.AreEqual(1, entityRelationships.Count(r => r is Relationship));

}

[TestMethod]
public void Parse_TwoRelationships_Label()
{
var input = "[Student] *-isfriend-* [Student]" + "\r\n";
input += "[Student] *-follow-* [Course]\r\n";

var entityRelationships = ModelParser.Relationships.Parse(input);

Assert.AreEqual(2, entityRelationships.Count());

}

[TestMethod]
public void Parse_OneTernary_Label()
{
var input = "-SupplySchedule- [Vendor]* [Part]+ [Warehouse]+\r\n";

var entityRelationships = ModelParser.Relationships.Parse(input);

Assert.AreEqual(1, entityRelationships.Count());

}

[TestMethod]
public void Parse_ThreeRelationships_Label()
{
var input = "[Student] *-isfriend-* [Student]" + "\r\n";
input += "[Student] *-follow-* [Course]\r\n";
input += "-SupplySchedule- [Vendor]* [Part]+ [Warehouse]+\r\n";

var entityRelationships = ModelParser.Relationships.Parse(input);

Assert.AreEqual(3, entityRelationships.Count());
Assert.AreEqual(3, entityRelationships.Count(r => r is Relationship));

}

[TestMethod]
public void Parse_ThreeEntitiesAndTernaryRelationship_Label()
{
var input = "[Warehouse]" + "\r\n";
input += "-SupplySchedule- [Vendor]* [Part]+ [Warehouse]+" + "\r\n";
input += "[Part]" + "\r\n";
input += "[Vendor]" + "\r\n";

var entityRelationships = ModelParser.EntityRelationships.Parse(input);

Assert.AreEqual(3, entityRelationships.Count(e => e is Entity));
Assert.AreEqual(1, entityRelationships.Count(r => r is Relationship));

}

[TestMethod]
public void Parse_TwiceThreeRelationship_Label()
{
var input = "[Warehouse]" + "\r\n";
input += "-SupplySchedule- [Vendor]* [Part]+ [Warehouse]+" + "\r\n";
input += "[Part]" + "\r\n";
input += "[Vendor]" + "\r\n";
input += "[Student] *-isfriend-* [Student]" + "\r\n";
input += "[Student] *-follow-* [Course]\r\n";

var entityRelationships = ModelParser.EntityRelationships.Parse(input);

Assert.AreEqual(3, entityRelationships.Count(e => e is Entity));
Assert.AreEqual(3, entityRelationships.Count(r => r is Relationship));

}

[TestMethod]
public void Parse_TwiceThree2Relationship_Label()
{
var input = "[Warehouse]" + "\r\n";
input += "-SupplySchedule- [Vendor]* [Part]+ [Warehouse]+" + "\r\n";
input += "[Student] *-isfriend-* [Student]" + "\r\n";
input += "[Student] *-follow-* [Course]\r\n";
input += "[Part]" + "\r\n";
input += "[Vendor]" + "\r\n";

var entityRelationships = ModelParser.EntityRelationships.Parse(input);

Assert.AreEqual(3, entityRelationships.Count(e => e is Entity));
Assert.AreEqual(3, entityRelationships.Count(r => r is Relationship));

}
}
Expand Down
21 changes: 18 additions & 3 deletions ERMine.Core.UnitTesting/Parsing/RelationshipParserTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class RelationshipParserTest
public void Relationship_Binary_WithLabel()
{
var input = "[Student] +-follow-* [Course]";
var relationship = RelationshipParser.Relationship.Parse(input);
var relationship = RelationshipBinaryParser.Relationship.Parse(input);

Assert.AreEqual("follow", relationship.Label);
Assert.AreEqual("Student", relationship.Entities.ElementAt(0).Label);
Expand All @@ -27,7 +27,7 @@ public void Relationship_Binary_WithLabel()
public void Relationship_Binary_WithoutLabel()
{
var input = "[Post]*--1[Comment]";
var relationship = RelationshipParser.Relationship.Parse(input);
var relationship = RelationshipBinaryParser.Relationship.Parse(input);

Assert.AreEqual(null, relationship.Label);
Assert.AreEqual("Post", relationship.Entities.ElementAt(0).Label);
Expand All @@ -40,12 +40,27 @@ public void Relationship_Binary_WithoutLabel()
public void Relationship_Binary_Self()
{
var input = "[Employee] *-manages-1 [Employee]";
var relationship = RelationshipParser.Relationship.Parse(input);
var relationship = RelationshipBinaryParser.Relationship.Parse(input);

Assert.AreEqual("Employee", relationship.Entities.ElementAt(0).Label);
Assert.AreEqual("Employee", relationship.Entities.ElementAt(1).Label);
Assert.IsTrue(relationship.Entities.ElementAt(0).Label == relationship.Entities.ElementAt(1).Label);
}

[TestMethod]
public void Relationship_Ternary_Simple()
{
var input = "-SupplySchedule- [Vendor]* [Part]+ [Warehouse]+ ";
var relationship = RelationshipTernaryParser.Relationship.Parse(input);

Assert.AreEqual("Vendor", relationship.Entities.ElementAt(0).Label);
Assert.AreEqual(Cardinality.ZeroOrMore, relationship.Cardinality.ElementAt(0));
Assert.AreEqual("Part", relationship.Entities.ElementAt(1).Label);
Assert.AreEqual(Cardinality.OneOrMore, relationship.Cardinality.ElementAt(1));
Assert.AreEqual("Warehouse", relationship.Entities.ElementAt(2).Label);
Assert.AreEqual(Cardinality.OneOrMore, relationship.Cardinality.ElementAt(2));

}

}
}
3 changes: 2 additions & 1 deletion ERMine.Core/ERMine.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
<Compile Include="Modeling\Repository\ModelRepository.cs" />
<Compile Include="Parsing\ModelParser.cs" />
<Compile Include="Parsing\Parser.cs" />
<Compile Include="Parsing\RelationshipParser.cs" />
<Compile Include="Parsing\RelationshipTernaryParser.cs" />
<Compile Include="Parsing\RelationshipBinaryParser.cs" />
<Compile Include="Parsing\EntityParser.cs" />
<Compile Include="Parsing\Grammar.cs" />
<Compile Include="Modeling\Factory\RelationshipFactory.cs" />
Expand Down
9 changes: 9 additions & 0 deletions ERMine.Core/Modeling/Factory/RelationshipFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ public Relationship Create(string label, IEnumerable<Tuple<Entity, Cardinality>>
return relationship;
}

public Relationship Create(string label, IEnumerable<Tuple<string, Cardinality>> members)
{
var relationship = new Relationship(members.Count());
relationship.Label = label;
foreach (var item in members)
relationship.Add(new Entity(item.Item1), item.Item2);
return relationship;
}

public Relationship Create(string label, string firstEntity, Cardinality firstCardinality, string secondEntity, Cardinality secondCardinality)
{
var tuples = new List<Tuple<Entity, Cardinality>>();
Expand Down
24 changes: 17 additions & 7 deletions ERMine.Core/Parsing/ModelParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,25 @@ namespace ERMine.Core.Parsing
{
static class ModelParser
{
public readonly static Parser<IEnumerable<IEntityRelationship>> Relationships =
(
from binaryRelationships in RelationshipBinaryParser.Relationship.Many()
from ternaryRelationships in RelationshipTernaryParser.Relationship.Many()
select binaryRelationships
.Union(ternaryRelationships)
);

public readonly static Parser<IEnumerable<IEntityRelationship>> Entities =
(
from entities in EntityParser.Entity.Many()
select entities
);

readonly static Parser<IEnumerable<IEntityRelationship>> EntityRelationship =
(
from relationships in RelationshipParser.Relationship.Optional()
from entities in EntityParser.Entity.Optional()
select entities.IsDefined && relationships.IsDefined
? Enumerable.Repeat(entities.GetOrDefault() as IEntityRelationship, 1)
.Union(Enumerable.Repeat(relationships.GetOrDefault() as IEntityRelationship, 1))
: entities.IsDefined ? Enumerable.Repeat(entities.GetOrDefault() as IEntityRelationship, 1)
: Enumerable.Repeat(relationships.GetOrDefault() as IEntityRelationship, 1)
from relationships in Relationships.Many()
from entity in EntityParser.Entity.Optional()
select entity.IsDefined ? relationships.SelectMany(r => r).Union(Enumerable.Repeat((IEntityRelationship) entity.GetOrDefault(), 1)) : relationships.SelectMany(r => r)
);

public readonly static Parser<IEnumerable<IEntityRelationship>> EntityRelationships =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace ERMine.Core.Parsing
{
static class RelationshipParser
static class RelationshipBinaryParser
{
readonly static Parser<Cardinality> Cardinality =
(
Expand Down
53 changes: 53 additions & 0 deletions ERMine.Core/Parsing/RelationshipTernaryParser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sprache;
using ERMine.Core.Modeling;
using ERMine.Core.Modeling.Factory;
using System;

namespace ERMine.Core.Parsing
{
static class RelationshipTernaryParser
{
readonly static Parser<Cardinality> Cardinality =
(
from cardinality in Parse.Char('*').Return(Modeling.Cardinality.ZeroOrMore)
.Or(Parse.Char('?').Return(Modeling.Cardinality.ZeroOrOne)
.Or(Parse.Char('1').Return(Modeling.Cardinality.ExactyOne)
.Or(Parse.Char('+').Return(Modeling.Cardinality.OneOrMore)
)))
select cardinality
);

public readonly static Parser<Relationship> Relationship =
(

from firstSeparator in Parse.Char('-')
from label in Grammar.Textual.Optional()
from secondSeparator in Parse.Char('-')
from firstEntity in Grammar.BracketTextual
from firstCardinality in Cardinality
from secondEntity in Grammar.BracketTextual
from secondCardinality in Cardinality
from thirdEntity in Grammar.BracketTextual
from thirdCardinality in Cardinality
select new RelationshipFactory().Create( label.GetOrDefault()
, new List<Tuple<string, Cardinality>>()
{
new Tuple<string, Modeling.Cardinality> (firstEntity, firstCardinality)
, new Tuple<string, Modeling.Cardinality> (secondEntity, secondCardinality)
, new Tuple<string, Modeling.Cardinality> (thirdEntity, thirdCardinality)
}
)
);

public readonly static Parser<IEnumerable<Relationship>> Relationships =
(
Relationship.Many()
);


}
}
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ Derivated attributes are noted with a percentage (%).

# Relationships

Currently, ERMine supports unary and binary relationships
Currently, ERMine supports unary, binary and ternary relationships

*first_entity_name* [ ? | 1 | * | + ] - *ralationship_name* - [ ? | 1 | * | + ] *second_entity_name*
*first_entity_name* [ ? | 1 | * | + ] - *relationship_name* - [ ? | 1 | * | + ] *second_entity_name*

for unary relationships the name of the first and second entities must be identical.

Ternary relationships are noted differently

*relationship_name* *first_entity_name* [ ? | 1 | * | + ] *second_entity_name* [ ? | 1 | * | + ] *third_entity_name* [ ? | 1 | * | + ]

## Cardinalities

* ```?``` stands for O..1
Expand Down

0 comments on commit 1253bf8

Please sign in to comment.