Skip to content

Commit e10cf90

Browse files
committed
Improved: Make ‘FormRenderer#getUsedFields’ more generic
(OFBIZ-11135) We want to be able to reuse the selection of used fields for any form renderers. As a consequence it seems more appropriate to move the behavior of ‘FormRenderer#getUsedFields’ to the ‘ModelFormField’ class. Additionally we have decoupled the filtering logic from the iteration process by constructing a stateful predicate. The corresponding unit tests have been adapted to both changes. git-svn-id: https://svn.apache.org/repos/asf/ofbiz/ofbiz-framework/trunk@1862636 13f79535-47bb-0310-9956-ffa450edef68
1 parent d9a0273 commit e10cf90

File tree

4 files changed

+128
-121
lines changed

4 files changed

+128
-121
lines changed

framework/widget/src/main/java/org/apache/ofbiz/widget/model/ModelFormField.java

+36-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import java.util.Map;
3636
import java.util.StringTokenizer;
3737
import java.util.TimeZone;
38+
import java.util.function.Consumer;
39+
import java.util.function.Predicate;
3840

3941
import org.apache.ofbiz.base.conversion.ConversionException;
4042
import org.apache.ofbiz.base.conversion.DateTimeConverters;
@@ -102,6 +104,18 @@ public class ModelFormField {
102104

103105
public static final String module = ModelFormField.class.getName();
104106

107+
/**
108+
* Constructs a form field model from a builder specification.
109+
*
110+
* @param spec the specification of form field definition
111+
* @return the form field model corresponding to the specification.
112+
*/
113+
public static ModelFormField from(Consumer<ModelFormFieldBuilder> spec) {
114+
ModelFormFieldBuilder builder = new ModelFormFieldBuilder();
115+
spec.accept(builder);
116+
return new ModelFormField(builder);
117+
}
118+
105119
public static ModelFormField from(ModelFormFieldBuilder builder) {
106120
return new ModelFormField(builder);
107121
}
@@ -929,6 +943,27 @@ public boolean shouldUse(Map<String, Object> context) {
929943
}
930944
}
931945

946+
/**
947+
* Provides a stateful predicate checking if a field must be used.
948+
*
949+
* @param context the context determining if the field must be used
950+
* @return a stateful predicate checking if a field must be used.
951+
*/
952+
public static Predicate<ModelFormField> usedFields(Map<String, Object> context) {
953+
HashMap<String, Boolean> seenUseWhen = new HashMap<>();
954+
return field -> {
955+
if (!field.isUseWhenEmpty()) {
956+
String name = field.getName();
957+
boolean shouldUse = field.shouldUse(context);
958+
if (seenUseWhen.containsKey(name)) {
959+
return shouldUse != seenUseWhen.get(name);
960+
}
961+
seenUseWhen.put(name, shouldUse);
962+
}
963+
return true;
964+
};
965+
}
966+
932967
/**
933968
* Models the &lt;auto-complete&gt; element.
934969
*
@@ -4360,4 +4395,4 @@ public void renderFieldString(Appendable writer, Map<String, Object> context, Fo
43604395
formStringRenderer.renderTextFindField(writer, context, this);
43614396
}
43624397
}
4363-
}
4398+
}

framework/widget/src/main/java/org/apache/ofbiz/widget/renderer/FormRenderer.java

+8-21
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*******************************************************************************/
1919
package org.apache.ofbiz.widget.renderer;
2020

21+
import static org.apache.ofbiz.widget.model.ModelFormField.usedFields;
22+
2123
import java.io.IOException;
2224
import java.util.ArrayList;
2325
import java.util.Collection;
@@ -668,25 +670,6 @@ private void renderItemRow(Appendable writer, Map<String, Object> localContext,
668670
formStringRenderer.renderFormatItemRowClose(writer, localContext, modelForm);
669671
}
670672

