1.9.30 sync.
[gae.git] / java / src / main / com / google / apphosting / utils / config / IndexesXml.java
blob4a881a8038519f6fbf61be8e7b6668422f466c8b
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;
7 import java.util.List;
9 /**
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";
22 /**
23 * A simple value object, encapsulating the specification of the
24 * part of the index configuration attributable to a single
25 * property.
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;
35 this.mode = mode;
38 public String getPropertyName() {
39 return propName;
42 public String getDirection() {
43 return direction;
46 public String getMode() {
47 return mode;
51 /**
52 * The type of index.
53 * <p>
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.
60 public enum Type {
61 /**
62 * A traditional Datastore index, with properties appearing in
63 * ascending or descending order.
65 ORDERED,
67 /**
68 * An index supporting 2-dimensional distance queries on points on
69 * the surface of the Earth.
71 GEO_SPATIAL
74 /**
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) {
82 this.kind = kind;
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() {
92 return kind;
95 public boolean doIndexAncestors() {
96 return ancestors;
99 public List<PropertySort> getProperties() {
100 return properties;
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
140 * style of yaml.
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");
170 builder.append(" ");
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>();
207 @Override
208 public Iterator<Index> iterator() {
209 return indexes.iterator();
212 public int size(){
213 return indexes.size();
216 public Index addNewIndex(String kind, Boolean ancestors) {
217 Index index = new Index(kind, ancestors);
218 indexes.add(index);
219 return index;
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.
227 * @param index
229 public void addNewIndex(Index index){
230 indexes.add(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
244 * yaml.
245 * @return A Yaml string.
247 public String toYaml(boolean serverStyle) {
248 StringBuilder builder = new StringBuilder(1024);
249 if (serverStyle) {
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();