// Path: examples/dictionary/client/src/main/java/com/bazaarvoice/ostrich/examples/dictionary/client/WordRange.java
// public class WordRange implements Predicate<String> {
//     private static final Pattern RANGE_PATTERN = Pattern.compile("(\\w*)-(\\w*)", Pattern.CASE_INSENSITIVE);
// 
//     private final String rangeString;
//     private final NavigableMap<String, String> ranges;
// 
//     public WordRange(String rangeString) {
//         this.rangeString = rangeString;
// 
//         // Parse the range string into a TreeMap of "start -> end".
//         NavigableMap<String, String> ranges = Maps.newTreeMap();
//         for (String range : Splitter.on(',').omitEmptyStrings().trimResults().split(rangeString)) {
//             Matcher matcher = RANGE_PATTERN.matcher(range);
//             if (!matcher.matches()) {
//                 throw new IllegalArgumentException(format("Invalid word range: %s", range));
//             }
//             String from = matcher.group(1).toLowerCase();
//             String to = matcher.group(2).toLowerCase() + Character.MAX_VALUE;
// 
//             // Make sure the low end of the range is less than the high end, unless the high end is open.
//             checkArgument(from.compareTo(to) <= 0 || to.isEmpty(), "Low end of range must be first: %s", range);
// 
//             // Check that the range don't overlap with each other (the apply fn below assumes ranges are disjoint)
//             Map.Entry<String, String> existingRange = ranges.floorEntry(to);
//             if (existingRange != null && existingRange.getValue().compareTo(from) >= 0) {
//                 String conflictFrom = existingRange.getKey();
//                 String conflictTo = existingRange.getValue();
//                 throw new IllegalArgumentException(format("Individual ranges may not overlap: %s-%s vs. %s",
//                         conflictFrom, conflictTo.substring(0, conflictTo.length() - 1), range));
//             }
// 
//             ranges.put(from, to);
//         }
//         checkArgument(!ranges.isEmpty(), "Empty word range: %s", rangeString);
// 
//         this.ranges = ranges;
//     }
// 
//     @Override
//     public boolean apply(String string) {
//         String lower = string.toLowerCase();
//         Map.Entry<String, String> entry = ranges.floorEntry(lower);
//         return entry != null && lower.compareTo(entry.getValue()) <= 0;
//     }
// 
//     @Override
//     @JsonValue
//     public String toString() {
//         return rangeString;
//     }
// }


import com.bazaarvoice.ostrich.examples.dictionary.client.WordRange;
import com.codahale.metrics.annotation.Timed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import static com.google.common.base.Preconditions.checkArgument;
package com.bazaarvoice.ostrich.examples.dictionary.service;




/**
 * A Dropwizard+Jersey-based RESTful implementation of a simple dictionary service.
 * <p>
 * Note: the url contains the service name "dictionary" to allow multiple services to be hosted on the same server.
 * It contains the version number "1" to allow multiple versions of the same service to be hosted on the same server.
 * Future backward-incompatible versions of the dictionary API can be hosted at "/dictionary/2", ....
 * <p>
 * Contains a backdoor for simulating server outages.
 */
@Path("/dictionary/1")
@Produces(MediaType.APPLICATION_JSON)
public class DictionaryResource {
    private final WordList _words;
// Path: examples/dictionary/client/src/main/java/com/bazaarvoice/ostrich/examples/dictionary/client/WordRange.java
// public class WordRange implements Predicate<String> {
//     private static final Pattern RANGE_PATTERN = Pattern.compile("(\\w*)-(\\w*)", Pattern.CASE_INSENSITIVE);
// 
//     private final String rangeString;
//     private final NavigableMap<String, String> ranges;
// 
//     public WordRange(String rangeString) {
//         this.rangeString = rangeString;
// 
//         // Parse the range string into a TreeMap of "start -> end".
//         NavigableMap<String, String> ranges = Maps.newTreeMap();
//         for (String range : Splitter.on(',').omitEmptyStrings().trimResults().split(rangeString)) {
//             Matcher matcher = RANGE_PATTERN.matcher(range);
//             if (!matcher.matches()) {
//                 throw new IllegalArgumentException(format("Invalid word range: %s", range));
//             }
//             String from = matcher.group(1).toLowerCase();
//             String to = matcher.group(2).toLowerCase() + Character.MAX_VALUE;
// 
//             // Make sure the low end of the range is less than the high end, unless the high end is open.
//             checkArgument(from.compareTo(to) <= 0 || to.isEmpty(), "Low end of range must be first: %s", range);
// 
//             // Check that the range don't overlap with each other (the apply fn below assumes ranges are disjoint)
//             Map.Entry<String, String> existingRange = ranges.floorEntry(to);
//             if (existingRange != null && existingRange.getValue().compareTo(from) >= 0) {
//                 String conflictFrom = existingRange.getKey();
//                 String conflictTo = existingRange.getValue();
//                 throw new IllegalArgumentException(format("Individual ranges may not overlap: %s-%s vs. %s",
//                         conflictFrom, conflictTo.substring(0, conflictTo.length() - 1), range));
//             }
// 
//             ranges.put(from, to);
//         }
//         checkArgument(!ranges.isEmpty(), "Empty word range: %s", rangeString);
// 
//         this.ranges = ranges;
//     }
// 
//     @Override
//     public boolean apply(String string) {
//         String lower = string.toLowerCase();
//         Map.Entry<String, String> entry = ranges.floorEntry(lower);
//         return entry != null && lower.compareTo(entry.getValue()) <= 0;
//     }
// 
//     @Override
//     @JsonValue
//     public String toString() {
//         return rangeString;
//     }
// }


// Path: examples/dictionary/service/src/main/java/com/bazaarvoice/ostrich/examples/dictionary/service/DictionaryResource.java
import com.bazaarvoice.ostrich.examples.dictionary.client.WordRange;
import com.codahale.metrics.annotation.Timed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import static com.google.common.base.Preconditions.checkArgument;

package com.bazaarvoice.ostrich.examples.dictionary.service;




/**
 * A Dropwizard+Jersey-based RESTful implementation of a simple dictionary service.
 * <p>
 * Note: the url contains the service name "dictionary" to allow multiple services to be hosted on the same server.
 * It contains the version number "1" to allow multiple versions of the same service to be hosted on the same server.
 * Future backward-incompatible versions of the dictionary API can be hosted at "/dictionary/2", ....
 * <p>
 * Contains a backdoor for simulating server outages.
 */
@Path("/dictionary/1")
@Produces(MediaType.APPLICATION_JSON)
public class DictionaryResource {
    private final WordList _words;
    private final WordRange _range;