KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > outerj > daisy > frontend > KeySetParser


1 /*
2  * Copyright 2004 Outerthought bvba and Schaubroeck nv
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.outerj.daisy.frontend;
17
18 import org.outerj.daisy.repository.*;
19 import org.outerj.daisy.repository.variant.*;
20 import org.outerj.daisy.emailnotifier.CollectionSubscriptionKey;
21 import org.apache.cocoon.forms.formmodel.Widget;
22 import org.apache.cocoon.forms.util.I18nMessage;
23 import org.apache.cocoon.forms.validation.ValidationErrorAware;
24 import org.apache.cocoon.forms.validation.ValidationError;
25 import org.apache.cocoon.forms.validation.WidgetValidator;
26 import org.apache.excalibur.xml.sax.XMLizable;
27
28 import java.util.HashSet JavaDoc;
29 import java.util.Set JavaDoc;
30 import java.util.regex.Matcher JavaDoc;
31 import java.util.regex.Pattern JavaDoc;
32 import java.io.LineNumberReader JavaDoc;
33 import java.io.StringReader JavaDoc;
34 import java.io.IOException JavaDoc;
35
36 /**
37  * This class provides utility methods for creating widget validators and parsing input for
38  * a specific type of input whereby the entered data consists of lines following an
39  * "item,branch,language" pattern. Since the same algorithm is needed in slightly different
40  * ways on different locations, this class generalises all the use cases to avoid code duplication.
41  */

