Skip to content
This repository has been archived by the owner on Nov 8, 2024. It is now read-only.

Commit

Permalink
Fix #318
Browse files Browse the repository at this point in the history
  • Loading branch information
Jiri Kratochvil committed May 23, 2016
1 parent 2aa80e9 commit de3993a
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/NamedTypesRegistry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ namespace drafter {
const std::string& name = i->node->name.symbol.literal;

const RefractElementFactory& factory = FactoryFromType(typeInfo.ResolveType(i->node));
refract::IElement* element = factory.Create(std::string(), false);
refract::IElement* element = factory.Create(std::string(), eValue);
element->meta["id"] = refract::IElement::Create(name);

context.GetNamedTypesRegistry().add(element);
Expand Down
14 changes: 9 additions & 5 deletions src/RefractDataStructure.cc
Original file line number Diff line number Diff line change
Expand Up @@ -387,13 +387,18 @@ namespace drafter {
RefractElements types;
for (mson::TypeNames::const_iterator it = typeNames.begin(); it != typeNames.end(); ++it) {
mson::BaseTypeName typeName = it->base;
FactoryCreateMethod method = eValue;

if (typeName == mson::UndefinedTypeName && !it->symbol.literal.empty()) {
typeName = GetMsonTypeFromName(it->symbol.literal, context);
}
method = it->symbol.variable ? eSample : eElement;
}

const RefractElementFactory& f = FactoryFromType(typeName);
types.push_back(f.Create(it->symbol.literal, it->symbol.variable));
types.push_back(f.Create(it->symbol.literal, method));

if (!it->symbol.literal.empty()) {
}
}

values.push_back(types);
Expand Down Expand Up @@ -477,14 +482,13 @@ namespace drafter {

const mson::BaseTypeName type = SelectNestedTypeSpecification(valueMember.node->valueDefinition.typeDefinition.typeSpecification.nestedTypes);

const RefractElementFactory& elementFactory = FactoryFromType(type);
const RefractElementFactory& f = FactoryFromType(type);
const mson::Values& values = valueMember.node->valueDefinition.values;

RefractElements elements;

for (mson::Values::const_iterator it = values.begin(); it != values.end(); ++it) {
refract::IElement* element = elementFactory.Create(it->literal, it->variable);
elements.push_back(element);
elements.push_back(f.Create(it->literal, it->variable ? eSample : eValue));
}

Store<S>()(storage, elements);
Expand Down
38 changes: 22 additions & 16 deletions src/RefractElementFactory.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "RefractElementFactory.h"
#include "refract/Element.h"

#include "Serialize.h" // LiteraralTo<>
#include "Serialize.h" // LiteralTo<>
#include "SourceAnnotation.h" // mson::Error

namespace drafter {
Expand All @@ -12,21 +12,30 @@ namespace drafter {

RefractElementFactoryImpl() {}

virtual refract::IElement* Create(const std::string& literal, bool sample = false) const
virtual refract::IElement* Create(const std::string& literal, FactoryCreateMethod method) const
{
E* element = new E;

if (literal.empty()) {
return element;
}

if (sample) {
refract::ArrayElement* samples = new refract::ArrayElement;
samples->push_back(refract::IElement::Create(LiteralTo<typename E::ValueType>(literal)));
element->attributes[SerializeKey::Samples] = samples;
}
else {
element->set(LiteralTo<V>(literal));
switch (method) {
case eSample: {
refract::ArrayElement* samples = new refract::ArrayElement;
samples->push_back(refract::IElement::Create(LiteralTo<typename E::ValueType>(literal)));
element->attributes[SerializeKey::Samples] = samples;
}
break;

case eValue:
element->set(LiteralTo<V>(literal));
break;

case eElement:
element->element(literal);
break;

}

return element;
Expand All @@ -39,9 +48,9 @@ namespace drafter {

RefractElementFactoryImpl() {}

virtual refract::IElement* Create(const std::string& literal, bool sample = false) const
virtual refract::IElement* Create(const std::string& literal, FactoryCreateMethod method) const
{
if (sample) {
if (method == eSample) {
refract::StringElement* element = new refract::StringElement;
element->element(SerializeKey::Generic);
element->set(literal);
Expand All @@ -50,17 +59,14 @@ namespace drafter {

E* element = new E;

if (literal.empty()) {
return element;
if (!literal.empty()) {
element->element(literal);
}

element->element(literal);

return element;
}
};


const RefractElementFactory& FactoryFromType(const mson::BaseTypeName typeName)
{

Expand Down
18 changes: 13 additions & 5 deletions src/RefractElementFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,29 @@ namespace drafter {
* - if `literal` is empty - return __empty__ element of required type
*
* For primitives (string|number|bool):
* - `sample` is false - return typed element with __value__ set via `ToLiteral<>` conversion
* - `sample` is true - return typed element with __attributes.samples__ set via `ToLiteral<>` conversion
* - `sample` eValue - return typed element with __value__ set via `ToLiteral<>` conversion
* - `sample` eSample - return typed element with __attributes.samples__ set via `ToLiteral<>` conversion
* - `sample` eElement - return typed element with set __element name__ to `literal`
*
* For complex elements (object|array|enum):
* - `sample` is false - return typed element with set element name to `literal`
* - `sample` is true - return StringElement with name __generic__ with value set to `literal`
* - `sample` eSample - return StringElement with name __generic__ with value set to `literal`
* - `sample` eValue|eElement - return return typed element with set __element name__ to `literal`
*
* This inconsistent behavior is determined by rules of converting legacy AST to Refract.
*
* Code will be deprecated (refactoring or remove) after remove legacy AST.
*/

enum FactoryCreateMethod {
eValue,
eSample,
eElement,
};

struct RefractElementFactory
{
virtual ~RefractElementFactory() {}
virtual refract::IElement* Create(const std::string& literal, bool sample) const = 0;
virtual refract::IElement* Create(const std::string& literal, FactoryCreateMethod type) const = 0;
};

/**
Expand Down
38 changes: 33 additions & 5 deletions test/test-ElementFactoryTest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ using namespace drafter;

TEST_CASE("Create empty primitive element","[ElementFactory]") {
const RefractElementFactory& factory = FactoryFromType(mson::StringTypeName);
IElement* e = factory.Create(std::string(), false);
IElement* e = factory.Create(std::string(), eValue);

StringElement* str = TypeQueryVisitor::as<StringElement>(e);
REQUIRE(str != NULL);
Expand All @@ -25,7 +25,7 @@ TEST_CASE("Create empty primitive element","[ElementFactory]") {

TEST_CASE("Create primitive element w/ value","[ElementFactory]") {
const RefractElementFactory& factory = FactoryFromType(mson::NumberTypeName);
IElement* e = factory.Create("42", false);
IElement* e = factory.Create("42", eValue);

NumberElement* number = TypeQueryVisitor::as<NumberElement>(e);
REQUIRE(number != NULL);
Expand All @@ -39,7 +39,7 @@ TEST_CASE("Create primitive element w/ value","[ElementFactory]") {

TEST_CASE("Create primitive element w/ sample","[ElementFactory]") {
const RefractElementFactory& factory = FactoryFromType(mson::NumberTypeName);
IElement* e = factory.Create("42", true);
IElement* e = factory.Create("42", eSample);

NumberElement* number = TypeQueryVisitor::as<NumberElement>(e);
REQUIRE(number != NULL);
Expand All @@ -53,9 +53,23 @@ TEST_CASE("Create primitive element w/ sample","[ElementFactory]") {
delete e;
}

TEST_CASE("Create primitive element w/ element","[ElementFactory]") {
const RefractElementFactory& factory = FactoryFromType(mson::NumberTypeName);
IElement* e = factory.Create("NAMED", eElement);

NumberElement* number = TypeQueryVisitor::as<NumberElement>(e);
REQUIRE(number != NULL);
REQUIRE(number->empty());
REQUIRE(number->meta.empty());
REQUIRE(number->attributes.empty());
REQUIRE(number->element() == "NAMED");

delete e;
}

TEST_CASE("Create empty complex element","[ElementFactory]") {
const RefractElementFactory& factory = FactoryFromType(mson::EnumTypeName);
IElement* e = factory.Create(std::string(), false);
IElement* e = factory.Create(std::string(), eValue);

EnumElement* enm = TypeQueryVisitor::as<EnumElement>(e);
REQUIRE(enm != NULL);
Expand All @@ -67,9 +81,23 @@ TEST_CASE("Create empty complex element","[ElementFactory]") {
delete e;
}

TEST_CASE("Create complex named element","[ElementFactory]") {
const RefractElementFactory& factory = FactoryFromType(mson::ObjectTypeName);
IElement* e = factory.Create("NAMED", eElement);

ObjectElement* enm = TypeQueryVisitor::as<ObjectElement>(e);
REQUIRE(enm != NULL);
REQUIRE(enm->empty());
REQUIRE(enm->meta.empty());
REQUIRE(enm->attributes.empty());
REQUIRE(enm->element() == "NAMED");

delete e;
}

TEST_CASE("Create element as generic","[ElementFactory]") {
const RefractElementFactory& factory = FactoryFromType(mson::EnumTypeName);
IElement* e = factory.Create("Enumerator", true);
IElement* e = factory.Create("Enumerator", eSample);

StringElement* generic = TypeQueryVisitor::as<StringElement>(e);
REQUIRE(generic != NULL);
Expand Down

0 comments on commit de3993a

Please sign in to comment.