001package ball.xml;
002/*-
003 * ##########################################################################
004 * Utilities
005 * $Id: FluentDocument.html 5431 2020-02-12 19:03:17Z ball $
006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/hcf-dev/blog/2019-03-30-java-interface-facades/src/main/resources/javadoc/src-html/ball/xml/FluentDocument.html $
007 * %%
008 * Copyright (C) 2008 - 2020 Allen D. Ball
009 * %%
010 * Licensed under the Apache License, Version 2.0 (the "License");
011 * you may not use this file except in compliance with the License.
012 * You may obtain a copy of the License at
013 *
014 *      http://www.apache.org/licenses/LICENSE-2.0
015 *
016 * Unless required by applicable law or agreed to in writing, software
017 * distributed under the License is distributed on an "AS IS" BASIS,
018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
019 * See the License for the specific language governing permissions and
020 * limitations under the License.
021 * ##########################################################################
022 */
023import java.io.IOException;
024import java.util.stream.Stream;
025import javax.xml.parsers.DocumentBuilder;
026import org.w3c.dom.DOMImplementation;
027import org.w3c.dom.Document;
028import org.w3c.dom.Node;
029import org.xml.sax.EntityResolver;
030import org.xml.sax.ErrorHandler;
031import org.xml.sax.InputSource;
032import org.xml.sax.SAXException;
033
034import static java.util.Objects.requireNonNull;
035
036/**
037 * Fluent {@link Document} interface.  Note: This interface is an
038 * implementation detail of {@link FluentDocument.Builder} and should not be
039 * extended directly.
040 *
041 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
042 * @version $Revision: 5431 $
043 */
044public interface FluentDocument extends FluentNode, Document {
045    @Override
046    default FluentDocument owner() { return this; }
047
048    @Override
049    default FluentDocument add(Stream<Node> stream) {
050        return add(stream.toArray(Node[]::new));
051    }
052
053    @Override
054    default FluentDocument add(Node... nodes) {
055        return (FluentDocument) FluentNode.super.add(nodes);
056    }
057
058    /**
059     * {@link FluentDocument} {@link DocumentBuilder}.
060     */
061    public class Builder extends DocumentBuilder {
062        private final DocumentBuilder builder;
063
064        /**
065         * Sole constructor.
066         *
067         * @param   builder         The "wrapped" {@link DocumentBuilder}.
068         */
069        protected Builder(DocumentBuilder builder) {
070            super();
071
072            this.builder = requireNonNull(builder);
073        }
074
075        @Override
076        public FluentDocument newDocument() {
077            Document document = builder.newDocument();
078
079            return (FluentDocument) new InvocationHandler().enhance(document);
080        }
081
082        @Override
083        public Document parse(InputSource in) throws SAXException,
084                                                     IOException {
085            Document document = builder.parse(in);
086
087            return (FluentDocument) new InvocationHandler().enhance(document);
088        }
089
090        @Override
091        public boolean isNamespaceAware() {
092            return builder.isNamespaceAware();
093        }
094
095        @Override
096        public boolean isValidating() { return builder.isValidating(); }
097
098        @Override
099        public void setEntityResolver(EntityResolver resolver) {
100            builder.setEntityResolver(resolver);
101        }
102
103        @Override
104        public void setErrorHandler(ErrorHandler handler) {
105            builder.setErrorHandler(handler);
106        }
107
108        @Override
109        public DOMImplementation getDOMImplementation() {
110            return builder.getDOMImplementation();
111        }
112
113        @Override
114        public String toString() { return super.toString(); }
115    }
116}