1 // Copyright 2009 Google Inc. All Rights Reserved.
3 package com
.google
.apphosting
.utils
.config
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Iterator
;
10 * Parsed datastore-indexes.xml file.
12 * Any additions to this class should also be made to the YAML
13 * version in IndexYamlReader.java.
16 public class IndexesXml
implements Iterable
<IndexesXml
.Index
>{
18 public static final String DIRECTION_VALUE_ASC
= "asc";
19 public static final String DIRECTION_VALUE_DESC
= "desc";
20 public static final String MODE_VALUE_GEOSPATIAL
= "geospatial";
23 * A simple value object, encapsulating the specification of the
24 * part of the index configuration attributable to a single
27 public static class PropertySort
{
28 private final String propName
;
29 private final String direction
;
30 private final String mode
;
32 public PropertySort(String propName
, String direction
, String mode
) {
33 this.propName
= propName
;
34 this.direction
= direction
;
38 public String
getPropertyName() {
42 public String
getDirection() {
46 public String
getMode() {
54 * This is needed during parsing and validation. The type is
55 * not explicitly mentioned in the XML, but must be inferred from
56 * the presence of various attributes. Once the type is
57 * established, it constrains the attributes the may appear in the
58 * rest of the index configuration.
62 * A traditional Datastore index, with properties appearing in
63 * ascending or descending order.
68 * An index supporting 2-dimensional distance queries on points on
69 * the surface of the Earth.
76 public static class Index
{
77 private final String kind
;
78 private final Boolean ancestors
;
79 private final List
<PropertySort
> properties
;
81 public Index(String kind
, Boolean ancestors
) {
83 this.ancestors
= ancestors
;
84 this.properties
= new ArrayList
<PropertySort
>();
87 public void addNewProperty(String name
, String direction
, String mode
) {
88 properties
.add(new PropertySort(name
, direction
, mode
));
91 public String
getKind() {
95 public boolean doIndexAncestors() {
99 public List
<PropertySort
> getProperties() {
103 public String
toYaml() {
104 return toLocalStyleYaml();
108 * Builds a Yaml String representing this index, using the style of Yaml
109 * generation appropriate for a local indexes.yaml files.
110 * @return A Yaml String
112 private String
toLocalStyleYaml(){
113 StringBuilder builder
= new StringBuilder(50 * (1 + properties
.size()));
114 builder
.append("- kind: \"" + kind
+ "\"\n");
115 if (Boolean
.TRUE
.equals(ancestors
)) {
116 builder
.append(" ancestor: yes\n");
118 if (!properties
.isEmpty()) {
119 builder
.append(" properties:\n");
120 for (PropertySort prop
: properties
) {
121 builder
.append(" - name: \"" + prop
.getPropertyName() + "\"\n");
123 if (prop
.getDirection() != null) {
124 builder
.append(" direction: " + prop
.getDirection() + "\n");
127 if (prop
.getMode() != null) {
128 builder
.append(" mode: " + prop
.getMode() + "\n");
132 return builder
.toString();
136 * Builds a Yaml string representing this index, mimicking the style of Yaml
137 * generation used on the admin server. Since the admin server is written in
138 * python, it generates a slightly different style of yaml. This method is
139 * useful only for testing that the client-side code is able to parse this
142 * @return An admin-server-style Yaml String.
144 private String
toServerStyleYaml() {
145 StringBuilder builder
= new StringBuilder(50 * (1 + properties
.size()));
146 builder
.append("- ").append(IndexYamlReader
.INDEX_TAG
).append("\n");
147 builder
.append(" kind: " + kind
+ "\n");
148 if (Boolean
.TRUE
.equals(ancestors
)) {
149 builder
.append(" ancestor: yes\n");
151 if (!properties
.isEmpty()) {
152 builder
.append(" properties:\n");
153 for (PropertySort prop
: properties
) {
154 builder
.append(" - ");
155 builder
.append(IndexYamlReader
.PROPERTY_TAG
);
156 builder
.append(" {");
158 if (prop
.getDirection() != null) {
159 builder
.append("direction: ");
160 builder
.append(prop
.getDirection());
161 builder
.append(",\n");
164 if (prop
.getMode() != null) {
165 builder
.append("mode: ");
166 builder
.append(prop
.getMode());
167 builder
.append(",\n");
171 builder
.append("name: " + prop
.getPropertyName());
172 builder
.append("}\n");
175 return builder
.toString();
178 public String
toXmlString() {
179 StringBuilder builder
= new StringBuilder(100 * (1 + properties
.size()));
180 String ancestorAttribute
= ancestors
== null ?
""
181 : String
.format(" ancestor=\"%s\"", ancestors
);
182 builder
.append("<datastore-index kind=\"" + kind
+ "\"" + ancestorAttribute
+ ">\n");
183 for (PropertySort prop
: properties
) {
184 builder
.append(" <property name=\"" + prop
.getPropertyName() + "\"");
186 if (prop
.getDirection() != null) {
187 builder
.append(" direction=\"" + prop
.getDirection() + "\"");
190 if (prop
.getMode() != null) {
191 builder
.append(" mode=\"" + prop
.getMode() + "\"");
194 builder
.append("/>\n");
196 builder
.append("</datastore-index>\n");
197 return builder
.toString();
201 private final List
<Index
> indexes
;
203 public IndexesXml() {
204 indexes
= new ArrayList
<Index
>();
208 public Iterator
<Index
> iterator() {
209 return indexes
.iterator();
213 return indexes
.size();
216 public Index
addNewIndex(String kind
, Boolean ancestors
) {
217 Index index
= new Index(kind
, ancestors
);
223 * Adds the given {@link Index} to the collection
224 * contained in this object. Note that given {@link Index}
225 * is not cloned. The provided object instance will become
226 * incorporated into this object's collection.
229 public void addNewIndex(Index index
){
233 public String
toYaml() {
234 return toYaml(false);
238 * Builds yaml string representing the indexes
240 * @param serverStyle Use the admin server style of yaml generation. Since the
241 * admin server is written in python, it generates a slightly different
242 * style of yaml. Setting this parameter to {@code true} is useful only
243 * for testing that the client-side code is able to parse this style of
245 * @return A Yaml string.
247 public String
toYaml(boolean serverStyle
) {
248 StringBuilder builder
= new StringBuilder(1024);
250 builder
.append(IndexYamlReader
.INDEX_DEFINITIONS_TAG
).append("\n");
252 builder
.append("indexes:");
253 int numIndexes
= (null == indexes ?
0 : indexes
.size());
254 if (0 == numIndexes
&& serverStyle
) {
255 builder
.append(" []");
257 builder
.append("\n");
258 for (Index index
: indexes
) {
259 String indexYaml
= (serverStyle ? index
.toServerStyleYaml() : index
.toLocalStyleYaml());
260 builder
.append(indexYaml
);
262 return builder
.toString();