// Path: samples/java/shorturls/app/models/IdGenerator.java
// public class IdGenerator {
// 
//     public static  class Counter {
//         public Long value;
// 
//         public Counter() {}
//         public Counter(Long value) {
//             this.value = value;
//         }
//     }
// 
//     public static class IncrementAndGet {}
// 
//     public static ActorSystem system = ActorSystem.create("AgentSystem");
//     public static Timeout t = new Timeout(Duration.create(5, TimeUnit.SECONDS));
//     public static ActorRef generator = system.actorOf(new Props(Generator.class), "generator");
//     public static String counterKey = "urlidgenerator";
//     public static F.Promise<Object> nextId() {
//         return new F.Promise(ask(generator, new IncrementAndGet(), t));
//     }
// 
//     public static class Generator extends UntypedActor {
// 
//         public void onReceive(Object message) throws Exception {
//             if (message instanceof IncrementAndGet) {
//                 final ActorRef ref = sender();
//                 ShortURL.bucket.get(counterKey, Counter.class).map(new F.Function<Counter, Object>() {
//                     @Override
//                     public Object apply(Counter counter) throws Throwable {
//                         if (counter != null) {
//                             final Counter newValue = new Counter(counter.value + 1);
//                             ShortURL.bucket.set(counterKey, newValue).map(new F.Function<OpResult, Object>() {
//                                 @Override
//                                 public Object apply(OpResult operationStatus) throws Throwable {
//                                     ref.tell(newValue.value, self());
//                                     return null;
//                                 }
//                             });
//                             return null;
//                         } else {
//                             ShortURL.bucket.set(counterKey, 1L).map(new F.Function<OpResult, Object>() {
//                                 @Override
//                                 public Object apply(OpResult operationStatus) throws Throwable {
//                                     ref.tell(1L, self());
//                                     return null;
//                                 }
//                             });
//                             return null;
//                         }
//                     }
//                 });
//             }
//         }
//     }
// }
// 
// Path: samples/java/shorturls/app/models/ShortURL.java
// public class ShortURL {
// 
//     public static CouchbaseBucket bucket = Couchbase.bucket("default");
// 
//     public String id;
//     public String originalUrl;
//     public String t = "shorturl";
// 
//     public ShortURL() {}
// 
//     public ShortURL(String id, String originalUrl) {
//         this.id = id;
//         this.originalUrl = originalUrl;
//         this.t = "shorturl";
//     }
// 
//     public static class URLValue {
//         public String url;
//     }
// 
//     public static Form<URLValue> form = form(URLValue.class);
// 
//     public static F.Promise<ShortURL> findById(String id) {
//         return bucket.get(id, ShortURL.class);
//     }
// 
//     public static F.Promise<Collection<ShortURL>> findAll() {
//         return bucket.find("shorturls", "by_url", new Query().setIncludeDocs(true).setStale(Stale.FALSE), ShortURL.class);
//     }
// 
//     public static F.Promise<F.Option<ShortURL>> findByURL(String url) {
//         Query query = new Query()
//                 .setLimit(1)
//                 .setIncludeDocs(true)
//                 .setStale(Stale.FALSE)
//                 .setRangeStart(ComplexKey.of(url))
//                 .setRangeEnd(ComplexKey.of(url + "\uefff"));
//         return bucket.find("shorturls", "by_url", query, ShortURL.class).map(new F.Function<Collection<ShortURL>, F.Option<ShortURL>>() {
//             @Override
//             public F.Option<ShortURL> apply(Collection<ShortURL> shortURLs) throws Throwable {
//                 if (shortURLs.isEmpty()) {
//                     return F.Option.None();
//                 }
//                 return F.Option.Some(shortURLs.iterator().next());
//             }
//         });
//     }
// 
//     public static F.Promise<OpResult> save(ShortURL url) {
//         return bucket.set(url.id, url);
//     }
// 
//     public static F.Promise<OpResult> remove(String id) {
//         return bucket.delete(id);
//     }
// 
//     public static F.Promise<OpResult> remove(ShortURL url) {
//         return bucket.delete(url.id);
//     }
// }


