Skip to content

Commit 5d03110

Browse files
authored
Merge pull request #15 from MiriamGaus/main
Udpdate Readme, dependancies and the test/example structure
2 parents e1172de + 581f293 commit 5d03110

64 files changed

Lines changed: 336 additions & 4752 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,9 @@ buildNumber.properties
160160
.classpath
161161

162162
# End of https://www.toptal.com/developers/gitignore/api/maven,intellij,java
163+
164+
# local changes
165+
/src/main/java/uvl
166+
/.vscode
167+
/src/main/java/de/vill/main/modified_files/*
168+
!/src/main/java/de/vill/main/modified_files/.gitkeep

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "src/test/resources"]
2+
path = src/test/resources
3+
url = https://github.com/Universal-Variability-Language/uvl-models

README.md

Lines changed: 122 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,156 @@
1-
# UVL - Universal Variability Language Java Metamodel
2-
This is a small default library used to manipulate UVL metamodels in JAVA
1+
# UVL - Universal Variability Language Java Feature Model Metamodel
32

4-
## The Language
3+
This is a small default library used to manipulate UVL metamodels in JAVA. It uses the [UVL-Grammar](https://github.com/Universal-Variability-Language/) to parse the a given metamodel. If parsed the model can be modified in JAVA. It is possible to also convert the models to different levels.
54

6-
On a high level, each feature model in UVL consists of five optional separated elements:
5+
**How to use UVL** can be found in this paper
6+
[![DOI](https://img.shields.io/badge/DOI-10.1016%2Fj.jss.2024.112326-blue)](https://doi.org/10.1016/j.jss.2024.112326)
77

8-
1. **A list of used language levels**
9-
The model can use different concepts which are part of language levels. These levels can either be enumerated with the `include` keyword or be implicit.
10-
2. **A namespace which can be used for references in other models**
11-
3. **A list of imports that can be used to reference external feature models**
12-
The models are referenced by their file name and can be given an alias using a Java import like syntax.
13-
External models in subdirectories can be referenced like this: subdir.filename as fn
14-
4. **The tree hierarchy consisting of: features, group types, and attributes whose relations are specified using nesting (indentation)**
15-
Groups may have an arbitrary number of features as child nodes. A feature can also have a feature cardinality.
16-
Attributes consist of a key-value pair whose key is always a string and its value may be a boolean, number, string, a list attributes, a vector, or a constraint. If the value is a constraint the key must be `constraint`. If the value is a list of constraints the key must be `constraints`
17-
5. **Cross-tree constraints**
18-
Cross-tree constraints may be arbitrary propositional formulas with the following symbols: => (implies), <=> (iff), & (and), | (or), ! (not), or brackets. Through the usage of language levels cross-tree constraints can also contain equations (<,>,==) which consist of expressions (+,-,*,/) with numbers or numerical feature attributes as literals and aggregate functions (avg, sum).
8+
## ✨ Key Features
199

20-
The following snippet shows a simplified server architecture in UVL. We provide more examples (e.g., to show the composition mechanism) in [https://github.com/Universal-Variability-Language/uvl-models/tree/main/Feature_Models](https://github.com/Universal-Variability-Language/uvl-models/tree/main/Feature_Models).
10+
- full support of UVL-Syntax (namespaces, feature hierarchies and constraints)
11+
- convert between different language levels
12+
- direct access to feature model components like features, groups and attributes
2113

14+
## ⚙️ Setup
15+
16+
To clone this repository **with all submodules**, use:
17+
18+
```bash
19+
git clone --recurse-submodules https://github.com/Universal-Variability-Language/java-fm-metamodel.git
2220
```
23-
namespace Server
24-
25-
features
26-
Server {abstract}
27-
mandatory
28-
FileSystem
29-
or // with cardinality: [1..*]
30-
NTFS
31-
APFS
32-
EXT4
33-
OperatingSystem {abstract}
34-
alternative
35-
Windows
36-
macOS
37-
Debian
38-
optional
39-
Logging {
40-
default,
41-
log_level "warn" // Feature Attribute
42-
}
43-
44-
constraints
45-
Windows => NTFS
46-
macOS => APFS
21+
22+
If you have already cloned the repository **without** submodules, you can initialize and update them afterwards with:
23+
24+
```bash
25+
git submodule update --init --recursive
4726
```
4827

49-
In this snippet, we can recognize the following elements:
50-
* The feature `Server` is abstract (i.e., corresponds to no implementation artifact.
51-
* Each `Server` requires a `FileSystem`and an `OperatingSystem` denoted by the *mandatory* group
52-
* The `Server` may have `Logging` denoted by the *optional* group
53-
* A `FileSystem` requires at least one type of `NTFS`, `APFS`, and `Ext4` denoted by the *or* group
54-
* An `OperatingSystem` has exactly one type of `Windows`, `macOS`, and `Debian`denoted by the *alternative* group
55-
* `Logging` has the feature attribute `log_level` attached which is set to "warn"
56-
* `Windows` requires `NTFS` denoted by the first cross-tree constraint
57-
* `macOS`requires `APFS`
28+
This ensures that all required submodules (e.g., test resources) are available and the project will build and test correctly
29+
30+
## 💡 Usage
31+
32+
### 📦 Getting Started
5833

59-
## Building a jar
34+
First, **clone this repository** to your local machine as explained in `⚙️ Setup`.
35+
To use the Java-fm-metamodel, make sure you are in the project directory before running any further commands. Build the project with [Maven](https://maven.apache.org/):
6036

61-
The library is a maven project and can therefore be build with maven. To update the generated parser classes and create a jar with all necessary dependencies, use:
37+
```bash
38+
mvn clean compile
6239
```
63-
mvn clean compile assembly:single
40+
41+
This will compile all sources and ensure all dependencies (including submodules) are available.
42+
Now you can execute code for manipulating UVL feature models as shown in the `Examples` below
43+
44+
### 🧩 Using as a Maven Dependency
45+
46+
You can also use the Java-fm-metamodel as a dependency in your own Maven project.
47+
Add the following to your `pom.xml`:
48+
49+
```xml
50+
<dependency>
51+
<groupId>io.github.universal-variability-language</groupId>
52+
<artifactId>fm-metamodel</artifactId>
53+
<version>1.1</version>
54+
</dependency>
6455
```
6556

66-
The `target/uvl-parser-1.0-SNAPSHOT-jar-with-dependencies.jar` includes all dependencies.
57+
Make sure that the version matches the latest release.
6758

68-
## Usage from Java
69-
The class `de.vill.main.UVLModelFactory` exposes the static method `parse(String)` which will return an instance of a `de.vill.model.FeatureModel` class. If there is something wrong, a `de.vill.exception.ParseError` is thrown. The parser tries to parse the whole model, even if there are errors. If there are multiple errors, a `de.vill.exception.ParseErrorList` is returned which contains all errors that occurred.
70-
A model can be printed with the `toString()` method of the `de.vill.model.FeatureModel` object.
71-
The following snippet shows a minimal example to read and write UVL models using the jar. More usage examples that also show how to use the acquired UVLModel object can be found in [src/main/java/de/vill/main/Example.java](https://github.com/Universal-Variability-Language/uvl-parser2.0/blob/main/src/main/java/de/vill/main/Example.java)
59+
---
60+
61+
Now you can use the classes from this library in your own Java code!
62+
63+
## Examples
64+
65+
Some usage examples that show how to use the acquired UVLModel object can be found in [src/main/java/de/vill/main/Example.java](https://github.com/Universal-Variability-Language/java-fm-metamodel/blob/main/src/main/java/de/vill/main/Example.java)
66+
67+
### Parsing
7268

7369
```Java
74-
// Read
70+
// First option:
71+
UVLModelFactory uvlModelFactory = new UVLModelFactory();
72+
FeatureModel featureModel = uvlModelFactory.parse(Paths.get("path/to/your/file.uvl"));
73+
74+
// Second option:
7575
Path filePath = Paths.get(pathAsString);
7676
String content = new String(Files.readAllBytes(filePath));
7777
UVLModelFactory uvlModelFactory = new UVLModelFactory();
7878
FeatureModel featureModel = uvlModelFactory.parse(content);
79+
```
80+
81+
The class `de.vill.main.UVLModelFactory` exposes the static method `parse(String)` which will return an instance of a `de.vill.model.FeatureModel` class. If there is something wrong, a `de.vill.exception.ParseError` is thrown. The parser tries to parse the whole model, even if there are errors. If there are multiple errors, a `de.vill.exception.ParseErrorList` is returned which contains all errors that occurred.
7982

83+
### Modifying
8084

85+
```Java
86+
Feature feature = featureModel.getFeatureMap().get(featureName);
87+
if (feature != null) {
88+
Attribute<?> attribute = feature.getAttributes().get(attributeName);
89+
if (attribute != null) {
90+
System.out.println("Name of the feature" + feature.getFeatureName());
91+
System.out.println("Name of the attribute" + attribute.getName());
92+
}
93+
}
94+
95+
// Conversion
96+
ConvertTypeLevel converter = new ConvertTypeLevel();
97+
converter.convertFeatureModel(featureModel, convertedModel);
98+
```
99+
100+
### Writing into a file
101+
102+
```Java
81103
// Write
82104
String uvlModel = featureModel.toString();
83105
Path filePath = Paths.get(featureModel.getNamespace() + ".uvl");
84106
Files.write(filePath, uvlModel.getBytes());
85-
```
107+
```
108+
109+
A model can be printed with the `toString()` method of the `de.vill.model.FeatureModel` object.
110+
111+
## 🧪 Running Tests
112+
113+
The Java-fm-metamodel can be tested by running:
114+
115+
```bash
116+
mvn test
117+
```
118+
119+
## 📖 Citation
120+
121+
If you use UVL in your research, please cite:
122+
123+
```bibtex
124+
@article{UVL2024,
125+
title = {UVL: Feature modelling with the Universal Variability Language},
126+
journal = {Journal of Systems and Software},
127+
volume = {225},
128+
pages = {112326},
129+
year = {2025},
130+
issn = {0164-1212},
131+
doi = {https://doi.org/10.1016/j.jss.2024.112326},
132+
url = {https://www.sciencedirect.com/science/article/pii/S0164121224003704},
133+
author = {David Benavides and Chico Sundermann and Kevin Feichtinger and José A. Galindo and Rick Rabiser and Thomas Thüm},
134+
keywords = {Feature model, Software product lines, Variability}
135+
}
136+
```
86137

87138
## Links
139+
88140
UVL models:
89-
* https://github.com/Universal-Variability-Language/uvl-models
141+
142+
- https://github.com/Universal-Variability-Language/uvl-models
143+
144+
UVL parser:
145+
146+
- https://github.com/Universal-Variability-Language/uvl-parser
90147

91148
Other parsers:
92-
* https://github.com/Universal-Variability-Language/uvl-parser *deprecated, Initial UVL Parser, based on Clojure and instaparse* **UVL-Parser**
93-
* https://github.com/diverso-lab/uvl-diverso/ *Under development, Antlr4 Parser* **Diverso Lab**
94149

95-
Usage of UVL:
96-
* https://github.com/FeatureIDE/FeatureIDE *Feature modelling tool*
150+
- https://github.com/Universal-Variability-Language/uvl-parser _deprecated, Initial UVL Parser, based on Clojure and instaparse_ **UVL-Parser**
151+
- https://github.com/diverso-lab/uvl-diverso/ _Under development, Antlr4 Parser_ **Diverso Lab**
97152

153+
Usage of UVL:
98154

155+
- https://github.com/FeatureIDE/FeatureIDE _Feature modelling tool_
156+
- https://github.com/SECPS/TraVarT _Transformation Tool for Variability Artifacts_

pom.xml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
<developerConnection>scm:git:git@github.com:Universal-Variability-Language/java-fm-metamodel.git</developerConnection>
5050
<url>https://github.com/Universal-Variability-Language/java-fm-metamodel</url>
5151
<tag>HEAD</tag>
52-
</scm>
52+
</scm>
5353

5454
<distributionManagement>
5555
<snapshotRepository>
@@ -63,9 +63,9 @@
6363
</distributionManagement>
6464

6565
<properties>
66-
<antlr4.version>4.13.1</antlr4.version>
67-
<maven.compiler.source>11</maven.compiler.source>
68-
<maven.compiler.target>11</maven.compiler.target>
66+
<antlr4.version>4.13.2</antlr4.version>
67+
<maven.compiler.source>21</maven.compiler.source>
68+
<maven.compiler.target>21</maven.compiler.target>
6969
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
7070
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
7171
</properties>
@@ -74,7 +74,7 @@
7474
<dependency>
7575
<groupId>org.antlr</groupId>
7676
<artifactId>antlr4-runtime</artifactId>
77-
<version>4.13.1</version>
77+
<version>${antlr4.version}</version>
7878
</dependency>
7979
<dependency>
8080
<groupId>io.github.universal-variability-language</groupId>
@@ -84,13 +84,13 @@
8484
<dependency>
8585
<groupId>org.junit.jupiter</groupId>
8686
<artifactId>junit-jupiter</artifactId>
87-
<version>5.8.2</version>
87+
<version>5.13.1</version>
8888
<scope>test</scope>
8989
</dependency>
9090
<dependency>
9191
<groupId>com.google.guava</groupId>
9292
<artifactId>guava</artifactId>
93-
<version>31.0.1-jre</version>
93+
<version>33.4.8-jre</version>
9494
</dependency>
9595
</dependencies>
9696

@@ -99,7 +99,7 @@
9999
<plugin>
100100
<groupId>org.apache.maven.plugins</groupId>
101101
<artifactId>maven-surefire-plugin</artifactId>
102-
<version>2.22.0</version>
102+
<version>3.5.3</version>
103103
</plugin>
104104
<plugin>
105105
<artifactId>maven-assembly-plugin</artifactId>
@@ -117,7 +117,7 @@
117117
<plugin>
118118
<groupId>org.apache.maven.plugins</groupId>
119119
<artifactId>maven-compiler-plugin</artifactId>
120-
<version>3.8.1</version>
120+
<version>3.14.0</version>
121121
<configuration>
122122
<source>${maven.compiler.source}</source>
123123
<target>${maven.compiler.target}</target>
@@ -127,7 +127,7 @@
127127
<plugin>
128128
<groupId>org.apache.maven.plugins</groupId>
129129
<artifactId>maven-gpg-plugin</artifactId>
130-
<version>1.5</version>
130+
<version>3.2.7</version>
131131
<executions>
132132
<execution>
133133
<id>sign-artifacts</id>
@@ -142,7 +142,7 @@
142142
<plugin>
143143
<groupId>org.sonatype.plugins</groupId>
144144
<artifactId>nexus-staging-maven-plugin</artifactId>
145-
<version>1.6.7</version>
145+
<version>1.7.0</version>
146146
<extensions>true</extensions>
147147
<configuration>
148148
<serverId>ossrh</serverId>
@@ -154,7 +154,7 @@
154154
<plugin>
155155
<groupId>org.apache.maven.plugins</groupId>
156156
<artifactId>maven-source-plugin</artifactId>
157-
<version>3.2.1</version>
157+
<version>3.3.1</version>
158158
<executions>
159159
<execution>
160160
<id>attach-sources</id>
@@ -167,7 +167,7 @@
167167
<plugin>
168168
<groupId>org.apache.maven.plugins</groupId>
169169
<artifactId>maven-javadoc-plugin</artifactId>
170-
<version>3.2.0</version>
170+
<version>3.11.2</version>
171171
<executions>
172172
<execution>
173173
<id>attach-javadocs</id>
@@ -180,4 +180,4 @@
180180
</plugins>
181181
</build>
182182

183-
</project>
183+
</project>

src/main/java/de/vill/conversion/ConvertAggregateFunction.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ private void searchAggregateFunctionInExpression(Expression expression) {
5656

5757
private void replaceAggregateFunctionInExpression(Expression parentExpression, AggregateFunctionExpression aggregateFunctionExpression) {
5858
Feature rootFeature;
59-
Expression aggregateFunctionReplacement;
6059
if (aggregateFunctionExpression.getRootFeature() == null) {
6160
rootFeature = rootFeatureModel.getRootFeature();
6261
} else {
@@ -74,7 +73,6 @@ private void replaceAggregateFunctionInExpression(Expression parentExpression, A
7473

7574
private void replaceAggregateFunctionInExpressionConstraint(ExpressionConstraint parentExpression, AggregateFunctionExpression aggregateFunctionExpression) {
7675
Feature rootFeature;
77-
Expression aggregateFunctionReplacement;
7876
if (aggregateFunctionExpression.getRootFeature() == null) {
7977
rootFeature = rootFeatureModel.getRootFeature();
8078
} else {
@@ -155,7 +153,6 @@ private void removeAggregateFunctionFromAttributes(Feature feature) {
155153
}
156154
}
157155
if (attributeConstraintList != null && attributeConstraintList.getValue() instanceof List<?>) {
158-
List<Object> newConstraintList = new LinkedList<>();
159156
for (Object constraint : (List<?>) attributeConstraintList.getValue()) {
160157
if (constraint instanceof Constraint) {
161158
searchAggregateFunctionInConstraint((Constraint) constraint);

src/main/java/de/vill/conversion/ConvertSMTLevel.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import com.google.common.collect.Sets;
44
import de.vill.model.*;
55
import de.vill.model.constraint.*;
6-
import de.vill.model.expression.AggregateFunctionExpression;
7-
import de.vill.model.expression.BinaryExpression;
86
import de.vill.model.expression.Expression;
97
import de.vill.model.expression.LiteralExpression;
108

0 commit comments

Comments
 (0)