Skip to content

Commit

Permalink
#32 Implemented constructor for concrete concepts.
Browse files Browse the repository at this point in the history
  • Loading branch information
Quenio dos Santos committed Mar 23, 2017
1 parent 966df1b commit 9e60e0a
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 57 deletions.
Expand Up @@ -7,6 +7,10 @@ newLineIf2(cond1, cond2) ::= <<
<if(cond1 && cond2)><\n><endif>
>>

newLineIfEither(cond1, cond2) ::= <<
<if(cond1 || cond2)><\n><endif>
>>

commaIf(cond) ::= <<
<if(cond)>, <endif>
>>
Expand Down
67 changes: 47 additions & 20 deletions cml-compiler/cml-generator/src/main/resources/java_lang/class.stg
Expand Up @@ -2,50 +2,51 @@ import "/generic/generic.stg"
import "/java_lang/common.stg"

class(concept) ::= <<
<class9(
<class7(
concept=concept,
classNameSuffix="",
ancestors=concept.directAncestors,
interfaces=[],
fieldAncestors=[],
fieldProperties=concept.properties,
delegatedProperties=[],
superProperties=concept.inheritedProperties,
constructorParamProperties=concept.properties
superProperties=concept.inheritedProperties
)>
>>

class2(concept, classNameSuffix) ::= <<
<class9(
<class7(
concept=concept,
classNameSuffix=classNameSuffix,
ancestors=[],
interfaces=[concept],
fieldAncestors=concept.allAncestors,
fieldProperties=concept.properties,
delegatedProperties=concept.inheritedProperties,
superProperties=[],
constructorParamProperties=concept.properties
superProperties=[]
)>
>>

class9(
class7(
concept, classNameSuffix,
ancestors, interfaces,
fieldAncestors, fieldProperties,
delegatedProperties, superProperties, constructorParamProperties
fieldAncestors,
delegatedProperties, superProperties
) ::= <<
class <typeName(concept)><classNameSuffix><ancestorList(ancestors)><interfaceList(interfaces)>
<abstract(concept, superProperties)>class <typeName(concept)><classNameSuffix><ancestorList(ancestors)><interfaceList(interfaces)>
{
<ancestorFields(fieldAncestors)>
<propertyFields(fieldAncestors, fieldProperties)>
<constructor(concept, classNameSuffix, superProperties, fieldAncestors, constructorParamProperties)>
<propertyFields(fieldAncestors, concept.properties)>
<constructorForClients(concept, classNameSuffix, superProperties)>
<primaryConstructor(concept, classNameSuffix, superProperties, fieldAncestors)>
<fieldGetters(concept)>
<delegatedGetters(concept, delegatedProperties)>
<class_toString(concept)>
}
>>

abstract(concept, superProperties) ::= <<
<if(concept.abstract && superProperties)>abstract <endif>
>>

ancestorFieldDecl(concept) ::= <<
private final <typeName(concept)> <fieldName(concept)>;
>>
Expand Down Expand Up @@ -80,16 +81,34 @@ delegatedGetters(concept, delegatedProperties) ::= <<
<delegatedProperties:delegateGetter();separator="\n\n">
>>

constructor(concept, classNameSuffix, superProperties, paramAncestors, paramProperties) ::= <<
<if(paramAncestors || paramProperties)>
<newLineIf(fieldProperties)><\\>
public <typeName(concept)><classNameSuffix>(<constructorParamList(paramAncestors, [superProperties, paramProperties])>)
constructorForClients(concept, classNameSuffix, superProperties) ::= <<
<if(!concept.abstract && concept.allAncestors && !superProperties)>
<newLineIf(concept.properties)><\\>
public <typeName(concept)><classNameSuffix>(<constructorParamList([], [concept.allProperties])>)
{
this(
<constructorArgsForClients(concept)>
);
}<\\>
<endif>
>>

constructorArgsForClients(concept) ::= <<
<concept.allAncestors:createInvocation();separator=",\n"><\\>
<if(concept.allAncestors)>,<endif>
<concept.properties:fieldName();separator=",\n">
>>

primaryConstructor(concept, classNameSuffix, superProperties, paramAncestors) ::= <<
<if(paramAncestors || concept.properties)>
<newLineIfEither(paramAncestors, concept.properties)><\\>
public <typeName(concept)><classNameSuffix>(<constructorParamList(paramAncestors, [superProperties, concept.properties])>)
{
<superConstructor(superProperties)>
<if(superProperties)>
<[paramProperties]:fieldInit();separator="\n">
<[concept.properties]:fieldInit();separator="\n">
<else>
<[paramAncestors, paramProperties]:fieldInit();separator="\n">
<[paramAncestors, concept.properties]:fieldInit();separator="\n">
<endif>
}
<endif>
Expand All @@ -113,6 +132,14 @@ fieldInit(namedElement) ::= <<
this.<fieldName(namedElement)> = <fieldName(namedElement)>;
>>

createInvocation(concept) ::= <<
<typeName(concept)>.create(<\\>
<concept.allAncestors:fieldName();separator=", "><\\>
<commaIf(concept.allAncestors)><\\>
<concept.properties:fieldName();separator=", "><\\>
)
>>

superConstructor(inheritedProperties) ::= <<
<if(inheritedProperties)>super(<inheritedProperties:superArgs();separator=", ">);<endif>
>>
Expand Down
15 changes: 15 additions & 0 deletions cml-compiler/cml-generator/src/test/java/generic/GenericTest.java
Expand Up @@ -38,6 +38,21 @@ public void newLineIf_false(@FromDataPoints("falseConditions") Object cond)
testTemplateWithCond("newLineIf", cond, "");
}

@Theory
public void newLineIfEither_true(
@FromDataPoints("trueConditions") Object trueCond,
@FromDataPoints("falseConditions") Object falseCond)
{
testTemplateWithCond2("newLineIfEither", trueCond, falseCond, "\n");
testTemplateWithCond2("newLineIfEither", falseCond, trueCond, "\n");
}

@Theory
public void newLineIfEither_false(@FromDataPoints("falseConditions") Object cond)
{
testTemplateWithCond2("newLineIfEither", cond, cond, "");
}

@Theory
public void newLineIf2_true(@FromDataPoints("trueConditions") Object cond)
{
Expand Down
103 changes: 66 additions & 37 deletions cml-compiler/cml-generator/src/test/java/java_lang/ClassTest.java
Expand Up @@ -20,79 +20,86 @@ protected String getTemplateFileName()
}

@Test
public void class_emptyConcept() throws IOException
public void class2__concept_abstract_ancestor_multiple() throws IOException
{
final Concept concept = Concept.create("Book");
final Concept concept = createConceptWithMultipleAncestors(true);

testClassTemplateWithConcept(concept, "emptyConcept.txt");
testClassTemplateWithSuffix(concept, "class2__concept_abstract_ancestor_multiple.txt");
}

@Test
public void class_simpleConcept() throws IOException
public void class2__concept_concrete_ancestor_multiple() throws IOException
{
final Concept concept = Concept.create("Book");
final Concept concept = createConceptWithMultipleAncestors(false);

concept.addElement(Property.create("title", null, Type.create("String", null)));
testClassTemplateWithSuffix(concept, "class2__concept_concrete_ancestor_multiple.txt");
}

@Test
public void class__concept_abstract_ancestor() throws IOException
{
final Concept productConcept = Concept.create("Product");
productConcept.addElement(Property.create("description", null, Type.create("String", null)));

testClassTemplateWithConcept(concept, "simpleConcept.txt");
final Concept bookConcept = Concept.create("Book", true);
bookConcept.addElement(Property.create("title", null, Type.create("String", null)));
bookConcept.addDirectAncestor(productConcept);

testClassTemplateWithConcept(bookConcept, "class__concept_abstract_ancestor.txt");
}

@Test
public void class_conceptWithOptionalProperty() throws IOException
public void class__concept_concrete_ancestor() throws IOException
{
final Concept concept = Concept.create("Book");
final Concept productConcept = Concept.create("Product");
productConcept.addElement(Property.create("description", null, Type.create("String", null)));

concept.addElement(Property.create("title", null, Type.create("String", null)));
concept.addElement(Property.create("sequel", null, Type.create("Book", "?")));
final Concept bookConcept = Concept.create("Book");
bookConcept.addElement(Property.create("title", null, Type.create("String", null)));
bookConcept.addDirectAncestor(productConcept);

testClassTemplateWithConcept(concept, "conceptWithOptionalProperty.txt");
testClassTemplateWithConcept(bookConcept, "class__concept_concrete_ancestor.txt");
}

@Test
public void class_conceptWithSetProperty() throws IOException
public void class__concept_empty() throws IOException
{
final Concept concept = Concept.create("Book");

concept.addElement(Property.create("title", null, Type.create("String", null)));
concept.addElement(Property.create("sequel", null, Type.create("Book", "?")));
concept.addElement(Property.create("categories", null, Type.create("Category", "*")));

testClassTemplateWithConcept(concept, "conceptWithSetProperty.txt");
testClassTemplateWithConcept(concept, "class__concept_empty.txt");
}

@Test
public void class_conceptWithAncestor() throws IOException
public void class__concept_property_optional() throws IOException
{
final Concept productConcept = Concept.create("Product");
productConcept.addElement(Property.create("description", null, Type.create("String", null)));
final Concept concept = Concept.create("Book");

final Concept bookConcept = Concept.create("Book");
bookConcept.addElement(Property.create("title", null, Type.create("String", null)));
bookConcept.addDirectAncestor(productConcept);
concept.addElement(Property.create("title", null, Type.create("String", null)));
concept.addElement(Property.create("sequel", null, Type.create("Book", "?")));

testClassTemplateWithConcept(bookConcept, "conceptWithAncestor.txt");
testClassTemplateWithConcept(concept, "class__concept_property_optional.txt");
}

@Test
public void class2_conceptWithClassNameSuffixAndMultipleAncestors() throws IOException
public void class__concept_property_required() throws IOException
{
final Concept baseConcept = Concept.create("Base");
baseConcept.addElement(Property.create("baseProperty", null, Type.create("String", null)));
final Concept concept = Concept.create("Book");

final Concept productConcept = Concept.create("Product");
productConcept.addElement(Property.create("description", null, Type.create("String", null)));
productConcept.addDirectAncestor(baseConcept);
concept.addElement(Property.create("title", null, Type.create("String", null)));

final Concept stockItemConcept = Concept.create("StockItem");
stockItemConcept.addElement(Property.create("quantity", null, Type.create("Integer", null)));
stockItemConcept.addDirectAncestor(baseConcept);
testClassTemplateWithConcept(concept, "class__concept_property_required.txt");
}

@Test
public void class__concept_property_set() throws IOException
{
final Concept concept = Concept.create("Book");

concept.addElement(Property.create("title", null, Type.create("String", null)));
concept.addDirectAncestor(productConcept);
concept.addDirectAncestor(stockItemConcept);
concept.addElement(Property.create("sequel", null, Type.create("Book", "?")));
concept.addElement(Property.create("categories", null, Type.create("Category", "*")));

testClassTemplateWithSuffix(concept, "conceptWithClassNameSuffixAndMultipleAncestors.txt");
testClassTemplateWithConcept(concept, "class__concept_property_set.txt");
}

private void testClassTemplateWithConcept(Concept concept, String expectedOutputFileName) throws IOException
Expand All @@ -116,4 +123,26 @@ private void testClassTemplateWithSuffix(Concept concept, String expectedOutputF
final String result = template.render();
assertThatOutputMatches("/java_lang/class/" + expectedOutputFileName, result);
}

private static Concept createConceptWithMultipleAncestors(boolean _abstract)
{
final Concept baseConcept = Concept.create("Base");
baseConcept.addElement(Property.create("baseProperty", null, Type.create("String", null)));

final Concept productConcept = Concept.create("Product");
productConcept.addElement(Property.create("description", null, Type.create("String", null)));
productConcept.addDirectAncestor(baseConcept);

final Concept stockItemConcept = Concept.create("StockItem");
stockItemConcept.addElement(Property.create("quantity", null, Type.create("Integer", null)));
stockItemConcept.addDirectAncestor(baseConcept);

final Concept concept = Concept.create("Book", _abstract);
concept.addElement(Property.create("title", null, Type.create("String", null)));
concept.addDirectAncestor(productConcept);
concept.addDirectAncestor(stockItemConcept);

return concept;
}

}
@@ -0,0 +1,58 @@
class BookImpl implements Book
{
private final Base base;
private final Product product;
private final StockItem stockItem;

private final String title;

public BookImpl(String baseProperty, String description, Integer quantity, String title)
{
this(
Base.create(baseProperty),
Product.create(base, description),
StockItem.create(base, quantity),
title
);
}

public BookImpl(Base base, Product product, StockItem stockItem, String title)
{
this.base = base;
this.product = product;
this.stockItem = stockItem;
this.title = title;
}

public String getTitle()
{
return title;
}

public String getBaseProperty()
{
return base.getBaseProperty();
}

public String getDescription()
{
return product.getDescription();
}

public Integer getQuantity()
{
return stockItem.getQuantity();
}

public String toString()
{
return new StringBuilder(Book.class.getSimpleName())
.append('(')
.append("baseProperty=").append(String.format("\"%s\"", getBaseProperty())).append(", ")
.append("description=").append(String.format("\"%s\"", getDescription())).append(", ")
.append("quantity=").append(String.format("\"%s\"", getQuantity())).append(", ")
.append("title=").append(String.format("\"%s\"", getTitle()))
.append(')')
.toString();
}
}
@@ -0,0 +1,25 @@
abstract class Book extends Product
{
private final String title;

public Book(String description, String title)
{
super(description);
this.title = title;
}

public String getTitle()
{
return title;
}

public String toString()
{
return new StringBuilder(Book.class.getSimpleName())
.append('(')
.append("description=").append(String.format("\"%s\"", getDescription())).append(", ")
.append("title=").append(String.format("\"%s\"", getTitle()))
.append(')')
.toString();
}
}

0 comments on commit 9e60e0a

Please sign in to comment.