1 package pl.aislib.fm;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.Iterator;
7 import java.util.LinkedHashMap;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.TreeMap;
11
12 import org.apache.commons.logging.Log;
13
14 import pl.aislib.fm.forms.Field;
15 import pl.aislib.fm.forms.IEntity;
16 import pl.aislib.fm.forms.ValidateException;
17 import pl.aislib.fm.messages.IMessage;
18 import pl.aislib.fm.messages.IMessageConverter;
19 import pl.aislib.util.Pair;
20 import pl.aislib.util.messages.StandardMessageConverter;
21
22 /***
23 * Field container class.
24 *
25 * Please note the following:
26 * Messages from forms' validation can be converted using implementation of
27 * <code>IMessageConverter</code> interface. <br>
28 *
29 * One can use <code>MessageFormatConverter</code> to do that. In this case,
30 * message format arguments should be used for each message in the following way:
31 * <ul>
32 * <li>{1} - name of the entity (field or rule for which the message is generated)</li>
33 * <li>{2} - name of the dynamic entity (equals to name of the entity for non-dynamic fields or rules)</li>
34 * <li>{3} - number of the dynamic entity in collection of dynamic fields and rules (starting with 0)</li>
35 * <li>{4} - number of the dynamic entity in collection of dynamic fields and rules (starting with 1)</li>
36 * <li>{5} - suffix number of the dynamic entity</li>
37 * </ul>
38 *
39 * @author <a href="mailto:wswiatek@ais.pl">Wojciech Swiatek</a>, AIS.PL
40 * @version $Revision: 1.18 $
41 */
42 public abstract class FieldContainer {
43
44
45
46 /*** */
47 public static final String MC_ENTITY_OBJECT = "object";
48
49 /*** */
50 public static final String MC_ENTITY_NAME = "name";
51
52 /*** */
53 public static final String MC_ENTITY_GENERIC_NAME = "genericName";
54
55 /*** */
56 public static final String MC_ENTITY_NAME_SUFFIX = "nameSuffix";
57
58 /*** */
59 public static final String MC_ENTITY_VALIDATOR = "validator";
60
61 /*** */
62 public static final String MC_ENTITY_DYNAMIC_COUNT = "dynamicCount";
63
64 /*** */
65 public static final String MC_ENTITY_DYNAMIC_NUMBER_FROM_0 = "dynamicNumberFrom0";
66
67 /*** */
68 public static final String MC_ENTITY_DYNAMIC_NUMBER_FROM_1 = "dynamicNumberFrom1";
69
70 /*** */
71 public static final String MC_ENTITY_VALUE = "value";
72
73 /*** */
74 public static final String MC_ENTITY_ORIGINAL_VALUE = "originalValue";
75
76 /*** */
77 public static final String MC_ENTITY_FORM = "form";
78
79
80
81
82 /***
83 * Name of the container.
84 */
85 protected String name;
86
87 /***
88 * Map of fields.
89 */
90 protected Map fields;
91
92 /***
93 * Map of messages (codes and objects).
94 */
95 protected Map messages;
96
97 /***
98 * Groups of messages (codes and list of messages).
99 */
100 protected Map messageGroups;
101
102 /***
103 * Map of field values, converted after successful validation.
104 */
105 protected Map values;
106
107 /***
108 * Map of original field values.
109 */
110 protected Map originalValues;
111
112 /***
113 * Map of field names and booleans.
114 * Values of the map state whether fields (i.e. keys) have been validated.
115 */
116 protected Map validatedFields;
117
118 /***
119 * Map of field names and validator objects in case {@link ValidateException} occurs.
120 */
121 protected Map validators;
122
123 /***
124 * Map of messages from non-validated entities.
125 * Keys are entity names.
126 * Values are messages.
127 */
128 protected Map messagesMap;
129
130 /***
131 * Map of messages from non-validated entities.
132 * Same as messages map but messages are added in an ordered manner.
133 */
134 protected Map orderedMessagesMap;
135
136 /***
137 * Language of messages.
138 */
139 protected String lang;
140
141 /***
142 * Logging object.
143 */
144 protected Log log;
145
146 /***
147 * True if empty fields should be given null value.
148 */
149 protected boolean bTreatEmptyAsNull = false;
150
151
152
153
154 /***
155 * @param name name of the field.
156 */
157 public FieldContainer(String name) {
158 this.name = name;
159
160 fields = new LinkedHashMap();
161 messages = new LinkedHashMap();
162 messageGroups = new LinkedHashMap();
163 }
164
165
166
167
168 /***
169 * @param field field object.
170 */
171 public void addField(Field field) {
172 fields.put(field.getName(), field);
173 }
174
175 /***
176 * @param fieldName name of a field.
177 * @return the field.
178 */
179 public Field getField(String fieldName) {
180 return (Field) fields.get(fieldName);
181 }
182
183 /***
184 * @return name of the container.
185 */
186 public String getName() {
187 return name;
188 }
189
190 /***
191 * @param fieldName name of a field.
192 * @return original value of the field. It makes sense only when the field has been tried to be validated.
193 */
194 public String getOriginalValue(String fieldName) {
195 return originalValues != null ? (String) originalValues.get(fieldName) : null;
196 }
197
198 /***
199 * @return original field values.
200 */
201 public Map getOriginalValues() {
202 return originalValues;
203 }
204
205 /***
206 * @return map of validated fields.
207 */
208 public Map getValidatedFields() {
209 return validatedFields;
210 }
211
212 /***
213 * @return map of field names and validators in case {@link ValidateException} occurs.
214 */
215 public Map getValidators() {
216 return validators;
217 }
218
219 /***
220 * @param fieldName name of a field.
221 * @return value of the field. It makes sense only when the field has been validated.
222 */
223 public Object getValue(String fieldName) {
224 return getValue(fieldName, bTreatEmptyAsNull);
225 }
226
227 /***
228 *
229 * @param fieldName name of a field.
230 * @param treatEmptyAsNull true if empty field should be given null value.
231 * @return Object
232 */
233 public Object getValue(String fieldName, boolean treatEmptyAsNull) {
234 if (values != null) {
235 Object value = values.get(fieldName);
236 return treatEmptyAsNull && isValueEmpty(value) ? null : value;
237 }
238
239 return null;
240 }
241
242 /***
243 * @return map of field values, converted after successful validation.
244 */
245 public Map getValues() {
246 return getValues(bTreatEmptyAsNull);
247 }
248
249 /***
250 * @param treatEmptyAsNull true if empty fields should be given null value.
251 * @return map of field values.
252 */
253 public Map getValues(boolean treatEmptyAsNull) {
254 if (!treatEmptyAsNull || values == null) {
255 return values;
256 }
257
258 Map result = new LinkedHashMap(values);
259
260 for (Iterator i = result.entrySet().iterator(); i.hasNext();) {
261 Map.Entry me = (Map.Entry) i.next();
262 String fieldName = (String) me.getKey();
263 boolean fieldValidated = isFieldValidated(fieldName);
264 if (!fieldValidated || (fieldValidated && isValueEmpty(me.getValue()))) {
265 result.put(fieldName, null);
266 }
267 }
268
269 return result;
270 }
271
272 /***
273 *
274 * @param bTreatEmptyAsNull true if empty fields should be given null value.
275 */
276 public void treatEmptyAsNull(boolean bTreatEmptyAsNull) {
277 this.bTreatEmptyAsNull = bTreatEmptyAsNull;
278 }
279
280 /***
281 *
282 * @param value object to be checked against emptiness
283 * @return true if the object is empty.
284 */
285 protected boolean isValueEmpty(Object value) {
286 if (value == null) {
287 return true;
288 }
289
290 if (value instanceof String && ((String) value).trim().length() == 0) {
291 return true;
292 }
293
294 if (value instanceof String[] && ((String[]) value).length == 0) {
295 return true;
296 }
297
298 return false;
299 }
300
301 /***
302 * @param fieldName name of a field.
303 * @return true if the field has been validated successfully.
304 */
305 public boolean isFieldValidated(String fieldName) {
306 Boolean b = (Boolean) validatedFields.get(fieldName);
307 return (b != null ? b.booleanValue() : false);
308 }
309
310 /***
311 * @param log logging object.
312 */
313 public void setLog(Log log) {
314 this.log = log;
315 }
316
317 /***
318 * Validates fields in the container.
319 *
320 * @param fieldValues map of original string values.
321 * @return true if all fields have been successfully validated.
322 */
323 public boolean validate(Map fieldValues) {
324 return validate(fieldValues, null);
325 }
326
327 /***
328 * Validates fields in the container.
329 *
330 * @param fieldValues map of original string values.
331 * @param data an object specific for validators.
332 * @return true if all fields have been successfully validated.
333 */
334 public boolean validate(Map fieldValues, Object data) {
335 return preValidate(fieldValues, data)
336 && doValidate(fieldValues, data)
337 && postValidate(fieldValues, data);
338 }
339
340 /***
341 * Validates fields in the container.
342 *
343 * @param field a field.
344 * @param data an object specific for validators.
345 * @param fieldValues map of original string values.
346 * @return true if the field has been successfully validated.
347 */
348 public boolean validateField(Field field, Object data, Map fieldValues) {
349 String fieldName = field.getName();
350 Object fieldValue = null;
351
352 if (field.isComplex() && field.isDynamic()) {
353 Map fValues = new LinkedHashMap(fieldValues);
354 Map builderMapping = field.getBuilder().getMapping();
355
356
357
358 for (Iterator i = builderMapping.entrySet().iterator(); i.hasNext();) {
359 Map.Entry me = (Map.Entry) i.next();
360 String partFieldName = (String) me.getValue();
361 constrainValues(fValues, partFieldName);
362 }
363
364 boolean result = true;
365
366 List l = orderFieldValues(values, builderMapping, fValues);
367 for (Iterator i = l.iterator(); i.hasNext();) {
368 Pair pair = (Pair) i.next();
369 int j = ((Integer) pair.getFirst()).intValue();
370 Map builderValues = (Map) pair.getSecond();
371 if (builderValues != null) {
372 fieldValue = field.getBuilder().join(builderValues);
373 result &= validateField(field, field.getName() + j, data, fieldValue);
374 }
375 }
376
377 return result;
378 } else if (field.isComplex()) {
379 Map builderValues = constrainValues(values, field.getBuilder().getMapping(), true);
380 if (builderValues == null) {
381
382
383 return true;
384 }
385 fieldValue = field.getBuilder().join(builderValues);
386 } else if (field.isDynamic()) {
387 Map fValues = new LinkedHashMap(fieldValues);
388 Map constrainedValues = constrainValues(fValues, field.getName());
389 boolean result = true;
390 for (Iterator i = constrainedValues.entrySet().iterator(); i.hasNext();) {
391 Map.Entry me = (Map.Entry) i.next();
392 result &= validateField(field, (String) me.getKey(), data, me.getValue());
393 }
394 return result;
395 } else {
396 fieldValue = fieldValues.get(fieldName);
397 }
398
399 return validateField(field, data, fieldValue);
400 }
401
402 /***
403 * Validates a single field in the container.
404 *
405 * @param field a field.
406 * @param data an object specific for validators.
407 * @param fieldValue value of the field.
408 * @return true if the field has been successfully validated.
409 */
410 public boolean validateField(Field field, Object data, Object fieldValue) {
411 return validateField(field, field.getName(), data, fieldValue);
412 }
413
414 /***
415 * Validates a single field in the container.
416 *
417 * @param field a field.
418 * @param fieldName name of the field (used primarily for dynamic fields).
419 * @param data an object specific for validators.
420 * @param fieldValue value of the field.
421 * @return true if the field has been successfully validated.
422 */
423 public boolean validateField(Field field, String fieldName, Object data, Object fieldValue) {
424 stamp("Validating field: " + fieldName + " ...");
425
426 int valuesType = field.getValuesType();
427
428 if (fieldValue == null) {
429 if (valuesType == Field.VT_SINGLE) {
430 fieldValue = new String();
431 } else {
432 fieldValue = new String[0];
433 }
434 }
435
436 Object theValue = null;
437 try {
438 originalValues.put(fieldName, fieldValue);
439 validatedFields.put(fieldName, Boolean.TRUE);
440 switch (valuesType) {
441 case Field.VT_SINGLE:
442 if (fieldValue instanceof String) {
443 theValue = field.validate((String) fieldValue, messagesMap, fieldName, data);
444 break;
445 } else if (fieldValue instanceof String[]) {
446 String[] arr = (String[]) fieldValue;
447 originalValues.put(fieldName, arr[0]);
448 theValue = field.validate(arr[0], messagesMap, fieldName, data);
449 break;
450 } else {
451 validatedFields.put(fieldName, Boolean.FALSE);
452 return false;
453 }
454 case Field.VT_ARRAY:
455 if (fieldValue instanceof String) {
456 String[] arr = new String[1];
457 arr[0] = (String) fieldValue;
458 originalValues.put(fieldName, arr);
459 theValue = field.validate(arr, messagesMap, fieldName, data);
460 break;
461 } else if (fieldValue instanceof String[]) {
462 theValue = field.validate((String[]) fieldValue, messagesMap, fieldName, data);
463 break;
464 } else {
465 validatedFields.put(fieldName, Boolean.FALSE);
466 return false;
467 }
468 default :
469 if (fieldValue instanceof String) {
470 theValue = fieldValue;
471 } else if (fieldValue instanceof String[]) {
472 String[] aValue = (String[]) fieldValue;
473 if (aValue.length == 1) {
474 theValue = aValue[0];
475 } else {
476 theValue = aValue;
477 }
478 } else {
479 validatedFields.put(fieldName, Boolean.FALSE);
480 return false;
481 }
482 }
483 values.put(fieldName, isValueEmpty(theValue) ? null : theValue);
484 return true;
485 } catch (ValidateException ve) {
486 Iterator keys = messagesMap.values().iterator();
487 Object last = null;
488 while (keys.hasNext()) {
489 last = keys.next();
490 }
491 orderedMessagesMap.put(fieldName, last);
492 validatedFields.put(fieldName, Boolean.FALSE);
493 validators.put(fieldName, ve.getValidator());
494 stamp("Field '" + fieldName + "' has not been successfully validated. Returned message: " + ve.getMessage());
495 return false;
496 }
497 }
498
499
500
501
502 /***
503 * Contains all necessary steps taken before the proper validation of fields in the container.
504 *
505 * @param fieldValues map of field values.
506 * @param data an object specific for validators.
507 * @return true if all fields have been successfully pre-validated.
508 */
509 protected boolean preValidate(Map fieldValues, Object data) {
510 values = new LinkedHashMap();
511 originalValues = new LinkedHashMap();
512 validatedFields = new LinkedHashMap();
513 validators = new LinkedHashMap();
514 messagesMap = new LinkedHashMap();
515 orderedMessagesMap = new LinkedHashMap();
516 return true;
517 }
518
519 /***
520 * Main step of validation of fields in the container.
521 *
522 * @param fieldValues map of field values.
523 * @param data an object specific for validators.
524 * @return true if all fields have been successfully validated.
525 */
526 protected abstract boolean doValidate(Map fieldValues, Object data);
527
528 /***
529 * Contains all necessary steps taken after the proper validation of fields in the container.
530 * @param fieldValues map of field values.
531 * @param data an object specific for validators.
532 * @return true if all fields have been successfully post-validated.
533 */
534 protected boolean postValidate(Map fieldValues, Object data) {
535 return true;
536 }
537
538 /***
539 * @param fieldValues map of field values, as a reference.
540 * @param fieldName name of a field.
541 * @return map of values of fields that start with the given name.
542 */
543 protected Map constrainValues(Map fieldValues, String fieldName) {
544 Map result = new TreeMap();
545
546 int maxIndex = -1;
547 try {
548 maxIndex = Integer.parseInt((String) fieldValues.get(fieldName + "_count"));
549 } catch (Exception e) {
550 ;
551 }
552
553 for (Iterator i = fieldValues.entrySet().iterator(); i.hasNext();) {
554 Map.Entry me = (Map.Entry) i.next();
555 String key = (String) me.getKey();
556 if (key.startsWith(fieldName)) {
557 try {
558 int index = Integer.parseInt(key.substring(fieldName.length()));
559 if (index > maxIndex) {
560 maxIndex = index;
561 }
562 result.put(key, me.getValue());
563 } catch (Exception e) {
564 ;
565 }
566 }
567 }
568
569 for (int i = 1; i <= maxIndex; i++) {
570 if (!fieldValues.containsKey(fieldName + i)) {
571 result.put(fieldName + i, null);
572 }
573 }
574
575 return new LinkedHashMap(result);
576 }
577
578 /***
579 * Method constrainValues.
580 * @param values map of values.
581 * @param mapping a map.
582 * @param checkValidation true if values should be checked against having been validated.
583 * @return map of constrained values.
584 */
585 protected Map constrainValues(Map values, Map mapping, boolean checkValidation) {
586 Map result = new LinkedHashMap();
587 for (Iterator i = mapping.entrySet().iterator(); i.hasNext();) {
588 Map.Entry me = (Map.Entry) i.next();
589 String value = (String) me.getValue();
590 if (checkValidation && !isFieldValidated(value)) {
591 return null;
592 }
593 result.put(me.getKey(), values.get(value));
594 }
595 return result;
596 }
597
598 /***
599 * @param fieldValues map of field values.
600 * @param data an object specific for validators.
601 * @return true if all complex fields have been successfully validated.
602 */
603 protected boolean validateComplexFields(Map fieldValues, Object data) {
604 boolean result = true;
605
606 for (Iterator i = fields.entrySet().iterator(); i.hasNext();) {
607 Field field = (Field) ((Map.Entry) i.next()).getValue();
608 if (field.isConditional() || !field.isComplex()) {
609 continue;
610 }
611
612 boolean bFieldValidated = validateField(field, data, fieldValues);
613
614 validatedFields.put(field.getName(), new Boolean(bFieldValidated));
615 result &= bFieldValidated;
616 }
617
618 return result;
619 }
620
621 /***
622 * @param fieldValues map of field values.
623 * @param data an object specific for validators.
624 * @return true if all non-complex fields have been successfully validated.
625 */
626 protected boolean validateNonComplexFields(Map fieldValues, Object data) {
627 boolean result = true;
628
629 for (Iterator i = fields.entrySet().iterator(); i.hasNext();) {
630 Field field = (Field) ((Map.Entry) i.next()).getValue();
631 if (field.isConditional() || field.isComplex()) {
632 continue;
633 }
634
635 boolean bFieldValidated = validateField(field, data, fieldValues);
636
637 validatedFields.put(field.getName(), new Boolean(bFieldValidated));
638 result &= bFieldValidated;
639 }
640
641 return result;
642 }
643
644 /***
645 * @param str log message.
646 */
647 protected void stamp(String str) {
648 if (log != null && log.isDebugEnabled()) {
649 log.debug(str);
650 }
651 }
652
653
654
655
656 /***
657 * @return iterator of message codes.
658 */
659 public Iterator getErrorCodes() {
660 return getMessageCodes();
661 }
662
663 /***
664 * @param fieldName name of a field.
665 * @return message for the field.
666 */
667 public IMessage getErrorMessage(String fieldName) {
668 return (IMessage) messages.get(messagesMap.get(fieldName));
669 }
670
671 /***
672 * @return map of messages.
673 */
674 public Map getErrorMessages() {
675 return getErrorMessages(null);
676 }
677
678 public Map getErrorMessages(IMessageConverter messageConverter) {
679 return getErrorMessages(messageConverter, null);
680 }
681
682 /***
683 * This method should be called when one wants to use dynamic fields or rules.
684 *
685 * Two items are put into message converter values: the whole entity and a real entity name.
686 * Same objects go as message converter keys.
687 *
688 * @param messageConverter message converter object.
689 * @return map of messages with converted key and content.
690 */
691 protected Map getErrorMessages(IMessageConverter messageConverter, Map formEntityProperties) {
692 Map result = new LinkedHashMap();
693
694 if (formEntityProperties == null) {
695 formEntityProperties = getEntitiesProperties();
696 }
697
698 for (Iterator i = fields.keySet().iterator(); i.hasNext();) {
699 String fieldName = (String) i.next();
700 result.putAll(getEntityMessages(fieldName, messageConverter, formEntityProperties));
701 }
702
703 return result;
704 }
705
706 protected Map getEntitiesProperties() {
707 Map result = new HashMap();
708
709 for (Iterator iter = fields.keySet().iterator(); iter.hasNext(); ) {
710 String fieldName = (String) iter.next();
711 getEntityProperties(fieldName, result);
712 }
713
714 return result;
715 }
716
717 protected void getEntityProperties(String entityName, Map formEntityProperties) {
718 IEntity entity = getEntity(entityName);
719 if (entity == null) {
720 return;
721 }
722
723 List entities = null;
724 if (entity.isDynamic()) {
725 entities = getDynamicEntityNamesList(entityName);
726 } else {
727 entities = new ArrayList();
728 entities.add(entityName);
729 }
730
731 Integer entitiesCount = new Integer(entities.size());
732
733 int counter = 0;
734
735 for (Iterator i = entities.iterator(); i.hasNext(); counter++) {
736 String entName = (String) i.next();
737
738 Map entityProperties = new LinkedHashMap();
739
740 entityProperties.put(MC_ENTITY_OBJECT, entity);
741 entityProperties.put(MC_ENTITY_GENERIC_NAME, entityName);
742
743 if (entity.isDynamic()) {
744 entityProperties.put(MC_ENTITY_DYNAMIC_COUNT, entitiesCount);
745 }
746
747 entityProperties.put(MC_ENTITY_DYNAMIC_NUMBER_FROM_0, new Integer(counter));
748 entityProperties.put(MC_ENTITY_DYNAMIC_NUMBER_FROM_1, new Integer(counter + 1));
749
750 addSpecificEntityProperties(entity, entName, entityProperties);
751
752 formEntityProperties.put(entName, entityProperties);
753 }
754 }
755
756 /***
757 * @param entityName name of a field or a rule.
758 * @param messageConverter message converter object.
759 * @return map of messages for given entity (the entity may be dynamic).
760 */
761 protected Map getEntityMessages(String entityName, IMessageConverter messageConverter, Map formEntityProperties) {
762 if (messageConverter == null) {
763 messageConverter = new StandardMessageConverter();
764 }
765
766 Map result = new LinkedHashMap();
767
768 IEntity entity = getEntity(entityName);
769
770 if (entity == null) {
771 return result;
772 }
773
774 List entities = null;
775 if (entity.isDynamic()) {
776 entities = getDynamicEntityNamesList(entityName);
777 } else {
778 entities = new ArrayList();
779 entities.add(entityName);
780 }
781
782 int counter = 0;
783 for (Iterator i = entities.iterator(); i.hasNext(); counter++) {
784 String entName = (String) i.next();
785 Integer errorCode = (Integer) orderedMessagesMap.get(entName);
786 Message message = (Message) messages.get(errorCode);
787
788 Map entityProperties = (Map) formEntityProperties.get(entName);
789 entityProperties.put(MC_ENTITY_FORM, formEntityProperties);
790
791
792 if (message != null) {
793 IMessage cMessage = messageConverter.convert(message, lang, entityProperties, entityProperties);
794 result.put(cMessage.getKey(), cMessage.getContent());
795 } else {
796
797 List messageGroup = (List) messageGroups.get(errorCode);
798 if (messageGroup != null) {
799 for (Iterator j = messageGroup.iterator(); j.hasNext();) {
800 Message gMessage = (Message) j.next();
801 if (gMessage != null) {
802 IMessage cMessage = messageConverter.convert(gMessage, lang, entityProperties, entityProperties);
803 result.put(cMessage.getKey(), cMessage.getContent());
804 }
805 }
806 }
807 }
808 }
809
810 return result;
811 }
812
813 /***
814 * Adds specific entity properties to given map.
815 *
816 * @param entity <code>IEntity</code> object.
817 * @param entityName name of entity.
818 * @param entityProperties not nullable <code>Map</code> of entity properties.
819 */
820 protected void addSpecificEntityProperties(IEntity entity, String entityName, Map entityProperties) {
821 entityProperties.put(MC_ENTITY_NAME, entityName);
822 entityProperties.put(MC_ENTITY_NAME_SUFFIX, entityName.substring(entityName.lastIndexOf("_") + 1));
823
824 if (entity instanceof Field) {
825 entityProperties.put(MC_ENTITY_VALIDATOR, validators.get(entityName));
826 entityProperties.put(MC_ENTITY_VALUE, values.get(entityName));
827 entityProperties.put(MC_ENTITY_ORIGINAL_VALUE, originalValues.get(entityName));
828 }
829 }
830
831 /***
832 * @param entityName name of an entity.
833 * @return the entity.
834 */
835 protected IEntity getEntity(String entityName) {
836 return (IEntity) fields.get(entityName);
837 }
838
839 /***
840 * @param entityName name of a dynamic entity.
841 * @return list of all names of entity's instances.
842 */
843 protected List getDynamicEntityNamesList(String entityName) {
844 List result = new ArrayList();
845
846 IEntity entity = getEntity(entityName);
847
848 for (Iterator i = validatedFields.keySet().iterator(); i.hasNext();) {
849 String fieldName = (String) i.next();
850 if (fieldName.startsWith(entityName)) {
851 if (!entity.isDynamic()) {
852 result.add(fieldName);
853 } else {
854 try {
855 Integer.parseInt(fieldName.substring(fieldName.lastIndexOf("_") + 1));
856 result.add(fieldName);
857 } catch (Exception ex) {
858 ;
859 }
860 }
861 }
862 }
863
864 return result;
865 }
866
867 /***
868 * @param entityName name of a dynamic entity.
869 * @return iterator for all names of entity's instances.
870 */
871 protected Iterator getDynamicEntityNames(String entityName) {
872 return getDynamicEntityNamesList(entityName).iterator();
873 }
874
875 /***
876 * @return iterator of field names.
877 */
878 public Iterator getFieldNames() {
879 return fields.keySet().iterator();
880 }
881
882 /***
883 * @param fieldName of a field.
884 * @return message code for the field.
885 */
886 public int getMessageCode(String fieldName) {
887 return ((Integer) messagesMap.get(fieldName)).intValue();
888 }
889
890 /***
891 * @return iterator of message codes.
892 */
893 public Iterator getMessageCodes() {
894 return orderedMessagesMap.values().iterator();
895 }
896
897 /***
898 * @return map of original values.
899 */
900 public Map getStringValues() {
901 return getOriginalValues();
902 }
903
904 /***
905 * @param fieldValues string values of fields.
906 * @param fieldName name of a field.
907 * @return list of consecutive numbers of entity's instances.
908 */
909 protected List getDynamicNumbers(Map fieldValues, String fieldName) {
910 List result = new ArrayList();
911 for (Iterator i = fieldValues.entrySet().iterator(); i.hasNext();) {
912 Map.Entry me = (Map.Entry) i.next();
913 String key = (String) me.getKey();
914 if (key.startsWith(fieldName)) {
915 try {
916 Integer j = Integer.valueOf(key.substring(fieldName.length()));
917 result.add(j);
918 } catch (Exception e) {
919 ;
920 }
921 }
922 }
923 Collections.sort(result);
924 return result;
925 }
926
927 /***
928 * @param values values of fields.
929 * @param mapping mapping.
930 * @param fieldValues string values of fields.
931 * @return list of pairs: number and map of values of fields for entity's instance.
932 */
933 protected List orderFieldValues(Map values, Map mapping, Map fieldValues) {
934 List result = new ArrayList();
935
936 List l = new ArrayList();
937 boolean bDynamicFound = false;
938 boolean bNoDynamicFound = true;
939 for (Iterator i = mapping.entrySet().iterator(); i.hasNext();) {
940 Map.Entry me = (Map.Entry) i.next();
941 String fieldName = (String) me.getValue();
942 Field field = (Field) fields.get(fieldName);
943 if (field.isDynamic()) {
944 bNoDynamicFound = false;
945 if (field.isConditional() && field.isComplex()) {
946 for (Iterator j = field.getBuilder().getMapping().entrySet().iterator(); j.hasNext();) {
947 Map.Entry me2 = (Map.Entry) j.next();
948 String partFieldName = (String) me2.getValue();
949
950 if (!bDynamicFound) {
951 l = getDynamicNumbers(fieldValues, partFieldName);
952 bDynamicFound = true;
953 } else {
954 l.retainAll(getDynamicNumbers(fieldValues, partFieldName));
955 }
956 }
957 } else {
958 if (!bDynamicFound) {
959 l = getDynamicNumbers(
960 (isFieldValidated(fieldName) || fieldValues == null) ? values : fieldValues,
961 fieldName
962 );
963 bDynamicFound = true;
964 } else {
965 l.retainAll(
966 getDynamicNumbers(
967 (isFieldValidated(fieldName) || fieldValues == null) ? values : fieldValues,
968 fieldName
969 )
970 );
971 }
972 }
973 }
974 }
975
976 if (bNoDynamicFound) {
977 l.add(new Integer(-1));
978 }
979
980 for (Iterator i = l.iterator(); i.hasNext();) {
981 int j = ((Integer) i.next()).intValue();
982 Map map = new HashMap();
983 for (Iterator k = mapping.entrySet().iterator(); k.hasNext();) {
984 Map.Entry me = (Map.Entry) k.next();
985 String fieldName = (String) me.getValue();
986 Field field = (Field) fields.get(fieldName);
987 if (field.isDynamic()) {
988 if (isFieldValidated(fieldName + j) || fieldValues == null) {
989 map.put(me.getKey(), values.get(fieldName + j));
990 } else {
991 map.put(me.getKey(), fieldValues.get(fieldName + j));
992 }
993 } else {
994 if (isFieldValidated(fieldName) || fieldValues == null) {
995 map.put(me.getKey(), values.get(fieldName));
996 } else {
997 map.put(me.getKey(), fieldValues.get(fieldName));
998 }
999 }
1000 }
1001 result.add(new Pair(new Integer(j), map));
1002 }
1003
1004 return result;
1005 }
1006
1007 }