001    package org.apache.commons.digester3.binder;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import static org.w3c.dom.Node.ATTRIBUTE_NODE;
023    import static org.w3c.dom.Node.CDATA_SECTION_NODE;
024    import static org.w3c.dom.Node.COMMENT_NODE;
025    import static org.w3c.dom.Node.DOCUMENT_FRAGMENT_NODE;
026    import static org.w3c.dom.Node.DOCUMENT_NODE;
027    import static org.w3c.dom.Node.DOCUMENT_TYPE_NODE;
028    import static org.w3c.dom.Node.ELEMENT_NODE;
029    import static org.w3c.dom.Node.ENTITY_NODE;
030    import static org.w3c.dom.Node.ENTITY_REFERENCE_NODE;
031    import static org.w3c.dom.Node.NOTATION_NODE;
032    import static org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE;
033    import static org.w3c.dom.Node.TEXT_NODE;
034    
035    import javax.xml.parsers.DocumentBuilder;
036    import javax.xml.parsers.ParserConfigurationException;
037    
038    import org.apache.commons.digester3.NodeCreateRule;
039    
040    /**
041     * Builder chained when invoking {@link LinkedRuleBuilder#createNode()}.
042     *
043     * @since 3.0
044     */
045    public final class NodeCreateRuleProvider
046        extends AbstractBackToLinkedRuleBuilder<NodeCreateRule>
047    {
048    
049        private NodeType nodeType = NodeType.ELEMENT;
050    
051        private DocumentBuilder documentBuilder;
052    
053        NodeCreateRuleProvider( String keyPattern, String namespaceURI, RulesBinder mainBinder,
054                                LinkedRuleBuilder mainBuilder )
055        {
056            super( keyPattern, namespaceURI, mainBinder, mainBuilder );
057        }
058    
059        /**
060         * {@link NodeCreateRule} instance will be created either a DOM {@link org.w3c.dom.Element Element}
061         * or a DOM {@link org.w3c.dom.DocumentFragment DocumentFragment}, depending on the value of the
062         * <code>nodeType</code> parameter.
063         *
064         * @param nodeType the type of node to create, which can be either
065         *                 {@link org.w3c.dom.Node#ELEMENT_NODE Node.ELEMENT_NODE} or
066         *                 {@link org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE Node.DOCUMENT_FRAGMENT_NODE}
067         * @return this builder instance
068         */
069        public NodeCreateRuleProvider ofType( NodeType nodeType )
070        {
071            if ( nodeType == null )
072            {
073                reportError( "createNode().ofType( NodeType )", "Null NodeType not allowed" );
074            }
075    
076            this.nodeType = nodeType;
077            return this;
078        }
079    
080        /**
081         * {@link NodeCreateRule} instance will be created a DOM {@link org.w3c.dom.Element Element}, but
082         * lets users specify the JAXP <code>DocumentBuilder</code> that should be used when constructing the node tree.
083         *
084         * @param documentBuilder the JAXP <code>DocumentBuilder</code> to use
085         * @return this builder instance
086         */
087        public NodeCreateRuleProvider usingDocumentBuilder( DocumentBuilder documentBuilder )
088        {
089            this.documentBuilder = documentBuilder;
090            return this;
091        }
092    
093        /**
094         * {@inheritDoc}
095         */
096        @Override
097        protected NodeCreateRule createRule()
098        {
099            if ( documentBuilder == null )
100            {
101                try
102                {
103                    return new NodeCreateRule( nodeType.getDocumentType() );
104                }
105                catch ( ParserConfigurationException e )
106                {
107                    throw new RuntimeException( e );
108                }
109            }
110    
111            return new NodeCreateRule( nodeType.getDocumentType(), documentBuilder );
112        }
113    
114        /**
115         * Enumeration that wraps admitted {@link org.w3c.dom.Node} node constants.
116         */
117        public enum NodeType
118        {
119    
120            /**
121             * @see org.w3c.dom.Node#ATTRIBUTE_NODE
122             */
123            ATTRIBUTE( ATTRIBUTE_NODE ),
124            /**
125             * @see org.w3c.dom.Node#CDATA_SECTION_NODE
126             */
127            CDATA( CDATA_SECTION_NODE ),
128            /**
129             * @see org.w3c.dom.Node#COMMENT_NODE
130             */
131            COMMENT( COMMENT_NODE ),
132            /**
133             * @see org.w3c.dom.Node#DOCUMENT_FRAGMENT_NODE
134             */
135            DOCUMENT_FRAGMENT( DOCUMENT_FRAGMENT_NODE ),
136            /**
137             * @see org.w3c.dom.Node#DOCUMENT_NODE
138             */
139            DOCUMENT( DOCUMENT_NODE ),
140            /**
141             * @see org.w3c.dom.Node#DOCUMENT_TYPE_NODE
142             */
143            DOCUMENT_TYPE( DOCUMENT_TYPE_NODE ),
144            /**
145             * @see org.w3c.dom.Node#ELEMENT_NODE
146             */
147            ELEMENT( ELEMENT_NODE ),
148            /**
149             * @see org.w3c.dom.Node#ENTITY_NODE
150             */
151            ENTITY( ENTITY_NODE ),
152            /**
153             * @see org.w3c.dom.Node#ENTITY_REFERENCE_NODE
154             */
155            ENTITY_REFERENCE( ENTITY_REFERENCE_NODE ),
156            /**
157             * @see org.w3c.dom.Node#NOTATION_NODE
158             */
159            NOTATION( NOTATION_NODE ),
160            /**
161             * @see org.w3c.dom.Node#PROCESSING_INSTRUCTION_NODE
162             */
163            PROCESSING_INSTRUCTION( PROCESSING_INSTRUCTION_NODE ),
164            /**
165             * @see org.w3c.dom.Node#TEXT_NODE
166             */
167            TEXT( TEXT_NODE );
168    
169            private final int documentType;
170    
171            private NodeType( final int documentType )
172            {
173                this.documentType = documentType;
174            }
175    
176            private int getDocumentType()
177            {
178                return documentType;
179            }
180    
181        }
182    
183    }