Skip to content

Commit 905d62e

Browse files
Merge pull request #6663 from deutschebank/db-contrib/waltz-6662-flat-hier-export
Db contrib/waltz 6662 flat hier export
2 parents da4b41c + 457b18e commit 905d62e

3 files changed

Lines changed: 232 additions & 24 deletions

File tree

waltz-jobs/src/main/java/org/finos/waltz/jobs/harness/EntityHierarchyHarness.java

Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,128 @@
1919
package org.finos.waltz.jobs.harness;
2020

2121
import org.finos.waltz.model.EntityKind;
22-
import org.finos.waltz.service.DIConfiguration;
23-
import org.finos.waltz.service.entity_hierarchy.EntityHierarchyService;
22+
import org.finos.waltz.schema.tables.EntityHierarchy;
23+
import org.finos.waltz.schema.tables.Measurable;
24+
import org.finos.waltz.schema.tables.MeasurableCategory;
25+
import org.finos.waltz.service.DIBaseConfiguration;
26+
import org.jooq.DSLContext;
27+
import org.jooq.Field;
28+
import org.jooq.Record;
29+
import org.jooq.SelectOnConditionStep;
30+
import org.jooq.impl.DSL;
31+
import org.jooq.lambda.tuple.Tuple3;
2432
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2533