42 public class KeySetParser {
43     private static final Pattern JavaDoc LINE_PATTERN = Pattern.compile("([^,#]+)(\\s*,\\s*([a-zA-Z\\-_0-9*]+)(\\s*,\\s*([a-zA-Z\\-_0-9*]+)))\\s*(#.*)?");
44     private static final Pattern JavaDoc LINE_PATTERN_VARIANT_OPTIONAL = Pattern.compile("([^,#]+)(\\s*,\\s*([a-zA-Z\\-_0-9*]+)(\\s*,\\s*([a-zA-Z\\-_0-9*]+))?)?\\s*(#.*)?");
45
46     /**
47      *
48      * @param allowWildcards if true, then each of the components on a line can be a star (*). In this case
49      * branch and language must be specified, while if this parameter is false branch
50      * and language do not have to be specified and 1 will be taken as default. An input
51      * of * will be translated to -1 when parsing.
52      * @param needAtLeastOne at least one entry is needed, otherwise an error will be raised
53      */

54     public static VariantKey[] parseVariantKeys(String JavaDoc input, VariantManager variantManager, boolean allowWildcards, boolean needAtLeastOne) throws Exception JavaDoc {
55         input = input == null ? "" : input;
56         Set JavaDoc keys = (Set JavaDoc)processInput(input, variantManager, false, new VariantsCustomiser(), "Unexpected error in variants list: ", allowWildcards, needAtLeastOne);
57         return (VariantKey[])keys.toArray(new VariantKey[keys.size()]);
58     }
59
60     public static CollectionSubscriptionKey[] parseCollectionKeys(String JavaDoc input, Repository repository) throws Exception JavaDoc {
61         input = input == null ? "" : input;
62         Set JavaDoc keys = (Set JavaDoc)processInput(input, repository.getVariantManager(), false, new CollectionsCustomiser(repository.getCollectionManager()), "Unexpected error in collection subscription list: ", true, false);
63         return (CollectionSubscriptionKey[])keys.toArray(new CollectionSubscriptionKey[keys.size()]);
64     }
65     
66     public static WidgetValidator getVariantKeysWidgetValidator(VariantManager variantManager, boolean allowWildcards, boolean needAtLeastOne) {
67         return new KeyListValidator(variantManager, new VariantsCustomiser(), allowWildcards, needAtLeastOne);
68     }
69
70     public static WidgetValidator getCollectionSubscriptionKeysWidgetValidator(Repository repository, boolean allowWildcards, boolean needAtLeastOne) {
71         return new KeyListValidator(repository.getVariantManager(),
72                 new CollectionsCustomiser(repository.getCollectionManager()), allowWildcards, needAtLeastOne);
73     }
74
75     /**
76      * Abstraction so that the same algorithm is usable for document IDs
77      * and collection IDs.
78      */

79     private interface KeySetParserCustomiser {
80         long parseItem(String JavaDoc value) throws Exception JavaDoc;
81
82         XMLizable validateItem(String JavaDoc value, long lineNumber) throws Exception JavaDoc;
83
84         Object JavaDoc instantiateObject(long item, long branchId, long languageId);
85     }
86
87     private static class VariantsCustomiser implements KeySetParserCustomiser {
88         public long parseItem(String JavaDoc value) throws Exception JavaDoc {
89             try {
90                 return Long.parseLong(value);
91             } catch (NumberFormatException JavaDoc e) {
92                 throw new Exception JavaDoc("invalid document ID.");
93             }
94         }
95
96         public XMLizable validateItem(String JavaDoc value, long lineNumber) {
97             try {
98                 Long.parseLong(value);
99                 return null;
100             } catch (NumberFormatException JavaDoc e) {
101                 return new I18nMessage("keylist.invalid-docid", new String JavaDoc[] { String.valueOf(lineNumber)});
102             }
103         }
104
105         public Object JavaDoc instantiateObject(long item, long branchId, long languageId) {
106             return new VariantKey(item, branchId, languageId);
107         }
108     }
109
110     private static class CollectionsCustomiser implements KeySetParserCustomiser {
111         private final CollectionManager collectionManager;
112
113         public CollectionsCustomiser(CollectionManager collectionManager) {
114             this.collectionManager = collectionManager;
115         }
116
117         public long parseItem(String JavaDoc value) throws Exception JavaDoc {
118             return collectionManager.getCollection(value, false).getId();
119         }
120
121         public XMLizable validateItem(String JavaDoc value, long lineNumber) {
122             try {
123                 collectionManager.getCollection(value, false).getId();
124                 return null;
125             } catch (CollectionNotFoundException e) {
126                 return new I18nMessage("keylist.collection-does-not-exist", new String JavaDoc[] { String.valueOf(lineNumber)});
127             } catch (RepositoryException e) {
128                 return new I18nMessage("keylist.collection-retrieval-error", new String JavaDoc[] { String.valueOf(lineNumber), e.toString()});
129             }
130         }
131
132         public Object JavaDoc instantiateObject(long item, long branchId, long languageId) {
133             return new CollectionSubscriptionKey(item, branchId, languageId);
134         }
135     }
136
137     /**
138      *
139      * @param allowWildcards if true, '*' is allowed instead of IDs or names (-1 will be put in the resulting ID),
140      * and in this case there will also be no variant defaulting (i.e. all 3 parts on each
141      * line are required)
142      */

143     private static Object JavaDoc processInput(String JavaDoc input, VariantManager variantManager, boolean validateMode,
144             KeySetParserCustomiser customiser, String JavaDoc exceptionPrefix, boolean allowWildcards,
145             boolean needsAtLeastOneEntry) throws Exception JavaDoc {
146         
147         LineNumberReader JavaDoc reader = new LineNumberReader JavaDoc(new StringReader JavaDoc(input));
148
149         // the following variables are for when we're working in validate mode
150
XMLizable error = null;
151         boolean hasLines = false;
152         // the following variable is for when we're working in parse mode
153
HashSet JavaDoc keys = validateMode ? null : new HashSet JavaDoc();
154
155         String JavaDoc line;
156         try {
157             while ((line = reader.readLine()) != null) {
158                 line = line.trim();
159                 if (line.length() > 0 && !(line.charAt(0) == '#')) {
160                     Pattern JavaDoc pattern = allowWildcards ? LINE_PATTERN : LINE_PATTERN_VARIANT_OPTIONAL;
161                     Matcher JavaDoc matcher = pattern.matcher(line);
162                     if (!matcher.matches()) {
163                         if (validateMode) {
164                             error = new I18nMessage("keylist.entry-invalid", new String JavaDoc[] { String.valueOf(reader.getLineNumber())});
165                             break;
166                         } else {
167                             throw new Exception JavaDoc(exceptionPrefix + "entry on line " + reader.getLineNumber() + " is not in the correct format.");
168                         }
169                     } else {
170                         long itemId = -1;
171                         String JavaDoc itemString = matcher.group(1);
172                         if (!(allowWildcards && itemString.equals("*"))) {
173                             if (validateMode) {
174                                 error = customiser.validateItem(matcher.group(1), reader.getLineNumber());
175                                 if (error != null)
176                                     break;
177                             } else {
178                                 try {
179                                     itemId = customiser.parseItem(matcher.group(1));
180                                 } catch (Exception JavaDoc e) {
181                                     throw new Exception JavaDoc(exceptionPrefix + "entry on line " + reader.getLineNumber() + " is not valid: " + e.toString());
182                                 }
183                             }
184                         }
185                         long branchId = allowWildcards ? -1 : Branch.MAIN_BRANCH_ID;
186                         long languageId = allowWildcards ? -1 : Language.DEFAULT_LANGUAGE_ID;
187                         String JavaDoc branch = matcher.group(3);
188                         if (!(allowWildcards && branch.equals("*"))) {
189                             if (branch != null) {
190                                 try {
191                                     branchId = variantManager.getBranch(branch, false).getId();
192                                 } catch (BranchNotFoundException e) {
193                                     if (validateMode) {
194                                         error = new I18nMessage("keylist.branch-does-not-exist", new String JavaDoc[] { String.valueOf(reader.getLineNumber())});
195                                         break;
196                                     } else {
197                                         throw new Exception JavaDoc(exceptionPrefix + "branch specified on line " + reader.getLineNumber() + " does not exist.");
198                                     }
199                                 } catch (RepositoryException e) {
200                                     if (validateMode) {
201                                         error = new I18nMessage("keylist.branch-retrieval-error", new String JavaDoc[] { String.valueOf(reader.getLineNumber()), e.getMessage()});
202                                         break;
203                                     } else {
204                                         throw new Exception JavaDoc(exceptionPrefix + "problem getting branch specified on line " + reader.getLineNumber() + ": " + e.getMessage());
205                                     }
206                                 }
207                             }
208                         }
209                         String JavaDoc language = matcher.group(5);
210                         if (!(allowWildcards && language.equals("*"))) {
211                             if (language != null) {
212                                 try {
213                                     languageId = variantManager.getLanguage(language, false).getId();
214                                 } catch (LanguageNotFoundException e) {
215                                     if (validateMode) {
216                                         error = new I18nMessage("keylist.lang-does-not-exist", new String JavaDoc[] { String.valueOf(reader.getLineNumber())});
217                                         break;
218                                     } else {
219                                         throw new Exception JavaDoc(exceptionPrefix + "language specified on line " + reader.getLineNumber() + " does not exist.");
220                                     }
221                                 } catch (RepositoryException e) {
222                                     if (validateMode) {
223                                         error = new I18nMessage("keylist.lang-retrieval-error", new String JavaDoc[] { String.valueOf(reader.getLineNumber()), e.getMessage()});
224                                         break;
225                                     } else {
226                                         throw new Exception JavaDoc(exceptionPrefix + "problem getting language specified on line " + reader.getLineNumber() + ": " + e.getMessage());
227                                     }
228                                 }
229                             }
230                         }
231                         if (validateMode) {
232                             if (!hasLines)
233                                 hasLines = true;
234                         } else {
235                             keys.add(customiser.instantiateObject(itemId, branchId, languageId));
236                         }
237                     }
238                 }
239             }
240         } catch (IOException JavaDoc e) {
241             throw new Exception JavaDoc(exceptionPrefix + "highly unexpected IOException.", e);
242         }
243
244         if (validateMode) {
245             if (error == null && !hasLines && needsAtLeastOneEntry)
246                 error = new I18nMessage("keylist.need-at-least-one-entry");
247
248             return error;
249         } else {
250             return keys;
251         }
252     }
253     
254     private static class KeyListValidator implements WidgetValidator {
255         private final VariantManager variantManager;
256         private final KeySetParserCustomiser customiser;
257         private final boolean allowWildcards;
258         private final boolean needAtLeastOne;
259
260         public KeyListValidator(VariantManager variantManager, KeySetParserCustomiser customiser, boolean allowWildcards,
261                 boolean needAtLeastOne) {
262             this.variantManager = variantManager;
263             this.customiser = customiser;
264             this.allowWildcards = allowWildcards;
265             this.needAtLeastOne = needAtLeastOne;
266         }
267         
268         public boolean validate(Widget widget) {
269             String JavaDoc input = (String JavaDoc)widget.getValue();
270             if (input != null) {
271                 XMLizable error = null;
272                 try {
273                     error = (XMLizable)processInput(input, variantManager, true, customiser, null, allowWildcards, needAtLeastOne);
274                 } catch (Exception JavaDoc e) {
275                     throw new RuntimeException JavaDoc("Unexpected error during keylist validation: " + e.toString(), e);
276                 }
277                 if (error != null) {
278                     ((ValidationErrorAware)widget).setValidationError(new ValidationError(error));
279                     return false;
280                 }
281             }
282             return true;
283         }
284     }
285 }
286
Popular Tags