Skip to content

Commit

Permalink
Merge pull request #1301 from umple/Issue_689
Browse files Browse the repository at this point in the history
Fixes #689 Adds multivalued attribute initialization implementation
  • Loading branch information
TimLethbridge committed Jun 16, 2018
2 parents 969b04b + e3c2f76 commit 543d9aa
Show file tree
Hide file tree
Showing 21 changed files with 497 additions and 10 deletions.
@@ -1,4 +1,11 @@
class UmpleToJava {
constructor_AttributeAssignList <<!<</*constructor_AttributeAssignList*/>>
<<=gen.translate("attributeMany",av)>> = new ArrayList<<<=gen.translate("typeMany",av)>>>();!>>
<<=gen.translate("attributeMany",av)>> = new ArrayList<<<=gen.translate("typeMany",av)>>>();<<#
if (av.getValue() != null && av.getValue() != "") {
String[] values = av.getValue().split(",");
if (values[0] != av.getValue()) {
for (String value : values) {
value = value.replaceAll("(?<!new)\\s+","");#>>
<<=gen.translate("attributeMany",av)>>.add(<<=value>>);
<<#}}}#>>!>>
}
9 changes: 8 additions & 1 deletion UmpleToJava/UmpleTLTemplates/members_AllStatics.ump
Expand Up @@ -45,7 +45,14 @@ class UmpleToJava {
{
appendln(realSb, "");
if (av.numberOfComments() > 0) { append(realSb, "\n {0}\n", Comment.format("Attribute Javadoc", av.getComments())); }
append(realSb, " public static final {0} {1} = {2};", gen.getType(av), av.getName(), gen.translate("parameterValue",av));
if (av.getIsList())
{
append(realSb, " public static final {0}[] {1} = {{2}};", gen.getType(av), av.getName(), gen.translate("parameterValue",av));
}
else
{
append(realSb, " public static final {0} {1} = {2};", gen.getType(av), av.getName(), gen.translate("parameterValue",av));
}
}
else if (av.getIsAutounique())
{
Expand Down
@@ -1,4 +1,10 @@
class UmpleToPhp {
constructor_AttributeAssignList <<!<</*constructor_AttributeAssignList*/>>
$<<=instanceIdentifier>>-><<=gen.translate("attributeMany",av)>> = array();!>>
$<<=instanceIdentifier>>-><<=gen.translate("attributeMany",av)>> = array(<<#
if (av.getValue() != null && av.getValue() != "") {
String[] values = av.getValue().split(",");
if (values[0] != av.getValue()) {
for (int i = 0; i < values.length; i++) {
String addingComma = (i == values.length-1) ? "" : ",";
String value = values[i].replaceAll("(?<!new)\\s+","");#>><<=value>><<=addingComma>><<#}}}#>>);!>>
}
10 changes: 9 additions & 1 deletion UmpleToPhp/UmpleTLTemplates/members_AllStatics.ump
Expand Up @@ -23,7 +23,15 @@ class UmpleToPhp {
if (av.isConstant())
{
appendln(realSb, "");
append(realSb, " public static ${0} = {1};", av.getName(), gen.translate("parameterValue",av));
if(av.getIsList())
{
append(realSb, " public static ${0} = array({1});", av.getName(), gen.translate("parameterValue",av));
}
else
{
append(realSb, " public static ${0} = {1};", av.getName(), gen.translate("parameterValue",av));
}

}
else if (av.getIsAutounique())
{
Expand Down
21 changes: 21 additions & 0 deletions build/reference/9081InvalidMultivaluedAttributeAssignment.txt
@@ -0,0 +1,21 @@
E081 Invalid Multivalued Attribute Assignment
Errors and Warnings 51-99
noreferences

@@description

<h2>Umple semantic error raised when initializing multivalued attributes with invalid values</h2>

<p>When indicating initial values for a multivalued attribute, an error is raised if the values to
assign cannot be parsed properly. <br/>
The error might be caused by a typographical mistake.
</p>


@@example
@@source manualexamples/E081InvalidMultivaluedAttributeAssignment1.ump
@@endexample

@@example
@@source manualexamples/E081InvalidMultivaluedAttributeAssignment2.ump
@@endexample
25 changes: 24 additions & 1 deletion cruise.umple/src/UmpleInternalParser_CodeClass.ump
Expand Up @@ -4343,6 +4343,17 @@ private Boolean checkIsDistributed(UmpleInterface uInterface)
attribute.setPosition(attributeToken.getPosition());

attribute.setIsList(isList);

// If the list has values to be assigned, verify if it is valid
if(isList && value != null) {
String[] values = value.split(",");
if(!value.contains(",") && (values[0].contains(" ") || values[0].matches("^.*[^a-zA-Z0-9 ].*$")) && !value.contains("new")) {
setFailedPosition(attributeToken.getPosition(), 81, aClass.getName(), name);
}
else if(!compareTypeToValueList(type, values)) {
setFailedPosition(attributeToken.getPosition(),141,type,value);
}
}

// Add comments above the attribute to the attribute.
for (Comment c : lastComments)
Expand Down Expand Up @@ -4516,7 +4527,19 @@ private Boolean checkIsDistributed(UmpleInterface uInterface)
{
return inferredType.equals(type);
}
}
}
private boolean compareTypeToValueList(String type, String[] values)
{
for (String value : values)
{
value = value.replaceAll("(?<!new)\\s+","");
if (!compareTypeToValue(type, value))
{
return false;
}
}
return true;
}

private Boolean isLazyRedundant(Boolean isLazy, String value)
{
Expand Down
2 changes: 1 addition & 1 deletion cruise.umple/src/Umple_Code.ump
Expand Up @@ -4378,7 +4378,7 @@ class ModelConstraint
lazy String target;
String linkNext = "";
lazy String link;
ModelConstraint mostRecent = { getModelConstraint(numberOfModelConstraints()-1) } ;
ModelConstraint mostRecent = { getModelConstraint(numberOfModelConstraints()-1) }

const ModelConstraintResult SUCCESS = new ModelConstraintResult(null,-1,null,null);
const ModelConstraintResult AND = new ModelConstraintResult(null,-1,null,null);
Expand Down
3 changes: 2 additions & 1 deletion cruise.umple/src/en.error
Expand Up @@ -82,7 +82,8 @@
73: 2, "http://manual.umple.org/?E073DuplicateParallelStateMachineName.html", Composite state '{0}' contains parallel state machines with the same name '{1}' on lines '{2}' and '{3}' ;
74: 2, "http://manual.umple.org/?E074UserDefinedStateCannotBeNamedFinal.html", Cannot name user-defined state on line '{0}' as Final because it is a reserved keyword ;

80: 2, "http://manual.umple.org/?E080InvalidAbstractClassAssociation.html", The association bettween a class and an abstract class declared in '{0}' must be a directed association or have one end whose multiplicity lower bound is 0 ;
80: 2, "http://manual.umple.org/?E080InvalidAbstractClassAssociation.html", The association between a class and an abstract class declared in '{0}' must be a directed association or have one end whose multiplicity lower bound is 0 ;
81: 2, "http://manual.umple.org/?E081InvalidMultivaluedAttributeAssignment.html", Invalid multivalued attribute assignment of attribute '{1}' in class '{0}' ;

# Model Constraints' Error messages
90: 2, "http://manual.umple.org/?E090AttributeNameNotFoundConstraint.html", Attribute named {0} was not found in class {1}, as required in constraint ;
Expand Down
3 changes: 2 additions & 1 deletion cruise.umple/src/umple_classes.grammar
Expand Up @@ -74,9 +74,10 @@ multiplicity- : [!lowerBound:\d+|[*]] .. [!upperBound:\d+|[*]] | [!bound:\d+|[*]
isSorted- : sorted { [priority] }

// Details of attributes. See user manual page [*AttributeDefinition*]
attribute : [[simpleAttribute]] | [[autouniqueAttribute]] | [[derivedAttribute]] | [[complexAttribute]]
attribute : [[simpleAttribute]] | [[autouniqueAttribute]] | [[multivaluedAttribute]] | [[derivedAttribute]] | [[complexAttribute]]
simpleAttribute- : [~name] ;
autouniqueAttribute- : [=autounique] [~name] ;
multivaluedAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable|settable|internal|defaulted|const|fixml]? [type]? [[list]] [~name] (= { [**value] })? ;
derivedAttribute- : [=modifier:immutable|settable|internal|defaulted|const|fixml]? [[typedName]] = ( [[moreCode]] )+
complexAttribute- : [=unique]? [=lazy]? [=ivar]? [=modifier:immutable|settable|internal|defaulted|const|fixml]? [[typedName]] (= [**value])? ;

Expand Down
@@ -0,0 +1,3 @@
class A {
String[] attr = {"str", 20, "str2"};
}
@@ -0,0 +1,3 @@
class MultivaluedAttributeAssignment {
String[] attr = {invalid.values};
}
@@ -0,0 +1,3 @@
class MultivaluedAttributeAssignment {
String[] attr = {arbitraryCode();};
}
8 changes: 8 additions & 0 deletions cruise.umple/test/cruise/umple/compiler/UmpleParserTest.java
Expand Up @@ -1352,6 +1352,7 @@ public void internalConst(){
public void TypeValueMismatchWarning()
{
assertHasWarningsParse("008_attributeTypeValueMismatch.ump",141);
assertHasWarningsParse("008_attributeTypeValueMismatch2.ump",141);
}

@Test
Expand Down Expand Up @@ -3025,6 +3026,13 @@ public void typeIsAccessSpecifier() {
assertHasWarningsParse("142_typeIsAccessSpecifierPrivate.ump", 142);
}

@Test
public void multivaluedAttributeAssignment()
{
assertFailedParse("008_multivaluedAttributeAssignment1.ump", 81);
assertFailedParse("008_multivaluedAttributeAssignment2.ump", 81);
}


@Test
public void mixsetDefinition()
Expand Down
Expand Up @@ -397,6 +397,15 @@ public void AbstractClassAvoidingInstantiationMN()
}
}

@Test
public void MultivaluedAttributeAssignment()
{
if (languagePath.equals("java") || languagePath.equals("php"))
{
assertUmpleTemplateFor("ClassTemplateTest_MultivaluedAttributesAssignment.ump", languagePath + "/ClassTemplateTest_MultivaluedAttributesAssignment."+languagePath+".txt", "Foo");
}
}

@Ignore @Test
public void LazyAttributeOnImmutableClass()
{
Expand Down
@@ -0,0 +1,9 @@
class Foo {
String[] someStrings = {"a","b","c"};
Integer[] numbers = {1,2,3,10};
Token[] objects = {new Token("first"),new Token("second")};
}

class Token {
attr;
}
Expand Up @@ -5,6 +5,6 @@ class X {
displayColor "#FFCCCC";
Float x;
Float y;
Float sum = {x + y};
Float sum = {x + y}
}

Expand Up @@ -8,5 +8,5 @@ class X {

Float x;
Float y;
Float sum = {x + y};
Float sum = {x + y}
}

0 comments on commit 543d9aa

Please sign in to comment.