Skip to content

Commit 09286ad

Browse files
authored
Merge pull request #14 from nenadjakic/feature/add-code-to-entities
Added 'code' field to entities, update DTOs and converters, adjust sq…
2 parents 333770f + 80fa91a commit 09286ad

25 files changed

+137
-56
lines changed

.scripts/002-test-data.sql

+11-10
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,17 @@ VALUES ((SELECT id FROM "security"."user" WHERE username = 'admin@eav.eav'), (SE
1313
INSERT INTO "security"."user_role" (user_id, role_id)
1414
VALUES ((SELECT id FROM "security"."user" WHERE username = 'reader@eav.eav'), (SELECT id from "security"."role" WHERE "name" = 'READER'));
1515

16-
INSERT INTO "public"."entity_type" (id, "name", "description") VALUES (nextval('public.entity_type_id_seq'), 'car', NULL);
17-
INSERT INTO "public"."entity_type" (id, "name", "description") VALUES (nextval('public.entity_type_id_seq'), 'book', NULL);
16+
INSERT INTO "public"."entity_type" (id, "code", "name", "description") VALUES (nextval('public.entity_type_id_seq'), 'C', 'car', NULL);
17+
INSERT INTO "public"."entity_type" (id, "code", "name", "description") VALUES (nextval('public.entity_type_id_seq'), 'B', 'book', NULL);
1818

19-
INSERT INTO "public"."attribute" (id, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), NULL, 'make', (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'));
20-
INSERT INTO "public"."attribute" (id, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), NULL, 'model', (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'));
21-
INSERT INTO "public"."attribute" (id, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), NULL, 'color', (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'));
19+
INSERT INTO "public"."attribute" (id, code, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), 'MAK', NULL, 'make', (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'));
20+
INSERT INTO "public"."attribute" (id, code, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), 'MOD', NULL, 'model', (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'));
21+
INSERT INTO "public"."attribute" (id, code, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), 'COL', NULL, 'color', (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'));
2222

23-
INSERT INTO "public"."attribute" (id, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), NULL, 'isbn', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
24-
INSERT INTO "public"."attribute" (id, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), NULL, 'author', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
25-
INSERT INTO "public"."attribute" (id, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), NULL, 'title', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
26-
INSERT INTO "public"."attribute" (id, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), NULL, 'publish_year', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
23+
INSERT INTO "public"."attribute" (id, code, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), 'ISBN', NULL, 'isbn', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
24+
INSERT INTO "public"."attribute" (id, code, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), 'AUT', NULL, 'author', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
25+
INSERT INTO "public"."attribute" (id, code, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), 'TIT', NULL, 'title', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
26+
INSERT INTO "public"."attribute" (id, code, description, "name", entity_type_id) VALUES(nextval('public.attribute_id_seq'), 'PYE', NULL, 'publish_year', (SELECT id FROM "public"."entity_type" WHERE "name" = 'book'));
2727

2828
INSERT INTO public.metadata (id, data_type, max_length, max_value, min_length, min_value, "repeatable", required, sub_attribute_ids)
2929
VALUES((SELECT id FROM "public"."attribute" WHERE "name" = 'make' AND entity_type_id = (SELECT id FROM "public"."entity_type" WHERE "name" = 'car')), 'STRING', NULL, NULL, NULL, NULL, false, true, '[]'::jsonb);
@@ -60,7 +60,8 @@ VALUES('["READ", "CREATE", "UPDATE", "DELETE"]'::jsonb, (SELECT id FROM "public"
6060
INSERT INTO "security"."attribute_permission" (actions, attribute_id, role_id)
6161
VALUES('["READ", "CREATE", "DELETE"]'::jsonb, (SELECT id FROM "public"."attribute" WHERE "name" = 'color' AND entity_type_id = (SELECT id FROM "public"."entity_type" WHERE "name" = 'car')), (SELECT id FROM "security"."role" WHERE "name" = 'ADMINISTRATOR'));
6262

63-
INSERT INTO "public"."entity" (id, entity_type_id) VALUES (nextval('public.entity_id_seq'), (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'));
63+
INSERT INTO "public"."entity" (id, entity_type_id, code, description)
64+
VALUES (nextval('public.entity_id_seq'), (SELECT id FROM "public"."entity_type" WHERE "name" = 'car'), 'C1', NULL);
6465

6566
INSERT INTO "public"."attribute_value" (value, "position", attribute_id, entity_id)
6667
VALUES('Ford', NULL, (SELECT id FROM "public"."attribute" WHERE "name" = 'make' AND entity_type_id = (SELECT id FROM "public"."entity_type" WHERE "name" = 'car')), (SELECT id from "public"."entity" LIMIT 1));

src/main/kotlin/com/github/nenadjakic/eav/controller/EavReadController.kt

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.github.nenadjakic.eav.controller
33
import org.springframework.data.domain.Page
44
import org.springframework.http.MediaType
55
import org.springframework.http.ResponseEntity
6+
import org.springframework.security.access.prepost.PostAuthorize
67
import org.springframework.security.access.prepost.PreAuthorize
78
import org.springframework.web.bind.annotation.GetMapping
89
import org.springframework.web.bind.annotation.PathVariable
@@ -17,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestParam
1718
interface EavReadController<RE> {
1819

1920
@PreAuthorize("hasRole('READER')")
21+
//@PostAuthorize("@attributeSecurityService.canRead(1L)")
2022
@GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
2123
fun findAll(): ResponseEntity<List<RE>>
2224

src/main/kotlin/com/github/nenadjakic/eav/dto/AttributeAddRequest.kt

+5
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ package com.github.nenadjakic.eav.dto
22

33
import jakarta.validation.Valid
44
import jakarta.validation.constraints.NotNull
5+
import jakarta.xml.bind.annotation.XmlElement
56

67
class AttributeAddRequest {
78
@NotNull
89
var entityTypeId: Long? = null
910

11+
@NotNull
12+
lateinit var code: String
13+
1014
@NotNull
1115
lateinit var name: String
16+
1217
var description: String? = null
1318

1419
@NotNull

src/main/kotlin/com/github/nenadjakic/eav/dto/AttributeResponse.kt

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.nenadjakic.eav.dto
22

33
data class AttributeResponse(
44
val id: Long,
5+
val code: String,
56
val name: String,
67
val description: String?,
78
val metadata: MetadataResponse

src/main/kotlin/com/github/nenadjakic/eav/dto/AttributeUpdateRequest.kt

+4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ class AttributeUpdateRequest {
77
@NotNull
88
var id: Long? = null
99

10+
@NotNull
11+
lateinit var code: String
12+
1013
@NotNull
1114
lateinit var name: String
15+
1216
var description: String? = null
1317

1418
@NotNull

src/main/kotlin/com/github/nenadjakic/eav/dto/AttributeValueResponse.kt

+4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@ package com.github.nenadjakic.eav.dto
22

33
data class EntitySimpleResponse(
44
val entityId: Long,
5+
val code: String,
6+
val description: String?
57
)
68

79
data class AttributeSimpleResponse(
810
val attributeId: Long,
11+
val code: String,
912
val attributeName: String,
13+
val description: String?
1014
)
1115

1216
data class AttributeValueSimpleResponse(

src/main/kotlin/com/github/nenadjakic/eav/dto/EntityAddRequest.kt

+5
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ import jakarta.validation.constraints.NotNull
55
class EntityAddRequest {
66
@NotNull
77
var entityTypeId: Long? = null
8+
9+
@NotNull
10+
lateinit var code: String
11+
12+
var description: String? = null
813
}

src/main/kotlin/com/github/nenadjakic/eav/dto/EntityResponse.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ package com.github.nenadjakic.eav.dto
33
data class EntityResponse(
44
val id: Long,
55
val entityType: EntityTypeSimpleResponse,
6+
val code: String,
7+
val description: String?,
68
val attributeValues: List<AttributeValueSimpleResponse>
7-
)
9+
)

src/main/kotlin/com/github/nenadjakic/eav/dto/EntityTypeAddRequest.kt

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import jakarta.xml.bind.annotation.XmlRootElement
99
@XmlAccessorType(XmlAccessType.FIELD)
1010
@XmlRootElement(name="EntityTypeAddRequest")
1111
class EntityTypeAddRequest {
12+
@NotNull
13+
@XmlElement(name = "Code")
14+
lateinit var code: String
15+
1216
@NotNull
1317
@XmlElement(name = "Name")
1418
lateinit var name: String

src/main/kotlin/com/github/nenadjakic/eav/dto/EntityTypeResponse.kt

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.nenadjakic.eav.dto
22

33
data class EntityTypeResponse(
44
val id: Long,
5+
val code: String?,
56
val name: String,
67
val description: String?,
78
val attributes: List<AttributeResponse>

src/main/kotlin/com/github/nenadjakic/eav/dto/EntityTypeSimpleResponse.kt

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.nenadjakic.eav.dto
22

33
data class EntityTypeSimpleResponse(
44
val id: Long,
5+
val code: String,
56
val name: String,
67
val description: String?,
78
)

src/main/kotlin/com/github/nenadjakic/eav/dto/EntityTypeUpdateRequest.kt

+4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ class EntityTypeUpdateRequest {
66
@NotNull
77
var id: Long? = null
88

9+
@NotNull
10+
lateinit var code: String
11+
912
@NotNull
1013
lateinit var name: String
14+
1115
var description: String? = null
1216
}

src/main/kotlin/com/github/nenadjakic/eav/dto/EntityUpdateRequest.kt

+4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ class EntityUpdateRequest {
77
@NotNull
88
var id: Long? = null
99

10+
@NotNull
11+
lateinit var code: String
12+
1013
@NotNull
1114
lateinit var name: String
15+
1216
var description: String? = null
1317
}

src/main/kotlin/com/github/nenadjakic/eav/dto/converter/AttributeAddRequestToAttributeConverter.kt

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class AttributeAddRequestToAttributeConverter : AbstractConverter<AttributeAddRe
1111
val destination = Attribute()
1212
destination.entityType = EntityType()
1313
destination.entityType.id = source!!.entityTypeId!!
14+
destination.code = source.code
1415
destination.name = source.name
1516
destination.description = source.description
1617

src/main/kotlin/com/github/nenadjakic/eav/dto/converter/AttributeToAttributeResponseConverter.kt

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class AttributeToAttributeResponseConverter : AbstractConverter<Attribute, Attri
2020
)
2121
return AttributeResponse(
2222
source.id!!,
23+
source.code,
2324
source.name,
2425
source.description,
2526
metadataResponse)

src/main/kotlin/com/github/nenadjakic/eav/dto/converter/AttributeUpdateRequestToAttributeConverter.kt

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class AttributeUpdateRequestToAttributeConverter : AbstractConverter<AttributeUp
99
override fun convert(source: AttributeUpdateRequest?): Attribute {
1010
val destination: Attribute = Attribute()
1111
destination.id = source!!.id
12+
destination.code = source.code
1213
destination.name = source.name
1314
destination.description = source.description
1415

src/main/kotlin/com/github/nenadjakic/eav/dto/converter/AttributeValueToAttributeValueResponseConverter.kt

+8-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,16 @@ class AttributeValueToAttributeValueResponseConverter : AbstractConverter<Attrib
1010
override fun convert(source: AttributeValue?): AttributeValueResponse {
1111

1212
return AttributeValueResponse(
13-
EntitySimpleResponse(source!!.entity.id!!),
13+
EntitySimpleResponse(
14+
source!!.entity.id!!,
15+
source.entity.code,
16+
source.entity.description
17+
),
1418
AttributeSimpleResponse(
1519
source.attribute.id!!,
16-
source.attribute.name
20+
source.attribute.code,
21+
source.attribute.name,
22+
source.attribute.description
1723
),
1824
source.value!!.toString())
1925
}

src/main/kotlin/com/github/nenadjakic/eav/dto/converter/EntityToEntityResponseConverter.kt

+12-3
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,25 @@ class EntityToEntityResponseConverter : AbstractConverter<Entity, EntityResponse
1111
override fun convert(source: Entity?): EntityResponse {
1212
val attibuteValues: MutableList<AttributeValueSimpleResponse> = mutableListOf()
1313
source!!.attributeValues.forEach { attibuteValues.add(AttributeValueSimpleResponse(
14-
AttributeSimpleResponse(it.attribute.id!!, it.attribute.name),
15-
it.value
16-
)) }
14+
AttributeSimpleResponse(
15+
it.attribute.id!!,
16+
it.attribute.code,
17+
it.attribute.name,
18+
it.attribute.description
19+
),
20+
it.value
21+
))
22+
}
1723
return EntityResponse(
1824
source.id!!,
1925
EntityTypeSimpleResponse(
2026
source.entityType.id!!,
27+
source.entityType.code,
2128
source.entityType.name,
2229
source.entityType.description
2330
),
31+
source.code,
32+
source.description,
2433
attibuteValues
2534
)
2635
}

src/main/kotlin/com/github/nenadjakic/eav/dto/converter/EntityTypeToEntityTypeResponseConverter.kt

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class EntityTypeToEntityTypeResponseConverter : AbstractConverter<EntityType, En
1111
val attributeResponses: MutableList<AttributeResponse> = mutableListOf()
1212
source!!.attributes.forEach { attributeResponses.add(AttributeResponse(
1313
it.id!!,
14+
it.code,
1415
it.name,
1516
it.description,
1617
MetadataResponse(
@@ -26,6 +27,7 @@ class EntityTypeToEntityTypeResponseConverter : AbstractConverter<EntityType, En
2627
)) }
2728
return EntityTypeResponse(
2829
source.id!!,
30+
source.code,
2931
source.name,
3032
source.description,
3133
attributeResponses

src/main/kotlin/com/github/nenadjakic/eav/entity/Attribute.kt

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import jakarta.persistence.Entity
1212
schema = "public",
1313
name = "attribute",
1414
uniqueConstraints = [
15+
UniqueConstraint(name = "uq_attribute_code", columnNames = [ "code" ]),
1516
UniqueConstraint(name = "uq_attribute_entity_type_id_name", columnNames = ["entity_type_id", "name"])
1617
])
1718
class Attribute : AbstractEntityId<Long>() {
@@ -25,6 +26,9 @@ class Attribute : AbstractEntityId<Long>() {
2526
@JoinColumn(name = "entity_type_id", nullable = false, updatable = false)
2627
lateinit var entityType: EntityType
2728

29+
@Column(name = "code", nullable = false, unique = true, length = 25)
30+
lateinit var code: String
31+
2832
@Column(name = "name", nullable = false, unique = true, length = 100)
2933
lateinit var name: String
3034

src/main/kotlin/com/github/nenadjakic/eav/entity/Entity.kt

+12-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import jakarta.persistence.Entity
88
* This class is mapped to the "entity" table in the "public" schema.
99
*/
1010
@Entity
11-
@Table(schema = "public", name = "entity")
11+
@Table(
12+
schema = "public",
13+
name = "entity",
14+
uniqueConstraints = [
15+
UniqueConstraint(name = "uq_entity_entity_type_id_code", columnNames = [ "entity_type_id", "code"])
16+
])
1217
class Entity : AbstractEntityId<Long>() {
1318
@Id
1419
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "entity_id_seq")
@@ -21,6 +26,12 @@ class Entity : AbstractEntityId<Long>() {
2126
@JoinColumn(name = "entity_type_id", nullable = false, updatable = false)
2227
lateinit var entityType: EntityType
2328

29+
@Column(name = "code", nullable = false)
30+
lateinit var code: String
31+
32+
@Column(name = "description", length = 1000)
33+
var description: String? = null
34+
2435
@OneToMany(mappedBy = "entity")
2536
private val _attributeValues: MutableList<AttributeValue> = mutableListOf()
2637

src/main/kotlin/com/github/nenadjakic/eav/entity/EntityType.kt

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import jakarta.persistence.Entity
88
schema = "public",
99
name = "entity_type",
1010
uniqueConstraints = [
11+
UniqueConstraint(name = "uq_entity_type_code", columnNames = [ "code" ]),
1112
UniqueConstraint(name = "uq_entity_type_name", columnNames = [ "name" ])
1213
])
1314
class EntityType : AbstractEntityId<Long>() {
@@ -18,6 +19,9 @@ class EntityType : AbstractEntityId<Long>() {
1819
@Column(name = "id")
1920
override var id: Long? = null
2021

22+
@Column(name = "code", nullable = false, unique = true, length = 25)
23+
lateinit var code: String
24+
2125
@Column(name = "name", nullable = false, unique = true, length = 100)
2226
lateinit var name: String
2327

src/test/kotlin/com/github/nenadjakic/eav/controller/EntityControllerTest.kt

+2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class EntityControllerTest {
109109
fun create() {
110110
val body = EntityAddRequest()
111111
body.entityTypeId = 10001
112+
body.code = "ET1"
112113

113114
val postResponse = restTemplate.exchange(
114115
"/entity",
@@ -131,6 +132,7 @@ class EntityControllerTest {
131132
fun update() {
132133
val body = EntityUpdateRequest()
133134
body.id = 10001
135+
body.code = "ET1"
134136
body.name = "new_name_updated"
135137
body.description = "new_description"
136138
val putResponse = restTemplate.exchange(

src/test/kotlin/com/github/nenadjakic/eav/controller/EntityTypeControllerTest.kt

+2
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class EntityTypeControllerTest {
116116
@DisplayName("Create new entity type.")
117117
fun create() {
118118
val body = EntityTypeAddRequest()
119+
body.code = "ET1"
119120
body.name = "new_name_added"
120121
body.description = "new_description"
121122
val postResponse = restTemplate.exchange<Void>(
@@ -140,6 +141,7 @@ class EntityTypeControllerTest {
140141
fun update() {
141142
val body = EntityTypeUpdateRequest()
142143
body.id = 10001
144+
body.code = "001"
143145
body.name = "new_name_updated"
144146
body.description = "new_description"
145147
val putResponse = restTemplate.exchange(

0 commit comments

Comments
 (0)