Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
monticore
EmbeddedMontiArc
generators
EMAM2Wasm
Commits
35e1c688
Verified
Commit
35e1c688
authored
Apr 14, 2018
by
Stefan Brunecker
Browse files
Add more tests for GeneratorUtil
parent
68da7bb5
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/main/java/de/monticore/lang/monticar/generator/GeneratorUtil.java
View file @
35e1c688
...
...
@@ -3,25 +3,49 @@ package de.monticore.lang.monticar.generator;
import
static
de
.
monticore
.
lang
.
monticar
.
contract
.
Precondition
.
requiresNotNull
;
import
static
de
.
monticore
.
lang
.
monticar
.
contract
.
StringPrecondition
.
requiresNotBlank
;
import
com.google.common.annotations.VisibleForTesting
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymbol
;
import
de.monticore.lang.monticar.common2._ast.ASTCommonDimensionElement
;
import
de.monticore.lang.monticar.common2._ast.ASTCommonMatrixType
;
import
de.monticore.lang.monticar.ts.MCTypeSymbol
;
import
de.monticore.lang.monticar.ts.references.MCASTTypeSymbolReference
;
import
de.monticore.lang.monticar.ts.references.MCTypeReference
;
import
de.monticore.lang.monticar.types2._ast.ASTElementType
;
import
de.monticore.lang.monticar.types2._ast.ASTType
;
import
de.monticore.symboltable.Symbol
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Optional
;
import
org.springframework.util.StringUtils
;
/**
* Class for methods commonly used by generator classes.
*/
public
class
GeneratorUtil
{
private
static
final
String
GETTER_PREFIX
=
"get"
;
private
static
final
String
SETTER_PREFIX
=
"set"
;
private
static
final
String
BOOLEAN_TYPE
=
"B"
;
private
static
final
String
NATURAL_NUMBER_TYPE
=
"N"
;
private
static
final
String
INTEGER_NUMBER_TYPE
=
"Z"
;
private
static
final
String
RATIONAL_NUMBER_TYPE
=
"Q"
;
private
static
final
String
COMPLEX_NUMBER_TYPE
=
"C"
;
/**
* Takes a collection of {@link PortSymbol}s and filters out ports that
* belong to an array except for one. The order of the ports in the supplied
* collection remains otherwise unchanged.<p>
* It is guaranteed that the first port of an array as returned by the
* collections iterator is put into the returned collection. All subsequent
* ports belonging to this array will be discarded.<p>
* Two ports are determined to belong to the same port array if their names
* match disregarding the trailing square brackets.
*
* @param ports a collection of ports
* @return collection that contains only one port for each port array and is
* otherwise unchanged from the supplied collection
*/
public
static
Collection
<
PortSymbol
>
filterMultipleArrayPorts
(
Collection
<
PortSymbol
>
ports
)
{
List
<
PortSymbol
>
filteredPorts
=
new
ArrayList
<>();
List
<
String
>
processedArrays
=
new
ArrayList
<>();
...
...
@@ -38,23 +62,123 @@ public class GeneratorUtil {
return
filteredPorts
;
}
/**
* Returns the method name to be used when generating a setter method for the
* supplied port.
*
* @param port {@code PortSymbol}
* @return method name for the supplied port
*/
public
static
String
getSetterMethodName
(
PortSymbol
port
)
{
return
getSetterMethodName
(
requiresNotNull
(
port
).
getNameWithoutArrayBracketPart
());
}
/**
* Returns the method name to be used when generating a setter method for a
* {@link PortSymbol} with the supplied name.
*
* @param portName the name of a {@code PortSymbol}
* @return method name for the supplied port name
*/
public
static
String
getSetterMethodName
(
String
portName
)
{
return
SETTER_PREFIX
+
StringUtils
.
capitalize
(
requiresNotBlank
(
portName
));
}
/**
* Returns the method name to be used when generating a getter method for the
* supplied port.
*
* @param port {@code PortSymbol}
* @return method name for the supplied port
*/
public
static
String
getGetterMethodName
(
PortSymbol
port
)
{
return
getGetterMethodName
(
requiresNotNull
(
port
).
getNameWithoutArrayBracketPart
());
}
/**
* Returns the method name to be used when generating a getter method for a
* {@link PortSymbol} with the supplied name.
*
* @param portName the name of a {@code PortSymbol}
* @return method name for the supplied port name
*/
public
static
String
getGetterMethodName
(
String
portName
)
{
return
GETTER_PREFIX
+
StringUtils
.
capitalize
(
requiresNotBlank
(
portName
));
}
@VisibleForTesting
/**
* Returns the component name for the supplied {@code Symbol}. This name
* always starts with an capital letter.
*
* @param model {@code Symbol}
* @return component name for the supplied symbol
*/
public
static
String
getComponentName
(
Symbol
model
)
{
return
StringUtils
.
capitalize
(
requiresNotNull
(
model
).
getName
());
}
/**
* Tries to determine the supplied {@code PortSymbol}'s type. The type
* includes the number set, any defined range and corresponding units.
*
* @param port {@code PortSymbol}
* @return the port's type
* @throws RuntimeException if it failed to determine the port's type
*/
public
static
String
getType
(
PortSymbol
port
)
{
MCASTTypeSymbolReference
typeReference
=
(
MCASTTypeSymbolReference
)
port
.
getTypeReference
();
ASTType
astType
=
typeReference
.
getAstType
();
if
(
astType
instanceof
ASTCommonMatrixType
)
{
return
matrixType
((
ASTCommonMatrixType
)
astType
);
}
else
if
(
astType
instanceof
ASTElementType
)
{
ASTElementType
type
=
(
ASTElementType
)
astType
;
Optional
<
String
>
elementType
=
type
.
getTElementType
();
return
elementType
.
orElse
(
typeReference
.
getName
());
}
else
{
throw
new
RuntimeException
(
"Unexpected ASTType: "
+
astType
);
}
}
private
static
String
matrixType
(
ASTCommonMatrixType
type
)
{
ASTElementType
elementType
=
type
.
getElementType
();
Optional
<
String
>
tElementTypeOpt
=
elementType
.
getTElementType
();
if
(
tElementTypeOpt
.
isPresent
())
{
return
tElementTypeOpt
.
get
();
}
else
{
if
(
elementType
.
isIsBoolean
())
{
return
BOOLEAN_TYPE
;
}
else
if
(
elementType
.
isIsNatural
())
{
return
NATURAL_NUMBER_TYPE
;
}
else
if
(
elementType
.
isIsWholeNumberNumber
())
{
return
INTEGER_NUMBER_TYPE
;
}
else
if
(
elementType
.
isIsRational
())
{
return
RATIONAL_NUMBER_TYPE
;
}
else
if
(
elementType
.
isIsComplex
())
{
return
COMPLEX_NUMBER_TYPE
;
}
else
{
throw
new
RuntimeException
(
"Unable to determine type from "
+
type
);
}
}
}
/**
* Returns a string array representing the dimension of the supplied port.
* The entries in this array are strings of integer numbers. The dimension
* is a combination of the port's potential matrix dimension and array size.
* In case the supplied port is defined as an array of matrices, a string
* array with the array and matrix dimension is returned. The size of the
* port array will be in position 0 of the returned array.
* In case the supplied port is either defined as a matrix or belongs to an
* array, the respective dimension is returned.
* Otherwise, a string array of size 0 is returned.<p>
* A collection of all ports of the component that the supplied port belongs
* to is needed to determine a potential array size.
*
* @param ports all ports directly belonging to the component of the
* supplied port
* @param port PortSymbol to determine the dimension for
* @return dimension of the port or an empty array
*/
public
static
String
[]
getDimension
(
Collection
<
PortSymbol
>
ports
,
PortSymbol
port
)
{
int
arrayDimension
=
port
.
isPartOfPortArray
()
?
getArrayDimension
(
ports
,
port
.
getNameWithoutArrayBracketPart
())
:
0
;
...
...
src/main/java/de/monticore/lang/monticar/generator/html/HtmlGenerator.java
View file @
35e1c688
package
de.monticore.lang.monticar.generator.html
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
filterMultipleArrayPorts
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getComponentName
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getDimension
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getType
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.ExpandedComponentInstanceSymbol
;
import
de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymbol
;
import
de.monticore.lang.monticar.common2._ast.ASTCommonMatrixType
;
import
de.monticore.lang.monticar.freemarker.TemplateProcessor
;
import
de.monticore.lang.monticar.generator.GeneratorUtil
;
import
de.monticore.lang.monticar.ts.references.MCASTTypeSymbolReference
;
import
de.monticore.lang.monticar.types2._ast.ASTElementType
;
import
de.monticore.lang.monticar.types2._ast.ASTType
;
import
freemarker.template.TemplateException
;
import
java.io.IOException
;
import
java.util.Arrays
;
...
...
@@ -18,10 +16,8 @@ import java.util.Collection;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Optional
;
import
java.util.function.Function
;
import
java.util.stream.Collectors
;
import
org.springframework.util.StringUtils
;
/**
* This generator generates html files that can be used in combination with a
...
...
@@ -63,7 +59,7 @@ public class HtmlGenerator {
List
<
Port
>
outports
=
produceOutports
(
model
.
getOutgoingPorts
());
Map
<
String
,
Object
>
dataModel
=
new
HashMap
<>();
dataModel
.
put
(
"modelName"
,
get
Model
Name
(
model
));
dataModel
.
put
(
"modelName"
,
get
Component
Name
(
model
));
dataModel
.
put
(
"model"
,
wasmNamingFunction
.
apply
(
model
));
dataModel
.
put
(
"model_wrapper"
,
wrapperNamingFunction
.
apply
(
model
));
dataModel
.
put
(
"inports"
,
inports
);
...
...
@@ -84,23 +80,11 @@ public class HtmlGenerator {
Function
<
PortSymbol
,
String
>
methodNameFunction
)
{
return
filterMultipleArrayPorts
(
ports
).
stream
().
map
(
p
->
port
(
p
.
getNameWithoutArrayBracketPart
(),
methodNameFunction
.
apply
(
p
),
get
Type
(
ports
,
p
))).
collect
(
Collectors
.
toList
());
get
PortDefinition
(
ports
,
p
))).
collect
(
Collectors
.
toList
());
}
private
String
getType
(
Collection
<
PortSymbol
>
ports
,
PortSymbol
port
)
{
MCASTTypeSymbolReference
typeReference
=
(
MCASTTypeSymbolReference
)
port
.
getTypeReference
();
ASTType
astType
=
typeReference
.
getAstType
();
Optional
<
String
>
elementType
;
if
(
astType
instanceof
ASTCommonMatrixType
)
{
ASTCommonMatrixType
type
=
(
ASTCommonMatrixType
)
astType
;
elementType
=
type
.
getElementType
().
getTElementType
();
}
else
if
(
astType
instanceof
ASTElementType
)
{
ASTElementType
type
=
(
ASTElementType
)
astType
;
elementType
=
type
.
getTElementType
();
}
else
{
throw
new
RuntimeException
(
"Unexpected ASTType: "
+
astType
);
}
String
type
=
elementType
.
orElse
(
typeReference
.
getName
());
private
String
getPortDefinition
(
Collection
<
PortSymbol
>
ports
,
PortSymbol
port
)
{
String
type
=
getType
(
port
);
String
[]
dimension
=
getDimension
(
ports
,
port
);
String
dim
=
dimension
.
length
>
0
?
...
...
@@ -109,10 +93,6 @@ public class HtmlGenerator {
return
type
+
dim
;
}
private
String
getModelName
(
ExpandedComponentInstanceSymbol
model
)
{
return
StringUtils
.
capitalize
(
model
.
getName
());
}
private
Port
port
(
String
name
,
String
wrapperFunction
,
String
type
)
{
Port
port
=
new
Port
();
port
.
setName
(
name
);
...
...
src/test/java/de/monticore/lang/monticar/generator/GeneratorUtilTest.java
View file @
35e1c688
package
de.monticore.lang.monticar.generator
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
filterMultipleArrayPorts
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getComponentName
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getDimension
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getGetterMethodName
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getSetterMethodName
;
import
static
de
.
monticore
.
lang
.
monticar
.
generator
.
GeneratorUtil
.
getType
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThatExceptionOfType
;
import
static
org
.
mockito
.
Mockito
.
mock
;
...
...
@@ -14,6 +16,7 @@ import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.PortSymb
import
de.monticore.lang.monticar.contract.Precondition.PreconditionViolationException
;
import
de.monticore.lang.monticar.resolver.Resolver
;
import
de.monticore.lang.monticar.resolver.ResolverFactory
;
import
de.monticore.symboltable.Symbol
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.Collection
;
...
...
@@ -21,7 +24,10 @@ import java.util.stream.Collectors;
import
org.junit.jupiter.api.BeforeEach
;
import
org.junit.jupiter.api.Nested
;
import
org.junit.jupiter.api.Test
;
import
org.junit.jupiter.params.ParameterizedTest
;
import
org.junit.jupiter.params.provider.CsvSource
;
@SuppressWarnings
(
"ConstantConditions"
)
class
GeneratorUtilTest
{
private
static
final
Path
RESOLVING_BASE_DIR
=
Paths
.
get
(
"src/test/resources/generatorutil"
);
...
...
@@ -49,6 +55,14 @@ class GeneratorUtilTest {
private
static
final
String
COLUMN_VECTOR
=
"ColumnVector"
;
private
static
final
String
MATRIX
=
"Matrix"
;
private
static
final
String
MATRIX_ARRAY
=
"MatrixArray[2]"
;
private
static
final
Symbol
NULL_SYMBOL
=
null
;
private
static
final
String
ALL_LOWERCASE_NAME
=
"somename"
;
private
static
final
String
EXPECTED_ALL_LOWERCASE_COMPONENT_NAME
=
"Somename"
;
private
static
final
String
EXPECTED_FIRST_UPPERCASE_COMPONENT_NAME
=
"Somename"
;
private
static
final
String
EXPECTED_ALL_UPPERCASE_COMPONENT_NAME
=
"SOMENAME"
;
private
static
final
String
FIRST_UPPERCASE_NAME
=
"Somename"
;
private
static
final
String
ALL_UPPERCASE_NAME
=
"SOMENAME"
;
private
static
final
String
TYPES_MODEL
=
"models.types"
;
private
static
String
portName
(
String
direction
,
String
name
)
{
return
direction
+
name
;
...
...
@@ -292,6 +306,101 @@ class GeneratorUtilTest {
}
}
@Nested
class
GetComponentName
{
@Nested
class
ShouldThrowException
{
@Test
void
whenSymbolIsNull
()
{
assertThatExceptionOfType
(
PreconditionViolationException
.
class
)
.
isThrownBy
(()
->
getComponentName
(
NULL_SYMBOL
));
}
}
@Nested
class
ShouldReturnCapitalizedSymbolName
{
@Test
void
whenAllLowercase
()
{
Symbol
symbol
=
mock
(
Symbol
.
class
);
when
(
symbol
.
getName
()).
thenReturn
(
ALL_LOWERCASE_NAME
);
assertThat
(
getComponentName
(
symbol
)).
isEqualTo
(
EXPECTED_ALL_LOWERCASE_COMPONENT_NAME
);
}
@Test
void
whenFirstUppercase
()
{
Symbol
symbol
=
mock
(
Symbol
.
class
);
when
(
symbol
.
getName
()).
thenReturn
(
FIRST_UPPERCASE_NAME
);
assertThat
(
getComponentName
(
symbol
)).
isEqualTo
(
EXPECTED_FIRST_UPPERCASE_COMPONENT_NAME
);
}
@Test
void
whenAllUppercase
()
{
Symbol
symbol
=
mock
(
Symbol
.
class
);
when
(
symbol
.
getName
()).
thenReturn
(
ALL_UPPERCASE_NAME
);
assertThat
(
getComponentName
(
symbol
)).
isEqualTo
(
EXPECTED_ALL_UPPERCASE_COMPONENT_NAME
);
}
}
}
@Nested
class
GetType
{
private
ExpandedComponentInstanceSymbol
typesModel
;
@BeforeEach
void
setUp
()
{
ResolverFactory
resolverFactory
=
new
ResolverFactory
(
RESOLVING_BASE_DIR
);
Resolver
resolver
=
resolverFactory
.
get
();
typesModel
=
resolver
.
getExpandedComponentInstanceSymbol
(
TYPES_MODEL
);
}
@ParameterizedTest
@CsvSource
({
"bool, B"
,
// "natural, N",
"integer, Z"
,
"rational, Q"
,
"complex, C"
,
"boolMatrix, B"
,
"naturalMatrix, N"
,
"integerMatrix, Z"
,
"rationalMatrix, Q"
,
"complexMatrix, C"
,
"boolArray[1], B"
,
"boolArray[2], B"
,
// "naturalArray[1], N",
// "naturalArray[2], N",
// "naturalArray[3], N",
"integerArray[1], Z"
,
"integerArray[2], Z"
,
"rationalArray[1], Q"
,
"rationalArray[2], Q"
,
"complexArray[1], C"
,
"complexArray[2], C"
,
"boolMatrixArray[1], B"
,
"boolMatrixArray[2], B"
,
"naturalMatrixArray[1], N"
,
"naturalMatrixArray[2], N"
,
"integerMatrixArray[1], Z"
,
"integerMatrixArray[2], Z"
,
"rationalMatrixArray[1], Q"
,
"rationalMatrixArray[2], Q"
,
"complexMatrixArray[1], C"
,
"complexMatrixArray[2], C"
,
"rangeNoUnit, Q(-10 : 0.01 : oo)"
,
"rangeUnit, Z(0 g : 1 kg)"
,
"matrixRangeUnit, Q(-oo m/s : 0.5 m/s : oo m/s)"
,
})
void
testType
(
String
portName
,
String
expectedType
)
{
PortSymbol
port
=
typesModel
.
getPort
(
portName
).
get
();
assertThat
(
getType
(
port
)).
isEqualToIgnoringWhitespace
(
expectedType
);
}
}
@Nested
class
GetDimension
{
...
...
src/test/resources/generatorutil/models/Types.emam
0 → 100644
View file @
35e1c688
package
models
;
component
Types
{
ports
in
B
bool
,
//
out
N
natural
,
in
Z
integer
,
out
Q
rational
,
in
C
complex
,
out
B
^{
3
,
4
}
boolMatrix
,
in
N
^{
3
,
4
}
naturalMatrix
,
out
Z
^{
3
,
4
}
integerMatrix
,
in
Q
^{
3
,
4
}
rationalMatrix
,
out
C
^{
3
,
4
}
complexMatrix
,
in
B
boolArray
[
3
],
//
out
N
naturalArray
[
3
],
in
Z
integerArray
[
3
],
out
Q
rationalArray
[
3
],
in
C
complexArray
[
3
],
out
B
^{
2
,
2
}
boolMatrixArray
[
2
],
in
N
^{
2
,
2
}
naturalMatrixArray
[
2
],
out
Z
^{
2
,
2
}
integerMatrixArray
[
2
],
in
Q
^{
2
,
2
}
rationalMatrixArray
[
2
],
out
C
^{
2
,
2
}
complexMatrixArray
[
2
],
in
Q
(-
10
:
0.01
:
oo
)
rangeNoUnit
,
out
Z
(
0
g
:
1
kg
)
rangeUnit
,
in
Q
(-
oo
m
/
s
:
0.5
m
/
s
:
oo
m
/
s
)^{
3
,
4
}
matrixRangeUnit
;
}
\ No newline at end of file
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment