Coverage Report - com.allanbank.mongodb.bson.element.AbstractElement
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractElement
97%
43/44
93%
30/32
2.062
 
 1  
 /*
 2  
  * #%L
 3  
  * AbstractElement.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.element;
 21  
 
 22  
 import static com.allanbank.mongodb.util.Assertions.assertNotNull;
 23  
 
 24  
 import java.io.StringWriter;
 25  
 import java.util.Collections;
 26  
 import java.util.List;
 27  
 
 28  
 import com.allanbank.mongodb.bson.Element;
 29  
 
 30  
 /**
 31  
  * A base class for the basic BSON types.
 32  
  * 
 33  
  * @api.yes This class is part of the driver's API. Public and protected members
 34  
  *          will be deprecated for at least 1 non-bugfix release (version
 35  
  *          numbers are <major>.<minor>.<bugfix>) before being
 36  
  *          removed or modified.
 37  
  * @copyright 2011-2014, Allanbank Consulting, Inc., All Rights Reserved
 38  
  */
 39  0
 public abstract class AbstractElement implements Element {
 40  
 
 41  
     /** The base type (interface) for all elements. */
 42  1
     protected static final Class<Element> ELEMENT_TYPE = Element.class;
 43  
 
 44  
     /** Serialization version for the class. */
 45  
     private static final long serialVersionUID = 7537761445549731633L;
 46  
 
 47  
     /**
 48  
      * Compares two {@code int} values numerically. The value returned is
 49  
      * identical to what would be returned by:
 50  
      * 
 51  
      * <pre>
 52  
      * Integer.valueOf(x).compareTo(Integer.valueOf(y))
 53  
      * </pre>
 54  
      * 
 55  
      * @param x
 56  
      *            the first {@code int} to compare
 57  
      * @param y
 58  
      *            the second {@code int} to compare
 59  
      * @return the value {@code 0} if {@code x == y}; a value less than
 60  
      *         {@code 0} if {@code x < y}; and a value greater than {@code 0} if
 61  
      *         {@code x > y}
 62  
      * @since 1.7
 63  
      */
 64  
     /* package */static int compare(final int x, final int y) {
 65  63
         return (x < y) ? -1 : ((x == y) ? 0 : 1);
 66  
     }
 67  
 
 68  
     /**
 69  
      * Compares two {@code long} values numerically. The value returned is
 70  
      * identical to what would be returned by:
 71  
      * 
 72  
      * <pre>
 73  
      * Long.valueOf(x).compareTo(Long.valueOf(y))
 74  
      * </pre>
 75  
      * 
 76  
      * @param x
 77  
      *            the first {@code long} to compare
 78  
      * @param y
 79  
      *            the second {@code long} to compare
 80  
      * @return the value {@code 0} if {@code x == y}; a value less than
 81  
      *         {@code 0} if {@code x < y}; and a value greater than {@code 0} if
 82  
      *         {@code x > y}
 83  
      * @since 1.7
 84  
      */
 85  
     /* package */static int compare(final long x, final long y) {
 86  15
         return (x < y) ? -1 : ((x == y) ? 0 : 1);
 87  
     }
 88  
 
 89  
     /** The name for the BSON type. */
 90  
     private final String myName;
 91  
 
 92  
     /** The size of the element when encoded in bytes. */
 93  
     private final long mySize;
 94  
 
 95  
     /**
 96  
      * Constructs a new {@link AbstractElement}.
 97  
      * 
 98  
      * @param name
 99  
      *            The name for the BSON type.
 100  
      * @param size
 101  
      *            The size of the element when encoded in bytes.
 102  
      * @throws IllegalArgumentException
 103  
      *             If the {@code name} is <code>null</code>.
 104  
      */
 105  
     public AbstractElement(final String name, final long size)
 106  3532137
             throws IllegalArgumentException {
 107  3532137
         assertNotNull(name, "Cannot have an null name on an element.");
 108  
 
 109  3532110
         myName = name;
 110  3532110
         mySize = size;
 111  3532107
     }
 112  
 
 113  
     /**
 114  
      * {@inheritDoc}
 115  
      * <p>
 116  
      * Returns this element.
 117  
      * </p>
 118  
      */
 119  
     @Override
 120  
     public Element asElement() {
 121  1639493
         return this;
 122  
     }
 123  
 
 124  
     /**
 125  
      * {@inheritDoc}
 126  
      * <p>
 127  
      * Overridden to compare the elements based on the tuple (name, type).
 128  
      * Derived classes are responsible for the value portion of the full
 129  
      * comparison.
 130  
      * </p>
 131  
      */
 132  
     @Override
 133  
     public int compareTo(final Element otherElement) {
 134  192
         int result = myName.compareTo(otherElement.getName());
 135  
 
 136  192
         if (result == 0) {
 137  
             // Use the specialized comparison to match MongoDB's ordering of
 138  
             // types.
 139  156
             result = getType().compare(otherElement.getType());
 140  
         }
 141  
 
 142  192
         return result;
 143  
     }
 144  
 
 145  
     /**
 146  
      * Determines if the passed object is of this same type as this object and
 147  
      * if so that its fields are equal.
 148  
      * 
 149  
      * @param object
 150  
      *            The object to compare to.
 151  
      * 
 152  
      * @see java.lang.Object#equals(java.lang.Object)
 153  
      */
 154  
     @Override
 155  
     public boolean equals(final Object object) {
 156  915128
         boolean result = false;
 157  915128
         if (this == object) {
 158  63
             result = true;
 159  
         }
 160  915065
         else if ((object != null) && (getClass() == object.getClass())) {
 161  915013
             final AbstractElement other = (AbstractElement) object;
 162  
 
 163  915013
             result = nullSafeEquals(myName, other.myName);
 164  
         }
 165  915128
         return result;
 166  
     }
 167  
 
 168  
     /**
 169  
      * {@inheritDoc}
 170  
      * <p>
 171  
      * Returns a singleton list if the nameRegexs is empty and this element's
 172  
      * type is assignable to E. An empty list otherwise.
 173  
      * </p>
 174  
      * 
 175  
      * @see Element#find
 176  
      */
 177  
     @Override
 178  
     public <E extends Element> List<E> find(final Class<E> clazz,
 179  
             final String... nameRegexs) {
 180  371
         if ((nameRegexs.length == 0) && clazz.isAssignableFrom(this.getClass())) {
 181  
             // End of the path. Match this element.
 182  367
             return Collections.singletonList(clazz.cast(this));
 183  
         }
 184  
 
 185  4
         return Collections.emptyList();
 186  
     }
 187  
 
 188  
     /**
 189  
      * {@inheritDoc}
 190  
      * <p>
 191  
      * Returns a singleton list if the nameRegexs is empty. An empty list
 192  
      * otherwise.
 193  
      * </p>
 194  
      * 
 195  
      * @see Element#find
 196  
      */
 197  
     @Override
 198  
     public List<Element> find(final String... nameRegexs) {
 199  2
         return find(ELEMENT_TYPE, nameRegexs);
 200  
     }
 201  
 
 202  
     /**
 203  
      * {@inheritDoc}
 204  
      * <p>
 205  
      * Returns a {@code this} if the nameRegexs is empty and this element's type
 206  
      * is assignable to E. An empty list otherwise.
 207  
      * </p>
 208  
      * 
 209  
      * @see Element#findFirst
 210  
      */
 211  
     @Override
 212  
     public <E extends Element> E findFirst(final Class<E> clazz,
 213  
             final String... nameRegexs) {
 214  511
         if ((nameRegexs.length == 0) && clazz.isAssignableFrom(this.getClass())) {
 215  
             // End of the path. Match this element.
 216  505
             return clazz.cast(this);
 217  
         }
 218  
 
 219  6
         return null;
 220  
     }
 221  
 
 222  
     /**
 223  
      * {@inheritDoc}
 224  
      * <p>
 225  
      * Searches this sub-elements for matching elements on the path and are of
 226  
      * the right type.
 227  
      * </p>
 228  
      * 
 229  
      * @see Element#findFirst
 230  
      */
 231  
     @Override
 232  
     public Element findFirst(final String... nameRegexs) {
 233  2
         return findFirst(ELEMENT_TYPE, nameRegexs);
 234  
     }
 235  
 
 236  
     /**
 237  
      * Returns the name for the BSON type.
 238  
      * 
 239  
      * @return The name for the BSON type.
 240  
      */
 241  
     @Override
 242  
     public String getName() {
 243  6276783
         return myName;
 244  
     }
 245  
 
 246  
     /**
 247  
      * {@inheritDoc}
 248  
      * <p>
 249  
      * Uses the {@link JsonSerializationVisitor} to encode the value. In some
 250  
      * cases it will be more efficient to override this method with a more
 251  
      * straight forward conversion.
 252  
      * </p>
 253  
      */
 254  
     @Override
 255  
     public String getValueAsString() {
 256  17
         final StringWriter writer = new StringWriter();
 257  17
         final JsonSerializationVisitor visitor = new JsonSerializationVisitor(
 258  
                 writer, false);
 259  
 
 260  
         // Just the value.
 261  17
         visitor.setSuppressNames(true);
 262  
 
 263  17
         accept(visitor);
 264  
 
 265  17
         return writer.toString();
 266  
     }
 267  
 
 268  
     /**
 269  
      * Computes a reasonable hash code.
 270  
      * 
 271  
      * @return The hash code value.
 272  
      */
 273  
     @Override
 274  
     public int hashCode() {
 275  4883171
         int result = 1;
 276  4883171
         result = (31 * result) + ((myName == null) ? 0 : myName.hashCode());
 277  4883171
         return result;
 278  
     }
 279  
 
 280  
     /**
 281  
      * Returns the number of bytes that are used to encode the element.
 282  
      * 
 283  
      * @return The bytes that are used to encode the element.
 284  
      */
 285  
     @Override
 286  
     public long size() {
 287  2758811
         return mySize;
 288  
     }
 289  
 
 290  
     /**
 291  
      * String form of the object.
 292  
      * 
 293  
      * @return A human readable form of the object.
 294  
      * 
 295  
      * @see java.lang.Object#toString()
 296  
      */
 297  
     @Override
 298  
     public String toString() {
 299  2514
         final StringWriter writer = new StringWriter();
 300  2514
         final JsonSerializationVisitor visitor = new JsonSerializationVisitor(
 301  
                 writer, false);
 302  
 
 303  2514
         accept(visitor);
 304  
 
 305  2514
         return writer.toString();
 306  
     }
 307  
 
 308  
     /**
 309  
      * Does a null safe equals comparison.
 310  
      * 
 311  
      * @param rhs
 312  
      *            The right-hand-side of the comparison.
 313  
      * @param lhs
 314  
      *            The left-hand-side of the comparison.
 315  
      * @return True if the rhs equals the lhs. Note: nullSafeEquals(null, null)
 316  
      *         returns true.
 317  
      */
 318  
     protected boolean nullSafeEquals(final Object rhs, final Object lhs) {
 319  918560
         return (rhs == lhs) || ((rhs != null) && rhs.equals(lhs));
 320  
     }
 321  
 }