1 /*
2 * #%L
3 * ReplyLongCallback.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
21 package com.allanbank.mongodb.client.callback;
22
23 import java.util.List;
24
25 import com.allanbank.mongodb.Callback;
26 import com.allanbank.mongodb.MongoDbException;
27 import com.allanbank.mongodb.bson.Document;
28 import com.allanbank.mongodb.bson.Element;
29 import com.allanbank.mongodb.bson.NumericElement;
30 import com.allanbank.mongodb.client.message.Reply;
31 import com.allanbank.mongodb.error.ReplyException;
32
33 /**
34 * Callback to expect and extract a single document from the reply and then
35 * extract a contained {@link NumericElement} and coerce it to a long value.
36 *
37 * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
38 * mutated in incompatible ways between any two releases of the driver.
39 * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved
40 */
41 public class ReplyLongCallback extends AbstractReplyCallback<Long> {
42
43 /** The default name for the long value to return. */
44 public static final String DEFAULT_NAME = "n";
45
46 /**
47 * The name of the {@link NumericElement value} expected in the reply
48 * document.
49 */
50 private final String myName;
51
52 /**
53 * Create a new ReplyLongCallback.
54 *
55 * @param results
56 * The callback to notify of the value.
57 */
58 public ReplyLongCallback(final Callback<Long> results) {
59 this(DEFAULT_NAME, results);
60 }
61
62 /**
63 * Create a new ReplyLongCallback.
64 *
65 * @param name
66 * The name of the {@link NumericElement numeric} value.
67 * @param results
68 * The callback to notify of the value.
69 */
70 public ReplyLongCallback(final String name, final Callback<Long> results) {
71 super(results);
72
73 myName = name;
74 }
75
76 /**
77 * {@inheritDoc}
78 * <p>
79 * Creates an exception from the {@link Reply} if the 'n' field is missing.
80 * </p>
81 *
82 * @param reply
83 * The raw reply.
84 * @return The exception created.
85 */
86 @Override
87 protected MongoDbException asError(final Reply reply) {
88 MongoDbException error = super.asError(reply);
89 if (error == null) {
90 final List<Document> results = reply.getResults();
91 if (results.size() == 1) {
92 final Document doc = results.get(0);
93 final Element nElem = doc.get(myName);
94 if (!(nElem instanceof NumericElement)) {
95 error = new ReplyException(reply, "Missing '" + myName
96 + "' field in reply.");
97 }
98 }
99 }
100 return error;
101 }
102
103 /**
104 * {@inheritDoc}
105 * <p>
106 * Overridden to return the 'n' field in the reply document.
107 * </p>
108 *
109 * @see AbstractReplyCallback#convert(Reply)
110 */
111 @Override
112 protected Long convert(final Reply reply) throws MongoDbException {
113 final List<Document> results = reply.getResults();
114 if (results.size() == 1) {
115 final Document doc = results.get(0);
116 final Element nElem = doc.get(myName);
117 return Long.valueOf(toLong(nElem));
118 }
119
120 return Long.valueOf(-1);
121 }
122
123 /**
124 * Converts a {@link NumericElement} into a <tt>long</tt> value. If not a
125 * {@link NumericElement} then -1 is returned.
126 *
127 * @param element
128 * The element to convert.
129 * @return The element's long value or -1.
130 */
131 protected long toLong(final Element element) {
132 if (element instanceof NumericElement) {
133 return ((NumericElement) element).getLongValue();
134 }
135
136 return -1;
137 }
138 }