Class PetStore

java.lang.Object
org.apache.juneau.petstore.service.PetStore

public class PetStore extends Object
In-memory Pet/Order/User store seeded from classpath JSON.

Backed by ConcurrentHashMaps; pet and order IDs auto-assign via AtomicLong starting from the highest seeded ID plus one (or 1 if no seeds existed). Seed files live on the classpath at petstore/init/{Pets,Orders,Users}.json and are loaded lazily on first access.

This is a sample/demo store — there is no persistence, no transactions, and no replication. Restart wipes state back to the seeded baseline (and clears the audit trail).

Every successful create, update or delete is recorded in the audit trail; see getAudit().

See Also:
  • Field Details

  • Constructor Details

    • PetStore

      public PetStore()
      Constructor using the system UTC clock.

      Eagerly loads the bundled classpath seed data. Seeding writes no audit.

    • PetStore

      public PetStore(Clock clock)
      Constructor.
      Parameters:
      clock - The clock used to timestamp audit entries. Must not be null.
  • Method Details

    • clock

      public Clock clock()
      Returns:
      The clock this store timestamps with.
    • getPets

      public Collection<Pet> getPets()
      Returns all pets.
      Returns:
      All pets, in arbitrary order. Never null.
    • getPet

      public Pet getPet(long id)
      Returns a pet by ID.
      Parameters:
      id - The pet ID.
      Returns:
      The pet, or null if not found.
    • createPet

      public Pet createPet(Pet pet)
      Creates a new pet.

      Assigns the next available ID, ignoring any caller-supplied ID.

      Parameters:
      pet - The pet to create. Must not be null.
      Returns:
      The created pet (same instance, with assigned ID).
    • createPet

      public Pet createPet(Pet pet, String actor)
      Creates a pet and records a CREATE audit entry.
      Parameters:
      pet - The pet. Its ID is overwritten. Must not be null.
      actor - Who is creating it, e.g. "console:alice".
      Returns:
      The stored pet.
    • restock

      public List<Pet> restock(Map<Species,Integer> perSpecies, String actor)
      Adds a batch of available pets, one per requested count, and records one summary RESTOCK audit entry.
      Example:

      var added = store.restock(Map.of(Species.DOG, 2, Species.CAT, 1), "job:restock"); // 3 new pets named "DOG #101", "DOG #102", "CAT #103" (species + store-unique id), plus one RESTOCK audit entry.

      Parameters:
      perSpecies - How many pets of each species to add. Must not be null; each count must be 0..MAX_RESTOCK_PER_SPECIES.
      actor - Who is restocking, e.g. "job:restock:console:alice".
      Returns:
      The created pets.
      Throws:
      IllegalArgumentException - If the map, a species, or a count is null, negative, or above the cap. Nothing is added.
    • updatePet

      public Pet updatePet(Pet pet)
      Updates an existing pet.
      Parameters:
      pet - The pet to update. Must not be null; must carry an ID matching an existing pet.
      Returns:
      The updated pet.
      Throws:
      PetstoreNotFoundException - If no pet with the given ID exists.
    • updatePet

      public Pet updatePet(Pet pet, String actor)
      Replaces a pet and records an UPDATE audit entry.
      Parameters:
      pet - The pet. Must not be null.
      actor - Who is updating it.
      Returns:
      The stored pet.
      Throws:
      PetstoreNotFoundException - If no pet with the given ID exists.
    • deletePet

      public void deletePet(long id)
      Deletes a pet by ID.
      Parameters:
      id - The pet ID.
      Throws:
      PetstoreNotFoundException - If no pet with the given ID exists.
    • deletePet

      public void deletePet(long id, String actor)
      Deletes a pet and records a DELETE audit entry.
      Parameters:
      id - The pet ID.
      actor - Who is deleting it.
      Throws:
      PetstoreNotFoundException - If no pet with the given ID exists.
    • getOrders

      Returns all orders.
      Returns:
      All orders, in arbitrary order. Never null.
    • getOrder

      public Order getOrder(long id)
      Returns an order by ID.
      Parameters:
      id - The order ID.
      Returns:
      The order, or null if not found.
    • createOrder

      public Order createOrder(Order order)
      Creates a new order.

      Assigns the next available ID, ignoring any caller-supplied ID.

      Parameters:
      order - The order to create. Must not be null.
      Returns:
      The created order (same instance, with assigned ID).
    • createOrder

      public Order createOrder(Order order, String actor)
      Creates an order and records a CREATE audit entry.
      Parameters:
      order - The order. Its ID is overwritten. Must not be null.
      actor - Who is creating it.
      Returns:
      The stored order.
    • updateOrder

      public Order updateOrder(Order order)
      Updates an existing order.
      Parameters:
      order - The order to update. Must not be null; must carry an ID matching an existing order.
      Returns:
      The updated order.
      Throws:
      PetstoreNotFoundException - If no order with the given ID exists.
    • updateOrder

      public Order updateOrder(Order order, String actor)
      Replaces an order and records an UPDATE audit entry.
      Parameters:
      order - The order. Must not be null.
      actor - Who is updating it.
      Returns:
      The stored order.
      Throws:
      PetstoreNotFoundException - If no order with the given ID exists.
    • deleteOrder

      public void deleteOrder(long id)
      Deletes an order by ID.
      Parameters:
      id - The order ID.
      Throws:
      PetstoreNotFoundException - If no order with the given ID exists.
    • deleteOrder

      public void deleteOrder(long id, String actor)
      Deletes an order and records a DELETE audit entry.
      Parameters:
      id - The order ID.
      actor - Who is deleting it.
      Throws:
      PetstoreNotFoundException - If no order with the given ID exists.
    • deleteOrder

      public void deleteOrder(long id, String actor, String reason)
      Cancels an order, recording the reason as the DELETE audit detail.
      Parameters:
      id - The order ID.
      actor - Who is cancelling it.
      reason - Why, or null or blank for none (the audit detail is then the order status).
      Throws:
      PetstoreNotFoundException - If no order with the given ID exists.
    • getUsers

      Returns all users.
      Returns:
      All users, in arbitrary order. Never null.
    • getUser

      public User getUser(String username)
      Returns a user by username.
      Parameters:
      username - The username (primary key).
      Returns:
      The user, or null if not found.
    • createUser

      public User createUser(User user)
      Creates a new user.
      Parameters:
      user - The user to create. Must not be null; must carry a non-null username not already in use.
      Returns:
      The created user.
      Throws:
      IllegalArgumentException - If the username is already in use.
    • createUser

      public User createUser(User user, String actor)
      Creates a user and records a CREATE audit entry.
      Parameters:
      user - The user. Must carry a non-null username not already in use.
      actor - Who is creating it.
      Returns:
      The stored user.
      Throws:
      IllegalArgumentException - If the username is already in use.
    • updateUser

      public User updateUser(User user)
      Updates an existing user.
      Parameters:
      user - The user to update. Must not be null; must carry a username matching an existing user.
      Returns:
      The updated user.
      Throws:
      PetstoreNotFoundException - If no user with the given username exists.
    • updateUser

      public User updateUser(User user, String actor)
      Replaces a user and records an UPDATE audit entry.

      The password is write-only and never read back, so a null or blank password on the replacement keeps the stored one.

      Parameters:
      user - The user. Must carry a username matching an existing user.
      actor - Who is updating it.
      Returns:
      The stored user.
      Throws:
      PetstoreNotFoundException - If no user with the given username exists.
    • deleteUser

      public void deleteUser(String username)
      Deletes a user by username.
      Parameters:
      username - The username.
      Throws:
      PetstoreNotFoundException - If no user with the given username exists.
    • deleteUser

      public void deleteUser(String username, String actor)
      Deletes a user and records a DELETE audit entry.
      Parameters:
      username - The username.
      actor - Who is deleting it.
      Throws:
      PetstoreNotFoundException - If no user with the given username exists.
    • getAudit

      Returns the audit trail.
      Returns:
      An immutable snapshot, oldest first. Never null.
    • recordAudit

      public AuditEntry recordAudit(String actor, String entity, String entityId, String action, String detail)
      Appends an audit entry stamped with this store's clock.

      Public so console operations that are not plain CRUD (restock, apply/discard pending changes) are audited too.

      Parameters:
      actor - Who did it.
      entity - The entity kind.
      entityId - The entity id.
      action - The action.
      detail - A short detail, or null.
      Returns:
      The new entry.
    • pendingChanges

      Returns the staging area for console inline edits (pet detail to Pending changes).
      Returns:
      The pending-changes staging area. Never null.
    • load

      public void load(Collection<Pet> newPets, Collection<Order> newOrders, Collection<User> newUsers, Collection<AuditEntry> newAudit)
      Bulk-loads rows with their ids preserved, writing no audit. Used by PetstoreSeed.

      Id counters advance past the highest loaded id, so later creates never collide.

      Parameters:
      newPets - Pets to add or replace.
      newOrders - Orders to add or replace.
      newUsers - Users to add or replace.
      newAudit - Audit rows to append, in order.
    • queryPets

      Opens a query session over a snapshot of the pets.
      Example:

      try (var s = store.queryPets()) { return DataTablesQuery.run(req, s); }

      Returns:
      A new session; close it.
    • queryOrders

      Returns:
      A new session over a snapshot of the orders; close it.
    • queryUsers

      Returns:
      A new session over a snapshot of the users; close it.
    • queryAudit

      Returns:
      A new session over a snapshot of the audit trail; close it.
    • queryPendingChanges

      Returns:
      A new session over a snapshot of the staged changes; close it.