34+
import java.util.ArrayList;
35+
import java.util.List;
36+
import java.util.stream.Collectors;
37+
import java.util.stream.Stream;
38+
39+
import static org.finos.waltz.schema.Tables.ENTITY_HIERARCHY;
40+
import static org.finos.waltz.schema.Tables.MEASURABLE;
41+
import static org.finos.waltz.schema.Tables.MEASURABLE_CATEGORY;
42+
import static org.jooq.lambda.tuple.Tuple.tuple;
43+
2644
/**
2745
* Created by dwatkins on 30/07/2016.
2846
*/
2947
public class EntityHierarchyHarness {
3048

49+
private static final long MEASURABLE_CATEGORY_ID = 9L;
50+
51+
/**
52+
*
53+
54+
select max(level) from entity_hierarchy where id in (select id from measurable where measurable_category_id = 33);
55+
56+
57+
58+
59+
select l1m.name, eh1.descendant_level, l2m.name, eh2.descendant_level, l3m.name, eh3.descendant_level
60+
from measurable l1m
61+
inner join entity_hierarchy eh1 on eh1.id = l1m.id and eh1.kind = 'MEASURABLE' and eh1.descendant_level = 1
62+
63+
64+
65+
inner join entity_hierarchy eh2 on eh2.ancestor_id = eh1.id and eh2.kind = 'MEASURABLE' and eh2.descendant_level = 2
66+
inner join measurable l2m on l2m.id = eh2.id and l1m.measurable_category_id = 33
67+
68+
69+
inner join entity_hierarchy eh3 on eh3.ancestor_id = eh2.id and eh3.kind = 'MEASURABLE' and eh3.descendant_level = 3
70+
inner join measurable l3m on l3m.id = eh3.id and l1m.measurable_category_id = 33
71+
72+
* @param args
73+
*/
3174
public static void main(String[] args) {
32-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(DIConfiguration.class);
75+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(DIBaseConfiguration.class);
76+
77+
EntityHierarchy eh = ENTITY_HIERARCHY.as("eh");
78+
Measurable m = MEASURABLE.as("m");
79+
MeasurableCategory mc = MEASURABLE_CATEGORY.as("mc");
80+
81+
DSLContext dsl = ctx.getBean(DSLContext.class);
82+
83+
Field<Integer> maxLevelField = DSL.max(eh.LEVEL).as("maxLevel");
84+
Integer maxLevel = dsl
85+
.select(maxLevelField)
86+
.from(eh)
87+
.where(eh.KIND.eq(EntityKind.MEASURABLE.name()))
88+
.and(eh.ID.in(DSL
89+
.select(m.ID)
90+
.from(m)
91+
.where(m.MEASURABLE_CATEGORY_ID.eq(MEASURABLE_CATEGORY_ID))))
92+
.fetchOne(maxLevelField);
93+
94+
ArrayList<Tuple3<Integer, EntityHierarchy, Measurable>> ehAndMeasurableTablesForLevel = new ArrayList<>(maxLevel);
95+
96+
for (int i = 0; i < maxLevel; i++) {
97+
ehAndMeasurableTablesForLevel.add(i, tuple(i + 1, ENTITY_HIERARCHY.as("eh" + i), MEASURABLE.as("l" + i)));
98+
}
99+
100+
List<Field<?>> fields = ehAndMeasurableTablesForLevel
101+
.stream()
102+
.flatMap(t -> Stream.of(
103+
_m(t).NAME.as("Level " + t.v1 + " Name"),
104+
_m(t).EXTERNAL_ID.as("Level " + t.v1 + " External Id"),
105+
_m(t).ID.as("Level " + t.v1 + " Waltz Id")))
106+
.collect(Collectors.toList());
107+
108+
Tuple3<Integer, EntityHierarchy, Measurable> l1 = ehAndMeasurableTablesForLevel.get(0);
109+
110+
SelectOnConditionStep<Record> baseQry = dsl
111+
.select(fields)
112+
.from(_m(l1))
113+
.innerJoin(_eh(l1))
114+
.on(_eh(l1).ID.eq(_m(l1).ID)
115+
.and(_eh(l1).KIND.eq(EntityKind.MEASURABLE.name()))
116+
.and(_eh(l1).DESCENDANT_LEVEL.eq(_lvl(l1)))
117+
.and(_m(l1).MEASURABLE_CATEGORY_ID.eq(MEASURABLE_CATEGORY_ID)));
118+
119+
for (int i = 1; i < maxLevel; i++) {
120+
Tuple3<Integer, EntityHierarchy, Measurable> curr = ehAndMeasurableTablesForLevel.get(i);
121+
Tuple3<Integer, EntityHierarchy, Measurable> prev = ehAndMeasurableTablesForLevel.get(i - 1);
122+
baseQry = baseQry
123+
.leftJoin(_eh(curr))
124+
.on(_eh(curr).ANCESTOR_ID.eq(_eh(prev).ID)
125+
.and(_eh(curr).KIND.eq(EntityKind.MEASURABLE.name())
126+
.and(_eh(curr).DESCENDANT_LEVEL.eq(_lvl(curr)))))
127+
.leftJoin(_m(curr))
128+
.on(_m(curr).ID.eq(_eh(curr).ID));
129+
}
130+
131+
System.out.println(baseQry);
132+
133+
}
134+
135+
private static Measurable _m(Tuple3<Integer, EntityHierarchy, Measurable> l1) {
136+
return l1.v3;
137+
}
138+
139+
private static EntityHierarchy _eh(Tuple3<Integer, EntityHierarchy, Measurable> l1) {
140+
return l1.v2;
141+
}
33142

34-
EntityHierarchyService svc = ctx.getBean(EntityHierarchyService.class);
35-
svc.buildFor(EntityKind.ORG_UNIT);
143+
private static Integer _lvl(Tuple3<Integer, EntityHierarchy, Measurable> l1) {
144+
return l1.v1;
36145
}
37146
}

waltz-ng/client/measurable-category/pages/list/measurable-category-list.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,20 @@
6969

7070
<hr>
7171

72-
<waltz-data-extract-link name="Export"
72+
<waltz-data-extract-link name="Export as Parent Child"
7373
uib-popover="Exports this taxonomy and the key people associated with it"
7474
popover-trigger="mouseenter"
7575
extract="measurable-category/{{$ctrl.category.id}}"
7676
filename="{{$ctrl.category.name}}.csv">
7777
</waltz-data-extract-link>
7878

79+
<waltz-data-extract-link name="Export as Flattened Hierarchy"
80+
uib-popover="Exports this taxonomy with L1, L2, L3 etc"
81+
popover-trigger="mouseenter"
82+
extract="measurable-category/flat/{{$ctrl.category.id}}"
83+
filename="{{$ctrl.category.name}}.csv">
84+
</waltz-data-extract-link>
85+
7986
<span ng-if="$ctrl.visibility.editButton">
8087
&nbsp;
8188
<a class="btn btn-primary btn-xs clickable"

waltz-web/src/main/java/org/finos/waltz/web/endpoints/extracts/MeasurableCategoryExtractor.java

Lines changed: 110 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,39 @@
2121

