package com.lyndir.omicron.webapp.data.service; import com.google.common.base.Verify; import com.google.common.collect.*; import com.lyndir.omicron.api.IGame; import java.net.URI; import java.security.SecureRandom; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentMap; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; /** * @author lhunath, 1/28/2014 */ public class StateManager { private static final Random RANDOM = new SecureRandom(); private static final ConcurrentMap<Long, IGame> games = Maps.newConcurrentMap(); private static final ConcurrentMap<Long, IGame.IBuilder> gameBuilders = Maps.newConcurrentMap(); private static final Table<Map<Long, ?>, Long, URI> redirections = HashBasedTable.create(); @Nonnull public IGame getGame(final long gameID) { return Verify.verifyNotNull( findGame( gameID ), "Game not found: %s", gameID ); } @Nullable public IGame findGame(final long gameID) { return get( games, gameID ); } public long addGame(@Nonnull final IGame game) { return add( games, game ); } @Nonnull public IGame.IBuilder getGameBuilder(final long gameBuilderID) { return Verify.verifyNotNull( findGameBuilder( gameBuilderID ), "Game builder not found: %s", gameBuilderID ); } @Nullable public IGame.IBuilder findGameBuilder(final long gameBuilderID) { return get( gameBuilders, gameBuilderID ); } public long addGameBuilder(@Nonnull final IGame.IBuilder gameBuilder) { return add( gameBuilders, gameBuilder ); } public void dropAndRedirectGameBuilder(final long gameBuilderID, final URI destination) { redirections.put( gameBuilders, gameBuilderID, destination ); gameBuilders.remove( gameBuilderID ); } private static <T> T get(final Map<Long, T> map, final long key) { URI redirection = redirections.get( map, key ); if (redirection != null) throw new WebApplicationException( Response.temporaryRedirect( redirection ).build() ); return map.get( key ); } private static <T> long add(final ConcurrentMap<Long, T> map, final T value) { long id; synchronized (map) { do { id = RANDOM.nextInt( Integer.MAX_VALUE ); } while (map.containsKey( id )); map.put( id, value ); } return id; } }