import models.IdGenerator;
import models.ShortURL;
import net.spy.memcached.ops.OperationStatus;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.reactivecouchbase.client.OpResult;
import play.libs.F;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Result;
import java.util.Collection;
        try {
            urlValue = ShortURL.form.bindFromRequest().get().url;
        } catch(Exception e) {}

        if (urlValue == null) {
            ObjectNode node = Json.newObject();
            node.put("status", "error");
            node.put("error", true);
            node.put("deleted", false);
            node.put("message", "You need to pass a non empty url value");
            return badRequest(node);
        } else {
            final String url = urlValue;
            return async(ShortURL.findByURL(url).flatMap(new F.Function<F.Option<ShortURL>, F.Promise<Result>>() {
                @Override
                public F.Promise<Result> apply(F.Option<ShortURL> maybe) throws Throwable {
                    return maybe.map(new F.Function<ShortURL, F.Promise<Result>>() {
                        @Override
                        public F.Promise<Result> apply(ShortURL shortURL) throws Throwable {
                            ObjectNode node = Json.newObject();
                            node.put("status", "existing");
                            node.put("error", false);
                            node.put("deleted", true);
                            node.put("message", "already exists");
                            node.put("url", Json.toJson(shortURL));
                            return F.Promise.pure((Result) ok(node));
                        }
                    }).getOrElse(new F.Function<Void, F.Promise<Result>>() {
                        @Override
                        public F.Promise<Result> apply(Void aVoid) throws Throwable {
// Path: samples/java/shorturls/app/models/IdGenerator.java
// public class IdGenerator {
// 
//     public static  class Counter {
//         public Long value;
// 
//         public Counter() {}
//         public Counter(Long value) {
//             this.value = value;
//         }
//     }
// 
//     public static class IncrementAndGet {}
// 
//     public static ActorSystem system = ActorSystem.create("AgentSystem");
//     public static Timeout t = new Timeout(Duration.create(5, TimeUnit.SECONDS));
//     public static ActorRef generator = system.actorOf(new Props(Generator.class), "generator");
//     public static String counterKey = "urlidgenerator";
//     public static F.Promise<Object> nextId() {
//         return new F.Promise(ask(generator, new IncrementAndGet(), t));
//     }
// 
//     public static class Generator extends UntypedActor {
// 
//         public void onReceive(Object message) throws Exception {
//             if (message instanceof IncrementAndGet) {
//                 final ActorRef ref = sender();
//                 ShortURL.bucket.get(counterKey, Counter.class).map(new F.Function<Counter, Object>() {
//                     @Override
//                     public Object apply(Counter counter) throws Throwable {
//                         if (counter != null) {
//                             final Counter newValue = new Counter(counter.value + 1);
//                             ShortURL.bucket.set(counterKey, newValue).map(new F.Function<OpResult, Object>() {
//                                 @Override
//                                 public Object apply(OpResult operationStatus) throws Throwable {
//                                     ref.tell(newValue.value, self());
//                                     return null;
//                                 }
//                             });
//                             return null;
//                         } else {
//                             ShortURL.bucket.set(counterKey, 1L).map(new F.Function<OpResult, Object>() {
//                                 @Override
//                                 public Object apply(OpResult operationStatus) throws Throwable {
//                                     ref.tell(1L, self());
//                                     return null;
//                                 }
//                             });
//                             return null;
//                         }
//                     }
//                 });
//             }
//         }
//     }
// }
// 
// Path: samples/java/shorturls/app/models/ShortURL.java
// public class ShortURL {
// 
//     public static CouchbaseBucket bucket = Couchbase.bucket("default");
// 
//     public String id;
//     public String originalUrl;
//     public String t = "shorturl";
// 
//     public ShortURL() {}
// 
//     public ShortURL(String id, String originalUrl) {
//         this.id = id;
//         this.originalUrl = originalUrl;
//         this.t = "shorturl";
//     }
// 
//     public static class URLValue {
//         public String url;
//     }
// 
//     public static Form<URLValue> form = form(URLValue.class);
// 
//     public static F.Promise<ShortURL> findById(String id) {
//         return bucket.get(id, ShortURL.class);
//     }
// 
//     public static F.Promise<Collection<ShortURL>> findAll() {
//         return bucket.find("shorturls", "by_url", new Query().setIncludeDocs(true).setStale(Stale.FALSE), ShortURL.class);
//     }
// 
//     public static F.Promise<F.Option<ShortURL>> findByURL(String url) {
//         Query query = new Query()
//                 .setLimit(1)
//                 .setIncludeDocs(true)
//                 .setStale(Stale.FALSE)
//                 .setRangeStart(ComplexKey.of(url))
//                 .setRangeEnd(ComplexKey.of(url + "\uefff"));
//         return bucket.find("shorturls", "by_url", query, ShortURL.class).map(new F.Function<Collection<ShortURL>, F.Option<ShortURL>>() {
//             @Override
//             public F.Option<ShortURL> apply(Collection<ShortURL> shortURLs) throws Throwable {
//                 if (shortURLs.isEmpty()) {
//                     return F.Option.None();
//                 }
//                 return F.Option.Some(shortURLs.iterator().next());
//             }
//         });
//     }
// 
//     public static F.Promise<OpResult> save(ShortURL url) {
//         return bucket.set(url.id, url);
//     }
// 
//     public static F.Promise<OpResult> remove(String id) {
//         return bucket.delete(id);
//     }
// 
//     public static F.Promise<OpResult> remove(ShortURL url) {
//         return bucket.delete(url.id);
//     }
// }


// Path: samples/java/shorturls/app/controllers/ApiController.java
import models.IdGenerator;
import models.ShortURL;
import net.spy.memcached.ops.OperationStatus;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.reactivecouchbase.client.OpResult;
import play.libs.F;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Result;
import java.util.Collection;

        try {
            urlValue = ShortURL.form.bindFromRequest().get().url;
        } catch(Exception e) {}

        if (urlValue == null) {
            ObjectNode node = Json.newObject();
            node.put("status", "error");
            node.put("error", true);
            node.put("deleted", false);
            node.put("message", "You need to pass a non empty url value");
            return badRequest(node);
        } else {
            final String url = urlValue;
            return async(ShortURL.findByURL(url).flatMap(new F.Function<F.Option<ShortURL>, F.Promise<Result>>() {
                @Override
                public F.Promise<Result> apply(F.Option<ShortURL> maybe) throws Throwable {
                    return maybe.map(new F.Function<ShortURL, F.Promise<Result>>() {
                        @Override
                        public F.Promise<Result> apply(ShortURL shortURL) throws Throwable {
                            ObjectNode node = Json.newObject();
                            node.put("status", "existing");
                            node.put("error", false);
                            node.put("deleted", true);
                            node.put("message", "already exists");
                            node.put("url", Json.toJson(shortURL));
                            return F.Promise.pure((Result) ok(node));
                        }
                    }).getOrElse(new F.Function<Void, F.Promise<Result>>() {
                        @Override
                        public F.Promise<Result> apply(Void aVoid) throws Throwable {
                            return IdGenerator.nextId().flatMap(new F.Function<Object, F.Promise<Result>>() {