001package 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
022import static org.w3c.dom.Node.ATTRIBUTE_NODE;
023import static org.w3c.dom.Node.CDATA_SECTION_NODE;
024import static org.w3c.dom.Node.COMMENT_NODE;
025import static org.w3c.dom.Node.DOCUMENT_FRAGMENT_NODE;
026import static org.w3c.dom.Node.DOCUMENT_NODE;
027import static org.w3c.dom.Node.DOCUMENT_TYPE_NODE;
028import static org.w3c.dom.Node.ELEMENT_NODE;
029import static org.w3c.dom.Node.ENTITY_NODE;
030import static org.w3c.dom.Node.ENTITY_REFERENCE_NODE;
031import static org.w3c.dom.Node.NOTATION_NODE;
032import static org.w3c.dom.Node.PROCESSING_INSTRUCTION_NODE;
033import static org.w3c.dom.Node.TEXT_NODE;
034
035import javax.xml.parsers.DocumentBuilder;
036import javax.xml.parsers.ParserConfigurationException;
037
038import org.apache.commons.digester3.NodeCreateRule;
039
040/**
041 * Builder chained when invoking {@link LinkedRuleBuilder#createNode()}.
042 *
043 * @since 3.0
044 */
045public 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}