001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: AbstractValidationBuilder.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.site;
009:
010: import java.util.*;
011: import java.util.logging.Logger;
012:
013: import com.uwyn.rife.site.exceptions.MissingMarkingBlockException;
014: import com.uwyn.rife.site.exceptions.ValidationBuilderException;
015: import com.uwyn.rife.template.InternalValue;
016: import com.uwyn.rife.template.Template;
017: import com.uwyn.rife.template.exceptions.TemplateException;
018: import com.uwyn.rife.tools.ExceptionUtils;
019:
020: public abstract class AbstractValidationBuilder implements
021: ValidationBuilder {
022: public void setFallbackErrorArea(Template template, String message) {
023: if (null == template) {
024: return;
025: }
026:
027: if (null == message) {
028: message = "";
029: }
030:
031: if (template.hasValueId(ID_ERRORS)
032: && template.hasBlock(ID_ERRORS_FALLBACK)) {
033: if (template.hasValueId(ID_ERRORMESSAGE)
034: && template.hasBlock(ID_ERRORMESSAGE_WILDCARD)) {
035: template.setValue(ID_ERRORMESSAGE, message);
036: template.setBlock(ID_ERRORS, ID_ERRORMESSAGE_WILDCARD);
037: template.setBlock(ID_ERRORS_WILDCARD,
038: ID_ERRORS_FALLBACK);
039:
040: template.removeValue(ID_ERRORMESSAGE);
041: template.removeValue(ID_ERRORS);
042: } else {
043: template.setValue(ID_ERRORS, message);
044: template.setBlock(ID_ERRORS_WILDCARD,
045: ID_ERRORS_FALLBACK);
046:
047: template.removeValue(ID_ERRORS);
048: }
049: } else if (template.hasValueId(ID_ERRORS)
050: && template.hasBlock(ID_ERRORS_WILDCARD)) {
051: if (template.hasValueId(ID_ERRORMESSAGE)
052: && template.hasBlock(ID_ERRORMESSAGE_WILDCARD)) {
053: template.setValue(ID_ERRORMESSAGE, message);
054: template.setBlock(ID_ERRORS, ID_ERRORMESSAGE_WILDCARD);
055: template.setBlock(ID_ERRORS_WILDCARD,
056: ID_ERRORS_WILDCARD);
057:
058: template.removeValue(ID_ERRORMESSAGE);
059: template.removeValue(ID_ERRORS);
060: } else {
061: template.setValue(ID_ERRORS, message);
062: template.setBlock(ID_ERRORS_WILDCARD,
063: ID_ERRORS_WILDCARD);
064:
065: template.removeValue(ID_ERRORS);
066: }
067: } else {
068: template.setValue(ID_ERRORS_WILDCARD, message);
069: }
070: }
071:
072: public Collection<String> generateValidationErrors(
073: Template template, Collection<ValidationError> errors,
074: Collection<String> onlySubjectsToClear, String prefix) {
075: if (null == template || null == errors || 0 == errors.size()) {
076: return Collections.EMPTY_LIST;
077: }
078:
079: ArrayList<String> set_values = new ArrayList<String>();
080:
081: // adapt for subject prefixes
082: if (prefix != null && onlySubjectsToClear != null) {
083: ArrayList<String> prefixed_subjects = new ArrayList<String>();
084: for (String property : onlySubjectsToClear) {
085: prefixed_subjects.add(prefix + property);
086: }
087: onlySubjectsToClear = prefixed_subjects;
088: }
089:
090: // check if validation errors are already present in the bean,
091: // and generate the formatted errors
092: boolean has_wildcard_errors_block = template
093: .hasBlock(ID_ERRORS_WILDCARD);
094: boolean has_fallback_errors_block = template
095: .hasBlock(ID_ERRORS_FALLBACK);
096:
097: boolean has_fallback_errors_value = template
098: .hasValueId(ID_ERRORS_WILDCARD);
099: InternalValue fallback_errors_construction = null;
100: if (has_fallback_errors_value) {
101: template.removeValue(ID_ERRORS_WILDCARD);
102: fallback_errors_construction = template
103: .createInternalValue();
104: }
105:
106: // Reorder the filtered error values so that they're ordered according
107: // to the number of properties they declare. Those with the same
108: // number of properties will be ordered according to the their order
109: // of declaration.
110: // Also, all the content from the filtered values will be cleared to
111: // ensure that errors from previous submissions will not prevail.
112: List<String[]> filtered_errorvalues = template
113: .getFilteredValues(TAG_ERRORS);
114: ArrayList<List<String[]>> sorted_errorvalues = null;
115: if (filtered_errorvalues.size() > 0) {
116: sorted_errorvalues = new ArrayList<List<String[]>>();
117:
118: List<String[]> errorvalues;
119: for (String[] filtered_value : filtered_errorvalues) {
120: // only clear the filtered value if one of the subjects is
121: // validated
122: if (null == onlySubjectsToClear) {
123: template.removeValue(filtered_value[0]);
124: } else {
125: for (int i = 1; i < filtered_value.length; i++) {
126: if (onlySubjectsToClear
127: .contains(filtered_value[i])) {
128: template.removeValue(filtered_value[0]);
129: break;
130: }
131: }
132: }
133:
134: if (filtered_value.length - 1 < sorted_errorvalues
135: .size()) {
136: errorvalues = sorted_errorvalues
137: .get(filtered_value.length - 1);
138: } else {
139: errorvalues = null;
140: while (!(filtered_value.length - 1 < sorted_errorvalues
141: .size())) {
142: sorted_errorvalues.add(null);
143: }
144: }
145: if (null == errorvalues) {
146: errorvalues = new ArrayList<String[]>();
147: sorted_errorvalues.set(filtered_value.length - 1,
148: errorvalues);
149: }
150: errorvalues.add(filtered_value);
151: }
152: }
153:
154: // Reorder the filtered error blocks so that they're ordered according
155: // to the number of properties they declare. Those with the same
156: // number of properties will be ordered according to the their order
157: // of declaration.
158: List<String[]> filtered_errorblocks = template
159: .getFilteredBlocks(TAG_ERRORS);
160: ArrayList<List<String[]>> sorted_errorblocks = null;
161: if (filtered_errorblocks.size() > 0) {
162: sorted_errorblocks = new ArrayList<List<String[]>>();
163:
164: List<String[]> errorblocks;
165: for (String[] filtered_block : filtered_errorblocks) {
166: if (filtered_block.length - 1 < sorted_errorblocks
167: .size()) {
168: errorblocks = sorted_errorblocks
169: .get(filtered_block.length - 1);
170: } else {
171: errorblocks = null;
172: while (!(filtered_block.length - 1 < sorted_errorblocks
173: .size())) {
174: sorted_errorblocks.add(null);
175: }
176: }
177: if (null == errorblocks) {
178: errorblocks = new ArrayList<String[]>();
179: sorted_errorblocks.set(filtered_block.length - 1,
180: errorblocks);
181: }
182: errorblocks.add(filtered_block);
183: }
184: }
185:
186: // Re-arrange the filtered blocks to be able to easily select the
187: // block id that corresponds to an error value.
188: // The block have been sorted so that the most specific one
189: // (less properties) is considered before a more general one
190: // (more properties). When they have the same specificity they
191: // are processed according to their order of declaration.
192: // A block id with 'property1' will thus gain precedence
193: // over a block id with 'property1,property2', but when only the
194: // latter is defined it will be used even if either property
195: // has an error individually.
196: LinkedHashMap<String, ArrayList<String>> block_properties_mapping = null;
197: if (sorted_errorblocks != null) {
198: block_properties_mapping = new LinkedHashMap<String, ArrayList<String>>();
199:
200: ArrayList<String> block_properties;
201:
202: for (List<String[]> categorized_errorblocks : sorted_errorblocks) {
203: if (null == categorized_errorblocks) {
204: continue;
205: }
206:
207: for (String[] filtered_block : categorized_errorblocks) {
208: block_properties = new ArrayList<String>();
209: block_properties_mapping.put(filtered_block[0],
210: block_properties);
211:
212: for (int i = 1; i < filtered_block.length; i++) {
213: block_properties.add(filtered_block[i]);
214: }
215: }
216: }
217: }
218:
219: Collection<String> invalid_subjects = collectSubjects(errors,
220: prefix);
221:
222: // Go over the error values according to their order of importance.
223: // Values with a broader scope (more properties) get precedence of
224: // those with a narrower scope (less properties) and inside the
225: // same scope level they are handled according to their order
226: // of declaration.
227: // For each value that is used to report errors in, an internal
228: // construction variable is created. It is there that the error
229: // messages will be appended.
230: // The formatting block that corresponds best to the used value
231: // is also determined and stored for later retrieval during
232: // the template construction.
233: HashMap<String, InternalValue> values_construction = null;
234: HashMap<String, String> property_value_mapping = null;
235: HashMap<String, String> values_block_mapping = null;
236: if (filtered_errorvalues.size() > 0) {
237: values_construction = new HashMap<String, InternalValue>();
238: property_value_mapping = new HashMap<String, String>();
239: values_block_mapping = new HashMap<String, String>();
240:
241: List<String[]> errorvalues;
242:
243: for (int i = sorted_errorvalues.size() - 1; i >= 0; i--) {
244: errorvalues = sorted_errorvalues.get(i);
245: if (null == errorvalues) {
246: continue;
247: }
248:
249: for (String[] filtered_value : errorvalues) {
250: // check if the filtered value contains only subjects
251: // that are invalid
252: boolean use_value = true;
253: for (int j = 1; j < filtered_value.length; j++) {
254: if (!invalid_subjects
255: .contains(filtered_value[j])) {
256: use_value = false;
257: break;
258: }
259: }
260:
261: // If the value can be used, register its id for
262: // all the declared subjects. If the subject is already
263: // bound to another value, it is simply skipped.
264: if (use_value) {
265: boolean tied_to_properties = false;
266: for (int j = 1; j < filtered_value.length; j++) {
267: if (!property_value_mapping
268: .containsKey(filtered_value[j])) {
269: property_value_mapping.put(
270: filtered_value[j],
271: filtered_value[0]);
272: tied_to_properties = true;
273: }
274: }
275:
276: if (tied_to_properties) {
277: // prepare an internal value to construct the value
278: values_construction.put(filtered_value[0],
279: template.createInternalValue());
280:
281: // go over all the error blocks until one is found that supports the
282: // same properties as the value
283: ArrayList<String> error_block_properties;
284: if (block_properties_mapping != null) {
285: for (Map.Entry<String, ArrayList<String>> error_block : block_properties_mapping
286: .entrySet()) {
287: boolean matching_block = true;
288:
289: error_block_properties = error_block
290: .getValue();
291: for (int j = 1; j < filtered_value.length; j++) {
292: if (!error_block_properties
293: .contains(filtered_value[j])) {
294: matching_block = false;
295: break;
296: }
297: }
298:
299: if (matching_block) {
300: values_block_mapping.put(
301: filtered_value[0],
302: error_block.getKey());
303: break;
304: }
305: }
306: }
307: }
308: }
309: }
310: }
311: }
312:
313: // Process the sorted error message blocks so that for each
314: // property the first occuring block will be used.
315: List<String[]> filtered_errormessages = template
316: .getFilteredBlocks(TAG_ERRORMESSAGE);
317: HashMap<String, String> property_errormessages_mapping = null;
318: if (filtered_errormessages.size() > 0) {
319: property_errormessages_mapping = new HashMap<String, String>();
320:
321: for (String[] filtered_errormessage : filtered_errormessages) {
322: for (int i = 1; i < filtered_errormessage.length; i++) {
323: if (property_errormessages_mapping
324: .containsKey(filtered_errormessage[i])) {
325: continue;
326: }
327:
328: property_errormessages_mapping.put(
329: filtered_errormessage[i],
330: filtered_errormessage[0]);
331: }
332: }
333: }
334:
335: // Go over all the validation errors and format them according to
336: // their subject.
337: String property_value;
338: InternalValue value_construction;
339: String subject;
340: for (ValidationError error : errors) {
341: subject = error.getSubject();
342: if (prefix != null) {
343: subject = prefix + subject;
344: }
345:
346: // get the value where the error has to be displayed
347: if (property_value_mapping != null) {
348: property_value = property_value_mapping.get(subject);
349: } else {
350: property_value = null;
351: }
352:
353: if (property_value != null) {
354: value_construction = values_construction
355: .get(property_value);
356:
357: // generate the error message
358: generateErrorMessage(template, error, prefix,
359: value_construction,
360: property_errormessages_mapping);
361: } else if (has_fallback_errors_value) {
362: // generate the error message
363: generateErrorMessage(template, error, prefix,
364: fallback_errors_construction,
365: property_errormessages_mapping);
366: }
367: }
368:
369: // Now that all the values have been constructed, go over
370: // the corresponding blocks to format the content.
371: if (values_construction != null) {
372: for (Map.Entry<String, InternalValue> property_value_id : values_construction
373: .entrySet()) {
374: if (values_block_mapping != null
375: && values_block_mapping
376: .containsKey(property_value_id.getKey())) {
377: template.setValue(ID_ERRORS, property_value_id
378: .getValue());
379: template.setBlock(property_value_id.getKey(),
380: values_block_mapping.get(property_value_id
381: .getKey()));
382: template.removeValue(ID_ERRORS);
383: } else if (has_wildcard_errors_block) {
384: template.setValue(ID_ERRORS, property_value_id
385: .getValue());
386: template.setBlock(property_value_id.getKey(),
387: ID_ERRORS_WILDCARD);
388: template.removeValue(ID_ERRORS);
389: } else {
390: template.setValue(property_value_id.getKey(),
391: property_value_id.getValue());
392: }
393:
394: set_values.add(property_value_id.getKey());
395: }
396: }
397:
398: // Set the global errors value content.
399: if (fallback_errors_construction != null
400: && !fallback_errors_construction.isEmpty()) {
401: if (has_fallback_errors_block) {
402: template.setValue(ID_ERRORS,
403: fallback_errors_construction);
404: template.setBlock(ID_ERRORS_WILDCARD,
405: ID_ERRORS_FALLBACK);
406: template.removeValue(ID_ERRORS);
407: } else if (has_wildcard_errors_block) {
408: template.setValue(ID_ERRORS,
409: fallback_errors_construction);
410: template.setBlock(ID_ERRORS_WILDCARD,
411: ID_ERRORS_WILDCARD);
412: template.removeValue(ID_ERRORS);
413: } else {
414: template.setValue(ID_ERRORS_WILDCARD,
415: fallback_errors_construction);
416: }
417:
418: set_values.add(ID_ERRORS_WILDCARD);
419: }
420:
421: return set_values;
422: }
423:
424: private Collection<String> collectSubjects(
425: Collection<ValidationError> errors, String prefix) {
426: // Collect the invalid subjects in a seperate collection which
427: // only contains their name.
428: ArrayList<String> invalid_subjects = new ArrayList<String>();
429: String subject;
430: for (ValidationError error : errors) {
431: subject = error.getSubject();
432: if (prefix != null) {
433: subject = prefix + subject;
434: }
435: if (!invalid_subjects.contains(error.getSubject())) {
436: invalid_subjects.add(subject);
437: }
438: }
439:
440: return invalid_subjects;
441: }
442:
443: private String generateErrorBlockId(ValidationError error,
444: String prefix) {
445: StringBuilder result = new StringBuilder(error.getIdentifier());
446: result.append(":");
447: if (prefix != null) {
448: result.append(prefix);
449: }
450: result.append(error.getSubject());
451: return result.toString();
452: }
453:
454: private String generateFallbackSubjectBlockId(
455: ValidationError error, String prefix) {
456: StringBuilder result = new StringBuilder(PREFIX_ERROR);
457: if (prefix != null) {
458: result.append(prefix);
459: }
460: result.append(error.getSubject());
461: return result.toString();
462: }
463:
464: private String generateFallbackIdentifierBlockId(
465: ValidationError error) {
466: StringBuilder result = new StringBuilder(error.getIdentifier());
467: result.append(":*");
468: return result.toString();
469: }
470:
471: private void generateErrorMessage(Template template,
472: ValidationError error, String prefix,
473: InternalValue valueConstruction,
474: HashMap<String, String> errormessagesMapping)
475: throws TemplateException {
476: // try to obtain the id of a block that formats each error message
477: // for the provided error
478: String errormessage_block_id = null;
479: String subject = error.getSubject();
480: if (prefix != null) {
481: subject = prefix + subject;
482: }
483:
484: if (errormessagesMapping != null) {
485: errormessage_block_id = errormessagesMapping.get(subject);
486: }
487:
488: if (null == errormessage_block_id
489: && template.hasBlock(ID_ERRORMESSAGE_WILDCARD)) {
490: errormessage_block_id = ID_ERRORMESSAGE_WILDCARD;
491: }
492:
493: // if a custom error message formatting block was found, set the
494: // actual error message and append the formatted result to the
495: // error construction
496: if (errormessage_block_id != null) {
497: if (template.hasValueId(ID_ERRORMESSAGE)) {
498: String errorblock_id = generateErrorBlockId(error,
499: prefix);
500: // support the IDENTIFIER:subject block id
501: if (template.hasBlock(errorblock_id)) {
502: template.setBlock(ID_ERRORMESSAGE, errorblock_id);
503: } else {
504: String fallback_subject_errorblock_id = generateFallbackSubjectBlockId(
505: error, prefix);
506: // support the ERROR:subject block id
507: if (template
508: .hasBlock(fallback_subject_errorblock_id)) {
509: template.setBlock(ID_ERRORMESSAGE,
510: fallback_subject_errorblock_id);
511: } else {
512: // support the IDENTIFIER:* block id
513: String fallback_identifier_errorblock_id = generateFallbackIdentifierBlockId(error);
514: if (template
515: .hasBlock(fallback_identifier_errorblock_id)) {
516: template.setBlock(ID_ERRORMESSAGE,
517: fallback_identifier_errorblock_id);
518: } else {
519: // support the ERROR:* block id
520: if (template.hasBlock(ID_ERROR_WILDCARD)) {
521: template.setBlock(ID_ERRORMESSAGE,
522: ID_ERROR_WILDCARD);
523: } else {
524: // just output an IDENTIFIER:subject string
525: template.setValue(ID_ERRORMESSAGE,
526: errorblock_id);
527: }
528: }
529: }
530: }
531:
532: valueConstruction.appendBlock(errormessage_block_id);
533: template.removeValue(ID_ERRORMESSAGE);
534: } else {
535: valueConstruction.appendBlock(errormessage_block_id);
536: }
537: }
538: // append a generic error message to the error construction
539: else {
540: String error_value_id = generateErrorBlockId(error, prefix);
541: if (template.hasBlock(error_value_id)) {
542: valueConstruction.appendBlock(error_value_id);
543: } else {
544: String errorblock_id = generateErrorBlockId(error,
545: prefix);
546: // support the IDENTIFIER:subject block id
547: if (template.hasBlock(errorblock_id)) {
548: valueConstruction.appendBlock(errorblock_id);
549: } else {
550: String fallback_subject_errorblock_id = generateFallbackSubjectBlockId(
551: error, prefix);
552: // support the ERROR:subject block id
553: if (template
554: .hasBlock(fallback_subject_errorblock_id)) {
555: valueConstruction
556: .appendBlock(fallback_subject_errorblock_id);
557: } else {
558: // support the IDENTIFIER:* block id
559: String fallback_identifier_errorblock_id = generateFallbackIdentifierBlockId(error);
560: if (template
561: .hasBlock(fallback_identifier_errorblock_id)) {
562: valueConstruction
563: .appendBlock(fallback_identifier_errorblock_id);
564: } else {
565: // support the ERROR:* block id
566: if (template.hasBlock(ID_ERROR_WILDCARD)) {
567: valueConstruction
568: .appendBlock(ID_ERROR_WILDCARD);
569: } else {
570: // just output an IDENTIFIER:subject string
571: valueConstruction
572: .appendValue(formatLine(errorblock_id));
573: }
574: }
575: }
576: }
577: }
578: }
579: }
580:
581: protected abstract String formatLine(String content);
582:
583: public Collection<String> generateErrorMarkings(Template template,
584: Collection<ValidationError> errors,
585: Collection<String> onlySubjectsToClear, String prefix)
586: throws ValidationBuilderException {
587: if (null == template || null == errors || 0 == errors.size()) {
588: return Collections.EMPTY_LIST;
589: }
590:
591: ArrayList<String> set_values = new ArrayList<String>();
592:
593: // adapt for subject prefixes
594: if (prefix != null && onlySubjectsToClear != null) {
595: ArrayList<String> prefixed_subjects = new ArrayList<String>();
596: for (String property : onlySubjectsToClear) {
597: prefixed_subjects.add(prefix + property);
598: }
599: onlySubjectsToClear = prefixed_subjects;
600: }
601:
602: // Reorder the filtered mark so that they're ordered according
603: // to the number of subjects they declare for each mark extension.
604: // Those with the same number of subjects will be ordered according
605: // to the their order of declaration.
606: // Also, all the content from the filtered marks will be cleared to
607: // ensure that errors from previous submissions will not prevail.
608: List<String[]> filtered_marks = template
609: .getFilteredValues(TAG_MARK);
610: HashMap<String, ArrayList<List<String[]>>> sorted_marks_map = null;
611: if (filtered_marks.size() > 0) {
612: sorted_marks_map = new HashMap<String, ArrayList<List<String[]>>>();
613:
614: ArrayList<List<String[]>> sorted_marks;
615: List<String[]> marks;
616: for (String[] filtered_mark : filtered_marks) {
617: // only clear the filtered mark if one of the subjects is
618: // validated
619: if (null == onlySubjectsToClear) {
620: template.removeValue(filtered_mark[0]);
621: } else {
622: for (int i = 1; i < filtered_mark.length; i++) {
623: if (onlySubjectsToClear
624: .contains(filtered_mark[i])) {
625: template.removeValue(filtered_mark[0]);
626: break;
627: }
628: }
629: }
630:
631: // get the sorted marks for the specific mark extension
632: sorted_marks = sorted_marks_map.get(filtered_mark[1]);
633: // or create a new collection if it doesn't exist yet
634: if (null == sorted_marks) {
635: sorted_marks = new ArrayList<List<String[]>>();
636: sorted_marks_map
637: .put(filtered_mark[1], sorted_marks);
638: }
639:
640: // setup the collection of marks with the same number of
641: // properties and create a new one if that's needed
642: int number_of_properties = (filtered_mark.length - 2) / 2;
643: if (number_of_properties < sorted_marks.size()) {
644: marks = sorted_marks.get(number_of_properties);
645: } else {
646: marks = null;
647: while (!(number_of_properties < sorted_marks.size())) {
648: sorted_marks.add(null);
649: }
650: }
651: if (null == marks) {
652: marks = new ArrayList<String[]>();
653: sorted_marks.set(number_of_properties, marks);
654: }
655:
656: // add the filtered mark to the collection of all marks with
657: // the same number of properties
658: marks.add(filtered_mark);
659: }
660: }
661:
662: Collection<String> invalid_subjects = collectSubjects(errors,
663: prefix);
664:
665: // Go over the mark extensions according to their order of importance.
666: // Marks with a broader scope (more properties) get precedence of
667: // those with a narrower scope (less properties) and inside the
668: // same scope level they are handled according to their order
669: // of declaration.
670: if (sorted_marks_map != null) {
671: for (Map.Entry<String, ArrayList<List<String[]>>> sorted_marks_entry : sorted_marks_map
672: .entrySet()) {
673: String mark_block_id;
674: String mark_extension = sorted_marks_entry.getKey();
675: if (null == mark_extension) {
676: mark_block_id = PREFIX_MARK_ERROR;
677: } else {
678: StringBuilder buffer = new StringBuilder(
679: PREFIX_MARK_ERROR);
680: buffer.append(":");
681: buffer.append(mark_extension);
682: mark_block_id = buffer.toString();
683: }
684:
685: HashMap<String, String> property_mark_mapping = new HashMap<String, String>();
686:
687: ArrayList<List<String[]>> sorted_marks = sorted_marks_entry
688: .getValue();
689: List<String[]> marks;
690: for (int i = sorted_marks.size() - 1; i >= 0; i--) {
691: marks = sorted_marks.get(i);
692: if (null == marks) {
693: continue;
694: }
695:
696: for (String[] filtered_mark : marks) {
697: // check if the filtered mark contains only subjects
698: // that are invalid
699: boolean use_mark = true;
700: for (int j = 2; j < filtered_mark.length; j += 2) {
701: if (!invalid_subjects
702: .contains(filtered_mark[j])) {
703: use_mark = false;
704: break;
705: }
706: }
707:
708: // If the mark can be used, register its id for
709: // all the declared subjects. If the subject is already
710: // bound to another value, it is simply skipped.
711: if (use_mark) {
712: boolean tied_to_properties = false;
713: for (int j = 2; j < filtered_mark.length; j += 2) {
714: if (!property_mark_mapping
715: .containsKey(filtered_mark[j])) {
716: property_mark_mapping.put(
717: filtered_mark[j],
718: filtered_mark[0]);
719: tied_to_properties = true;
720: }
721: }
722:
723: if (tied_to_properties) {
724: if (!template.hasBlock(mark_block_id)) {
725: throw new MissingMarkingBlockException(
726: mark_block_id);
727: }
728:
729: template.setBlock(filtered_mark[0],
730: mark_block_id);
731: set_values.add(filtered_mark[0]);
732: }
733: }
734: }
735: }
736: }
737: }
738:
739: return set_values;
740: }
741:
742: public void removeValidationErrors(Template template,
743: Collection<String> subjects, String prefix) {
744: if (null == template) {
745: return;
746: }
747:
748: if (null == subjects || 0 == subjects.size()) {
749: return;
750: }
751:
752: if (template.hasValueId(ID_ERRORS_WILDCARD)) {
753: template.removeValue(ID_ERRORS_WILDCARD);
754: }
755:
756: if (prefix != null) {
757: ArrayList<String> prefixed_subjects = new ArrayList<String>();
758: for (String property : subjects) {
759: prefixed_subjects.add(prefix + property);
760: }
761: subjects = prefixed_subjects;
762: }
763:
764: List<String[]> filtered_errorvalues = template
765: .getFilteredValues(TAG_ERRORS);
766: if (filtered_errorvalues.size() > 0) {
767: for (String[] filtered_value : filtered_errorvalues) {
768: for (int i = 1; i < filtered_value.length; i++) {
769: if (subjects.contains(filtered_value[i])) {
770: template.removeValue(filtered_value[0]);
771: break;
772: }
773: }
774: }
775: }
776: }
777:
778: public void removeErrorMarkings(Template template,
779: Collection<String> subjects, String prefix) {
780: if (null == template) {
781: return;
782: }
783:
784: if (null == subjects || 0 == subjects.size()) {
785: return;
786: }
787:
788: if (prefix != null) {
789: ArrayList<String> prefixed_subjects = new ArrayList<String>();
790: for (String property : subjects) {
791: prefixed_subjects.add(prefix + property);
792: }
793: subjects = prefixed_subjects;
794: }
795:
796: List<String[]> filtered_marks = template
797: .getFilteredValues(TAG_MARK);
798: if (filtered_marks.size() > 0) {
799: for (String[] filtered_mark : filtered_marks) {
800: for (int i = 2; i < filtered_mark.length; i += 2) {
801: if (subjects.contains(filtered_mark[i])) {
802: template.removeValue(filtered_mark[0]);
803: break;
804: }
805: }
806: }
807: }
808: }
809:
810: public Object clone() {
811: try {
812: return super .clone();
813: } catch (CloneNotSupportedException e) {
814: ///CLOVER:OFF
815: // this should never happen
816: Logger.getLogger("com.uwyn.rife.site").severe(
817: ExceptionUtils.getExceptionStackTrace(e));
818: return null;
819: ///CLOVER:ON
820: }
821: }
822: }
|