Skip to content

Commit 11977d5

Browse files
authored
Merge pull request #594 from peter-plochan/execute-vis
support for execution of visualization object
2 parents 04edbb9 + ff8ced5 commit 11977d5

13 files changed

Lines changed: 375 additions & 47 deletions

File tree

src/main/java/com/gooddata/GoodData.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,4 @@ public ExecuteAfmService getExecuteAfmService() {
518518
public LcmService getLcmService() {
519519
return lcmService;
520520
}
521-
522-
523521
}

src/main/java/com/gooddata/executeafm/ExecuteAfmService.java

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,22 @@
2222
import static com.gooddata.util.Validate.notNull;
2323

2424
/**
25-
* Service for executeAfm resource
25+
* Service for executing reports with new visualization structures like AFM or Visualization Object.
26+
* This includes GD API endpoints:
27+
* <ul>
28+
* <li>{@code /executeAfm}</li>
29+
* <li>{@code /executeVisualization}</li>
30+
* </ul>
2631
*/
2732
public class ExecuteAfmService extends AbstractService {
2833

29-
private static final String EXECUTION_URI = "/gdc/app/projects/{projectId}/executeAfm";
34+
private static final String AFM_EXECUTION_URI = "/gdc/app/projects/{projectId}/executeAfm";
35+
private static final String VISUALIZATION_EXECUTION_URI = "/gdc/app/projects/{projectId}/executeVisualization";
3036
private static final String RESULT_OFFSET = "offset";
3137
private static final String RESULT_LIMIT = "limit";
3238

3339
/**
34-
* Service for executeAfm resource
40+
* Constructor.
3541
*
3642
* @param restTemplate rest template
3743
* @param settings settings
@@ -41,17 +47,25 @@ public ExecuteAfmService(final RestTemplate restTemplate, final GoodDataSettings
4147
}
4248

4349
/**
44-
* Executes the given execution returning the execution response
50+
* @deprecated use {@link ExecuteAfmService#executeAfm(Project, Execution)}
51+
*/
52+
@Deprecated
53+
public ExecutionResponse execute(final Project project, final Execution execution) {
54+
return executeAfm(project, execution);
55+
}
56+
57+
/**
58+
* Executes the given AFM execution returning the execution response
4559
* @param project project of the execution
4660
* @param execution execution
4761
* @return response of the submitted execution
4862
*/
49-
public ExecutionResponse execute(final Project project, final Execution execution) {
63+
public ExecutionResponse executeAfm(final Project project, final Execution execution) {
5064
final String projectId = notNull(notNull(project, "project").getId(), "projectId");
5165
final ExecutionResponse response;
5266
try {
5367
response = restTemplate.postForObject(
54-
EXECUTION_URI,
68+
AFM_EXECUTION_URI,
5569
notNull(execution, "execution"),
5670
ExecutionResponse.class,
5771
projectId);
@@ -66,6 +80,32 @@ public ExecutionResponse execute(final Project project, final Execution executio
6680
return response;
6781
}
6882

83+
/**
84+
* Executes the given execution returning the execution response
85+
* @param project project of the execution
86+
* @param execution execution
87+
* @return response of the submitted execution
88+
*/
89+
public ExecutionResponse executeVisualization(final Project project, final VisualizationExecution execution) {
90+
final String projectId = notNull(notNull(project, "project").getId(), "projectId");
91+
final ExecutionResponse response;
92+
try {
93+
response = restTemplate.postForObject(
94+
VISUALIZATION_EXECUTION_URI,
95+
notNull(execution, "execution"),
96+
ExecutionResponse.class,
97+
projectId);
98+
} catch (GoodDataException | RestClientException e) {
99+
throw new GoodDataException("Unable to execute visualization", e);
100+
}
101+
102+
if (response == null) {
103+
throw new GoodDataException("Empty response when execution posted to API");
104+
}
105+
106+
return response;
107+
}
108+
69109
/**
70110
* Get for result of given response.
71111
* @param executionResponse response to get the result
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (C) 2004-2018, GoodData(R) Corporation. All rights reserved.
3+
* This source code is licensed under the BSD-style license found in the
4+
* LICENSE.txt file in the root directory of this source tree.
5+
*/
6+
7+
package com.gooddata.executeafm;
8+
9+
import com.fasterxml.jackson.annotation.JsonCreator;
10+
import com.fasterxml.jackson.annotation.JsonInclude;
11+
import com.fasterxml.jackson.annotation.JsonProperty;
12+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
13+
import com.fasterxml.jackson.annotation.JsonTypeName;
14+
import com.gooddata.executeafm.afm.CompatibilityFilter;
15+
import com.gooddata.executeafm.resultspec.ResultSpec;
16+
17+
import java.util.ArrayList;
18+
import java.util.Collections;
19+
import java.util.List;
20+
21+
/**
22+
* Represents structure for triggering execution with reference to visualization object.
23+
* Contains additional filters which should be merged with original ones defined in viz. object.
24+
*/
25+
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
26+
@JsonInclude(JsonInclude.Include.NON_NULL)
27+
@JsonTypeName("visualizationExecution")
28+
public class VisualizationExecution {
29+
30+
private final String reference;
31+
private List<CompatibilityFilter> filters;
32+
private ResultSpec resultSpec;
33+
34+
/**
35+
* Constructor.
36+
* Creates execution of visualization object without any additional filters or result specification.
37+
*
38+
* @param reference reference uri to visualization object metadata
39+
*/
40+
public VisualizationExecution(final String reference) {
41+
this(reference, null, null);
42+
}
43+
44+
/**
45+
* @param reference reference uri to visualization object metadata
46+
* @param filters additional filters which should be merged
47+
* @param resultSpec result specification of executed viz. object
48+
*/
49+
@JsonCreator
50+
VisualizationExecution(@JsonProperty("reference") final String reference,
51+
@JsonProperty("filters") final List<CompatibilityFilter> filters,
52+
@JsonProperty("resultSpec") final ResultSpec resultSpec) {
53+
this.reference = reference;
54+
this.resultSpec = resultSpec;
55+
this.filters = filters;
56+
}
57+
58+
/**
59+
* @return reference uri to visualization object metadata
60+
*/
61+
public String getReference() {
62+
return reference;
63+
}
64+
65+
public List<CompatibilityFilter> getFilters() {
66+
return filters;
67+
}
68+
69+
/**
70+
* Sets the result specification and returns this instance
71+
*
72+
* @param resultSpec result specification of executed viz. object
73+
* @return updated execution
74+
*/
75+
public VisualizationExecution setResultSpec(final ResultSpec resultSpec) {
76+
this.resultSpec = resultSpec;
77+
return this;
78+
}
79+
80+
/**
81+
* @return result specification of executed viz. object
82+
*/
83+
public ResultSpec getResultSpec() {
84+
return resultSpec;
85+
}
86+
87+
/**
88+
* Sets additional filters to this execution.
89+
*
90+
* @param filters additional filters
91+
* @return updated execution
92+
*/
93+
public VisualizationExecution setFilters(final List<CompatibilityFilter> filters) {
94+
this.filters = filters;
95+
return this;
96+
}
97+
}

src/main/java/com/gooddata/executeafm/afm/ExpressionFilter.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2007-2017, GoodData(R) Corporation. All rights reserved.
2+
* Copyright (C) 2007-2018, GoodData(R) Corporation. All rights reserved.
33
* This source code is licensed under the BSD-style license found in the
44
* LICENSE.txt file in the root directory of this source tree.
55
*/
@@ -10,11 +10,13 @@
1010
import com.fasterxml.jackson.annotation.JsonRootName;
1111
import com.gooddata.util.GoodDataToStringBuilder;
1212

13+
import java.util.Objects;
14+
1315
/**
1416
* To be deprecated filter using plain expression
1517
*/
1618
@JsonRootName("expression")
17-
public class ExpressionFilter implements CompatibilityFilter {
19+
public final class ExpressionFilter implements CompatibilityFilter {
1820
static final String NAME = "expression";
1921
private final String value;
2022

@@ -27,12 +29,27 @@ public ExpressionFilter(@JsonProperty("value") final String value) {
2729
this.value = value;
2830
}
2931

30-
public String getValue() {
32+
public String getValue() {
3133
return value;
3234
}
3335

3436
@Override
3537
public String toString() {
3638
return GoodDataToStringBuilder.defaultToString(this);
3739
}
40+
41+
@Override
42+
public boolean equals(Object o) {
43+
if (this == o)
44+
return true;
45+
if (!(o instanceof ExpressionFilter))
46+
return false;
47+
ExpressionFilter that = (ExpressionFilter) o;
48+
return Objects.equals(value, that.value);
49+
}
50+
51+
@Override
52+
public int hashCode() {
53+
return Objects.hash(value);
54+
}
3855
}

src/main/java/com/gooddata/md/visualization/VisualizationConverter.java

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,11 @@
1818
import com.gooddata.executeafm.afm.NegativeAttributeFilter;
1919
import com.gooddata.executeafm.afm.PositiveAttributeFilter;
2020
import com.gooddata.executeafm.afm.SimpleMeasureDefinition;
21-
import com.gooddata.executeafm.resultspec.AttributeSortItem;
2221
import com.gooddata.executeafm.resultspec.Dimension;
23-
import com.gooddata.executeafm.resultspec.Direction;
24-
import com.gooddata.executeafm.resultspec.MeasureLocatorItem;
25-
import com.gooddata.executeafm.resultspec.MeasureSortItem;
2622
import com.gooddata.executeafm.resultspec.ResultSpec;
2723
import com.gooddata.executeafm.resultspec.SortItem;
2824

2925
import java.util.ArrayList;
30-
import java.util.Collections;
3126
import java.util.List;
3227
import java.util.function.Function;
3328
import java.util.stream.Collectors;
@@ -47,35 +42,49 @@ public abstract class VisualizationConverter {
4742
private static final ObjectMapper MAPPER = new ObjectMapper();
4843

4944
/**
50-
* Generate Execution from Visualization object. Currently {@link ResultSpec}'s {@link Dimension}s can be generated
51-
* for table and four types of chart: bar, column, line and pie.
45+
* Generate Execution from Visualization object.
5246
*
5347
* @param visualizationObject which will be converted to {@link Execution}
5448
* @param visualizationClassGetter {@link Function} for fetching VisualizationClass, which is necessary for correct generation of {@link ResultSpec}
5549
* @return {@link Execution} object
50+
*
51+
* @see #convertToAfm(VisualizationObject)
52+
* @see #convertToResultSpec(VisualizationObject, Function)
5653
*/
5754
public static Execution convertToExecution(final VisualizationObject visualizationObject, final Function<String, VisualizationClass> visualizationClassGetter) {
58-
VisualizationClass visualizationClass = notNull(visualizationClassGetter).apply(notNull(visualizationObject).getVisualizationClassUri());
59-
60-
ResultSpec resultSpec = convertToResultSpec(visualizationObject, visualizationClass.getVisualizationType());
55+
ResultSpec resultSpec = convertToResultSpec(visualizationObject, visualizationClassGetter);
6156
Afm afm = convertToAfm(visualizationObject);
6257
return new Execution(afm, resultSpec);
6358
}
6459

65-
static Afm convertToAfm(final VisualizationObject visualizationObject) {
60+
/**
61+
* Generate Afm from Visualization object.
62+
*
63+
* @param visualizationObject which will be converted to {@link Execution}
64+
* @return {@link Afm} object
65+
*/
66+
public static Afm convertToAfm(final VisualizationObject visualizationObject) {
6667
final List<AttributeItem> attributes = convertAttributes(visualizationObject.getAttributes());
6768
final List<CompatibilityFilter> filters = convertFilters(visualizationObject.getFilters());
6869
final List<MeasureItem> measures = convertMeasures(visualizationObject.getMeasures());
6970

7071
return new Afm(attributes, filters, measures, null);
7172
}
7273

73-
static ResultSpec convertToResultSpec(final VisualizationObject visualizationObject,
74-
final VisualizationType visualizationType) {
75-
notNull(visualizationObject);
76-
notNull(visualizationType);
74+
/**
75+
* Generate ResultSpec from Visualization object. Currently {@link ResultSpec}'s {@link Dimension}s can be generated
76+
* for table and four types of chart: bar, column, line and pie.
77+
*
78+
* @param visualizationObject which will be converted to {@link Execution}
79+
* @param visualizationClassGetter {@link Function} for fetching VisualizationClass, which is necessary for correct generation of {@link ResultSpec}
80+
* @return {@link Execution} object
81+
*/
82+
public static ResultSpec convertToResultSpec(final VisualizationObject visualizationObject,
83+
final Function<String, VisualizationClass> visualizationClassGetter) {
84+
VisualizationClass visualizationClass = notNull(visualizationClassGetter).apply(notNull(visualizationObject).getVisualizationClassUri());
85+
7786
List<SortItem> sorts = getSorting(visualizationObject);
78-
List<Dimension> dimensions = getDimensions(visualizationObject, visualizationType);
87+
List<Dimension> dimensions = getDimensions(visualizationObject, visualizationClass.getVisualizationType());
7988
return new ResultSpec(dimensions, sorts);
8089
}
8190

@@ -206,12 +215,11 @@ private static List<CompatibilityFilter> convertFilters(final List<FilterItem> f
206215
}
207216

208217
private static List<MeasureItem> convertMeasures(final List<Measure> measures) {
209-
List<MeasureItem> measuresForAfm = measures.stream()
218+
return measures.stream()
210219
.map(VisualizationConverter::removeFormat)
211220
.map(VisualizationConverter::getAfmMeasure)
212221
.map(VisualizationConverter::convertMeasureFilters)
213222
.collect(toList());
214-
return measuresForAfm;
215223
}
216224

217225
private static Measure removeFormat(final Measure measure) {

src/main/java/com/gooddata/md/visualization/VisualizationObject.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
import static org.apache.commons.lang3.Validate.notNull;
2020

2121
import com.gooddata.executeafm.UriObjQualifier;
22+
import com.gooddata.executeafm.afm.Afm;
2223
import com.gooddata.executeafm.afm.FilterItem;
2324
import com.gooddata.executeafm.Execution;
25+
import com.gooddata.executeafm.resultspec.ResultSpec;
2426
import com.gooddata.md.AbstractObj;
2527
import com.gooddata.md.Meta;
2628
import com.gooddata.md.Queryable;
@@ -255,11 +257,30 @@ public void setVisualizationClass(UriObjQualifier uri) {
255257
content.setVisualizationClass(uri);
256258
}
257259

260+
/**
261+
* @see VisualizationConverter#convertToExecution(VisualizationObject, Function)
262+
*/
258263
@JsonIgnore
259264
public Execution convertToExecution(Function<String, VisualizationClass> visualizationClassgetter) {
260265
return VisualizationConverter.convertToExecution(this, visualizationClassgetter);
261266
}
262267

268+
/**
269+
* @see VisualizationConverter#convertToAfm(VisualizationObject)
270+
*/
271+
@JsonIgnore
272+
public Afm convertToAfm() {
273+
return VisualizationConverter.convertToAfm(this);
274+
}
275+
276+
/**
277+
* @see VisualizationConverter#convertToResultSpec(VisualizationObject, Function)
278+
*/
279+
@JsonIgnore
280+
public ResultSpec convertToResultSpec(Function<String, VisualizationClass> visualizationClassgetter) {
281+
return VisualizationConverter.convertToResultSpec(this, visualizationClassgetter);
282+
}
283+
263284
private Content getContent() {
264285
return content;
265286
}

0 commit comments

Comments
 (0)