2222
import org.finos.waltz.model.EntityKind;
2323
import org.finos.waltz.model.EntityLifecycleStatus;
24+
import org.finos.waltz.schema.Tables;
25+
import org.finos.waltz.schema.tables.EntityHierarchy;
26+
import org.finos.waltz.schema.tables.Measurable;
2427
import org.finos.waltz.web.WebUtilities;
2528
import org.jooq.DSLContext;
29+
import org.jooq.Field;
2630
import org.jooq.Record;
2731
import org.jooq.SelectConditionStep;
28-
import org.slf4j.Logger;
29-
import org.slf4j.LoggerFactory;
32+
import org.jooq.SelectOnConditionStep;
33+
import org.jooq.impl.DSL;
34+
import org.jooq.lambda.tuple.Tuple3;
3035
import org.springframework.beans.factory.annotation.Autowired;
3136
import org.springframework.stereotype.Service;
3237

38+
import java.util.ArrayList;
39+
import java.util.List;
40+
import java.util.stream.Collectors;
41+
import java.util.stream.Stream;
42+
43+
import static org.finos.waltz.common.Checks.checkNotNull;
3344
import static org.finos.waltz.schema.Tables.ENTITY_HIERARCHY;
3445
import static org.finos.waltz.schema.Tables.INVOLVEMENT;
3546
import static org.finos.waltz.schema.tables.InvolvementKind.INVOLVEMENT_KIND;
3647
import static org.finos.waltz.schema.tables.Measurable.MEASURABLE;
3748
import static org.finos.waltz.schema.tables.MeasurableCategory.MEASURABLE_CATEGORY;
3849
import static org.finos.waltz.schema.tables.Person.PERSON;
39-
import static org.finos.waltz.common.Checks.checkNotNull;
50+
import static org.jooq.lambda.tuple.Tuple.tuple;
4051
import static spark.Spark.get;
4152

4253

