1 /*
2 * #%L
3 * CreateIndexCommand.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.client.message;
21
22 import com.allanbank.mongodb.ReadPreference;
23 import com.allanbank.mongodb.Version;
24 import com.allanbank.mongodb.bson.Document;
25 import com.allanbank.mongodb.bson.DocumentAssignable;
26 import com.allanbank.mongodb.bson.Element;
27 import com.allanbank.mongodb.bson.NumericElement;
28 import com.allanbank.mongodb.bson.builder.BuilderFactory;
29 import com.allanbank.mongodb.bson.builder.DocumentBuilder;
30 import com.allanbank.mongodb.client.VersionRange;
31
32 /**
33 * Helper class to make generating a {@code createIndexes} command easier.
34 *
35 * @see <a
36 * href="http://docs.mongodb.org/manual/reference/command/createIndexes">createIndexes
37 * reference manual.</a>
38 * @api.no This class is <b>NOT</b> part of the drivers API. This class may be
39 * mutated in incompatible ways between any two releases of the driver.
40 * @copyright 2014, Allanbank Consulting, Inc., All Rights Reserved
41 */
42 public class CreateIndexCommand extends Command {
43 /**
44 * The first version of MongoDB to support the {@code createIndexes}
45 * command.
46 */
47 public static final Version REQUIRED_VERSION = Version.VERSION_2_6;
48
49 /** The required server version range for the {@code createIndexes} command. */
50 public static final VersionRange REQUIRED_VERSION_RANGE = VersionRange
51 .minimum(REQUIRED_VERSION);
52
53 /**
54 * Generates a name for the index based on the keys.
55 *
56 * @param keys
57 * The keys for the index.
58 * @return The name for the index.
59 */
60 public static String buildIndexName(final Element... keys) {
61 final StringBuilder nameBuilder = new StringBuilder();
62 for (final Element key : keys) {
63 if (nameBuilder.length() > 0) {
64 nameBuilder.append('_');
65 }
66 nameBuilder.append(key.getName().replace(' ', '_'));
67 nameBuilder.append("_");
68 if (key instanceof NumericElement) {
69 nameBuilder.append(((NumericElement) key).getIntValue());
70 }
71 else {
72 nameBuilder.append(key.getValueAsString());
73 }
74 }
75 return nameBuilder.toString();
76 }
77
78 /**
79 * Constructs the {@code createIndexes} command.
80 *
81 * @param collectionName
82 * The name of the collection the command is using. This should
83 * be the real collection and not
84 * {@link Command#COMMAND_COLLECTION $cmd}.
85 * @param keys
86 * The index keys for the index.
87 * @param indexName
88 * The name of the index.
89 * @param options
90 * Options for the index. May be <code>null</code>.
91 * @return The {@code createIndexes} command.
92 */
93 private static Document buildCommand(final String collectionName,
94 final Element[] keys, final String indexName,
95 final DocumentAssignable options) {
96 final DocumentBuilder builder = BuilderFactory.start();
97
98 builder.add("createIndexes", collectionName);
99
100 final DocumentBuilder index = builder.pushArray("indexes").push();
101 final DocumentBuilder keysDoc = index.push("key");
102 for (final Element key : keys) {
103 keysDoc.add(key);
104 }
105
106 index.add("name", indexName == null ? buildIndexName(keys) : indexName);
107
108 if (options != null) {
109 for (final Element option : options.asDocument()) {
110 index.add(option);
111 }
112 }
113
114 return builder.build();
115 }
116
117 /**
118 * Create a new CreateIndexCommand.
119 *
120 * @param databaseName
121 * The name of the database.
122 * @param collectionName
123 * The name of the collection the command is using. This should
124 * be the real collection and not
125 * {@link Command#COMMAND_COLLECTION $cmd}.
126 * @param keys
127 * The index keys for the index.
128 * @param indexName
129 * The name of the index.
130 * @param options
131 * Options for the index. May be <code>null</code>.
132 */
133 public CreateIndexCommand(final String databaseName,
134 final String collectionName, final Element[] keys,
135 final String indexName, final DocumentAssignable options) {
136 super(databaseName, collectionName, buildCommand(collectionName, keys,
137 indexName, options), ReadPreference.PRIMARY,
138 REQUIRED_VERSION_RANGE);
139 }
140
141 /**
142 * Determines if the passed object is of this same type as this object and
143 * if so that its fields are equal.
144 *
145 * @param object
146 * The object to compare to.
147 *
148 * @see java.lang.Object#equals(java.lang.Object)
149 */
150 @Override
151 public boolean equals(final Object object) {
152 boolean result = false;
153 if (this == object) {
154 result = true;
155 }
156 else if ((object != null) && (getClass() == object.getClass())) {
157 result = super.equals(object);
158 }
159 return result;
160 }
161
162 /**
163 * Computes a reasonable hash code.
164 *
165 * @return The hash code value.
166 */
167 @Override
168 public int hashCode() {
169 int result = 1;
170 result = (31 * result) + super.hashCode();
171 return result;
172 }
173 }