671-
// Filter the field lists by removing the ones with both the same names and "use-when" values.
672-
// Keep all fields without a "use-when" attribute.
673-
List<ModelFormField> getUsedFields(Map<String, Object> context) {
674-
HashMap<String, Boolean> seenUseWhen = new HashMap<>();
675-
return modelForm.getFieldList().stream()
676-
.filter(field -> {
677-
if (!field.isUseWhenEmpty()) {
678-
String name = field.getName();
679-
boolean shouldUse = field.shouldUse(context);
680-
if (seenUseWhen.containsKey(name)) {
681-
return shouldUse != seenUseWhen.get(name);
682-
}
683-
seenUseWhen.put(name, shouldUse);
684-
}
685-
return true;
686-
})
687-
.collect(Collectors.toList());
688-
}
689-
690673
private void renderItemRows(Appendable writer, Map<String, Object> context, FormStringRenderer formStringRenderer,
691674
boolean formPerItem, int numOfColumns) throws IOException {
692675
String lookupName = modelForm.getListName();
@@ -777,7 +760,9 @@ private void renderItemRows(Appendable writer, Map<String, Object> context, Form
777760
Debug.logVerbose("In form got another row, context is: " + localContext, module);
778761
}
779762

780-
List<ModelFormField> tempFieldList = getUsedFields(localContext);
763+
List<ModelFormField> tempFieldList = modelForm.getFieldList().stream()
764+
.filter(usedFields(localContext))
765+
.collect(Collectors.toList());
781766

782767
// Each single item is rendered in one or more rows if its fields have
783768
// different "position" attributes. All the fields with the same position
@@ -972,7 +957,9 @@ private void renderMultiFormString(Appendable writer, Map<String, Object> contex
972957

973958
private void renderSingleFormString(Appendable writer, Map<String, Object> context,
974959
int positions) throws IOException {
975-
List<ModelFormField> tempFieldList = getUsedFields(context);
960+
List<ModelFormField> tempFieldList = modelForm.getFieldList().stream()
961+
.filter(usedFields(context))
962+
.collect(Collectors.toList());
976963
Set<String> alreadyRendered = new TreeSet<>();
977964
FieldGroup lastFieldGroup = null;
978965
// render form open
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.ofbiz.widget.model;
20+
21+
import static org.apache.ofbiz.widget.model.ModelFormField.from;
22+
import static org.hamcrest.Matchers.containsInAnyOrder;
23+
import static org.junit.Assert.assertThat;
24+
25+
import java.util.Arrays;
26+
import java.util.HashMap;
27+
import java.util.List;
28+
import java.util.stream.Collectors;
29+
30+
import org.junit.Before;
31+
import org.junit.Test;
32+
33+
public class ModelFormFieldTest {
34+
private HashMap<String, Object> context;
35+
36+
@Before
37+
public void setUp() throws Exception {
38+
context = new HashMap<>();
39+
}
40+
41+
/**
42+
* Filter a list of fields with {@link ModelFormField#usedFields} predicate.
43+
* <p>
44+
* This is useful since Hamcrest does not provide any Stream matchers.
45+
*
46+
* @param fields the fields to filter
47+
* @return a list a filtered fields.
48+
*/
49+
List<ModelFormField> getUsedField(ModelFormField... fields) {
50+
return Arrays.stream(fields)
51+
.filter(ModelFormField.usedFields(context))
52+
.collect(Collectors.toList());
53+
}
54+
55+
@Test
56+
public void fieldsToRenderBasic() {
57+
ModelFormField fA = from(b -> b.setName("A"));
58+
ModelFormField fB = from(b -> b.setName("B"));
59+
assertThat(getUsedField(fA, fB), containsInAnyOrder(fA, fB));
60+
}
61+
62+
@Test
63+
public void fieldsToRenderDuplicates() {
64+
ModelFormField fA0 = from(b -> b.setName("A"));
65+
ModelFormField fB = from(b -> b.setName("B"));
66+
ModelFormField fA1 = from(b -> b.setName("A"));
67+
assertThat(getUsedField(fA0, fB, fA1), containsInAnyOrder(fA0, fA1, fB));
68+
}
69+
70+
@Test
71+
public void fieldsToRenderBasicUseWhen() {
72+
ModelFormField fA0 = from(b -> b.setName("A").setUseWhen("true"));
73+
ModelFormField fA1 = from(b -> b.setName("A").setUseWhen("false"));
74+
assertThat(getUsedField(fA0, fA1), containsInAnyOrder(fA0, fA1));
75+
}
76+
77+
@Test
78+
public void fieldsToRenderDuplicatesUseWhen() {
79+
ModelFormField fA0 = from(b -> b.setName("A").setUseWhen("true"));
80+
ModelFormField fA1 = from(b -> b.setName("A").setUseWhen("false"));
81+
ModelFormField fA2 = from(b -> b.setName("A").setUseWhen("true"));
82+
assertThat(getUsedField(fA0, fA1, fA2), containsInAnyOrder(fA0, fA1));
83+
}
84+
}

framework/widget/src/test/java/org/apache/ofbiz/widget/renderer/FormRendererTest.java

-99
This file was deleted.

0 commit comments

Comments
 (0)