| ... |
... |
@@ -26,7 +26,6 @@ import com.google.common.collect.ImmutableSet; |
|
26
|
26
|
import fr.ird.observe.client.ObserveSwingApplicationContext;
|
|
27
|
27
|
import fr.ird.observe.client.ui.content.data.seine.FloatingObjectUIModel;
|
|
28
|
28
|
import fr.ird.observe.dto.data.seine.ObjectMaterialHierarchyDto;
|
|
29
|
|
-import fr.ird.observe.dto.referential.FormulaHelper;
|
|
30
|
29
|
import fr.ird.observe.dto.referential.ReferentialLocale;
|
|
31
|
30
|
import fr.ird.observe.dto.referential.seine.ObjectMaterialTypeReference;
|
|
32
|
31
|
import org.apache.commons.logging.Log;
|
| ... |
... |
@@ -62,13 +61,13 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
62
|
61
|
static FloatingObjectPartsTreeNode createRoot(FloatingObjectUIModel model, ObjectMaterialHierarchyDto dto) {
|
|
63
|
62
|
FloatingObjectPartsTreeNode root;
|
|
64
|
63
|
FloatingObjectPartsTreeNodeContext rootModel = new FloatingObjectPartsTreeNodeContext(model);
|
|
65
|
|
- if (dto != null) {
|
|
|
64
|
+ if (dto == null) {
|
|
|
65
|
+ root = new FloatingObjectPartsTreeNode(rootModel);
|
|
|
66
|
+ } else {
|
|
66
|
67
|
FloatingObjectPartsTreeNodeContext childModel = new FloatingObjectPartsTreeNodeContext(dto, rootModel);
|
|
67
|
68
|
root = new FloatingObjectPartsTreeNode(childModel);
|
|
68
|
69
|
root.computeCompanions(null);
|
|
69
|
70
|
root.setCompanions(null);
|
|
70
|
|
- } else {
|
|
71
|
|
- root = new FloatingObjectPartsTreeNode(rootModel);
|
|
72
|
71
|
}
|
|
73
|
72
|
return root;
|
|
74
|
73
|
}
|
| ... |
... |
@@ -166,6 +165,8 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
166
|
165
|
getUserObject().text = null;
|
|
167
|
166
|
getUserObject().validWhenArriving = true;
|
|
168
|
167
|
getUserObject().validWhenLeaving = true;
|
|
|
168
|
+ getUserObject().needOneSelectionOnArriving = false;
|
|
|
169
|
+ getUserObject().needOneSelectionOnLeaving = false;
|
|
169
|
170
|
}
|
|
170
|
171
|
|
|
171
|
172
|
@Override
|
| ... |
... |
@@ -173,44 +174,68 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
173
|
174
|
return (FloatingObjectPartsTreeNode) super.getParent();
|
|
174
|
175
|
}
|
|
175
|
176
|
|
|
176
|
|
- void fillNodeSets(ImmutableSet.Builder<FloatingObjectPartsTreeNode> allNodesBuilder,
|
|
177
|
|
- ImmutableSet.Builder<FloatingObjectPartsTreeNode> needOneSelectionNodesBuilder,
|
|
178
|
|
- ImmutableSet.Builder<FloatingObjectPartsTreeNode> mandatoryNodesBuilder) {
|
|
|
177
|
+ ImmutableSet<FloatingObjectPartsTreeNode> getShell() {
|
|
179
|
178
|
|
|
180
|
|
- allNodesBuilder.add(this);
|
|
181
|
|
- if (getUserObject().needOneSelection) {
|
|
182
|
|
- needOneSelectionNodesBuilder.add(this);
|
|
183
|
|
- }
|
|
184
|
|
- if (getUserObject().mandatory) {
|
|
185
|
|
- mandatoryNodesBuilder.add(this);
|
|
186
|
|
- }
|
|
|
179
|
+ ImmutableSet.Builder<FloatingObjectPartsTreeNode> allNodesBuilder = ImmutableSet.builder();
|
|
|
180
|
+ getShell(allNodesBuilder);
|
|
|
181
|
+ return allNodesBuilder.build();
|
|
|
182
|
+ }
|
|
187
|
183
|
|
|
|
184
|
+ private void getShell(ImmutableSet.Builder<FloatingObjectPartsTreeNode> allNodesBuilder) {
|
|
|
185
|
+ allNodesBuilder.add(this);
|
|
188
|
186
|
for (FloatingObjectPartsTreeNode child : this) {
|
|
189
|
|
- child.fillNodeSets(allNodesBuilder, needOneSelectionNodesBuilder, mandatoryNodesBuilder);
|
|
|
187
|
+ child.getShell(allNodesBuilder);
|
|
190
|
188
|
}
|
|
|
189
|
+ }
|
|
191
|
190
|
|
|
|
191
|
+ boolean withMandatoryConstraintsOnChildren() {
|
|
|
192
|
+ ObjectMaterialHierarchyDto userObject = getUserObject().dto;
|
|
|
193
|
+ return userObject == null || userObject.isChildSelectionMandatory();
|
|
192
|
194
|
}
|
|
193
|
195
|
|
|
194
|
196
|
void computeNeedAtLeastOnSelectValidState(boolean whenArriving, boolean whenLeaving) {
|
|
195
|
|
-
|
|
|
197
|
+ boolean needSelect = isEditable();
|
|
|
198
|
+ FloatingObjectPartsTreeNodeContext userObject = getUserObject();
|
|
196
|
199
|
if (whenArriving) {
|
|
197
|
|
- getUserObject().validWhenArriving = isAtLeastOneSelected(1);
|
|
|
200
|
+ userObject.needOneSelectionOnArriving = (!needSelect || withValue(1)) && isAtLeastOneSelected(1);
|
|
198
|
201
|
}
|
|
199
|
202
|
if (whenLeaving) {
|
|
200
|
|
- getUserObject().validWhenLeaving = isAtLeastOneSelected(2);
|
|
|
203
|
+ userObject.needOneSelectionOnLeaving = (!needSelect || withValue(2)) && isAtLeastOneSelected(2);
|
|
|
204
|
+ }
|
|
|
205
|
+ if (userObject.needOneSelectionOnArriving || userObject.needOneSelectionOnLeaving) {
|
|
|
206
|
+ log.info("Validate node " + this);
|
|
201
|
207
|
}
|
|
202
|
208
|
|
|
203
|
|
- log.info("Validate node " + this);
|
|
|
209
|
+ }
|
|
204
|
210
|
|
|
|
211
|
+ private FloatingObjectPartsTreeNode getFirstAncestorNeedOneSelection(int column) {
|
|
|
212
|
+ if (withMandatoryConstraintsOnChildren()) {
|
|
|
213
|
+ if (parent == null) {
|
|
|
214
|
+ return this;
|
|
|
215
|
+ }
|
|
|
216
|
+ if (withValue(column)) {
|
|
|
217
|
+ return this;
|
|
|
218
|
+ }
|
|
|
219
|
+ }
|
|
|
220
|
+ return getParent().getFirstAncestorNeedOneSelection(column);
|
|
205
|
221
|
}
|
|
206
|
222
|
|
|
207
|
223
|
void computeMandatoryValidState(boolean whenArriving, boolean whenLeaving) {
|
|
208
|
224
|
FloatingObjectPartsTreeNodeContext userObject = getUserObject();
|
|
|
225
|
+ FloatingObjectPartsTreeNode parent = getParent();
|
|
209
|
226
|
if (whenArriving) {
|
|
210
|
|
- userObject.validWhenArriving = getParent().getUserObject().validWhenArriving;
|
|
|
227
|
+ if (parent != null && !parent.getUserObject().validWhenArriving) {
|
|
|
228
|
+ userObject.validWhenArriving = false;
|
|
|
229
|
+ } else {
|
|
|
230
|
+ userObject.validWhenArriving = getFirstAncestorNeedOneSelection(1).getUserObject().needOneSelectionOnArriving;
|
|
|
231
|
+ }
|
|
211
|
232
|
}
|
|
212
|
233
|
if (whenLeaving) {
|
|
213
|
|
- userObject.validWhenLeaving = getParent().getUserObject().validWhenLeaving;
|
|
|
234
|
+ if (parent != null && !parent.getUserObject().validWhenLeaving) {
|
|
|
235
|
+ userObject.validWhenLeaving = false;
|
|
|
236
|
+ } else {
|
|
|
237
|
+ userObject.validWhenLeaving = getFirstAncestorNeedOneSelection(2).getUserObject().needOneSelectionOnLeaving;
|
|
|
238
|
+ }
|
|
214
|
239
|
}
|
|
215
|
240
|
|
|
216
|
241
|
if (userObject.getValueAt(1) != null || userObject.getValueAt(2) != null) {
|
| ... |
... |
@@ -218,41 +243,19 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
218
|
243
|
}
|
|
219
|
244
|
}
|
|
220
|
245
|
|
|
221
|
|
- void computeFormulaValidState(boolean whenArriving, boolean whenLeaving) {
|
|
222
|
|
- if (getUserObject().dto == null || getUserObject().dto.isBoolean()) {
|
|
223
|
|
- return;
|
|
224
|
|
- }
|
|
225
|
|
- String validation = getUserObject().dto.getValidation();
|
|
226
|
|
- if (whenArriving && getUserObject().validWhenArriving) {
|
|
227
|
|
- Object value = getUserObject().getValueAt(1);
|
|
228
|
|
- if (value != null) {
|
|
229
|
|
- if (getUserObject().dto.isText()) {
|
|
230
|
|
- getUserObject().validWhenArriving = FormulaHelper.validateObjectMaterialValidation(validation, value);
|
|
231
|
|
- } else if (getUserObject().dto.isInteger()) {
|
|
232
|
|
- getUserObject().validWhenArriving = FormulaHelper.validateObjectMaterialValidation(validation, Integer.valueOf(value.toString()));
|
|
233
|
|
- } else if (getUserObject().dto.isFloat()) {
|
|
234
|
|
- getUserObject().validWhenArriving = FormulaHelper.validateObjectMaterialValidation(validation, Float.valueOf(value.toString()));
|
|
235
|
|
- }
|
|
236
|
|
- }
|
|
237
|
|
- }
|
|
238
|
|
- if (whenLeaving && getUserObject().validWhenLeaving) {
|
|
239
|
|
- Object value = getUserObject().getValueAt(2);
|
|
240
|
|
- if (value != null) {
|
|
241
|
|
- if (getUserObject().dto.isText()) {
|
|
242
|
|
- getUserObject().validWhenLeaving = FormulaHelper.validateObjectMaterialValidation(validation, value);
|
|
243
|
|
- } else if (getUserObject().dto.isInteger()) {
|
|
244
|
|
- getUserObject().validWhenLeaving = FormulaHelper.validateObjectMaterialValidation(validation, Integer.valueOf(value.toString()));
|
|
245
|
|
- } else if (getUserObject().dto.isFloat()) {
|
|
246
|
|
- getUserObject().validWhenLeaving = FormulaHelper.validateObjectMaterialValidation(validation, Float.valueOf(value.toString()));
|
|
247
|
|
- }
|
|
248
|
|
- }
|
|
249
|
|
- }
|
|
250
|
|
-
|
|
251
|
|
- }
|
|
252
|
|
-
|
|
253
|
|
- boolean withValidation() {
|
|
254
|
|
- return getUserObject().dto != null && getUserObject().dto.withValidation();
|
|
255
|
|
- }
|
|
|
246
|
+// void computeFormulaValidState(boolean whenArriving, boolean whenLeaving) {
|
|
|
247
|
+// FloatingObjectPartsTreeNodeContext userObject = getUserObject();
|
|
|
248
|
+// ObjectMaterialHierarchyDto dto = Objects.requireNonNull(userObject.dto);
|
|
|
249
|
+// if (whenArriving && userObject.validWhenArriving) {
|
|
|
250
|
+// Object value = userObject.getValueAt(1);
|
|
|
251
|
+// userObject.validWhenArriving = dto.isValid(value);
|
|
|
252
|
+// }
|
|
|
253
|
+// if (whenLeaving && userObject.validWhenLeaving) {
|
|
|
254
|
+// Object value = userObject.getValueAt(2);
|
|
|
255
|
+// userObject.validWhenLeaving = dto.isValid(value);
|
|
|
256
|
+// }
|
|
|
257
|
+//
|
|
|
258
|
+// }
|
|
256
|
259
|
|
|
257
|
260
|
private void setCompanions(ImmutableSet.Builder<FloatingObjectPartsTreeNode> companionsBuilder) {
|
|
258
|
261
|
if (companionsBuilder != null) {
|
| ... |
... |
@@ -263,12 +266,21 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
263
|
266
|
}
|
|
264
|
267
|
}
|
|
265
|
268
|
|
|
|
269
|
+ private boolean withValue(int column) {
|
|
|
270
|
+ return getValueAt(column) != null;
|
|
|
271
|
+ }
|
|
|
272
|
+
|
|
|
273
|
+ private boolean withValidValue(int column) {
|
|
|
274
|
+ return withValue(column) && (column == 1 ? getUserObject().valueValidOnArriving : getUserObject().valueValidOnLeaving);
|
|
|
275
|
+ }
|
|
|
276
|
+
|
|
266
|
277
|
private boolean isAtLeastOneSelected(int column) {
|
|
267
|
|
- if (getValueAt(column) != null) {
|
|
268
|
|
- return true;
|
|
269
|
|
- }
|
|
270
|
278
|
for (FloatingObjectPartsTreeNode child : this) {
|
|
271
|
|
- if (child.isAtLeastOneSelected(column)) {
|
|
|
279
|
+ if (child.withValidValue(column)) {
|
|
|
280
|
+ return true;
|
|
|
281
|
+ }
|
|
|
282
|
+ boolean result = child.isAtLeastOneSelected(column);
|
|
|
283
|
+ if (result) {
|
|
272
|
284
|
return true;
|
|
273
|
285
|
}
|
|
274
|
286
|
}
|
| ... |
... |
@@ -293,6 +305,7 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
293
|
305
|
return dto != null && !dto.isChildrenMultiSelectable() && !isLeaf();
|
|
294
|
306
|
}
|
|
295
|
307
|
|
|
|
308
|
+ //TODO Improve the design, we should not store anything in uiModel and separate leaving and arriving data
|
|
296
|
309
|
private static class FloatingObjectPartsTreeNodeContext {
|
|
297
|
310
|
|
|
298
|
311
|
// main model to get and store values
|
| ... |
... |
@@ -303,16 +316,22 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
303
|
316
|
private final boolean enabled;
|
|
304
|
317
|
// Is this node editable ?
|
|
305
|
318
|
private final boolean editable;
|
|
306
|
|
- // Is this node need at least one child selected ?
|
|
307
|
|
- private final boolean needOneSelection;
|
|
308
|
|
- // Is this node in the path of at least one mandatory child ancestor ?
|
|
309
|
|
- private final boolean mandatory;
|
|
310
|
319
|
// Is the node is exclusive (means only one value possible for him and his brothers) ?
|
|
311
|
320
|
private final boolean exclusive;
|
|
|
321
|
+ // Is the node use validation on his value ?
|
|
|
322
|
+ private final boolean useValidation;
|
|
312
|
323
|
private final ReferentialLocale referentialLocale;
|
|
313
|
|
- // Is the node valid for whenArriving column ?
|
|
|
324
|
+ // Is this node (on arriving) need at least one child selected ? (if editable then node must be selected)
|
|
|
325
|
+ private boolean needOneSelectionOnLeaving;
|
|
|
326
|
+ // Is this node (on leaving) need at least one child selected ? (if editable then node must be selected)
|
|
|
327
|
+ private boolean needOneSelectionOnArriving;
|
|
|
328
|
+ // for a validation node (on arriving), is value valid (if no value then it is valid)
|
|
|
329
|
+ private boolean valueValidOnLeaving = true;
|
|
|
330
|
+ // for a validation node (on leaving), is value valid (if no value then it is valid)
|
|
|
331
|
+ private boolean valueValidOnArriving = true;
|
|
|
332
|
+ // Is the node valid (on arriving) column ?
|
|
314
|
333
|
private boolean validWhenArriving = true;
|
|
315
|
|
- // Is the node valid for whenLeaving column ?
|
|
|
334
|
+ // Is the node valid (on leeaving) column ?
|
|
316
|
335
|
private boolean validWhenLeaving = true;
|
|
317
|
336
|
// Set of brothers of this node that is in a exclusive group of node (only one value among all of them)
|
|
318
|
337
|
private ImmutableSet<FloatingObjectPartsTreeNode> companions;
|
| ... |
... |
@@ -320,35 +339,33 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
320
|
339
|
private String text;
|
|
321
|
340
|
|
|
322
|
341
|
FloatingObjectPartsTreeNodeContext(FloatingObjectUIModel uiModel) {
|
|
323
|
|
- Objects.requireNonNull(uiModel);
|
|
324
|
|
- this.uiModel = uiModel;
|
|
|
342
|
+ this.uiModel = Objects.requireNonNull(uiModel);
|
|
325
|
343
|
this.dto = null;
|
|
326
|
344
|
this.enabled = true;
|
|
327
|
345
|
this.editable = false;
|
|
328
|
|
- this.mandatory = false;
|
|
329
|
346
|
this.exclusive = false;
|
|
330
|
|
- this.needOneSelection = false;
|
|
331
|
|
- this.referentialLocale=ObserveSwingApplicationContext.get().getDecoratorService().getReferentialLocale();
|
|
|
347
|
+ this.useValidation = false;
|
|
|
348
|
+ this.valueValidOnArriving = true;
|
|
|
349
|
+ this.valueValidOnLeaving = true;
|
|
|
350
|
+ this.referentialLocale = ObserveSwingApplicationContext.get().getDecoratorService().getReferentialLocale();
|
|
332
|
351
|
}
|
|
333
|
352
|
|
|
334
|
353
|
FloatingObjectPartsTreeNodeContext(ObjectMaterialHierarchyDto dto, FloatingObjectPartsTreeNodeContext parent) {
|
|
335
|
|
- Objects.requireNonNull(dto);
|
|
336
|
|
- Objects.requireNonNull(parent);
|
|
337
|
|
- this.uiModel = parent.uiModel;
|
|
338
|
|
- this.dto = dto;
|
|
|
354
|
+ this.uiModel = Objects.requireNonNull(parent).uiModel;
|
|
|
355
|
+ this.dto = Objects.requireNonNull(dto);
|
|
339
|
356
|
// enabled if parent is enabled and dto is enabled
|
|
340
|
357
|
this.enabled = parent.enabled && dto.isEnabled();
|
|
341
|
|
- // need one selection if is enabled and dto requires it
|
|
342
|
|
- this.needOneSelection = enabled && dto.isChildSelectionMandatory();
|
|
343
|
358
|
// editable if dto is selectable (we also make sure that the object material type is here too)
|
|
344
|
359
|
this.editable = dto.isSelectable() && dto.getObjectMaterialType() != null;
|
|
345
|
|
-
|
|
346
|
|
- // mandatory if enabled parent is so or parent makes this child to be
|
|
347
|
|
- this.mandatory = parent.mandatory || parent.needOneSelection;
|
|
|
360
|
+ this.useValidation = enabled && editable && dto.withValidation();
|
|
|
361
|
+ if (!useValidation) {
|
|
|
362
|
+ valueValidOnArriving = true;
|
|
|
363
|
+ valueValidOnLeaving = true;
|
|
|
364
|
+ }
|
|
348
|
365
|
// exclusive if his parent requires it
|
|
349
|
366
|
this.exclusive = parent.dto != null && !parent.dto.isChildrenMultiSelectable();
|
|
350
|
|
- this.referentialLocale=ObserveSwingApplicationContext.get().getDecoratorService().getReferentialLocale();
|
|
351
|
|
- log.info(String.format("New node: %s - mandatory %s - needOneSelection %s - exclusive %s", dto.getLabel(referentialLocale), mandatory, needOneSelection, exclusive));
|
|
|
367
|
+ this.referentialLocale = ObserveSwingApplicationContext.get().getDecoratorService().getReferentialLocale();
|
|
|
368
|
+ log.info(String.format("New node: %s %s - needOneSelection %b-%b - exclusive %s", dto.getCode(), dto.getLabel(referentialLocale), needOneSelectionOnArriving, needOneSelectionOnLeaving, exclusive));
|
|
352
|
369
|
}
|
|
353
|
370
|
|
|
354
|
371
|
Object getValueAt(int column) {
|
| ... |
... |
@@ -368,9 +385,15 @@ public class FloatingObjectPartsTreeNode extends AbstractMutableTreeTableNode im |
|
368
|
385
|
switch (column) {
|
|
369
|
386
|
case 1: // when arriving
|
|
370
|
387
|
uiModel.setWhenArriving(dto.getId(), aValue == null ? null : String.valueOf(aValue));
|
|
|
388
|
+ if (useValidation) {
|
|
|
389
|
+ valueValidOnArriving = dto.isValid(aValue);
|
|
|
390
|
+ }
|
|
371
|
391
|
return;
|
|
372
|
392
|
case 2: // when leaving
|
|
373
|
393
|
uiModel.setWhenLeaving(dto.getId(), aValue == null ? null : String.valueOf(aValue));
|
|
|
394
|
+ if (useValidation) {
|
|
|
395
|
+ valueValidOnLeaving = dto.isValid(aValue);
|
|
|
396
|
+ }
|
|
374
|
397
|
return;
|
|
375
|
398
|
}
|
|
376
|
399
|
throw new IllegalStateException();
|