diff --git a/pom.xml b/pom.xml
index 7c96e8e..baa9790 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,13 @@
1.8
+
+ org.antlr
+ ST4
+ 4.3
+ compile
+
+
diff --git a/src/main/java/com/patternpedia/api/PatternPediaAPI.java b/src/main/java/com/patternpedia/api/PatternPediaAPI.java
index 3183bbf..60ebdf5 100644
--- a/src/main/java/com/patternpedia/api/PatternPediaAPI.java
+++ b/src/main/java/com/patternpedia/api/PatternPediaAPI.java
@@ -1,34 +1,23 @@
package com.patternpedia.api;
-import com.patternpedia.api.rest.controller.UserController;
-import com.patternpedia.api.service.IssueService;
import com.vladmihalcea.hibernate.type.util.Configuration;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.info.License;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
-import org.springframework.web.bind.annotation.RestController;
@EnableTransactionManagement
@Slf4j
-@RestController
@SpringBootApplication
@OpenAPIDefinition(info = @Info(title = "pattern-atlas-api", version = "1.0", contact = @Contact(url = "https://github.com/PatternAtlas/pattern-atlas-api", name = "Pattern Atlas API")))
public class PatternPediaAPI implements CommandLineRunner {
- @Autowired
- private UserController userController;
-
- @Autowired
- private IssueService issueService;
-
public static void main(String[] args) {
System.setProperty(Configuration.PropertyKey.PRINT_BANNER.getKey(), Boolean.FALSE.toString());
SpringApplication.run(PatternPediaAPI.class, args);
@@ -36,15 +25,6 @@ public static void main(String[] args) {
@Override
public void run(String... args) {
-
log.info("PatternPediaAPI is up");
- // Used this for testing purposes, will be deleted in the final build
-// userController.defaultUsers();
-// Issue issue = new Issue();
-// issue.setUri("uri");
-// issue.setName("name");
-// issue.setDescription("description");
-// Issue p = issueService.createIssue(issue);
-// log.info(p.toString());
}
}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/AggregationData.java b/src/main/java/com/patternpedia/api/entities/designmodel/AggregationData.java
new file mode 100644
index 0000000..3daa1e9
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/AggregationData.java
@@ -0,0 +1,32 @@
+package com.patternpedia.api.entities.designmodel;
+
+import com.patternpedia.api.rest.model.FileDTO;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+@Data
+public class AggregationData {
+
+ private DesignModelPatternInstance source;
+
+ private DesignModelPatternInstance target;
+
+ private DesignModelPatternEdge edge;
+
+ private Map templateContext = new HashMap<>();
+
+ private FileDTO result;
+
+
+ public AggregationData(DesignModelPatternInstance source, DesignModelPatternInstance target, DesignModelPatternEdge edge) {
+ this.source = source;
+ this.target = target;
+ this.edge = edge;
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/ConcreteSolution.java b/src/main/java/com/patternpedia/api/entities/designmodel/ConcreteSolution.java
new file mode 100644
index 0000000..1c0deec
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/ConcreteSolution.java
@@ -0,0 +1,35 @@
+package com.patternpedia.api.entities.designmodel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.springframework.hateoas.server.core.Relation;
+
+import javax.persistence.*;
+import java.util.List;
+import java.util.UUID;
+
+
+@Entity
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode
+@Relation(value = "concreteSolution", collectionRelation = "concreteSolutions")
+public class ConcreteSolution {
+
+ @Id
+ @GeneratedValue(generator = "pg-uuid")
+ protected UUID id;
+
+ @Column(nullable = false)
+ private String patternUri;
+
+ private String name;
+
+ @ElementCollection
+ private List properties;
+
+ private String templateUri;
+
+ private String aggregatorType;
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModel.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModel.java
new file mode 100644
index 0000000..bf68cd5
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModel.java
@@ -0,0 +1,34 @@
+package com.patternpedia.api.entities.designmodel;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.patternpedia.api.entities.EntityWithURI;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.*;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+@Entity
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class DesignModel extends EntityWithURI {
+
+ private URL logo;
+
+ @JsonIgnore
+ @OneToMany(mappedBy = "designModel", cascade = CascadeType.ALL, orphanRemoval = true)
+ private List patterns = new ArrayList<>();
+
+ @JsonIgnore
+ @OneToMany(mappedBy = "designModel", cascade = CascadeType.ALL, orphanRemoval = true)
+ private List directedEdges;
+
+ @JsonIgnore
+ @OneToMany(mappedBy = "designModel", cascade = CascadeType.ALL, orphanRemoval = true)
+ private List undirectedEdges;
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelEdgeType.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelEdgeType.java
new file mode 100644
index 0000000..47aac0c
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelEdgeType.java
@@ -0,0 +1,16 @@
+package com.patternpedia.api.entities.designmodel;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+@Data
+public class DesignModelEdgeType {
+
+ @Id
+ private String name;
+
+ private Boolean swap;
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternEdge.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternEdge.java
new file mode 100644
index 0000000..707714c
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternEdge.java
@@ -0,0 +1,64 @@
+package com.patternpedia.api.entities.designmodel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapsId;
+
+import static java.lang.Boolean.TRUE;
+
+@Entity
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode
+public class DesignModelPatternEdge {
+
+ @EmbeddedId
+ @EqualsAndHashCode.Exclude
+ private DesignModelPatternEdgeId edgeId;
+
+ @ManyToOne
+ @EqualsAndHashCode.Include
+ private DesignModel designModel;
+
+ @ManyToOne
+ @MapsId("patternInstanceId1")
+ @EqualsAndHashCode.Include
+ private DesignModelPatternInstance patternInstance1;
+
+ @ManyToOne
+ @MapsId("patternInstanceId2")
+ @EqualsAndHashCode.Include
+ private DesignModelPatternInstance patternInstance2;
+
+ private Boolean isDirectedEdge;
+
+ private String type;
+
+ private String description;
+
+
+ public boolean isDirectedEdge() {
+ return TRUE.equals(isDirectedEdge);
+ }
+
+ public void setPatternInstance1(DesignModelPatternInstance patternInstance) {
+ if(edgeId == null) {
+ this.edgeId = new DesignModelPatternEdgeId();
+ }
+ this.edgeId.setPatternInstanceId1(patternInstance.getPatternInstanceId());
+ this.patternInstance1 = patternInstance;
+ }
+
+ public void setPatternInstance2(DesignModelPatternInstance patternInstance) {
+ if(edgeId == null) {
+ this.edgeId = new DesignModelPatternEdgeId();
+ }
+ this.edgeId.setPatternInstanceId2(patternInstance.getPatternInstanceId());
+ this.patternInstance2 = patternInstance;
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternEdgeId.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternEdgeId.java
new file mode 100644
index 0000000..5ffc1b0
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternEdgeId.java
@@ -0,0 +1,22 @@
+package com.patternpedia.api.entities.designmodel;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Embeddable;
+import java.io.Serializable;
+import java.util.UUID;
+
+@Embeddable
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DesignModelPatternEdgeId implements Serializable {
+
+ protected UUID patternInstanceId1;
+
+ protected UUID patternInstanceId2;
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternGraphData.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternGraphData.java
new file mode 100644
index 0000000..52768a0
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternGraphData.java
@@ -0,0 +1,23 @@
+package com.patternpedia.api.entities.designmodel;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DesignModelPatternGraphData {
+
+ private Double x;
+ private Double y;
+ private Double vx;
+ private Double vy;
+ private String type;
+ private Integer index;
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternInstance.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternInstance.java
new file mode 100644
index 0000000..97ed806
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelPatternInstance.java
@@ -0,0 +1,41 @@
+package com.patternpedia.api.entities.designmodel;
+
+import com.patternpedia.api.entities.Pattern;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.springframework.hateoas.server.core.Relation;
+
+import javax.persistence.*;
+import java.util.UUID;
+
+@Entity
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode
+@Relation(value = "pattern", collectionRelation = "patterns")
+public class DesignModelPatternInstance {
+
+ @Id
+ @GeneratedValue(generator = "pg-uuid")
+ protected UUID patternInstanceId;
+
+ @ManyToOne
+ @EqualsAndHashCode.Include
+ private DesignModel designModel;
+
+ @ManyToOne
+ @EqualsAndHashCode.Include
+ private Pattern pattern;
+
+ private DesignModelPatternGraphData graphData;
+
+ @Transient
+ private ConcreteSolution concreteSolution;
+
+
+ public DesignModelPatternInstance(DesignModel designModel, Pattern pattern) {
+ this.designModel = designModel;
+ this.pattern = pattern;
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelUndirectedEdge.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelUndirectedEdge.java
new file mode 100644
index 0000000..604ca7b
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelUndirectedEdge.java
@@ -0,0 +1,38 @@
+package com.patternpedia.api.entities.designmodel;
+
+import com.patternpedia.api.entities.UndirectedEdge;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapsId;
+
+@Entity
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode
+public class DesignModelUndirectedEdge {
+
+ @EmbeddedId
+ @EqualsAndHashCode.Exclude
+ private DesignModelUndirectedEdgeId id;
+
+ @ManyToOne
+ @MapsId("designModelId")
+ @EqualsAndHashCode.Include
+ private DesignModel designModel;
+
+ @ManyToOne
+ @MapsId("undirectedEdgeId")
+ @EqualsAndHashCode.Include
+ private UndirectedEdge undirectedEdge;
+
+ public DesignModelUndirectedEdge(DesignModel designModel, UndirectedEdge undirectedEdge) {
+ this.designModel = designModel;
+ this.undirectedEdge = undirectedEdge;
+ this.id = new DesignModelUndirectedEdgeId(designModel.getId(), undirectedEdge.getId());
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelUndirectedEdgeId.java b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelUndirectedEdgeId.java
new file mode 100644
index 0000000..65a5d1e
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/entities/designmodel/DesignModelUndirectedEdgeId.java
@@ -0,0 +1,20 @@
+package com.patternpedia.api.entities.designmodel;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+import javax.persistence.Embeddable;
+import java.io.Serializable;
+import java.util.UUID;
+
+@Embeddable
+@NoArgsConstructor
+@AllArgsConstructor
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DesignModelUndirectedEdgeId implements Serializable {
+ protected UUID designModelId;
+ protected UUID undirectedEdgeId;
+}
diff --git a/src/main/java/com/patternpedia/api/exception/AggregationException.java b/src/main/java/com/patternpedia/api/exception/AggregationException.java
new file mode 100644
index 0000000..3d076ed
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/exception/AggregationException.java
@@ -0,0 +1,8 @@
+package com.patternpedia.api.exception;
+
+public class AggregationException extends RuntimeException {
+
+ public AggregationException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/exception/ConcreteSolutionNotFoundException.java b/src/main/java/com/patternpedia/api/exception/ConcreteSolutionNotFoundException.java
new file mode 100644
index 0000000..bdf80d9
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/exception/ConcreteSolutionNotFoundException.java
@@ -0,0 +1,21 @@
+package com.patternpedia.api.exception;
+
+import com.patternpedia.api.entities.designmodel.ConcreteSolution;
+import org.springframework.data.rest.webmvc.ResourceNotFoundException;
+
+import java.util.UUID;
+
+public class ConcreteSolutionNotFoundException extends ResourceNotFoundException {
+
+ public ConcreteSolutionNotFoundException(String message) {
+ super(message);
+ }
+
+ public ConcreteSolutionNotFoundException(UUID concreteSolutionId) {
+ super(String.format("ConcreteSolution \"%s\" not found!", concreteSolutionId));
+ }
+
+ public ConcreteSolutionNotFoundException(ConcreteSolution concreteSolution) {
+ super(String.format("ConcreteSolution \"%s\" not found!", concreteSolution.getId()));
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/exception/DesignModelNotFoundException.java b/src/main/java/com/patternpedia/api/exception/DesignModelNotFoundException.java
new file mode 100644
index 0000000..4261681
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/exception/DesignModelNotFoundException.java
@@ -0,0 +1,21 @@
+package com.patternpedia.api.exception;
+
+import com.patternpedia.api.entities.designmodel.DesignModel;
+import org.springframework.data.rest.webmvc.ResourceNotFoundException;
+
+import java.util.UUID;
+
+public class DesignModelNotFoundException extends ResourceNotFoundException {
+
+ public DesignModelNotFoundException(String message) {
+ super(message);
+ }
+
+ public DesignModelNotFoundException(UUID designModelId) {
+ super(String.format("DesignModel \"%s\" not found!", designModelId));
+ }
+
+ public DesignModelNotFoundException(DesignModel designModel) {
+ super(String.format("DesignModel \"%s\" not found!", designModel.getId()));
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/exception/DesignModelPatternInstanceNotFoundException.java b/src/main/java/com/patternpedia/api/exception/DesignModelPatternInstanceNotFoundException.java
new file mode 100644
index 0000000..ec76f48
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/exception/DesignModelPatternInstanceNotFoundException.java
@@ -0,0 +1,21 @@
+package com.patternpedia.api.exception;
+
+import com.patternpedia.api.entities.designmodel.DesignModelPatternInstance;
+import org.springframework.data.rest.webmvc.ResourceNotFoundException;
+
+import java.util.UUID;
+
+public class DesignModelPatternInstanceNotFoundException extends ResourceNotFoundException {
+
+ public DesignModelPatternInstanceNotFoundException(String message) {
+ super(message);
+ }
+
+ public DesignModelPatternInstanceNotFoundException(UUID designModelId, UUID patternInstanceId) {
+ super(String.format("PatternInstance \"%s\" not found in DesignModel \"%s\"!", patternInstanceId, designModelId));
+ }
+
+ public DesignModelPatternInstanceNotFoundException(DesignModelPatternInstance patternInstance) {
+ super(String.format("PatternInstance \"%s\" not found in DesignModel \"%s\"!", patternInstance.getPatternInstanceId(), patternInstance.getDesignModel().getId()));
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/exception/NullDesignModelException.java b/src/main/java/com/patternpedia/api/exception/NullDesignModelException.java
new file mode 100644
index 0000000..6ece16c
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/exception/NullDesignModelException.java
@@ -0,0 +1,12 @@
+package com.patternpedia.api.exception;
+
+public class NullDesignModelException extends RuntimeException {
+
+ public NullDesignModelException() {
+ super("DesignModel is null");
+ }
+
+ public NullDesignModelException(String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/com/patternpedia/api/repositories/ConcreteSolutionRepository.java b/src/main/java/com/patternpedia/api/repositories/ConcreteSolutionRepository.java
new file mode 100644
index 0000000..9fd3076
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/repositories/ConcreteSolutionRepository.java
@@ -0,0 +1,21 @@
+package com.patternpedia.api.repositories;
+
+import com.patternpedia.api.entities.designmodel.ConcreteSolution;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+
+public interface ConcreteSolutionRepository extends JpaRepository {
+
+ List findAllByPatternUri(String uri);
+
+ Optional findTopByPatternUriAndAggregatorType(String uri, String technology);
+
+ Optional findTopById(UUID uuid);
+
+ boolean existsByPatternUri(URI uri);
+}
diff --git a/src/main/java/com/patternpedia/api/repositories/DesignModelEdgeTypeRepository.java b/src/main/java/com/patternpedia/api/repositories/DesignModelEdgeTypeRepository.java
new file mode 100644
index 0000000..53bbcfd
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/repositories/DesignModelEdgeTypeRepository.java
@@ -0,0 +1,11 @@
+package com.patternpedia.api.repositories;
+
+import com.patternpedia.api.entities.designmodel.DesignModelEdgeType;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface DesignModelEdgeTypeRepository extends JpaRepository {
+
+ Optional findTopByName(String name);
+}
diff --git a/src/main/java/com/patternpedia/api/repositories/DesignModelPatternEdgeRepository.java b/src/main/java/com/patternpedia/api/repositories/DesignModelPatternEdgeRepository.java
new file mode 100644
index 0000000..74780ad
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/repositories/DesignModelPatternEdgeRepository.java
@@ -0,0 +1,22 @@
+package com.patternpedia.api.repositories;
+
+import com.patternpedia.api.entities.designmodel.DesignModelPatternEdge;
+import com.patternpedia.api.entities.designmodel.DesignModelPatternEdgeId;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+@RepositoryRestResource(exported = false)
+public interface DesignModelPatternEdgeRepository extends JpaRepository {
+
+ Optional> findAllByDesignModelId(UUID patternViewId);
+
+ Optional findTopByDesignModelIdAndEdgeId(UUID designModelId, DesignModelPatternEdgeId designModelPatternEdgeId);
+
+ void deleteAllByDesignModel_IdAndPatternInstance1_PatternInstanceIdOrPatternInstance2_PatternInstanceId(UUID designModelId, UUID patternInstanceId1, UUID patternInstanceId2);
+
+ void deleteAllByDesignModel_IdAndPatternInstance1_PatternInstanceIdAndPatternInstance2_PatternInstanceId(UUID designModelId, UUID patternInstanceId1, UUID patternInstanceId2);
+}
diff --git a/src/main/java/com/patternpedia/api/repositories/DesignModelPatternInstanceRepository.java b/src/main/java/com/patternpedia/api/repositories/DesignModelPatternInstanceRepository.java
new file mode 100644
index 0000000..da261d6
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/repositories/DesignModelPatternInstanceRepository.java
@@ -0,0 +1,19 @@
+package com.patternpedia.api.repositories;
+
+import com.patternpedia.api.entities.designmodel.DesignModelPatternInstance;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.rest.core.annotation.RepositoryRestResource;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+@RepositoryRestResource(exported = false)
+public interface DesignModelPatternInstanceRepository extends JpaRepository {
+
+ Optional> findAllByDesignModelId(UUID patternViewId);
+
+ Optional findTopByDesignModel_IdAndPatternInstanceId(UUID designModelId, UUID patternInstanceId);
+
+ void deleteAllByDesignModel_IdAndPatternInstanceId(UUID designModelId, UUID patternInstanceId);
+}
diff --git a/src/main/java/com/patternpedia/api/repositories/DesignModelRepository.java b/src/main/java/com/patternpedia/api/repositories/DesignModelRepository.java
new file mode 100644
index 0000000..8a9cd5c
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/repositories/DesignModelRepository.java
@@ -0,0 +1,16 @@
+package com.patternpedia.api.repositories;
+
+import com.patternpedia.api.entities.designmodel.DesignModel;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+import java.util.UUID;
+
+public interface DesignModelRepository extends JpaRepository {
+
+ Optional findByUri(String uri);
+
+ boolean existsByUri(String uri);
+
+ boolean existsById(UUID designModelId);
+}
diff --git a/src/main/java/com/patternpedia/api/rest/controller/DesignModelController.java b/src/main/java/com/patternpedia/api/rest/controller/DesignModelController.java
new file mode 100644
index 0000000..2c8b432
--- /dev/null
+++ b/src/main/java/com/patternpedia/api/rest/controller/DesignModelController.java
@@ -0,0 +1,226 @@
+package com.patternpedia.api.rest.controller;
+
+import com.patternpedia.api.entities.Pattern;
+import com.patternpedia.api.entities.designmodel.*;
+import com.patternpedia.api.rest.model.EdgeDTO;
+import com.patternpedia.api.rest.model.FileDTO;
+import com.patternpedia.api.rest.model.PatternInstanceDTO;
+import com.patternpedia.api.rest.model.PositionDTO;
+import com.patternpedia.api.service.ConcreteSolutionService;
+import com.patternpedia.api.service.DesignModelService;
+import lombok.extern.apachecommons.CommonsLog;
+import org.apache.commons.text.CaseUtils;
+import org.springframework.hateoas.CollectionModel;
+import org.springframework.hateoas.EntityModel;
+import org.springframework.hateoas.Link;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.net.URI;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static java.util.stream.Collectors.toList;
+import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
+
+
+@RestController
+@CommonsLog
+@CrossOrigin(allowedHeaders = "*", origins = "*")
+@RequestMapping(value = "/design-models", produces = "application/hal+json")
+public class DesignModelController {
+
+ private DesignModelService designModelService;
+ private ConcreteSolutionService concreteSolutionService;
+
+
+ public DesignModelController(DesignModelService designModelService, ConcreteSolutionService concreteSolutionService) {
+ this.designModelService = designModelService;
+ this.concreteSolutionService = concreteSolutionService;
+ }
+
+
+ private static List getDesignModelCollectionLinks() {
+ return Arrays.asList(
+ linkTo(methodOn(DesignModelController.class).getDesignModels()).withSelfRel()
+ .andAffordance(afford(methodOn(DesignModelController.class).createDesignModel(null))),
+ linkTo(methodOn(DesignModelController.class).getDesignModel(null)).withRel("designModel"),
+ linkTo(methodOn(DesignModelController.class).getDesignModelPatternEdgeTypes()).withRel("edgeTypes")
+ );
+ }
+
+
+ private static List getDesignModelLinks(UUID designModelId, String selfRel) {
+ Map linkMap = new HashMap<>();
+
+ linkMap.put("designModels", methodOn(DesignModelController.class).getDesignModels());
+ linkMap.put("designModel", methodOn(DesignModelController.class).getDesignModel(designModelId));
+ linkMap.put("patterns", methodOn(DesignModelController.class).getDesignModelPatternInstances(designModelId));
+ linkMap.put("edges", methodOn(DesignModelController.class).getDesignModelPatternEdges(designModelId));
+ linkMap.put("edgeTypes", methodOn(DesignModelController.class).getDesignModelPatternEdgeTypes());
+ linkMap.put("concreteSolutions", methodOn(DesignModelController.class).checkConcreteSolutions(designModelId));
+ linkMap.put("aggregate", methodOn(DesignModelController.class).aggregateConcreteSolutions(designModelId, null));
+
+ List linkList = new ArrayList<>();
+ if (linkMap.containsKey(selfRel)) {
+ linkList.add(linkTo(linkMap.get(selfRel)).withSelfRel());
+ } else {
+ log.error("_self link for " + selfRel + " not found in linkMap");
+ }
+ for (Map.Entry linkPair : linkMap.entrySet()) {
+ linkList.add(linkTo(linkPair.getValue()).withRel(linkPair.getKey()));
+ }
+
+ return linkList;
+ }
+
+
+ @GetMapping("")
+ public CollectionModel> getDesignModels() {
+
+ List> designModels = this.designModelService.getAllDesignModels()
+ .stream()
+ .map(designModel -> new EntityModel<>(designModel, getDesignModelLinks(designModel.getId(), "designModel")))
+ .collect(toList());
+
+ return new CollectionModel<>(designModels, getDesignModelCollectionLinks());
+ }
+
+
+ @PostMapping("")
+ @CrossOrigin(exposedHeaders = "Location")
+ @ResponseStatus(HttpStatus.CREATED)
+ public ResponseEntity> createDesignModel(@RequestBody DesignModel designModel) {
+ String nameAsCamelCase = CaseUtils.toCamelCase(designModel.getName(), false);
+ String uri = String.format("https://patternpedia.org/designModels/%s", nameAsCamelCase);
+ designModel.setUri(uri);
+
+ DesignModel createdDesignModel = this.designModelService.createDesignModel(designModel);
+
+ return ResponseEntity.created(linkTo(methodOn(DesignModelController.class)
+ .getDesignModel(createdDesignModel.getId())).toUri()).build();
+ }
+
+
+ @GetMapping("/edge-types")
+ public EntityModel