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: Submission.java 3701 2007-03-18 12:24:23Z gbevin $
007: */
008: package com.uwyn.rife.engine;
009:
010: import com.uwyn.rife.engine.exceptions.*;
011: import java.util.*;
012:
013: import com.uwyn.rife.site.Constrained;
014: import com.uwyn.rife.site.ConstrainedUtils;
015: import com.uwyn.rife.site.ValidatedConstrained;
016: import com.uwyn.rife.site.ValidationGroup;
017: import com.uwyn.rife.tools.BeanUtils;
018: import com.uwyn.rife.tools.ExceptionUtils;
019: import com.uwyn.rife.tools.StringUtils;
020: import com.uwyn.rife.tools.exceptions.BeanUtilsException;
021: import java.util.logging.Logger;
022: import java.util.regex.Matcher;
023: import java.util.regex.Pattern;
024: import java.util.regex.PatternSyntaxException;
025:
026: public class Submission implements Cloneable {
027: private String mName = null;
028: private ElementInfo mElementInfo = null;
029: private LinkedHashMap<String, String[]> mParameters = null;
030: private ArrayList<String> mParameterDefaults = null;
031: private ArrayList<Pattern> mParameterRegexps = null;
032: private ArrayList<String> mFiles = null;
033: private ArrayList<Pattern> mFileRegexps = null;
034: private boolean mHasParameterDefaults = false;
035: private ArrayList<BeanDeclaration> mBeans = null;
036: private LinkedHashMap<String, BeanDeclaration> mNamedBeans = null;
037: private Scope mScope = null;
038: private boolean mCancelContinuations = false;
039:
040: Submission() {
041: mParameters = new LinkedHashMap<String, String[]>();
042: mParameterDefaults = new ArrayList<String>();
043: mParameterRegexps = new ArrayList<Pattern>();
044: mFiles = new ArrayList<String>();
045: mFileRegexps = new ArrayList<Pattern>();
046: mBeans = new ArrayList<BeanDeclaration>();
047: mNamedBeans = new LinkedHashMap<String, BeanDeclaration>();
048: mScope = Scope.LOCAL;
049: }
050:
051: void setName(String name) {
052: assert name != null;
053: assert name.length() > 0;
054:
055: mName = name;
056: }
057:
058: public String getName() {
059: return mName;
060: }
061:
062: void setScope(Scope scope) {
063: if (null == scope) {
064: scope = Scope.LOCAL;
065: }
066:
067: mScope = scope;
068: }
069:
070: public Scope getScope() {
071: return mScope;
072: }
073:
074: void setElementInfo(ElementInfo elementInfo) {
075: mElementInfo = elementInfo;
076: }
077:
078: public ElementInfo getElementInfo() {
079: return mElementInfo;
080: }
081:
082: public Collection<String> getParameterNames() {
083: return mParameters.keySet();
084: }
085:
086: public Collection<Pattern> getParameterRegexps() {
087: return mParameterRegexps;
088: }
089:
090: public boolean containsParameter(String name) {
091: assert name != null;
092: assert name.length() > 0;
093:
094: // check if a fixed parameter exists with this name
095: if (mParameters.containsKey(name)) {
096: return true;
097: }
098:
099: // check if the name matches a parameter regular expression
100: if (StringUtils.getMatchingRegexp(name, mParameterRegexps) != null) {
101: return true;
102: }
103:
104: return false;
105: }
106:
107: public boolean hasParameterDefaults() {
108: return mHasParameterDefaults;
109: }
110:
111: public Collection<String> getParameterDefaultNames() {
112: return mParameterDefaults;
113: }
114:
115: public String[] getParameterDefaultValues(String name) {
116: assert name != null;
117: assert name.length() > 0;
118:
119: return mParameters.get(name);
120: }
121:
122: public boolean hasParameterDefaultValues(String name) {
123: assert name != null;
124: assert name.length() > 0;
125:
126: if (mParameters.get(name) != null) {
127: return true;
128: }
129:
130: return false;
131: }
132:
133: public Collection<BeanDeclaration> getBeans() {
134: return mBeans;
135: }
136:
137: public boolean hasNamedBeans() {
138: return mNamedBeans != null && mNamedBeans.size() > 0;
139: }
140:
141: public Collection<String> getBeanNames() {
142: return mNamedBeans.keySet();
143: }
144:
145: public BeanDeclaration getNamedBean(String name)
146: throws EngineException {
147: if (null == name)
148: throw new IllegalArgumentException("name can't be null.");
149: if (0 == name.length())
150: throw new IllegalArgumentException("name can't be empty.");
151:
152: validateBeanName(name);
153:
154: return mNamedBeans.get(name);
155: }
156:
157: public boolean containsNamedBean(String name) {
158: if (null == name)
159: throw new IllegalArgumentException("name can't be null.");
160: if (0 == name.length())
161: throw new IllegalArgumentException("name can't be empty.");
162:
163: return mNamedBeans.containsKey(name);
164: }
165:
166: void validateBeanName(String name) throws EngineException {
167: assert name != null;
168: assert name.length() > 0;
169:
170: if (!containsNamedBean(name)) {
171: throw new NamedSubmissionBeanUnknownException(mElementInfo
172: .getDeclarationName(), mName, name);
173: }
174: }
175:
176: void addParameter(String name, String[] defaultValues)
177: throws EngineException {
178: assert mElementInfo != null;
179: assert name != null;
180: assert name.length() > 0;
181:
182: if (defaultValues != null && 0 == defaultValues.length) {
183: defaultValues = null;
184: }
185:
186: // check if the parameter doesn't exist already
187: if (mParameters.containsKey(name)) {
188: throw new ParameterExistsException(mElementInfo
189: .getDeclarationName(), name, mName);
190: }
191:
192: // check if there's no conflicting input
193: if (mElementInfo.containsInput(name)) {
194: throw new ParameterInputConflictException(mElementInfo
195: .getDeclarationName(), name, mName);
196: }
197:
198: // check if there's no conflicting incookie
199: if (mElementInfo.containsIncookie(name)) {
200: throw new ParameterIncookieConflictException(mElementInfo
201: .getDeclarationName(), name, mName);
202: }
203:
204: // check if there's no conflicting file
205: if (mFiles.contains(name)) {
206: throw new ParameterFileConflictException(mElementInfo
207: .getDeclarationName(), name, mName);
208: }
209:
210: // check if there's no conflicting global var
211: if (mElementInfo.containsGlobalVar(name)) {
212: throw new ParameterGlobalVarConflictException(mElementInfo
213: .getDeclarationName(), name, mName);
214: }
215:
216: // check if there's no conflicting global cookie
217: if (mElementInfo.containsGlobalCookie(name)) {
218: throw new ParameterGlobalCookieConflictException(
219: mElementInfo.getDeclarationName(), name, mName);
220: }
221:
222: // check the parameter regular expressions
223: Matcher match_parameter = StringUtils.getMatchingRegexp(name,
224: mParameterRegexps);
225: if (match_parameter != null) {
226: throw new ParameterParameterRegexpConflictException(
227: mElementInfo.getDeclarationName(), name, mName,
228: match_parameter.pattern().pattern());
229: }
230:
231: // check the file regular expressions
232: Matcher match_file = StringUtils.getMatchingRegexp(name,
233: mFileRegexps);
234: if (match_file != null) {
235: throw new ParameterFileRegexpConflictException(mElementInfo
236: .getDeclarationName(), name, mName, match_file
237: .pattern().pattern());
238: }
239:
240: if (defaultValues != null) {
241: mHasParameterDefaults = true;
242: mParameterDefaults.add(name);
243:
244: if (mElementInfo != null) {
245: mElementInfo.setHasSubmissionDefaults(true);
246: }
247: }
248:
249: mParameters.put(name, defaultValues);
250: }
251:
252: void addParameterRegexp(String pattern) throws EngineException {
253: assert mElementInfo != null;
254: assert pattern != null;
255: assert pattern.length() > 0;
256:
257: if (!pattern.startsWith("^")) {
258: pattern = "^" + pattern;
259: }
260: if (!pattern.endsWith("$")) {
261: pattern = pattern + "$";
262: }
263:
264: Pattern compiled_pattern = null;
265: try {
266: compiled_pattern = Pattern.compile(pattern);
267: } catch (PatternSyntaxException e) {
268: throw new ParameterRegexpInvalidException(mElementInfo
269: .getDeclarationName(), pattern, mName, e);
270: }
271:
272: Matcher matcher = null;
273:
274: // check if there's no conflicting input
275: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
276: .getInputNames(), compiled_pattern)) != null) {
277: throw new ParameterRegexpInputConflictException(
278: mElementInfo.getDeclarationName(), pattern, mName,
279: matcher.group());
280: }
281:
282: // check if there's no conflicting incookie
283: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
284: .getIncookieNames(), compiled_pattern)) != null) {
285: throw new ParameterRegexpIncookieConflictException(
286: mElementInfo.getDeclarationName(), pattern, mName,
287: matcher.group());
288: }
289:
290: // check if there are no parameter conflicts
291: if ((matcher = StringUtils.getRegexpMatch(mParameters.keySet(),
292: compiled_pattern)) != null) {
293: throw new ParameterRegexpParameterConflictException(
294: mElementInfo.getDeclarationName(), pattern, mName,
295: matcher.group());
296: }
297:
298: // check if there's no conflicting file
299: if ((matcher = StringUtils.getRegexpMatch(mFiles,
300: compiled_pattern)) != null) {
301: throw new ParameterRegexpFileConflictException(mElementInfo
302: .getDeclarationName(), pattern, mName, matcher
303: .group());
304: }
305:
306: // check if there's no conflicting global var
307: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
308: .getGlobalVarNames(), compiled_pattern)) != null) {
309: throw new ParameterRegexpGlobalVarConflictException(
310: mElementInfo.getDeclarationName(), pattern, mName,
311: matcher.group());
312: }
313:
314: // check if there's no conflicting global cookie
315: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
316: .getGlobalCookieNames(), compiled_pattern)) != null) {
317: throw new ParameterRegexpGlobalCookieConflictException(
318: mElementInfo.getDeclarationName(), pattern, mName,
319: matcher.group());
320: }
321:
322: mParameterRegexps.add(compiled_pattern);
323: }
324:
325: void addBean(BeanDeclaration bean, String name)
326: throws EngineException {
327: assert bean != null;
328:
329: Class bean_class = null;
330: try {
331: bean_class = bean.getBeanClass();
332: } catch (ClassNotFoundException e) {
333: if (null == name) {
334: throw new SubmissionBeanClassnameErrorException(
335: mElementInfo.getDeclarationName(), mName, bean
336: .getClassname(), e);
337: } else {
338: throw new NamedSubmissionBeanClassnameErrorException(
339: mElementInfo.getDeclarationName(), mName, name,
340: bean.getClassname(), e);
341: }
342: }
343:
344: try {
345:
346: Object instance = bean_class.newInstance();
347: Constrained constrained = ConstrainedUtils
348: .makeConstrainedInstance(instance);
349: Set<String> properties;
350: if (bean.getGroupName() != null) {
351: if (!(instance instanceof ValidatedConstrained)) {
352: if (null == name) {
353: throw new SubmissionBeanGroupRequiresValidatedConstrainedException(
354: mElementInfo.getDeclarationName(),
355: mName, bean.getClassname(), bean
356: .getGroupName());
357: } else {
358: throw new NamedSubmissionBeanGroupRequiresValidatedConstrainedException(
359: mElementInfo.getDeclarationName(),
360: mName, name, bean.getClassname(), bean
361: .getGroupName());
362: }
363: }
364:
365: ValidatedConstrained validation = (ValidatedConstrained) instance;
366: ValidationGroup group = validation.getGroup(bean
367: .getGroupName());
368: if (null == group) {
369: if (null == name) {
370: throw new SubmissionBeanGroupNotFoundException(
371: mElementInfo.getDeclarationName(),
372: mName, bean.getClassname(), bean
373: .getGroupName());
374: } else {
375: throw new NamedSubmissionBeanGroupNotFoundException(
376: mElementInfo.getDeclarationName(),
377: mName, name, bean.getClassname(), bean
378: .getGroupName());
379: }
380: }
381: properties = new LinkedHashSet<String>();
382: if (null == bean.getPrefix()) {
383: properties.addAll(group.getPropertyNames());
384: } else {
385: for (String property_name : (List<String>) group
386: .getPropertyNames()) {
387: properties
388: .add(bean.getPrefix() + property_name);
389: }
390: }
391: } else {
392: properties = BeanUtils.getPropertyNames(bean_class,
393: null, null, bean.getPrefix());
394: }
395:
396: for (String property : properties) {
397: if (ConstrainedUtils.editConstrainedProperty(
398: constrained, property, bean.getPrefix())) {
399: if (ConstrainedUtils.fileConstrainedProperty(
400: constrained, property, bean.getPrefix())) {
401: if (!containsFile(property)) {
402: addFile(property);
403: }
404: } else {
405: if (!containsParameter(property)) {
406: addParameter(property, null);
407: }
408: }
409: }
410: }
411: } catch (IllegalAccessException e) {
412: if (null == name) {
413: throw new SubmissionBeanPropertiesErrorException(
414: mElementInfo.getDeclarationName(), mName, bean
415: .getClassname(), e);
416: } else {
417: throw new NamedSubmissionBeanPropertiesErrorException(
418: mElementInfo.getDeclarationName(), mName, name,
419: bean.getClassname(), e);
420: }
421: } catch (InstantiationException e) {
422: if (null == name) {
423: throw new SubmissionBeanPropertiesErrorException(
424: mElementInfo.getDeclarationName(), mName, bean
425: .getClassname(), e);
426: } else {
427: throw new NamedSubmissionBeanPropertiesErrorException(
428: mElementInfo.getDeclarationName(), mName, name,
429: bean.getClassname(), e);
430: }
431: } catch (BeanUtilsException e) {
432: if (null == name) {
433: throw new SubmissionBeanPropertiesErrorException(
434: mElementInfo.getDeclarationName(), mName, bean
435: .getClassname(), e);
436: } else {
437: throw new NamedSubmissionBeanPropertiesErrorException(
438: mElementInfo.getDeclarationName(), mName, name,
439: bean.getClassname(), e);
440: }
441: }
442:
443: if (name != null) {
444: if (mNamedBeans.containsKey(name)) {
445: throw new NamedSubmissionBeanExistsException(
446: mElementInfo.getDeclarationName(), mName, name);
447: }
448:
449: mNamedBeans.put(name, bean);
450: }
451: mBeans.add(bean);
452: }
453:
454: void addFile(String name) throws EngineException {
455: assert name != null;
456: assert name.length() > 0;
457:
458: // check if the file doesn't exist already
459: if (mFiles.contains(name)) {
460: throw new FileExistsException(mElementInfo
461: .getDeclarationName(), name, mName);
462: }
463:
464: // check if there's no conflicting input
465: if (mElementInfo.containsInput(name)) {
466: throw new FileInputConflictException(mElementInfo
467: .getDeclarationName(), name, mName);
468: }
469:
470: // check if there's no conflicting incookie
471: if (mElementInfo.containsIncookie(name)) {
472: throw new FileIncookieConflictException(mElementInfo
473: .getDeclarationName(), name, mName);
474: }
475:
476: // check if there's no conflicting parameter
477: if (mParameters.containsKey(name)) {
478: throw new FileParameterConflictException(mElementInfo
479: .getDeclarationName(), name, mName);
480: }
481:
482: // check if there's no conflicting global var
483: if (mElementInfo.containsGlobalVar(name)) {
484: throw new FileGlobalVarConflictException(mElementInfo
485: .getDeclarationName(), name, mName);
486: }
487:
488: // check if there's no conflicting global cookie
489: if (mElementInfo.containsGlobalCookie(name)) {
490: throw new FileGlobalCookieConflictException(mElementInfo
491: .getDeclarationName(), name, mName);
492: }
493:
494: // check the parameter regular expressions
495: Matcher match_parameter = StringUtils.getMatchingRegexp(name,
496: mParameterRegexps);
497: if (match_parameter != null) {
498: throw new FileParameterRegexpConflictException(mElementInfo
499: .getDeclarationName(), name, mName, match_parameter
500: .pattern().pattern());
501: }
502:
503: // check the file regular expressions
504: Matcher match_file = StringUtils.getMatchingRegexp(name,
505: mFileRegexps);
506: if (match_file != null) {
507: throw new FileFileRegexpConflictException(mElementInfo
508: .getDeclarationName(), name, mName, match_file
509: .pattern().pattern());
510: }
511:
512: mFiles.add(name);
513: }
514:
515: void addFileRegexp(String pattern) throws EngineException {
516: assert mElementInfo != null;
517: assert pattern != null;
518: assert pattern.length() > 0;
519:
520: if (!pattern.startsWith("^")) {
521: pattern = "^" + pattern;
522: }
523: if (!pattern.endsWith("$")) {
524: pattern = pattern + "$";
525: }
526:
527: Pattern compiled_pattern = null;
528: try {
529: compiled_pattern = Pattern.compile(pattern);
530: } catch (PatternSyntaxException e) {
531: throw new FileRegexpInvalidException(mElementInfo
532: .getDeclarationName(), pattern, mName, e);
533: }
534:
535: Matcher matcher = null;
536:
537: // check if there's no conflicting input
538: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
539: .getInputNames(), compiled_pattern)) != null) {
540: throw new FileRegexpInputConflictException(mElementInfo
541: .getDeclarationName(), pattern, mName, matcher
542: .group());
543: }
544:
545: // check if there's no conflicting incookie
546: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
547: .getIncookieNames(), compiled_pattern)) != null) {
548: throw new FileRegexpIncookieConflictException(mElementInfo
549: .getDeclarationName(), pattern, mName, matcher
550: .group());
551: }
552:
553: // check if there are no parameter conflicts
554: if ((matcher = StringUtils.getRegexpMatch(mParameters.keySet(),
555: compiled_pattern)) != null) {
556: throw new FileRegexpParameterConflictException(mElementInfo
557: .getDeclarationName(), pattern, mName, matcher
558: .group());
559: }
560:
561: // check if there's no conflicting file
562: if ((matcher = StringUtils.getRegexpMatch(mFiles,
563: compiled_pattern)) != null) {
564: throw new FileRegexpFileConflictException(mElementInfo
565: .getDeclarationName(), pattern, mName, matcher
566: .group());
567: }
568:
569: // check if there's no conflicting global var
570: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
571: .getGlobalVarNames(), compiled_pattern)) != null) {
572: throw new FileRegexpGlobalVarConflictException(mElementInfo
573: .getDeclarationName(), pattern, mName, matcher
574: .group());
575: }
576:
577: // check if there's no conflicting global cookie
578: if ((matcher = StringUtils.getRegexpMatch(mElementInfo
579: .getGlobalCookieNames(), compiled_pattern)) != null) {
580: throw new FileRegexpGlobalCookieConflictException(
581: mElementInfo.getDeclarationName(), pattern, mName,
582: matcher.group());
583: }
584:
585: mFileRegexps.add(compiled_pattern);
586: }
587:
588: public boolean hasFiles() {
589: return mFiles != null && mFiles.size() > 0;
590: }
591:
592: public Collection<String> getFileNames() {
593: return mFiles;
594: }
595:
596: public Collection<Pattern> getFileRegexps() {
597: return mFileRegexps;
598: }
599:
600: public boolean containsFile(String name) {
601: assert name != null;
602: assert name.length() > 0;
603:
604: // check if a fixed file exists with this name
605: if (mFiles.contains(name)) {
606: return true;
607: }
608:
609: // check if the name matches a file regular expression
610: if (StringUtils.getMatchingRegexp(name, mFileRegexps) != null) {
611: return true;
612: }
613:
614: return false;
615: }
616:
617: public void setCancelContinuations(boolean cancelContinuations) {
618: mCancelContinuations = cancelContinuations;
619: }
620:
621: public boolean getCancelContinuations() {
622: return mCancelContinuations;
623: }
624:
625: public synchronized Submission clone() {
626: Submission new_submission = null;
627: try {
628: new_submission = (Submission) super .clone();
629: } catch (CloneNotSupportedException e) {
630: // this should never happen
631: Logger.getLogger("com.uwyn.rife.engine").severe(
632: ExceptionUtils.getExceptionStackTrace(e));
633: }
634:
635: new_submission.mElementInfo = null;
636:
637: if (mParameters != null) {
638: new_submission.mParameters = new LinkedHashMap<String, String[]>(
639: mParameters);
640: }
641: if (mParameterRegexps != null) {
642: new_submission.mParameterRegexps = new ArrayList<Pattern>(
643: mParameterRegexps);
644: }
645: if (mFiles != null) {
646: new_submission.mFiles = new ArrayList<String>(mFiles);
647: }
648: if (mFileRegexps != null) {
649: new_submission.mFileRegexps = new ArrayList<Pattern>(
650: mFileRegexps);
651: }
652: if (mBeans != null) {
653: new_submission.mBeans = new ArrayList<BeanDeclaration>(
654: mBeans);
655: }
656: if (mNamedBeans != null) {
657: new_submission.mNamedBeans = new LinkedHashMap<String, BeanDeclaration>(
658: mNamedBeans);
659: }
660:
661: return new_submission;
662: }
663: }
|