Coverage Report - com.allanbank.mongodb.bson.builder.impl.AbstractBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractBuilder
100%
32/32
83%
10/12
1.357
AbstractBuilder$BuilderElement
46%
6/13
N/A
1.357
 
 1  
 /*
 2  
  * #%L
 3  
  * AbstractBuilder.java - mongodb-async-driver - Allanbank Consulting, Inc.
 4  
  * %%
 5  
  * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
 6  
  * %%
 7  
  * Licensed under the Apache License, Version 2.0 (the "License");
 8  
  * you may not use this file except in compliance with the License.
 9  
  * You may obtain a copy of the License at
 10  
  * 
 11  
  *      http://www.apache.org/licenses/LICENSE-2.0
 12  
  * 
 13  
  * Unless required by applicable law or agreed to in writing, software
 14  
  * distributed under the License is distributed on an "AS IS" BASIS,
 15  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 16  
  * See the License for the specific language governing permissions and
 17  
  * limitations under the License.
 18  
  * #L%
 19  
  */
 20  
 package com.allanbank.mongodb.bson.builder.impl;
 21  
 
 22  
 import java.io.IOException;
 23  
 import java.io.ObjectInputStream;
 24  
 import java.util.ArrayList;
 25  
 import java.util.HashSet;
 26  
 import java.util.List;
 27  
 import java.util.Set;
 28  
 
 29  
 import com.allanbank.mongodb.bson.Element;
 30  
 import com.allanbank.mongodb.bson.ElementType;
 31  
 import com.allanbank.mongodb.bson.Visitor;
 32  
 import com.allanbank.mongodb.bson.builder.ArrayBuilder;
 33  
 import com.allanbank.mongodb.bson.builder.Builder;
 34  
 import com.allanbank.mongodb.bson.builder.DocumentBuilder;
 35  
 import com.allanbank.mongodb.bson.element.AbstractElement;
 36  
 
 37  
 /**
 38  
  * Base class with common functionality for the all builders. A builder is
 39  
  * responsible for constructing a single level of the BSON document.
 40  
  * 
 41  
  * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
 42  
  *         mutated in incompatible ways between any two releases of the driver.
 43  
  * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
 44  
  */
 45  1
 public abstract class AbstractBuilder implements Builder {
 46  
 
 47  
     /** If true then assertions have been enabled for the class. */
 48  
     protected static final boolean ASSERTIONS_ENABLED;
 49  
 
 50  
     /** The class used for intermediate sub-builders in the elements list. */
 51  
     protected static final Class<BuilderElement> BUILDER_ELEMENT_CLASS;
 52  
 
 53  
     static {
 54  1
         BUILDER_ELEMENT_CLASS = BuilderElement.class;
 55  1
         ASSERTIONS_ENABLED = AbstractBuilder.class.desiredAssertionStatus();
 56  1
     }
 57  
 
 58  
     /** The list of elements in the builder. */
 59  
     protected final List<Element> myElements;
 60  
 
 61  
     /** The size of the document added. */
 62  
     protected long mySize;
 63  
 
 64  
     /** The outer scope to this builder. */
 65  
     private final AbstractBuilder myOuterBuilder;
 66  
 
 67  
     /**
 68  
      * Creates a new builder.
 69  
      * 
 70  
      * @param outerBuilder
 71  
      *            The outer scoped builder.
 72  
      */
 73  
     public AbstractBuilder(final AbstractBuilder outerBuilder) {
 74  809726
         super();
 75  809726
         myOuterBuilder = outerBuilder;
 76  809726
         myElements = new ArrayList<Element>(32);
 77  809726
         mySize = 0;
 78  809726
     }
 79  
 
 80  
     /**
 81  
      * {@inheritDoc}
 82  
      */
 83  
     @Override
 84  
     public Builder pop() {
 85  10
         return myOuterBuilder;
 86  
     }
 87  
 
 88  
     /**
 89  
      * {@inheritDoc}
 90  
      */
 91  
     @Override
 92  
     public Builder reset() {
 93  1273
         myElements.clear();
 94  1273
         return this;
 95  
     }
 96  
 
 97  
     /**
 98  
      * Constructs the final form of the element being constructed.
 99  
      * 
 100  
      * @param name
 101  
      *            The name of the element.
 102  
      * @return The Element constructed by the builder.
 103  
      */
 104  
     protected abstract Element build(String name);
 105  
 
 106  
     /**
 107  
      * Pushes a context for constructing a sub-document.
 108  
      * 
 109  
      * @param name
 110  
      *            The name of the sub-document.
 111  
      * @return A {@link DocumentBuilder} for constructing the sub-document.
 112  
      */
 113  
 
 114  
     protected DocumentBuilder doPush(final String name) {
 115  700802
         final DocumentBuilderImpl pushed = new DocumentBuilderImpl(this);
 116  700802
         myElements.add(new BuilderElement(name, pushed));
 117  700802
         return pushed;
 118  
     }
 119  
 
 120  
     /**
 121  
      * Pushes a context for constructing a sub-array.
 122  
      * 
 123  
      * @param name
 124  
      *            The name of the sub-array.
 125  
      * @return A {@link ArrayBuilder} for constructing the sub-array.
 126  
      */
 127  
     protected ArrayBuilder doPushArray(final String name) {
 128  3005
         final ArrayBuilderImpl pushed = new ArrayBuilderImpl(this);
 129  3005
         myElements.add(new BuilderElement(name, pushed));
 130  3005
         return pushed;
 131  
     }
 132  
 
 133  
     /**
 134  
      * Renders the final form of the sub elements in the builder replacing all
 135  
      * {@link BuilderElement}s with the final element form.
 136  
      * 
 137  
      * @return The final sub element list.
 138  
      */
 139  
     protected List<Element> subElements() {
 140  913827
         final List<Element> elements = new ArrayList<Element>(myElements.size());
 141  
 
 142  913827
         Set<String> names = null;
 143  913827
         for (Element element : myElements) {
 144  2552969
             if (element.getClass() == BUILDER_ELEMENT_CLASS) {
 145  705301
                 element = ((BuilderElement) element).build();
 146  
             }
 147  
 
 148  2552969
             if (ASSERTIONS_ENABLED) {
 149  2552969
                 if (names == null) {
 150  709873
                     names = new HashSet<String>(myElements.size() << 1);
 151  
                 }
 152  2552969
                 final String name = element.getName();
 153  2552969
                 if (!names.add(name)) {
 154  1
                     assert false : name + " is not unique in  " + myElements;
 155  
                 }
 156  
             }
 157  
 
 158  2552968
             elements.add(element);
 159  2552968
         }
 160  
 
 161  913826
         return elements;
 162  
     }
 163  
 
 164  
     /**
 165  
      * A temporary Element to stand in for a element being constructed with a
 166  
      * builder.
 167  
      * <p>
 168  
      * <b>Note:</b> This class if final to allow the class comparison in
 169  
      * {@link AbstractBuilder}.subElements() method.
 170  
      * </p>
 171  
      */
 172  0
     public static final class BuilderElement extends AbstractElement {
 173  
 
 174  
         /** Serialization version for the class. */
 175  
         private static final long serialVersionUID = 4421203621373216989L;
 176  
 
 177  
         /** The encapsulated builder. */
 178  
         private transient AbstractBuilder myBuilder;
 179  
 
 180  
         /**
 181  
          * Creates a new {@link BuilderElement}.
 182  
          * 
 183  
          * @param name
 184  
          *            The name for the element to build.
 185  
          * @param builder
 186  
          *            The Builder doing the building.
 187  
          */
 188  
         public BuilderElement(final String name, final AbstractBuilder builder) {
 189  703807
             super(name, 0);
 190  703807
             myBuilder = builder;
 191  703807
         }
 192  
 
 193  
         /**
 194  
          * {@inheritDoc}
 195  
          */
 196  
         @Override
 197  
         public void accept(final Visitor visitor) {
 198  1
             build().accept(visitor);
 199  1
         }
 200  
 
 201  
         /**
 202  
          * Constructs the final form of the element being constructed by the
 203  
          * encapsulated builder.
 204  
          * 
 205  
          * @return The Element constructed by the encapsulated builder.
 206  
          */
 207  
         public Element build() {
 208  705302
             return myBuilder.build(getName());
 209  
         }
 210  
 
 211  
         /**
 212  
          * {@inheritDoc}
 213  
          */
 214  
         @Override
 215  
         public ElementType getType() {
 216  0
             return null;
 217  
         }
 218  
 
 219  
         /**
 220  
          * {@inheritDoc}
 221  
          * <p>
 222  
          * Overridden to return null as this class should not be seen outside of
 223  
          * the builders.
 224  
          * </p>
 225  
          */
 226  
         @Override
 227  
         public Object getValueAsObject() {
 228  0
             return null;
 229  
         }
 230  
 
 231  
         /**
 232  
          * {@inheritDoc}
 233  
          * <p>
 234  
          * Returns a new {@link BuilderElement}.
 235  
          * </p>
 236  
          */
 237  
         @Override
 238  
         public BuilderElement withName(final String name) {
 239  0
             return new BuilderElement(name, myBuilder);
 240  
         }
 241  
 
 242  
         /**
 243  
          * Sets the transient state of this non-Element.
 244  
          * 
 245  
          * @param in
 246  
          *            The input stream.
 247  
          * @throws ClassNotFoundException
 248  
          *             On a failure loading a class in this classed reachable
 249  
          *             tree.
 250  
          * @throws IOException
 251  
          *             On a failure reading from the stream.
 252  
          */
 253  
         private void readObject(final ObjectInputStream in)
 254  
                 throws ClassNotFoundException, IOException {
 255  0
             in.defaultReadObject();
 256  0
             myBuilder = null;
 257  0
         }
 258  
     }
 259  
 }