4354
@Service
4455
public class MeasurableCategoryExtractor extends DirectQueryBasedDataExtractor {
4556

46-
private static final Logger LOG = LoggerFactory.getLogger(MeasurableCategoryExtractor.class);
47-
4857

4958
@Autowired
5059
public MeasurableCategoryExtractor(DSLContext dsl) {
@@ -54,21 +63,77 @@ public MeasurableCategoryExtractor(DSLContext dsl) {
5463

5564
@Override
5665
public void register() {
66+
String flatPath = WebUtilities.mkPath("data-extract", "measurable-category", "flat", ":id");
67+
get(flatPath, (request, response) -> {
68+
long categoryId = WebUtilities.getId(request);
69+
70+
EntityHierarchy eh = ENTITY_HIERARCHY.as("eh");
71+
Measurable m = Tables.MEASURABLE.as("m");
72+
Field<Integer> maxLevelField = DSL.max(eh.LEVEL).as("maxLevel");
73+
Integer maxLevel = dsl
74+
.select(maxLevelField)
75+
.from(eh)
76+
.where(eh.KIND.eq(EntityKind.MEASURABLE.name()))
77+
.and(eh.ID.in(DSL
78+
.select(m.ID)
79+
.from(m)
80+
.where(m.MEASURABLE_CATEGORY_ID.eq(categoryId))
81+
.and(m.ENTITY_LIFECYCLE_STATUS.ne(EntityLifecycleStatus.REMOVED.name()))))
82+
.fetchOne(maxLevelField);
83+
84+
ArrayList<Tuple3<Integer, EntityHierarchy, Measurable>> ehAndMeasurableTablesForLevel = new ArrayList<>(maxLevel);
85+
86+
for (int i = 0; i < maxLevel; i++) {
87+
ehAndMeasurableTablesForLevel.add(i, tuple(i + 1, ENTITY_HIERARCHY.as("eh" + i), Tables.MEASURABLE.as("l" + i)));
88+
}
89+
90+
List<Field<?>> fields = ehAndMeasurableTablesForLevel
91+
.stream()
92+
.flatMap(t -> Stream.of(
93+
_m(t).NAME.as("Level " + t.v1 + " Name"),
94+
_m(t).EXTERNAL_ID.as("Level " + t.v1 + " External Id"),
95+
_m(t).ID.as("Level " + t.v1 + " Waltz Id")))
96+
.collect(Collectors.toList());
97+
98+
Tuple3<Integer, EntityHierarchy, Measurable> l1 = ehAndMeasurableTablesForLevel.get(0);
99+
100+
SelectOnConditionStep<Record> qry = dsl
101+
.select(fields)
102+
.from(_m(l1))
103+
.innerJoin(_eh(l1))
104+
.on(_eh(l1).ID.eq(_m(l1).ID)
105+
.and(_eh(l1).KIND.eq(EntityKind.MEASURABLE.name()))
106+
.and(_eh(l1).DESCENDANT_LEVEL.eq(_lvl(l1)))
107+
.and(_m(l1).MEASURABLE_CATEGORY_ID.eq(categoryId))
108+
.and(_m(l1).ENTITY_LIFECYCLE_STATUS.ne(EntityLifecycleStatus.REMOVED.name())));
109+
110+
for (int i = 1; i < maxLevel; i++) {
111+
Tuple3<Integer, EntityHierarchy, Measurable> curr = ehAndMeasurableTablesForLevel.get(i);
112+
Tuple3<Integer, EntityHierarchy, Measurable> prev = ehAndMeasurableTablesForLevel.get(i - 1);
113+
qry = qry
114+
.leftJoin(_eh(curr))
115+
.on(_eh(curr).ANCESTOR_ID.eq(_eh(prev).ID)
116+
.and(_eh(curr).KIND.eq(EntityKind.MEASURABLE.name())
117+
.and(_eh(curr).DESCENDANT_LEVEL.eq(_lvl(curr)))))
118+
.leftJoin(_m(curr))
119+
.on(_m(curr).ID.eq(_eh(curr).ID)
120+
.and(_m(curr).ENTITY_LIFECYCLE_STATUS.ne(EntityLifecycleStatus.REMOVED.name())));
121+
}
122+
123+
return writeExtract(
124+
mkSuggestedFilename(categoryId),
125+
qry,
126+
request,
127+
response);
128+
});
57129

58-
String path = WebUtilities.mkPath("data-extract", "measurable-category", ":id");
59-
get(path, (request, response) -> {
130+
131+
132+
133+
String parentChildPath = WebUtilities.mkPath("data-extract", "measurable-category", ":id");
134+
get(parentChildPath, (request, response) -> {
60135
long categoryId = WebUtilities.getId(request);
61-
String categoryName = dsl
62-
.select(MEASURABLE_CATEGORY.NAME)
63-
.from(MEASURABLE_CATEGORY)
64-
.where(MEASURABLE_CATEGORY.ID.eq(categoryId))
65-
.fetchOne(MEASURABLE_CATEGORY.NAME);
66-
67-
checkNotNull(categoryName, "category cannot be null");
68-
String suggestedFilename = categoryName
69-
.replace(".", "-")
70-
.replace(" ", "-")
71-
.replace(",", "-");
136+
String suggestedFilename = mkSuggestedFilename(categoryId);
72137

73138
SelectConditionStep<Record> data = dsl
74139
.select(
@@ -103,4 +168,31 @@ public void register() {
103168
});
104169
}
105170

171+
private String mkSuggestedFilename(long categoryId) {
172+
String categoryName = dsl
173+
.select(MEASURABLE_CATEGORY.NAME)
174+
.from(MEASURABLE_CATEGORY)
175+
.where(MEASURABLE_CATEGORY.ID.eq(categoryId))
176+
.fetchOne(MEASURABLE_CATEGORY.NAME);
177+
178+
checkNotNull(categoryName, "category cannot be null");
179+
String suggestedFilename = categoryName
180+
.replace(".", "-")
181+
.replace(" ", "-")
182+
.replace(",", "-");
183+
return suggestedFilename;
184+
}
185+
186+
187+
private static Measurable _m(Tuple3<Integer, EntityHierarchy, Measurable> l1) {
188+
return l1.v3;
189+
}
190+
191+
private static EntityHierarchy _eh(Tuple3<Integer, EntityHierarchy, Measurable> l1) {
192+
return l1.v2;
193+
}
194+
195+
private static Integer _lvl(Tuple3<Integer, EntityHierarchy, Measurable> l1) {
196+
return l1.v1;
197+
}
106198
}

0 commit comments

Comments
 (0)