Source Code Cross Referenced for DefaultMaskFactory.java in  » Development » ivatamasks » com » ivata » mask » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » ivatamasks » com.ivata.mask 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2001 - 2005 ivata limited.
0003:         * All rights reserved.
0004:         * -----------------------------------------------------------------------------
0005:         * ivata masks may be redistributed under the GNU General Public
0006:         * License as published by the Free Software Foundation;
0007:         * version 2 of the License.
0008:         *
0009:         * These programs are free software; you can redistribute them and/or
0010:         * modify them under the terms of the GNU General Public License
0011:         * as published by the Free Software Foundation; version 2 of the License.
0012:         *
0013:         * These programs are distributed in the hope that they will be useful,
0014:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
0016:         *
0017:         * See the GNU General Public License in the file LICENSE.txt for more
0018:         * details.
0019:         *
0020:         * If you would like a copy of the GNU General Public License write to
0021:         *
0022:         * Free Software Foundation, Inc.
0023:         * 59 Temple Place - Suite 330
0024:         * Boston, MA 02111-1307, USA.
0025:         *
0026:         *
0027:         * To arrange commercial support and licensing, contact ivata at
0028:         *                  http://www.ivata.com/contact.jsp
0029:         * -----------------------------------------------------------------------------
0030:         * $Log: DefaultMaskFactory.java,v $
0031:         * Revision 1.15  2005/10/12 18:20:54  colinmacleod
0032:         * Fixed some style issues.
0033:         *
0034:         * Revision 1.14  2005/10/11 18:55:29  colinmacleod
0035:         * Fixed some checkstyle and javadoc issues.
0036:         *
0037:         * Revision 1.13  2005/10/03 10:17:24  colinmacleod
0038:         * Fixed some style and javadoc issues.
0039:         *
0040:         * Revision 1.12  2005/10/02 14:06:32  colinmacleod
0041:         * Added/improved log4j logging.
0042:         *
0043:         * Revision 1.11  2005/09/29 12:11:56  colinmacleod
0044:         * Added checking that the class referenced is available - throws a warning
0045:         * if not, but carries on working (makes it easier to re-use a common
0046:         * settings file).
0047:         *
0048:         * Revision 1.10  2005/09/16 13:41:18  colinmacleod
0049:         * Created new convertor class to handle timestamps.
0050:         *
0051:         * Revision 1.9  2005/09/14 12:51:22  colinmacleod
0052:         * Added serialVersionUID.
0053:         * Changed XPath expression for choice.
0054:         *
0055:         * Revision 1.8  2005/04/11 12:27:02  colinmacleod
0056:         * Added preliminary support for filters.
0057:         * Added FieldValueConvertor factor interface
0058:         * to split off value convertors for reuse.
0059:         *
0060:         * Revision 1.7  2005/04/09 18:04:14  colinmacleod
0061:         * Changed copyright text to GPL v2 explicitly.
0062:         *
0063:         * Revision 1.6  2005/03/10 10:25:56  colinmacleod
0064:         * Added getClass() method with defaulted name.
0065:         *
0066:         * Revision 1.5  2005/01/19 12:39:39  colinmacleod
0067:         * Changed Id --> Name.
0068:         *
0069:         * Revision 1.4  2005/01/07 13:08:24  colinmacleod
0070:         * Fixed default input and list masks - they were both
0071:         * still returning a hard-coded string.
0072:         *
0073:         * Revision 1.3  2005/01/06 22:13:21  colinmacleod
0074:         * Moved up a version number.
0075:         * Changed copyright notices to 2005.
0076:         * Updated the documentation:
0077:         *   - started working on multiproject:site docu.
0078:         *   - changed the logo.
0079:         * Added checkstyle and fixed LOADS of style issues.
0080:         * Added separate thirdparty subproject.
0081:         * Added struts (in web), util and webgui (in webtheme) from ivata op.
0082:         *
0083:         * Revision 1.2  2004/12/30 20:13:12  colinmacleod
0084:         * Added reflection to let you override the field writer classes used.
0085:         *
0086:         * Revision 1.1  2004/12/29 20:07:06  colinmacleod
0087:         * Renamed subproject masks to mask.
0088:         *
0089:         * Revision 1.3  2004/12/29 15:27:06  colinmacleod
0090:         * Added methods to get default input/list masks.
0091:         * Removed final to allow overrides to change default masks.
0092:         *
0093:         * Revision 1.2  2004/11/11 13:34:22  colinmacleod
0094:         * Added addDefaultFields method.
0095:         *
0096:         * Revision 1.1.1.1  2004/05/16 20:40:31  colinmacleod
0097:         * Ready for 0.1 release
0098:         * -----------------------------------------------------------------------------
0099:         */
0100:        package com.ivata.mask;
0101:
0102:        import java.beans.PropertyDescriptor;
0103:        import java.io.IOException;
0104:        import java.io.InputStream;
0105:        import java.io.Serializable;
0106:        import java.math.BigDecimal;
0107:        import java.sql.Timestamp;
0108:        import java.util.ArrayList;
0109:        import java.util.Date;
0110:        import java.util.HashMap;
0111:        import java.util.Iterator;
0112:        import java.util.List;
0113:        import java.util.Map;
0114:        import java.util.Properties;
0115:
0116:        import org.apache.commons.beanutils.PropertyUtils;
0117:        import org.apache.log4j.Logger;
0118:        import org.dom4j.Document;
0119:        import org.dom4j.DocumentException;
0120:        import org.dom4j.Element;
0121:        import org.dom4j.io.SAXReader;
0122:        import org.xml.sax.InputSource;
0123:
0124:        import com.ivata.mask.field.Field;
0125:        import com.ivata.mask.field.FieldImpl;
0126:        import com.ivata.mask.field.FieldValueConvertor;
0127:        import com.ivata.mask.field.FieldValueConvertorFactory;
0128:        import com.ivata.mask.filter.Filter;
0129:        import com.ivata.mask.filter.FilterImpl;
0130:        import com.ivata.mask.group.Group;
0131:        import com.ivata.mask.group.GroupImpl;
0132:        import com.ivata.mask.util.StringHandling;
0133:        import com.ivata.mask.util.SystemException;
0134:
0135:        /**
0136:         * <p>
0137:         * This factory class is at the heart of ivata masks. Use it to read in a
0138:         * configuration file (in XML), and then access groups of fields via their
0139:         * unique identifiers.
0140:         * </p>
0141:         *
0142:         * <p>
0143:         * It is called <code>DefaultMaskFactory</code> because the <strong>ivata
0144:         * masks </strong> system actually never refers to this class directly - it uses
0145:         * the interface {@link MaskFactory}, meaning you could create your own factory
0146:         * implementation, if you want to.
0147:         * </p>
0148:         *
0149:         * @author Colin MacLeod
0150:         * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
0151:         * @since ivata masks 0.1 (2004-02-26)
0152:         */
0153:        public final class DefaultMaskFactory implements  MaskFactory,
0154:                Serializable {
0155:            /**
0156:             * Logger for this class.
0157:             */
0158:            private static final Logger logger = Logger
0159:                    .getLogger(DefaultMaskFactory.class);
0160:
0161:            /**
0162:             * Serialization version (for <code>Serializable</code> interface).
0163:             */
0164:            private static final long serialVersionUID = 1L;
0165:            /**
0166:             * <p>
0167:             * The name of the default mask/screen used for user input.
0168:             * </p>
0169:             */
0170:            private String defaultInputMask;
0171:            /**
0172:             * <p>
0173:             * The name of the default mask/screen used to list.
0174:             * </p>
0175:             */
0176:            private String defaultListMask;
0177:            /**
0178:             * Used to create convertors to convert field values in the filters.
0179:             */
0180:            private FieldValueConvertorFactory fieldValueConvertorFactory;
0181:            /**
0182:             * Mapping of all config groups, mapped by identifier.
0183:             */
0184:            private Map groups;
0185:
0186:            /**
0187:             * <p>
0188:             * Default constructor. Initializes the mask factory with
0189:             * &quot;inputMask&quot; as the default input mask, and
0190:             * &quot;inputMask&quot; as the default list mask.
0191:             * </p>
0192:             * @param fieldValueConvertorFactoryParam creates convertors to convert
0193:             * field values in the filters.
0194:             */
0195:            public DefaultMaskFactory(
0196:                    final FieldValueConvertorFactory fieldValueConvertorFactoryParam) {
0197:                this ("inputMask", "listMask", fieldValueConvertorFactoryParam);
0198:            }
0199:
0200:            /**
0201:             * <p>
0202:             * Construct an instance of the factory with the default mask/screens
0203:             * provided.
0204:             * </p>
0205:             *
0206:             * @param defaultInputMaskParam
0207:             *            The name of the default mask/screen used for user input.
0208:             * @param defaultListMaskParam
0209:             *            The name of the default mask/screen used to list.
0210:             * @param fieldValueConvertorFactoryParam creates convertors to convert
0211:             * field values in the filters.
0212:             */
0213:            public DefaultMaskFactory(
0214:                    final String defaultInputMaskParam,
0215:                    final String defaultListMaskParam,
0216:                    final FieldValueConvertorFactory fieldValueConvertorFactoryParam) {
0217:                this .defaultInputMask = defaultInputMaskParam;
0218:                this .defaultListMask = defaultListMaskParam;
0219:                this .fieldValueConvertorFactory = fieldValueConvertorFactoryParam;
0220:            }
0221:
0222:            /**
0223:             * <p>
0224:             * Go thro' all the properties of the value object class and add fields for
0225:             * those properties which were not explicitly defined in the configuration
0226:             * file.
0227:             * </p>
0228:             *
0229:             * @param mask
0230:             *            Mask for which to add all the default fields
0231:             * @param parentField
0232:             *            If this mask applies to a field within another mask, (known as
0233:             *            a submask) this is the field to which it applies, otherwise
0234:             *            <code>null</code>.
0235:             */
0236:            private void addDefaultFields(final MaskImpl mask,
0237:                    final Field parentField) {
0238:                if (logger.isDebugEnabled()) {
0239:                    logger.debug("addDefaultFields(MaskImpl mask = " + mask
0240:                            + ", Field parentField = " + parentField
0241:                            + ") - start");
0242:                }
0243:
0244:                Class dOClass = mask.getDOClass();
0245:                PropertyDescriptor[] descriptors = PropertyUtils
0246:                        .getPropertyDescriptors(dOClass);
0247:                for (int i = 0; i < descriptors.length; i++) {
0248:                    PropertyDescriptor descriptor = descriptors[i];
0249:                    String fieldName = descriptor.getName();
0250:                    // ignore getClass() from Object
0251:                    if ("class".equals(fieldName)) {
0252:                        continue;
0253:                    }
0254:                    StringBuffer combinedName = new StringBuffer();
0255:                    if (parentField != null) {
0256:                        combinedName.append(parentField.getPath());
0257:                        combinedName.append(".");
0258:                    }
0259:                    combinedName.append(fieldName);
0260:                    if (mask.getField(combinedName.toString()) == null) {
0261:                        FieldImpl field = new FieldImpl(parentField, mask
0262:                                .getField(fieldName), this );
0263:                        field.setName(fieldName);
0264:                        Class fieldClass = descriptor.getPropertyType();
0265:                        // guess the field type
0266:                        if (Timestamp.class.isAssignableFrom(fieldClass)) {
0267:                            field.setType(Field.TYPE_TIMESTAMP);
0268:                        } else if (Date.class.isAssignableFrom(fieldClass)) {
0269:                            field.setType(Field.TYPE_DATE);
0270:                        } else if (BigDecimal.class
0271:                                .isAssignableFrom(fieldClass)
0272:                                || Double.class.isAssignableFrom(fieldClass)) {
0273:                            field.setType(Field.TYPE_AMOUNT);
0274:                        } else if (Integer.class.isAssignableFrom(fieldClass)) {
0275:                            field.setType(Field.TYPE_NUMBER);
0276:                        } else if (String.class.isAssignableFrom(fieldClass)) {
0277:                            field.setType(Field.TYPE_STRING);
0278:                        } else {
0279:                            field.setType(null);
0280:                        }
0281:                        mask.addField(field);
0282:                    }
0283:                }
0284:
0285:                if (logger.isDebugEnabled()) {
0286:                    logger.debug("addDefaultFields(MaskImpl, Field) - end");
0287:                }
0288:            }
0289:
0290:            /**
0291:             * Extract a field from a dom4j element.
0292:             *
0293:             * @param element
0294:             *            dom4j element which represents a field.
0295:             * @param group
0296:             *            group which will contain this field.
0297:             * @return field New field represented by the element provided.
0298:             * TODO: replace NullPointerException thrown here with a mask configuration
0299:             * exception.
0300:             */
0301:            private Field extractField(final Group group, final Element element) {
0302:                if (logger.isDebugEnabled()) {
0303:                    logger.debug("extractField(Group group = " + group
0304:                            + ", Element element = " + element + ") - start");
0305:                }
0306:
0307:                // the field can either extend another one in this group explicitly,
0308:                // or a field in a parent group implicitly
0309:                String extendsField = element.attributeValue("extends");
0310:                String name = element.attributeValue("name");
0311:                if (logger.isDebugEnabled()) {
0312:                    logger.debug("Extracting field '" + name + "'");
0313:                }
0314:                if (name == null) {
0315:                    throw new NullPointerException(
0316:                            "ERROR in mask configuration: "
0317:                                    + "mandatory name attribute null for field.");
0318:                }
0319:                Field extendedField;
0320:                if (extendsField == null) {
0321:                    // look for a field of the same id which already exists in this
0322:                    // group or a parent
0323:                    extendedField = group.getField(name);
0324:                } else {
0325:                    // look for a field with the extended name
0326:                    extendedField = group.getField(extendsField);
0327:                    // in this case, it is an error if the field is <code>null</code>
0328:                    if (extendedField == null) {
0329:                        throw new NullPointerException(
0330:                                "ERROR in mask configuration: " + "field '"
0331:                                        + name + "' extends unknown field '"
0332:                                        + extendsField + "'");
0333:                    }
0334:                }
0335:                FieldImpl field = new FieldImpl(null, extendedField, this );
0336:                field.setName(name);
0337:                String type = element.attributeValue("type");
0338:                field.setType(type);
0339:
0340:                String displayOnly = element.attributeValue("displayOnly");
0341:                field.setDisplayOnly("true".equalsIgnoreCase(displayOnly));
0342:                String hidden = element.attributeValue("hidden");
0343:                field.setHidden("true".equalsIgnoreCase(hidden));
0344:                String mandatory = element.attributeValue("mandatory");
0345:                field.setMandatory("true".equalsIgnoreCase(mandatory));
0346:                String oneToOne = element.attributeValue("oneToOne");
0347:                field.setOneToOne("true".equalsIgnoreCase(oneToOne));
0348:                String defaultValue = element.attributeValue("default");
0349:                field.setDefaultValue(defaultValue);
0350:                String labelKey = element.attributeValue("labelKey");
0351:                field.setLabelKey(labelKey);
0352:                String className = element.attributeValue("class");
0353:                // if a class name is set, find and set the dependent value object
0354:                if (className != null) {
0355:                    try {
0356:                        Class dOClass = Class.forName(className);
0357:                        field.setDOClass(dOClass);
0358:                    } catch (ClassNotFoundException e) {
0359:                        logger.error("extractField(Group, Element)", e);
0360:
0361:                        throw new RuntimeException("ERROR (" + e.getClass()
0362:                                + ") cannot locate class: " + className + ": "
0363:                                + e.getMessage());
0364:                    }
0365:                }
0366:                List choiceList = element.elements("choice");
0367:                Properties choiceProperties = field.getChoiceProperties();
0368:                if (choiceList.size() > 0) {
0369:                    choiceProperties = new Properties();
0370:                    List choicePropertyKeys = new ArrayList();
0371:                    for (Iterator iterator = choiceList.iterator(); iterator
0372:                            .hasNext();) {
0373:                        Element choice = (Element) iterator.next();
0374:                        String key = choice.attributeValue("value");
0375:                        String text = choice.getText();
0376:                        if (key == null) {
0377:                            key = text;
0378:                        }
0379:                        choiceProperties.setProperty(key, text);
0380:                        choicePropertyKeys.add(key);
0381:                    }
0382:                    field.setChoiceProperties(choiceProperties);
0383:                    field.setChoicePropertyKeys(choicePropertyKeys);
0384:                }
0385:                // for select or radio types, there must either be a value object class
0386:                if (("select".equals(type) || "radio".equals(type))
0387:                        && (className == null) && (choiceProperties == null)) {
0388:                    throw new RuntimeException(
0389:                            "ERROR in mask configuration: "
0390:                                    + "you must specify either choices or value object class for "
0391:                                    + "field " + type + ", name '" + name + "'");
0392:                }
0393:
0394:                if (logger.isDebugEnabled()) {
0395:                    logger
0396:                            .debug("extractField(Group, Element) - end - return value = "
0397:                                    + field);
0398:                }
0399:                return field;
0400:            }
0401:
0402:            /**
0403:             * Extract a single filter from the group provided.
0404:             *
0405:             * @param groupParam parent group surrounding the filter.
0406:             * @param element the document element from which to extract the filter.
0407:             * @return the extracted filter, represented by the XML in the
0408:             * <code>element</code>.
0409:             */
0410:            private Filter extractFilter(final Group groupParam,
0411:                    final Element element) {
0412:                if (logger.isDebugEnabled()) {
0413:                    logger.debug("extractFilter(Group groupParam = "
0414:                            + groupParam + ", Element element = " + element
0415:                            + ") - start");
0416:                }
0417:
0418:                String propertyName = element.attributeValue("propertyName");
0419:                String stringValue = element.attributeValue("value");
0420:                String className = element.attributeValue("propertyClass");
0421:                if (logger.isDebugEnabled()) {
0422:                    logger.debug("Extracting filter on property '"
0423:                            + propertyName + "' for value '" + stringValue
0424:                            + "'");
0425:                }
0426:                Class propertyClass;
0427:                try {
0428:                    propertyClass = Class.forName(className);
0429:                } catch (ClassNotFoundException e) {
0430:                    logger.error("extractFilter(Group, Element)", e);
0431:
0432:                    throw new RuntimeException(e);
0433:                }
0434:                FieldValueConvertor convertor;
0435:                try {
0436:                    convertor = fieldValueConvertorFactory
0437:                            .getFieldValueConvertorForClass(propertyClass);
0438:                } catch (SystemException e) {
0439:                    logger.error("extractFilter(Group, Element)", e);
0440:
0441:                    throw new RuntimeException(e);
0442:                }
0443:                Object value = convertor.convertFromString(propertyClass,
0444:                        stringValue);
0445:                Filter returnFilter = new FilterImpl(propertyName,
0446:                        propertyClass, value);
0447:                if (logger.isDebugEnabled()) {
0448:                    logger.debug("extractFilter - end - return value = "
0449:                            + returnFilter);
0450:                }
0451:                return returnFilter;
0452:            }
0453:
0454:            /**
0455:             * Extracts a single group from the element provided.
0456:             *
0457:             * @param element
0458:             *            The document element from which to extract the group.
0459:             * @return New group represented by the XML in <code>element</code>.
0460:             * TODO: replace NullPointerException thrown here with a mask configuration
0461:             * exception.
0462:             */
0463:            private Group extractGroup(final Element element) {
0464:                if (logger.isDebugEnabled()) {
0465:                    logger.debug("extractGroup(Element element = " + element
0466:                            + ") - start");
0467:                }
0468:
0469:                // the group can extend another one explicitly
0470:                String extendsGroup = element.attributeValue("extends");
0471:                String name = element.attributeValue("name");
0472:                if (logger.isDebugEnabled()) {
0473:                    logger.debug("Extracting group '" + name + "'");
0474:                }
0475:                if (StringHandling.isNullOrEmpty(name)) {
0476:                    throw new NullPointerException(
0477:                            "ERROR in mask configuration: "
0478:                                    + "mandatory name attribute null for group.");
0479:                }
0480:                Group parent = null;
0481:                if (extendsGroup != null) {
0482:                    parent = (Group) groups.get(extendsGroup);
0483:                    if (parent == null) {
0484:                        throw new NullPointerException(
0485:                                "ERROR in mask configuration: " + "group '"
0486:                                        + name + "' extends unknown group '"
0487:                                        + extendsGroup + "'");
0488:                    }
0489:                }
0490:                GroupImpl group = new GroupImpl(name, parent);
0491:                // groups contain field definitions and masks - first the fields
0492:                extractGroupFields(element, group);
0493:                // now extract the masks
0494:                for (Iterator i = element.elementIterator("mask"); i.hasNext();) {
0495:                    Element maskElement = (Element) i.next();
0496:                    Mask mask = extractMask(group, maskElement);
0497:                    // if the class is unavailable, don't create the mask
0498:                    if (mask != null) {
0499:                        String maskId = getMaskId(mask.getDOClass().getName(),
0500:                                mask.getName());
0501:                        groups.put(maskId, mask);
0502:                    }
0503:                }
0504:
0505:                if (logger.isDebugEnabled()) {
0506:                    logger
0507:                            .debug("extractGroup(Element) - end - return value = "
0508:                                    + group);
0509:                }
0510:                return group;
0511:            }
0512:
0513:            /**
0514:             * This section is used by both <code>extractMask</code> and
0515:             * <code>extractGroup</code>.
0516:             *
0517:             * @param element
0518:             *            dom4j element to extract the information from.
0519:             * @param group
0520:             *            group or mask to set the information into.
0521:             */
0522:            private void extractGroupFields(final Element element,
0523:                    final GroupImpl group) {
0524:                if (logger.isDebugEnabled()) {
0525:                    logger.debug("extractGroupFields(Element element = "
0526:                            + element + ", GroupImpl group = " + group
0527:                            + ") - start");
0528:                }
0529:
0530:                for (Iterator i = element.elementIterator("field"); i.hasNext();) {
0531:                    Element fieldElement = (Element) i.next();
0532:                    Field field = extractField(group, fieldElement);
0533:                    group.addField(field);
0534:                }
0535:                // find excluded fields
0536:                Element exclude = element.element("exclude");
0537:                if (exclude != null) {
0538:                    for (Iterator iter = exclude.elementIterator("fieldName"); iter
0539:                            .hasNext();) {
0540:                        Element fieldNameElement = (Element) iter.next();
0541:                        group.addExcludedFieldName(fieldNameElement
0542:                                .getTextTrim());
0543:                    }
0544:                }
0545:                // find included fields
0546:                Element include = element.element("include");
0547:                if (include != null) {
0548:                    for (Iterator iter = include.elementIterator("fieldName"); iter
0549:                            .hasNext();) {
0550:                        Element fieldNameElement = (Element) iter.next();
0551:                        group.addIncludedFieldName(fieldNameElement
0552:                                .getTextTrim());
0553:                    }
0554:                }
0555:                // if this group is marked display only, note that
0556:                String displayOnly = element.attributeValue("displayOnly");
0557:                if (displayOnly != null) {
0558:                    group.setDisplayOnly("true".equals(displayOnly));
0559:                }
0560:                // find fields at start and end
0561:                Element first = element.element("first");
0562:                if (first != null) {
0563:                    for (Iterator iter = first.elementIterator("fieldName"); iter
0564:                            .hasNext();) {
0565:                        Element fieldNameElement = (Element) iter.next();
0566:                        group.addFirstFieldName(fieldNameElement.getText());
0567:                    }
0568:                }
0569:                Element last = element.element("last");
0570:                if (last != null) {
0571:                    for (Iterator iter = last.elementIterator("fieldName"); iter
0572:                            .hasNext();) {
0573:                        Element fieldNameElement = (Element) iter.next();
0574:                        group.addLastFieldName(fieldNameElement.getText());
0575:                    }
0576:                }
0577:                // filters
0578:                for (Iterator i = element.elementIterator("filter"); i
0579:                        .hasNext();) {
0580:                    Element filterElement = (Element) i.next();
0581:                    Filter filter = extractFilter(group, filterElement);
0582:                    group.addFilter(filter);
0583:                }
0584:
0585:                if (logger.isDebugEnabled()) {
0586:                    logger
0587:                            .debug("extractGroupFields(Element, GroupImpl) - end");
0588:                }
0589:            }
0590:
0591:            /**
0592:             * Extracts a single mask from the mask element provided.
0593:             *
0594:             * @param group
0595:             *            The parent group surrounding the mask.
0596:             * @param element
0597:             *            The document element from which to extract the mask.
0598:             * @return New mask represented by the XML in <code>element</code>.
0599:             * TODO: replace NullPointerException thrown here with a mask configuration
0600:             * exception.
0601:             */
0602:            private Mask extractMask(final Group group, final Element element) {
0603:                if (logger.isDebugEnabled()) {
0604:                    logger.debug("extractMask(Group group = " + group
0605:                            + ", Element element = " + element + ") - start");
0606:                }
0607:
0608:                String name = element.attributeValue("name");
0609:                if (logger.isDebugEnabled()) {
0610:                    logger.debug("Extracting mask '" + name + "'");
0611:                }
0612:                String className = element.attributeValue("valueObject");
0613:                // you must always supply a class name for a mask
0614:                if (className == null) {
0615:                    throw new NullPointerException(
0616:                            "ERROR in mask configuration: "
0617:                                    + "mandatory 'valueObject' attribute null for mask'"
0618:                                    + name + "'.");
0619:                }
0620:                // now get the dependent value object class
0621:                Class dOClass;
0622:                try {
0623:                    dOClass = Class.forName(className);
0624:                } catch (ClassNotFoundException e) {
0625:                    String message = "Cannot locate class specified in ivata masks: "
0626:                            + className;
0627:                    logger.error(message, e);
0628:                    throw new RuntimeException(message, e);
0629:                }
0630:                // the mask can extend another one explicitly, or a containing group
0631:                // implicitly
0632:                String extendsMask = element.attributeValue("extends");
0633:                Group parent = null;
0634:                if (extendsMask != null) {
0635:                    // first try extends as a reference to another mask..
0636:                    String id = getMaskId(className, extendsMask);
0637:                    parent = (Group) groups.get(id);
0638:                    // if there is no mask with this combination, look for a group with
0639:                    // the extended name
0640:                    if (parent == null) {
0641:                        parent = (Group) groups.get(extendsMask);
0642:                        if (parent == null) {
0643:                            throw new NullPointerException(
0644:                                    "ERROR in mask configuration: mask '"
0645:                                            + name + "' (value object '"
0646:                                            + className
0647:                                            + "') extends unknown mask/group '"
0648:                                            + extendsMask + "'");
0649:                        }
0650:                    }
0651:                } else {
0652:                    // if there is no explicit extends, it extends from the parent
0653:                    // group around it
0654:                    parent = group;
0655:                }
0656:                MaskImpl mask = new MaskImpl(dOClass, parent, name);
0657:                // this section is shared with group
0658:                extractGroupFields(element, mask);
0659:                addDefaultFields(mask, null);
0660:
0661:                // extract any include paths
0662:                for (Iterator i = element.elementIterator("include"); i
0663:                        .hasNext();) {
0664:                    Element includeElement = (Element) i.next();
0665:                    String path = includeElement.attributeValue("path");
0666:                    if (StringHandling.isNullOrEmpty(path)) {
0667:                        path = includeElement.getTextTrim();
0668:                    }
0669:                    if (StringHandling.isNullOrEmpty(path)) {
0670:                        throw new NullPointerException(
0671:                                "ERROR in mask configuration: "
0672:                                        + "you must specify either a path or body content "
0673:                                        + "for all includes in mask '"
0674:                                        + mask.getName() + "'.");
0675:                    }
0676:                    mask.addIncludePath(path);
0677:                }
0678:
0679:                if (logger.isDebugEnabled()) {
0680:                    logger
0681:                            .debug("extractMask(Group, Element) - end - return value = "
0682:                                    + mask);
0683:                }
0684:                return mask;
0685:            }
0686:
0687:            /**
0688:             * <p>
0689:             * Get the name of the default mask/screen used for user input.
0690:             * </p>
0691:             *
0692:             * @return name of the default mask/screen used for user input.
0693:             * @see com.ivata.mask.MaskFactory#getDefaultInputMask()
0694:             */
0695:            public String getDefaultInputMask() {
0696:                if (logger.isDebugEnabled()) {
0697:                    logger.debug("getDefaultInputMask() - start");
0698:                }
0699:
0700:                // by default just return the name "inputMask"
0701:
0702:                if (logger.isDebugEnabled()) {
0703:                    logger
0704:                            .debug("getDefaultInputMask() - end - return value = "
0705:                                    + defaultInputMask);
0706:                }
0707:                return defaultInputMask;
0708:            }
0709:
0710:            /**
0711:             * <p>
0712:             * Get the name of the default mask/screen used for lists.
0713:             * </p>
0714:             *
0715:             * @return name of the default mask/screen used for lists.
0716:             * @see com.ivata.mask.MaskFactory#getDefaultListMask()
0717:             */
0718:            public String getDefaultListMask() {
0719:                if (logger.isDebugEnabled()) {
0720:                    logger.debug("getDefaultListMask() - start");
0721:                }
0722:
0723:                // by default just return the name "listMask"
0724:
0725:                if (logger.isDebugEnabled()) {
0726:                    logger.debug("getDefaultListMask() - end - return value = "
0727:                            + defaultListMask);
0728:                }
0729:                return defaultListMask;
0730:            }
0731:
0732:            /**
0733:             * <p>
0734:             * Get a group definition referenced by its id.
0735:             * </p>
0736:             *
0737:             * @param id
0738:             *            unique identifier of the group.
0739:             * @return Group definition with the id provided, or <code>null</code> if
0740:             *         there is no such group.
0741:             */
0742:            public Group getGroup(final String id) {
0743:                if (logger.isDebugEnabled()) {
0744:                    logger.debug("getGroup(String id = " + id + ") - start");
0745:                }
0746:
0747:                if (!isConfigured()) {
0748:                    throw new RuntimeException(
0749:                            "ERROR in MaskFactory: you must first read in configuration"
0750:                                    + " by calling readConfiguration.");
0751:                }
0752:                Group returnGroup = (Group) groups.get(id);
0753:                if (logger.isDebugEnabled()) {
0754:                    logger.debug("getGroup(String) - end - return value = "
0755:                            + returnGroup);
0756:                }
0757:                return returnGroup;
0758:            }
0759:
0760:            /**
0761:             * This will return the <u>default input mask</u> for the class provided.
0762:             * <copyDoc>Refer to {@link MaskFactory#getMask}.</copyDoc>
0763:             *
0764:             * @param valueObjectClassParam
0765:             * <copyDoc>Refer to {@link MaskFactory#getMask}.</copyDoc>
0766:             * @return <copyDoc>Refer to {@link MaskFactory#getMask}.</copyDoc>
0767:             */
0768:            public Mask getMask(final Class valueObjectClassParam) {
0769:                if (logger.isDebugEnabled()) {
0770:                    logger.debug("getMask(Class valueObjectClassParam = "
0771:                            + valueObjectClassParam + ") - start");
0772:                }
0773:
0774:                Mask returnMask = getMask(valueObjectClassParam,
0775:                        getDefaultInputMask());
0776:                if (logger.isDebugEnabled()) {
0777:                    logger.debug("getMask(Class) - end - return value = "
0778:                            + returnMask);
0779:                }
0780:                return returnMask;
0781:            }
0782:
0783:            /**
0784:             * <p>
0785:             * Get a mask, identified by its class and name.
0786:             * </p>
0787:             *
0788:             * @param valueObjectClass
0789:             *            class of value object for the mask to be returned.
0790:             * @param name
0791:             *            optional parameter defining multiple masks for the same value
0792:             *            object. May be <code>null</code>.
0793:             * @return Mask definition with the id provided, or <code>null</code> if
0794:             *         there is no such mask.
0795:             */
0796:            public Mask getMask(final Class valueObjectClass, final String name) {
0797:                if (logger.isDebugEnabled()) {
0798:                    logger.debug("getMask(Class valueObjectClass = "
0799:                            + valueObjectClass + ", String name = " + name
0800:                            + ") - start");
0801:                }
0802:
0803:                Mask returnMask = getMask(null, valueObjectClass, name);
0804:                if (logger.isDebugEnabled()) {
0805:                    logger
0806:                            .debug("getMask(Class, String) - end - return value = "
0807:                                    + returnMask);
0808:                }
0809:                return returnMask;
0810:            }
0811:
0812:            /**
0813:             * <p>
0814:             * This will return the <u>default input mask</u> for the class provided
0815:             * of the sub-classed field.
0816:             * </p>
0817:             *
0818:             * {@inheritDoc}
0819:             *
0820:             * @param parentField {@inheritDoc}
0821:             * @param valueObjectClassParam {@inheritDoc}
0822:             * @return {@inheritDoc}
0823:             */
0824:            public Mask getMask(final Field parentField,
0825:                    final Class valueObjectClassParam) {
0826:                if (logger.isDebugEnabled()) {
0827:                    logger.debug("getMask(Field parentField = " + parentField
0828:                            + ", Class valueObjectClassParam = "
0829:                            + valueObjectClassParam + ") - start");
0830:                }
0831:
0832:                Mask returnMask = getMask(parentField, valueObjectClassParam,
0833:                        getDefaultInputMask());
0834:                if (logger.isDebugEnabled()) {
0835:                    logger
0836:                            .debug("getMask(Field, Class) - end - return value = "
0837:                                    + returnMask);
0838:                }
0839:                return returnMask;
0840:            }
0841:
0842:            /**
0843:             * <p>
0844:             * Get a mask, identified by its class and name.
0845:             * </p>
0846:             *
0847:             * @param parentField
0848:             *            If this mask applies to a field within another mask, (known as
0849:             *            a submask) this is the field to which it applies, otherwise
0850:             *            use the other <code>getMask</code> method.
0851:             * @param valueObjectClass
0852:             *            class of value object for the mask to be returned.
0853:             * @param nameParam
0854:             *            describes this mask uniquely within the value object. (You
0855:             * can have more than one mask for each value object.)
0856:             * @return Mask definition with the id provided, or <code>null</code> if
0857:             *         there is no such mask.
0858:             * TODO: replace NullPointerException thrown here with a mask configuration
0859:             * exception.
0860:             */
0861:            public Mask getMask(final Field parentField,
0862:                    final Class valueObjectClass, final String nameParam) {
0863:                if (logger.isDebugEnabled()) {
0864:                    logger
0865:                            .debug("getMask(Field parentField = " + parentField
0866:                                    + ", Class valueObjectClass = "
0867:                                    + valueObjectClass
0868:                                    + ", String nameParam = " + nameParam
0869:                                    + ") - start");
0870:                }
0871:
0872:                StringBuffer combinedName = new StringBuffer();
0873:                if (parentField != null) {
0874:                    combinedName.append(parentField.getPath());
0875:                    combinedName.append(".");
0876:                }
0877:                combinedName.append(valueObjectClass.getName());
0878:                String id = getMaskId(combinedName.toString(), nameParam);
0879:                Group group = getGroup(id);
0880:                if (group == null) {
0881:                    // first see if there is a mask defined for this field. If so,
0882:                    // we'll extend this one to make the sublist mask
0883:                    String parentId = getMaskId(valueObjectClass.getName(),
0884:                            nameParam);
0885:                    Group parent = getGroup(parentId);
0886:                    // if there is no mask defined, create a default mask from the group
0887:                    if (parent == null) {
0888:                        parent = getGroup(nameParam);
0889:                        if (parent == null) {
0890:                            throw new NullPointerException(
0891:                                    "ERROR: no appropriate mask or group called '"
0892:                                            + nameParam + "' for class '"
0893:                                            + valueObjectClass.getName() + "'.");
0894:                        }
0895:                    }
0896:
0897:                    // if not, create a default mask in the parent group
0898:                    MaskImpl defaultMask = new MaskImpl(valueObjectClass,
0899:                            parent, nameParam);
0900:                    addDefaultFields(defaultMask, parentField);
0901:                    groups.put(combinedName.toString(), defaultMask);
0902:
0903:                    if (logger.isDebugEnabled()) {
0904:                        logger.debug("getMask - end - return value = "
0905:                                + defaultMask);
0906:                    }
0907:                    return defaultMask;
0908:                }
0909:                if (!(group instanceof  Mask)) {
0910:                    throw new RuntimeException("ERROR: the group '" + id
0911:                            + "' does not represent a mask.");
0912:                }
0913:                Mask returnMask = (Mask) group;
0914:                if (logger.isDebugEnabled()) {
0915:                    logger
0916:                            .debug("getMask - end - return value = "
0917:                                    + returnMask);
0918:                }
0919:                return returnMask;
0920:            }
0921:
0922:            /**
0923:             * <p>
0924:             * Create a unique identifier for the mask, based on the class and name.
0925:             * For groups, we use the name alone as unique.
0926:             * </p>
0927:             *
0928:             * @param className
0929:             *            name of the class of value object for the mask to be returned.
0930:             * @param name
0931:             *            describes this mask uniquely within the value object. (You
0932:             * can have more than one mask for each value object.)
0933:             * @return Unique identifier for the mask based on class name and mask name.
0934:             */
0935:            private String getMaskId(final String className, final String name) {
0936:                if (logger.isDebugEnabled()) {
0937:                    logger.debug("getMaskId(String className = " + className
0938:                            + ", String name = " + name + ") - start");
0939:                }
0940:
0941:                if (name == null) {
0942:                    if (logger.isDebugEnabled()) {
0943:                        logger.debug("getMaskId - end - return value = "
0944:                                + className);
0945:                    }
0946:                    return className;
0947:                } else {
0948:                    String returnString = className + "_" + name;
0949:                    if (logger.isDebugEnabled()) {
0950:                        logger.debug("getMaskId - end - return value = "
0951:                                + returnString);
0952:                    }
0953:                    return returnString;
0954:                }
0955:            }
0956:
0957:            /**
0958:             * <p>
0959:             * Discover whether or not this object has been configured.
0960:             * </p>
0961:             *
0962:             * @return <code>true</code> if the object has been configured, otherwise
0963:             *         <code>false</code>.
0964:             * @see com.ivata.mask.MaskFactory#isConfigured()
0965:             */
0966:            public boolean isConfigured() {
0967:                if (logger.isDebugEnabled()) {
0968:                    logger.debug("isConfigured() - start");
0969:                }
0970:
0971:                // if there are no groups, assume it wasn't configured
0972:                boolean returnboolean = groups != null;
0973:                if (logger.isDebugEnabled()) {
0974:                    logger.debug("isConfigured() - end - return value = "
0975:                            + returnboolean);
0976:                }
0977:                return returnboolean;
0978:            }
0979:
0980:            /**
0981:             * <p>
0982:             * Read in the configuration represented by the <strong>dom4j </strong>
0983:             * document provided.
0984:             * </p>
0985:             *
0986:             * @param document
0987:             *            <strong>dom4j </strong> document to read configuration from.
0988:             * @throws IOException
0989:             *             If there is any problem reading from the stream provided.
0990:             */
0991:            private synchronized void readConfiguration(final Document document)
0992:                    throws IOException {
0993:                if (logger.isDebugEnabled()) {
0994:                    logger.debug("readConfiguration(Document document = "
0995:                            + document + ") - start");
0996:                }
0997:
0998:                Element root = document.getRootElement();
0999:                groups = new HashMap();
1000:                for (Iterator i = root.elementIterator("group"); i.hasNext();) {
1001:                    Element groupElement = (Element) i.next();
1002:                    Group group = extractGroup(groupElement);
1003:                    groups.put(group.getName(), group);
1004:                }
1005:
1006:                if (logger.isDebugEnabled()) {
1007:                    logger.debug("readConfiguration(Document) - end");
1008:                }
1009:            }
1010:
1011:            /**
1012:             * Get the configuration represented by the <i>dom4j </i> document provided.
1013:             *
1014:             * @param inputStream
1015:             *            The input stream to read the XML from.
1016:             * @throws IOException
1017:             *             If there is any problem reading from the stream provided.
1018:             */
1019:            public void readConfiguration(final InputStream inputStream)
1020:                    throws IOException {
1021:                if (logger.isDebugEnabled()) {
1022:                    logger.debug("readConfiguration(InputStream inputStream = "
1023:                            + inputStream + ") - start");
1024:                }
1025:
1026:                SAXReader reader = new SAXReader();
1027:                Document document;
1028:                try {
1029:                    InputSource is = new InputSource();
1030:                    is.setByteStream(inputStream);
1031:                    document = reader.read(is);
1032:                } catch (DocumentException e) {
1033:                    logger.error("readConfiguration(InputStream)", e);
1034:
1035:                    e.printStackTrace();
1036:                    throw new IOException("ERROR in MaskConfigurationFactory: "
1037:                            + e.getMessage());
1038:                }
1039:                readConfiguration(document);
1040:
1041:                if (logger.isDebugEnabled()) {
1042:                    logger.debug("readConfiguration(InputStream) - end");
1043:                }
1044:            }
1045:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.