001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.examples.rest.petstore;
014
015import static java.text.MessageFormat.*;
016
017import java.io.*;
018import java.util.*;
019
020import javax.persistence.*;
021
022import org.apache.juneau.examples.rest.petstore.dto.*;
023import org.apache.juneau.examples.rest.petstore.rest.*;
024import org.apache.juneau.json.*;
025import org.apache.juneau.rest.client.*;
026import org.apache.juneau.utils.*;
027
028/**
029 * Pet store database application.
030 * <p>
031 * Uses JPA persistence to store and retrieve PetStore DTOs.
032 * JPA beans are defined in <code>META-INF/persistence.xml</code>.
033 */
034public class PetStoreService extends AbstractPersistenceService {
035
036   //-----------------------------------------------------------------------------------------------------------------
037   // Initialization methods.
038   //-----------------------------------------------------------------------------------------------------------------
039
040   /**
041    * Initialize the petstore database using JPA.
042    *
043    * @param w Console output.
044    * @return This object (for method chaining).
045    * @throws Exception
046    */
047   public PetStoreService initDirect(PrintWriter w) throws Exception {
048
049      EntityManager em = getEntityManager();
050      EntityTransaction et = em.getTransaction();
051      JsonParser parser = JsonParser.create().build();
052
053      et.begin();
054
055      for (Pet x : em.createQuery("select X from PetstorePet X", Pet.class).getResultList()) {
056         em.remove(x);
057         w.println(format("Deleted pet:  id={0}", x.getId()));
058      }
059      for (Order x : em.createQuery("select X from PetstoreOrder X", Order.class).getResultList()) {
060         em.remove(x);
061         w.println(format("Deleted order:  id={0}", x.getId()));
062      }
063      for (User x : em.createQuery("select X from PetstoreUser X", User.class).getResultList()) {
064         em.remove(x);
065         w.println(format("Deleted user:  username={0}", x.getUsername()));
066      }
067
068      et.commit();
069      et.begin();
070
071      for (Pet x : parser.parse(getStream("init/Pets.json"), Pet[].class)) {
072         x = em.merge(x);
073         w.println(format("Created pet:  id={0}, name={1}", x.getId(), x.getName()));
074      }
075      for (Order x : parser.parse(getStream("init/Orders.json"), Order[].class)) {
076         x = em.merge(x);
077         w.println(format("Created order:  id={0}", x.getId()));
078      }
079      for (User x: parser.parse(getStream("init/Users.json"), User[].class)) {
080         x = em.merge(x);
081         w.println(format("Created user:  username={0}", x.getUsername()));
082      }
083
084      et.commit();
085
086      return this;
087   }
088
089   /**
090    * Initialize the petstore database by using a remote resource interface against our REST.
091    *
092    * @param w Console output.
093    * @return This object (for method chaining).
094    * @throws Exception
095    */
096   public PetStoreService initViaRest(PrintWriter w) throws Exception {
097      JsonParser parser = JsonParser.create().ignoreUnknownBeanProperties().build();
098
099      String port = System.getProperty("juneau.serverPort", "8000");
100
101      try (RestClient rc = RestClient.create().json().rootUrl("http://localhost:" + port).build()) {
102         PetStore ps = rc.getRemoteResource(PetStore.class);
103
104         for (Pet x : ps.getPets()) {
105            ps.deletePet("apiKey", x.getId());
106            w.println(format("Deleted pet:  id={0}", x.getId()));
107         }
108         for (Order x : ps.getOrders()) {
109            ps.deleteOrder(x.getId());
110            w.println(format("Deleted order:  id={0}", x.getId()));
111         }
112         for (User x : ps.getUsers()) {
113            ps.deleteUser(x.getUsername());
114            w.println(format("Deleted user:  username={0}", x.getUsername()));
115         }
116         for (CreatePet x : parser.parse(getStream("init/Pets.json"), CreatePet[].class)) {
117            long id = ps.postPet(x);
118            w.println(format("Created pet:  id={0}, name={1}", id, x.getName()));
119         }
120         for (Order x : parser.parse(getStream("init/Orders.json"), Order[].class)) {
121            long id = ps.placeOrder(x.getPetId(), x.getUsername());
122            w.println(format("Created order:  id={0}", id));
123         }
124         for (User x: parser.parse(getStream("init/Users.json"), User[].class)) {
125            ps.postUser(x);
126            w.println(format("Created user:  username={0}", x.getUsername()));
127         }
128      }
129
130      return this;
131   }
132
133   //-----------------------------------------------------------------------------------------------------------------
134   // Service methods.
135   //-----------------------------------------------------------------------------------------------------------------
136
137   public Pet getPet(long id) throws IdNotFound {
138      return find(Pet.class, id);
139   }
140
141   public Order getOrder(long id) throws IdNotFound {
142      return find(Order.class, id);
143   }
144
145   public User getUser(String username) throws InvalidUsername, IdNotFound  {
146      assertValidUsername(username);
147      return find(User.class, username);
148   }
149
150   public List<Pet> getPets() {
151      return query("select X from PetstorePet X", Pet.class, (SearchArgs)null);
152   }
153
154   public List<Order> getOrders() {
155      return query("select X from PetstoreOrder X", Order.class, (SearchArgs)null);
156   }
157
158   public List<User> getUsers() {
159      return query("select X from PetstoreUser X", User.class, (SearchArgs)null);
160   }
161
162   public Pet create(CreatePet c) {
163      return merge(new Pet().status(PetStatus.AVAILABLE).apply(c));
164   }
165
166   public Order create(CreateOrder c) {
167      return merge(new Order().status(OrderStatus.PLACED).apply(c));
168   }
169
170   public User create(User c) {
171      return merge(new User().apply(c));
172   }
173
174   public Pet update(UpdatePet u) throws IdNotFound {
175      EntityManager em = getEntityManager();
176      return merge(em, find(em, Pet.class, u.getId()).apply(u));
177   }
178
179   public Order update(Order o) throws IdNotFound {
180      EntityManager em = getEntityManager();
181      return merge(em, find(em, Order.class, o.getId()).apply(o));
182   }
183
184   public User update(User u) throws IdNotFound, InvalidUsername {
185      assertValidUsername(u.getUsername());
186      EntityManager em = getEntityManager();
187      return merge(em, find(em, User.class, u.getUsername()).apply(u));
188   }
189
190   public void removePet(long id) throws IdNotFound {
191      EntityManager em = getEntityManager();
192      remove(em, find(em, Pet.class, id));
193   }
194
195   public void removeOrder(long id) throws IdNotFound {
196      EntityManager em = getEntityManager();
197      remove(em, find(em, Order.class, id));
198   }
199
200   public void removeUser(String username) throws IdNotFound {
201      EntityManager em = getEntityManager();
202      remove(em, find(em, User.class, username));
203   }
204
205   public Collection<Pet> getPetsByStatus(PetStatus[] status) {
206      return getEntityManager()
207         .createQuery("select X from PetstorePet X where X.status in :status", Pet.class)
208         .setParameter("status", status)
209         .getResultList();
210   }
211
212   public Collection<Pet> getPetsByTags(String[] tags) throws InvalidTag {
213      return getEntityManager()
214         .createQuery("select X from PetstorePet X where X.tags in :tags", Pet.class)
215         .setParameter("tags", tags)
216         .getResultList();
217   }
218
219   public Map<PetStatus,Integer> getInventory() {
220      Map<PetStatus,Integer> m = new LinkedHashMap<>();
221      for (Pet p : getPets()) {
222         PetStatus ps = p.getStatus();
223         if (! m.containsKey(ps))
224            m.put(ps, 1);
225         else
226            m.put(ps, m.get(ps) + 1);
227      }
228      return m;
229   }
230
231   public boolean isValid(String username, String password) {
232      return getUser(username).getPassword().equals(password);
233   }
234
235   //-----------------------------------------------------------------------------------------------------------------
236   // Helper methods
237   //-----------------------------------------------------------------------------------------------------------------
238
239   private void assertValidUsername(String username) throws InvalidUsername {
240      if (username == null || ! username.matches("[\\w\\d]{3,8}"))
241         throw new InvalidUsername();
242   }
243
244   private InputStream getStream(String fileName) {
245      return getClass().getResourceAsStream(fileName);
246   }
247}