Coverage Report - com.allanbank.mongodb.bson.element.JavaScriptWithScopeElement
 
Classes in this File Line Coverage Branch Coverage Complexity
JavaScriptWithScopeElement
100%
52/52
96%
27/28
2.636
 
 1  
 /*
 2  
  * #%L
 3  
  * JavaScriptWithScopeElement.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.util.Iterator;
 25  
 
 26  
 import com.allanbank.mongodb.bson.Document;
 27  
 import com.allanbank.mongodb.bson.Element;
 28  
 import com.allanbank.mongodb.bson.ElementType;
 29  
 import com.allanbank.mongodb.bson.Visitor;
 30  
 import com.allanbank.mongodb.bson.builder.BuilderFactory;
 31  
 import com.allanbank.mongodb.bson.builder.DocumentBuilder;
 32  
 import com.allanbank.mongodb.bson.io.StringEncoder;
 33  
 
 34  
 /**
 35  
  * A wrapper for a BSON JavaScript with Scope.
 36  
  * 
 37  
  * @api.yes This class is part of the driver's API. Public and protected members
 38  
  *          will be deprecated for at least 1 non-bugfix release (version
 39  
  *          numbers are <major>.<minor>.<bugfix>) before being
 40  
  *          removed or modified.
 41  
  * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
 42  
  */
 43  21
 public class JavaScriptWithScopeElement extends JavaScriptElement {
 44  
 
 45  
     /** The BSON type for a string. */
 46  
     @SuppressWarnings("hiding")
 47  1
     public static final ElementType TYPE = ElementType.JAVA_SCRIPT_WITH_SCOPE;
 48  
 
 49  
     /** Serialization version for the class. */
 50  
     private static final long serialVersionUID = -5697976862389984453L;
 51  
 
 52  
     /**
 53  
      * Computes and returns the number of bytes that are used to encode the
 54  
      * element.
 55  
      * 
 56  
      * @param name
 57  
      *            The name for the element.
 58  
      * @param javaScript
 59  
      *            The BSON JavaScript value.
 60  
      * @param scope
 61  
      *            The scope for the JavaScript
 62  
      * @return The size of the element when encoded in bytes.
 63  
      */
 64  
     private static long computeSize(final String name, final String javaScript,
 65  
             final Document scope) {
 66  146
         long result = 15; // type (1) + name null byte (1) + length (4)
 67  
         // javaScript length (4) and null byte (5)
 68  146
         result += StringEncoder.utf8Size(name);
 69  146
         result += StringEncoder.utf8Size(javaScript);
 70  146
         if (scope != null) {
 71  145
             result += scope.size();
 72  
         }
 73  
 
 74  146
         return result;
 75  
     }
 76  
 
 77  
     /** The BSON scope value. */
 78  
     private final Document myScope;
 79  
 
 80  
     /**
 81  
      * Constructs a new {@link JavaScriptWithScopeElement}.
 82  
      * 
 83  
      * @param name
 84  
      *            The name for the BSON string.
 85  
      * @param javaScript
 86  
      *            The BSON JavaScript value.
 87  
      * @param scope
 88  
      *            The scope for the JavaScript
 89  
      * @throws IllegalArgumentException
 90  
      *             If the {@code name}, {@code javaScript}, or {@code scope} is
 91  
      *             <code>null</code>.
 92  
      */
 93  
     public JavaScriptWithScopeElement(final String name,
 94  
             final String javaScript, final Document scope) {
 95  146
         this(name, javaScript, scope, computeSize(name, javaScript, scope));
 96  
 
 97  143
         assertNotNull(scope, "JavaScript element's scope cannot be null.");
 98  143
     }
 99  
 
 100  
     /**
 101  
      * Constructs a new {@link JavaScriptWithScopeElement}.
 102  
      * 
 103  
      * @param name
 104  
      *            The name for the BSON string.
 105  
      * @param javaScript
 106  
      *            The BSON JavaScript value.
 107  
      * @param scope
 108  
      *            The scope for the JavaScript
 109  
      * @param size
 110  
      *            The size of the element when encoded in bytes. If not known
 111  
      *            then use the
 112  
      *            {@link JavaScriptWithScopeElement#JavaScriptWithScopeElement(String, String, Document)}
 113  
      *            constructor instead.
 114  
      * @throws IllegalArgumentException
 115  
      *             If the {@code name}, {@code javaScript}, or {@code scope} is
 116  
      *             <code>null</code>.
 117  
      */
 118  
     public JavaScriptWithScopeElement(final String name,
 119  
             final String javaScript, final Document scope, final long size) {
 120  154
         super(name, javaScript, size);
 121  
 
 122  152
         assertNotNull(scope, "JavaScript element's scope cannot be null.");
 123  
 
 124  151
         myScope = scope;
 125  151
     }
 126  
 
 127  
     /**
 128  
      * Accepts the visitor and calls the
 129  
      * {@link Visitor#visitJavaScript(String,String,Document)} method.
 130  
      * 
 131  
      * @see Element#accept(Visitor)
 132  
      */
 133  
     @Override
 134  
     public void accept(final Visitor visitor) {
 135  21
         visitor.visitJavaScript(getName(), getJavaScript(), getScope());
 136  21
     }
 137  
 
 138  
     /**
 139  
      * {@inheritDoc}
 140  
      * <p>
 141  
      * Overridden to compare the Java Script (as text) if the base class
 142  
      * comparison is equals.
 143  
      * </p>
 144  
      */
 145  
     @Override
 146  
     public int compareTo(final Element otherElement) {
 147  18
         int result = super.compareTo(otherElement);
 148  
 
 149  18
         if (result == 0) {
 150  11
             final JavaScriptWithScopeElement other = (JavaScriptWithScopeElement) otherElement;
 151  
 
 152  11
             final Iterator<Element> thisIter = myScope.iterator();
 153  11
             final Iterator<Element> otherIter = other.myScope.iterator();
 154  18
             while (thisIter.hasNext() && otherIter.hasNext()) {
 155  9
                 result = thisIter.next().compareTo(otherIter.next());
 156  9
                 if (result != 0) {
 157  2
                     return result;
 158  
                 }
 159  
             }
 160  
 
 161  9
             if (thisIter.hasNext()) {
 162  3
                 return 1;
 163  
             }
 164  6
             else if (otherIter.hasNext()) {
 165  3
                 return -1;
 166  
             }
 167  
             else {
 168  3
                 return 0;
 169  
             }
 170  
         }
 171  
 
 172  7
         return result;
 173  
     }
 174  
 
 175  
     /**
 176  
      * Determines if the passed object is of this same type as this object and
 177  
      * if so that its fields are equal.
 178  
      * 
 179  
      * @param object
 180  
      *            The object to compare to.
 181  
      * 
 182  
      * @see java.lang.Object#equals(java.lang.Object)
 183  
      */
 184  
     @Override
 185  
     public boolean equals(final Object object) {
 186  1511
         boolean result = false;
 187  1511
         if (this == object) {
 188  62
             result = true;
 189  
         }
 190  1449
         else if ((object != null) && (getClass() == object.getClass())) {
 191  1288
             final JavaScriptWithScopeElement other = (JavaScriptWithScopeElement) object;
 192  
 
 193  1288
             result = super.equals(object)
 194  
                     && nullSafeEquals(myScope, other.myScope);
 195  
         }
 196  1511
         return result;
 197  
     }
 198  
 
 199  
     /**
 200  
      * Returns the BSON JavaScript scope.
 201  
      * 
 202  
      * @return The BSON JavaScript scope.
 203  
      */
 204  
     public Document getScope() {
 205  25
         return myScope;
 206  
     }
 207  
 
 208  
     /**
 209  
      * {@inheritDoc}
 210  
      */
 211  
     @Override
 212  
     public ElementType getType() {
 213  40
         return TYPE;
 214  
     }
 215  
 
 216  
     /**
 217  
      * {@inheritDoc}
 218  
      * <p>
 219  
      * Returns a document representing the code and scope similar to the strict
 220  
      * JSON encoding.
 221  
      * </p>
 222  
      * <p>
 223  
      * <b>Note:</b> This value will not be recreated is a Object-->Element
 224  
      * conversion. A more generic sub-document is created instead.
 225  
      * </p>
 226  
      */
 227  
     @Override
 228  
     public Document getValueAsObject() {
 229  1
         final DocumentBuilder b = BuilderFactory.start();
 230  1
         b.add("$code", getJavaScript());
 231  1
         b.add("$scope", myScope);
 232  
 
 233  1
         return b.build();
 234  
     }
 235  
 
 236  
     /**
 237  
      * Computes a reasonable hash code.
 238  
      * 
 239  
      * @return The hash code value.
 240  
      */
 241  
     @Override
 242  
     public int hashCode() {
 243  2646
         int result = 1;
 244  2646
         result = (31 * result) + super.hashCode();
 245  2646
         result = (31 * result) + ((myScope != null) ? myScope.hashCode() : 3);
 246  2646
         return result;
 247  
     }
 248  
 
 249  
     /**
 250  
      * {@inheritDoc}
 251  
      * <p>
 252  
      * Returns a new {@link JavaScriptElement}.
 253  
      * </p>
 254  
      */
 255  
     @Override
 256  
     public JavaScriptWithScopeElement withName(final String name) {
 257  23
         if (getName().equals(name)) {
 258  22
             return this;
 259  
         }
 260  1
         return new JavaScriptWithScopeElement(name, getJavaScript(), myScope);
 261  
     }
 262  
 }