Skip to content

Commit fc40807

Browse files
Enhabced validation, added filtering for fields to validate on entity creator form
1 parent 22d7358 commit fc40807

File tree

11 files changed

+341
-219
lines changed

11 files changed

+341
-219
lines changed

src/com/magento/idea/magento2plugin/actions/generation/dialog/AbstractDialog.java

Lines changed: 35 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,20 @@
55

66
package com.magento.idea.magento2plugin.actions.generation.dialog;
77

8+
import com.intellij.openapi.util.Pair;
9+
import com.magento.idea.magento2plugin.actions.generation.dialog.reflection.ExtractComponentFromFieldUtil;
810
import com.magento.idea.magento2plugin.actions.generation.dialog.util.DialogFieldErrorUtil;
9-
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.FieldValidation;
10-
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.FieldValidations;
11+
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.TypeFieldsRulesParser;
12+
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.data.FieldValidationData;
1113
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.ValidationRule;
1214
import com.magento.idea.magento2plugin.bundles.CommonBundle;
1315
import com.magento.idea.magento2plugin.bundles.ValidatorBundle;
1416
import java.awt.Container;
1517
import java.awt.Dimension;
1618
import java.awt.Toolkit;
1719
import java.lang.reflect.Field;
18-
import java.lang.reflect.InvocationTargetException;
19-
import java.util.ArrayList;
20-
import java.util.Arrays;
21-
import java.util.HashMap;
22-
import java.util.LinkedHashMap;
2320
import java.util.LinkedList;
2421
import java.util.List;
25-
import java.util.Map;
2622
import javax.swing.JComboBox;
2723
import javax.swing.JComponent;
2824
import javax.swing.JDialog;
@@ -35,17 +31,14 @@
3531
/**
3632
* All code generate dialog should extend this class.
3733
*/
38-
@SuppressWarnings({"PMD.ShortVariable", "PMD.MissingSerialVersionUID"})
3934
public abstract class AbstractDialog extends JDialog {
4035

4136
protected CommonBundle bundle;
4237
protected final ValidatorBundle validatorBundle = new ValidatorBundle();
38+
protected final List<FieldValidationData> fieldsValidationsList;
4339
private final String errorTitle;
44-
private final Map<Field, List<ValidationRule>> textFieldValidationRuleMap;
45-
private final Map<Field, Map<ValidationRule, String>> errorMessageFieldValidationRuleMap;
4640
private JTabbedPane tabbedPane;
4741
private boolean isValidationErrorShown;
48-
private boolean dialogHasErrors;
4942

5043
/**
5144
* Abstract Dialog Constructor.
@@ -54,15 +47,14 @@ public AbstractDialog() {
5447
super();
5548
bundle = new CommonBundle();
5649
errorTitle = bundle.message("common.error");
57-
textFieldValidationRuleMap = new LinkedHashMap<>();
58-
errorMessageFieldValidationRuleMap = new HashMap<>();
50+
fieldsValidationsList = new TypeFieldsRulesParser(this).parseValidationRules();
5951
}
6052

6153
protected void centerDialog(final AbstractDialog dialog) {
6254
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
63-
final int x = screenSize.width / 2 - dialog.getSize().width / 2;
64-
final int y = screenSize.height / 2 - dialog.getSize().height / 2;
65-
dialog.setLocation(x, y);
55+
final int cordX = screenSize.width / 2 - dialog.getSize().width / 2;
56+
final int cordY = screenSize.height / 2 - dialog.getSize().height / 2;
57+
dialog.setLocation(cordX, cordY);
6658
}
6759

6860
protected void onCancel() {
@@ -74,48 +66,52 @@ protected void onCancel() {
7466
*
7567
* @return boolean
7668
*/
69+
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.AvoidDeeplyNestedIfStmts"})
7770
protected boolean validateFormFields() {
78-
addValidationRulesFromAnnotations();
71+
boolean dialogHasErrors;
7972
isValidationErrorShown = dialogHasErrors = false;
8073

81-
for (final Map.Entry<Field, List<ValidationRule>> entry
82-
: textFieldValidationRuleMap.entrySet()) {
83-
final Field field = entry.getKey();
84-
final List<ValidationRule> rules = entry.getValue();
74+
for (final FieldValidationData fieldValidationData : getFieldsToValidate()) {
75+
final Field field = fieldValidationData.getField();
76+
final List<Pair<ValidationRule, String>> rules = fieldValidationData.getRules();
8577

86-
for (final ValidationRule rule : rules) {
78+
for (final Pair<ValidationRule, String> rulePair : rules) {
79+
final ValidationRule rule = rulePair.getFirst();
80+
final String message = rulePair.getSecond();
8781
final String value = resolveFieldValueByComponentType(field);
8882

8983
if (value != null && !rule.check(value)) {
90-
if (errorMessageFieldValidationRuleMap.containsKey(field)
91-
&& errorMessageFieldValidationRuleMap.get(field).containsKey(rule)) {
92-
if (!dialogHasErrors) {
93-
final JComponent component = getComponentForField(field);
84+
if (!dialogHasErrors) {
85+
final JComponent component =
86+
ExtractComponentFromFieldUtil.extract(field, this);
9487

95-
if (component != null && tabbedPane != null) {
96-
navigateToTabWithComponent(component);
97-
}
88+
if (component != null && tabbedPane != null) {
89+
navigateToTabWithComponent(component);
9890
}
99-
dialogHasErrors = true;
100-
showErrorMessage(
101-
field,
102-
errorMessageFieldValidationRuleMap.get(field).get(rule)
103-
);
10491
}
92+
dialogHasErrors = true;
93+
showErrorMessage(field, message);
10594
break;
10695
}
10796
}
10897
}
10998

11099
if (dialogHasErrors && !isValidationErrorShown) {
111-
showErrorMessage(
112-
validatorBundle.message("validator.someFieldsHaveErrors")
113-
);
100+
showErrorMessage(validatorBundle.message("validator.someFieldsHaveErrors"));
114101
}
115102

116103
return !dialogHasErrors;
117104
}
118105

106+
/**
107+
* Override this method to change which fields should or shouldn't be validated.
108+
*
109+
* @return List[FieldValidationData]
110+
*/
111+
protected List<FieldValidationData> getFieldsToValidate() {
112+
return new LinkedList<>(fieldsValidationsList);
113+
}
114+
119115
/**
120116
* Tabbed pane should be registered to be possible navigate to the tab in which error occurred.
121117
*
@@ -162,130 +158,6 @@ protected void showErrorMessage(final String errorMessage) {
162158
isValidationErrorShown = true;
163159
}
164160

165-
/**
166-
* Process validation rules from annotations.
167-
*/
168-
private void addValidationRulesFromAnnotations() {
169-
final Class<?> type = this.getClass();
170-
final List<FieldValidation> validations = new LinkedList<>();
171-
172-
for (final Field field : type.getDeclaredFields()) {
173-
field.setAccessible(true);
174-
validations.clear();
175-
176-
if (field.isAnnotationPresent(FieldValidation.class)) {
177-
validations.add(field.getAnnotation(FieldValidation.class));
178-
}
179-
if (field.isAnnotationPresent(FieldValidations.class)) {
180-
validations.addAll(
181-
Arrays.asList(field.getAnnotation(FieldValidations.class).value())
182-
);
183-
}
184-
185-
for (final FieldValidation validation : validations) {
186-
try {
187-
addValidationRuleToField(
188-
field,
189-
getRuleFromAnnotation(validation),
190-
getMessageFromAnnotation(validation)
191-
);
192-
} catch (NoSuchMethodException | IllegalAccessException
193-
| InvocationTargetException | InstantiationException exception) {
194-
return;
195-
} finally {
196-
field.setAccessible(false);
197-
}
198-
}
199-
field.setAccessible(false);
200-
}
201-
}
202-
203-
/**
204-
* Get error message from annotation.
205-
*
206-
* @param validation FieldValidation
207-
*
208-
* @return String
209-
*/
210-
private String getMessageFromAnnotation(final FieldValidation validation) {
211-
String[] params;
212-
final int minMessageArrayLength = 1;
213-
214-
if (validation.message().length > minMessageArrayLength) {
215-
params = Arrays.copyOfRange(validation.message(), 1, validation.message().length);
216-
} else {
217-
params = new String[]{};
218-
}
219-
return validatorBundle.message(validation.message()[0], (Object[]) params);
220-
}
221-
222-
/**
223-
* Get validation rule from annotation.
224-
*
225-
* @param validation FieldValidation
226-
*
227-
* @return ValidationRule
228-
*/
229-
private ValidationRule getRuleFromAnnotation(final FieldValidation validation)
230-
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
231-
InstantiationException {
232-
final Class<?> ruleType = validation.rule().getRule();
233-
234-
return (ValidationRule) ruleType.getConstructor().newInstance();
235-
}
236-
237-
/**
238-
* Add validation rule for field.
239-
*
240-
* @param field Field
241-
* @param rule ValidationRule
242-
* @param message String
243-
*/
244-
protected void addValidationRuleToField(
245-
final Field field,
246-
final ValidationRule rule,
247-
final String message
248-
) {
249-
if (getComponentForField(field) == null) {
250-
return;
251-
}
252-
List<ValidationRule> rules;
253-
254-
if (textFieldValidationRuleMap.containsKey(field)) {
255-
rules = textFieldValidationRuleMap.get(field);
256-
} else {
257-
rules = new ArrayList<>();
258-
}
259-
260-
if (!rules.contains(rule) && rule != null) {
261-
addFieldValidationRuleMessageAssociation(field, rule, message);
262-
rules.add(rule);
263-
textFieldValidationRuleMap.put(field, rules);
264-
}
265-
}
266-
267-
/**
268-
* Associate validation rule with field.
269-
*
270-
* @param field Field
271-
* @param rule ValidationRule
272-
* @param message String
273-
*/
274-
private void addFieldValidationRuleMessageAssociation(
275-
final Field field,
276-
final ValidationRule rule,
277-
final String message
278-
) {
279-
Map<ValidationRule, String> validationRuleErrorMessageMap;
280-
if (errorMessageFieldValidationRuleMap.containsKey(field)) {
281-
validationRuleErrorMessageMap = errorMessageFieldValidationRuleMap.get(field);
282-
} else {
283-
validationRuleErrorMessageMap = new HashMap<>();
284-
}
285-
validationRuleErrorMessageMap.put(rule, message);
286-
errorMessageFieldValidationRuleMap.put(field, validationRuleErrorMessageMap);
287-
}
288-
289161
/**
290162
* Resolve value of stored component by field.
291163
*
@@ -294,7 +166,7 @@ private void addFieldValidationRuleMessageAssociation(
294166
* @return String
295167
*/
296168
private String resolveFieldValueByComponentType(final Field field) {
297-
final JComponent component = getComponentForField(field);
169+
final JComponent component = ExtractComponentFromFieldUtil.extract(field, this);
298170

299171
if (component instanceof JTextField) {
300172
return ((JTextField) component).isEditable()
@@ -312,30 +184,6 @@ private String resolveFieldValueByComponentType(final Field field) {
312184
return null;
313185
}
314186

315-
/**
316-
* Get JComponent for field.
317-
*
318-
* @param field Field
319-
*
320-
* @return JComponent
321-
*/
322-
private JComponent getComponentForField(final @NotNull Field field) {
323-
try {
324-
field.setAccessible(true);
325-
final Object component = field.get(this);
326-
327-
if (component instanceof JComponent) {
328-
return (JComponent) component;
329-
}
330-
} catch (IllegalAccessException exception) {
331-
return null;
332-
} finally {
333-
field.setAccessible(false);
334-
}
335-
336-
return null;
337-
}
338-
339187
/**
340188
* Navigate to tab with specified component.
341189
*

src/com/magento/idea/magento2plugin/actions/generation/dialog/NewEntityDialog.java

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
import com.magento.idea.magento2plugin.actions.generation.data.dialog.EntityCreatorContextData;
1717
import com.magento.idea.magento2plugin.actions.generation.data.dialog.NewEntityDialogData;
1818
import com.magento.idea.magento2plugin.actions.generation.data.ui.ComboBoxItemData;
19+
import com.magento.idea.magento2plugin.actions.generation.dialog.reflection.GetReflectionFieldUtil;
1920
import com.magento.idea.magento2plugin.actions.generation.dialog.util.ClassPropertyFormatterUtil;
2021
import com.magento.idea.magento2plugin.actions.generation.dialog.util.ProcessWorker;
2122
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.FieldValidation;
2223
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.annotation.RuleRegistry;
24+
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.data.FieldValidationData;
2325
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.AclResourceIdRule;
2426
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.AlphanumericRule;
2527
import com.magento.idea.magento2plugin.actions.generation.dialog.validator.rule.AlphanumericWithUnderscoreRule;
@@ -57,6 +59,7 @@
5759
import java.awt.event.KeyEvent;
5860
import java.awt.event.WindowAdapter;
5961
import java.awt.event.WindowEvent;
62+
import java.lang.reflect.Field;
6063
import java.util.ArrayList;
6164
import java.util.Arrays;
6265
import java.util.Collection;
@@ -249,8 +252,9 @@ public void windowClosing(final WindowEvent event) {
249252
onCancel();
250253
}
251254

255+
@SuppressWarnings("PMD.AccessorMethodGeneration")
252256
@Override
253-
public void windowOpened(WindowEvent e) {
257+
public void windowOpened(final WindowEvent event) {
254258
entityName.requestFocus();
255259
}
256260
});
@@ -300,6 +304,34 @@ public static void open(final Project project, final PsiDirectory directory) {
300304
dialog.setVisible(true);
301305
}
302306

307+
/**
308+
* Filter fields to validate if createUiComponent checkbox isn't selected.
309+
*
310+
* @return List[FieldValidationData]
311+
*/
312+
@Override
313+
protected List<FieldValidationData> getFieldsToValidate() {
314+
final List<FieldValidationData> filteredFields = new LinkedList<>();
315+
316+
if (createUiComponent.isSelected()) {
317+
filteredFields.addAll(super.getFieldsToValidate());
318+
} else {
319+
final List<Field> fieldsToIgnore = new ArrayList<>();
320+
fieldsToIgnore.add(GetReflectionFieldUtil.getByName("route", this.getClass()));
321+
fieldsToIgnore.add(GetReflectionFieldUtil.getByName("formName", this.getClass()));
322+
fieldsToIgnore.add(GetReflectionFieldUtil.getByName("gridName", this.getClass()));
323+
324+
for (final FieldValidationData fieldData : super.getFieldsToValidate()) {
325+
if (fieldsToIgnore.contains(fieldData.getField())) {
326+
continue;
327+
}
328+
filteredFields.add(fieldData);
329+
}
330+
}
331+
332+
return filteredFields;
333+
}
334+
303335
/**
304336
* Initialize combobox sources.
305337
*/

0 commit comments

Comments
 (0)