View Javadoc
1   /**
2    * Copyright (c) 2014, stateful.co
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met: 1) Redistributions of source code must retain the above
8    * copyright notice, this list of conditions and the following
9    * disclaimer. 2) Redistributions in binary form must reproduce the above
10   * copyright notice, this list of conditions and the following
11   * disclaimer in the documentation and/or other materials provided
12   * with the distribution. 3) Neither the name of the stateful.co nor
13   * the names of its contributors may be used to endorse or promote
14   * products derived from this software without specific prior written
15   * permission.
16   *
17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21   * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28   * OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package co.stateful.rest;
31  
32  import co.stateful.spi.Counters;
33  import com.google.common.collect.Iterables;
34  import com.rexsl.page.JaxbBundle;
35  import com.rexsl.page.Link;
36  import com.rexsl.page.PageBuilder;
37  import java.io.IOException;
38  import java.util.logging.Level;
39  import javax.ws.rs.FormParam;
40  import javax.ws.rs.GET;
41  import javax.ws.rs.POST;
42  import javax.ws.rs.Path;
43  import javax.ws.rs.QueryParam;
44  import javax.ws.rs.core.Response;
45  import org.apache.commons.io.IOUtils;
46  
47  /**
48   * Counters of a user.
49   *
50   * @author Yegor Bugayenko (yegor@tpc2.com)
51   * @version $Id$
52   * @checkstyle MultipleStringLiteralsCheck (500 lines)
53   */
54  @Path("/counters")
55  public final class CountersRs extends BaseRs {
56  
57      /**
58       * Query param.
59       */
60      private static final String PARAM = "name";
61  
62      /**
63       * Get entrance page JAX-RS response.
64       * @return The JAX-RS response
65       * @throws Exception If some problem inside
66       */
67      @GET
68      @Path("/")
69      public Response index() throws Exception {
70          return new PageBuilder()
71              .stylesheet("/xsl/counters.xsl")
72              .build(StPage.class)
73              .init(this)
74              .append(
75                  new JaxbBundle(
76                      "documentation",
77                      IOUtils.toString(
78                          this.getClass().getResourceAsStream(
79                              "doc-counters.html"
80                          )
81                      )
82                  )
83              )
84              .append(this.list())
85              .append(new JaxbBundle("menu", "counters"))
86              .link(new Link("add", "./add"))
87              .render()
88              .build();
89      }
90  
91      /**
92       * Add a new counter.
93       * @param name Name of the counter
94       * @throws IOException If fails due to IO problem
95       */
96      @POST
97      @Path("/add")
98      public void add(@FormParam(CountersRs.PARAM) final String name)
99          throws IOException {
100         if (!name.matches("[0-9a-zA-Z\\-]{1,32}")) {
101             throw this.flash().redirect(
102                 this.uriInfo().getBaseUriBuilder()
103                     .clone()
104                     .path(CountersRs.class)
105                     .build(),
106                 "1-32 letters, numbers or dashes",
107                 Level.WARNING
108             );
109         }
110         if (Iterables.size(this.user().counters().names()) > Counters.MAX) {
111             throw this.flash().redirect(
112                 this.uriInfo().getBaseUriBuilder()
113                     .clone()
114                     .path(CountersRs.class)
115                     .build(),
116                 "too many counters in your account",
117                 Level.SEVERE
118             );
119         }
120         this.user().counters().create(name);
121         throw this.flash().redirect(
122             this.uriInfo().getBaseUriBuilder()
123                 .clone()
124                 .path(CountersRs.class)
125                 .build(),
126             String.format("counter %s created successfully", name),
127             Level.INFO
128         );
129     }
130 
131     /**
132      * Delete a counter.
133      * @param name Name of the counter
134      * @throws IOException If fails due to IO problem
135      */
136     @GET
137     @Path("/delete")
138     public void delete(@QueryParam(CountersRs.PARAM) final String name)
139         throws IOException {
140         this.user().counters().delete(name);
141         throw this.flash().redirect(
142             this.uriInfo().getBaseUriBuilder()
143                 .clone()
144                 .path(CountersRs.class)
145                 .build(),
146             String.format("counter %s deleted successfully", name),
147             Level.INFO
148         );
149     }
150 
151     /**
152      * Get all counters of a user.
153      * @return Counters
154      * @throws IOException If fails due to IO problem
155      */
156     private JaxbBundle list() throws IOException {
157         return new JaxbBundle("counters").add(
158             // @checkstyle AnonInnerLengthCheck (50 lines)
159             new JaxbBundle.Group<String>(this.user().counters().names()) {
160                 @Override
161                 public JaxbBundle bundle(final String name) {
162                     return new JaxbBundle("counter")
163                         .add("name", name)
164                         .up()
165                         .link(
166                             new Link(
167                                 "set",
168                                 CountersRs.this.uriInfo().getBaseUriBuilder()
169                                     .clone()
170                                     .path(CounterRs.class)
171                                     .path(CounterRs.class, "set")
172                                     .build(name)
173                             )
174                         )
175                         .link(
176                             new Link(
177                                 "increment",
178                                 CountersRs.this.uriInfo().getBaseUriBuilder()
179                                     .clone()
180                                     .path(CounterRs.class)
181                                     .path(CounterRs.class, "increment")
182                                     .build(name)
183                             )
184                         )
185                         .link(
186                             new Link(
187                                 "delete",
188                                 CountersRs.this.uriInfo().getBaseUriBuilder()
189                                     .clone()
190                                     .path(CountersRs.class)
191                                     .path(CountersRs.class, "delete")
192                                     .queryParam(CountersRs.PARAM, "{x}")
193                                     .build(name)
194                             )
195                         );
196                 }
197             }
198         );
199     }
200 
201 }