/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.jersey.examples.flight.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import org.glassfish.jersey.examples.flight.model.Aircraft;
import org.glassfish.jersey.examples.flight.model.AircraftType;
import org.glassfish.jersey.examples.flight.model.Flight;
import org.glassfish.jersey.examples.flight.model.Location;
/**
* Data store for the runtime object model of the application.
*
* @author Marek Potociar (marek.potociar at oracle.com)
*/
public class DataStore {
public static final int CONCURRENCY_LEVEL =
ceilingNextPowerOfTwo(Runtime.getRuntime().availableProcessors());
private static int ceilingNextPowerOfTwo(int x) {
// Hacker's Delight, Chapter 3, Harry S. Warren Jr.
return 1 << (Integer.SIZE - Integer.numberOfLeadingZeros(x - 1));
}
private static final ConcurrentMap<String, Flight> flights =
new ConcurrentHashMap<String, Flight>(16, 0.75f, CONCURRENCY_LEVEL);
private static final Comparator<Flight> FLIGHT_COMPARATOR = new Comparator<Flight>() {
@Override
public int compare(Flight f1, Flight f2) {
return f1.getId().compareTo(f2.getId());
}
};
private static final ConcurrentMap<Integer, Aircraft> aircrafts =
new ConcurrentHashMap<Integer, Aircraft>(16, 0.75f, CONCURRENCY_LEVEL);
private static final AtomicInteger nextAircraftId = new AtomicInteger(1);
private static final Comparator<Aircraft> AIRCRAFT_COMPARATOR = new Comparator<Aircraft>() {
@Override
public int compare(Aircraft a1, Aircraft a2) {
return a1.getId().compareTo(a2.getId());
}
};
public static List<Flight> selectAllFlights() {
final List<Flight> result = new ArrayList<Flight>(DataStore.flights.values());
Collections.sort(result, FLIGHT_COMPARATOR);
return result;
}
public static List<Flight> selectOpenFlights() {
final List<Flight> result = new ArrayList<Flight>(DataStore.flights.values());
final Iterator<Flight> it = result.iterator();
while (it.hasNext()) {
final Flight flight = it.next();
if (!flight.isOpen()) {
it.remove();
}
}
Collections.sort(result, FLIGHT_COMPARATOR);
return result;
}
public static Flight selectFlight(String id) {
return (id == null) ? null : flights.get(id);
}
public static Flight selectFlightByAircraft(Integer id) {
if (id == null) {
return null;
}
final Aircraft aircraft = selectAircraft(id);
if (aircraft == null || aircraft.isAvailable()) {
return null;
}
for (Flight flight : DataStore.flights.values()) {
if (flight.getAircraft().getId().equals(id)) {
return flight;
}
}
return null;
}
public static boolean addFlight(Flight flight) {
if (flight.getId() != null) {
return flights.putIfAbsent(flight.getId(), flight) == null;
}
do {
flight.setId(String.format("FL-%04d", rnd.nextInt(10000)));
} while (flights.putIfAbsent(flight.getId(), flight) != null);
return true;
}
public static Flight removeFlight(String id) {
return (id == null) ? null : flights.remove(id);
}
public static List<Aircraft> selectAllAircrafts() {
final List<Aircraft> result = new ArrayList<Aircraft>(aircrafts.values());
Collections.sort(result, AIRCRAFT_COMPARATOR);
return result;
}
public static List<Aircraft> selectAvailableAircrafts() {
final ArrayList<Aircraft> result = new ArrayList<Aircraft>(aircrafts.values());
final Iterator<Aircraft> it = result.iterator();
while (it.hasNext()) {
Aircraft a = it.next();
if (!a.isAvailable()) {
it.remove();
}
}
Collections.sort(result, AIRCRAFT_COMPARATOR);
return result;
}
public static Aircraft selectAircraft(Integer id) {
return (id == null) ? null : aircrafts.get(id);
}
public static boolean addAircraft(Aircraft aircraft) {
final int id = nextAircraftId.getAndIncrement();
boolean result = aircrafts.putIfAbsent(
id, aircraft) == null;
if (result) {
aircraft.setId(id);
}
return result;
}
public static Aircraft removeAircraft(Integer id) {
return (id == null) ? null : aircrafts.remove(id);
}
/*
* Data generation fields and methods.
*/
private static final Random rnd = new Random();
private static Flight generateFlight() {
final Flight flight = new Flight();
flight.setId(String.format("FL-%04d", rnd.nextInt(10000)));
return flight;
}
private static Aircraft generateAircraft() {
final Aircraft aircraft = new Aircraft();
final Iterator<AircraftType> iterator = aircraftTypes.iterator();
int i = rnd.nextInt(aircraftTypes.size());
AircraftType type = null;
while (iterator.hasNext()) {
type = iterator.next();
if (--i < 0) break;
}
aircraft.setType(type);
aircraft.setLocation(generateLocation(SimEngine.X_BOUND, SimEngine.Y_BOUND));
return aircraft;
}
public static Location generateLocation(int xBound, int yBound) {
return new Location(
rnd.nextInt(xBound), rnd.nextInt(yBound));
}
public static final int MAX_GEN_AIRCRAFTS = 20;
public static final int MAX_GEN_FLIGHTS = 10;
public static void generateData() {
flights.clear();
aircrafts.clear();
LinkedList<Aircraft> planes = new LinkedList<Aircraft>();
while (planes.size() < MAX_GEN_AIRCRAFTS) {
Aircraft a = generateAircraft();
if (addAircraft(a)) {
planes.add(a);
}
}
int count = 0;
while (count < MAX_GEN_FLIGHTS) {
final Flight flight = generateFlight();
if (addFlight(flight)) {
count++;
final Aircraft aircraft = planes.remove(rnd.nextInt(planes.size()));
aircraft.marAssigned();
flight.setAircraft(aircraft);
}
}
}
private static final Set<AircraftType> aircraftTypes = initAircraftTypes();
private static Set<AircraftType> initAircraftTypes() {
Set<AircraftType> ats = new LinkedHashSet<AircraftType>();
// Airbus
// Short-range
ats.add(new AircraftType("Airbus", "A318-100", 107));
ats.add(new AircraftType("Airbus", "A319-100", 124));
ats.add(new AircraftType("Airbus", "A320-200", 150));
ats.add(new AircraftType("Airbus", "A321-200", 185));
ats.add(new AircraftType("Airbus", "A330-200", 253));
ats.add(new AircraftType("Airbus", "A330-300", 295));
ats.add(new AircraftType("Airbus", "A330-500", 222));
ats.add(new AircraftType("Airbus", "A330-500", 222));
// Medium-range
ats.add(new AircraftType("Airbus" ,"A340-200", 240));
ats.add(new AircraftType("Airbus", "A340-300", 295));
ats.add(new AircraftType("Airbus", "A340-500", 313));
ats.add(new AircraftType("Airbus", "A340-600", 380));
// Long-range
ats.add(new AircraftType("Airbus" ,"A350-800", 270));
ats.add(new AircraftType("Airbus", "A350-900", 314));
ats.add(new AircraftType("Airbus", "A350-1000", 350));
ats.add(new AircraftType("Airbus", "A380-800", 525));
// Boeing
// Short-range
ats.add(new AircraftType("Boeing", "737-200", 97));
ats.add(new AircraftType("Boeing", "737-500", 146));
ats.add(new AircraftType("Boeing", "737-900", 177));
// Medium-range
ats.add(new AircraftType("Boeing", "767-200", 181));
ats.add(new AircraftType("Boeing", "767-300", 218));
ats.add(new AircraftType("Boeing", "767-400", 245));
// Long-range
ats.add(new AircraftType("Boeing", "777-200", 314));
ats.add(new AircraftType("Boeing", "777-300", 386));
ats.add(new AircraftType("Boeing", "787-8", 242));
ats.add(new AircraftType("Boeing", "787-9", 280));
ats.add(new AircraftType("Boeing", "787-10", 323));
return Collections.unmodifiableSet(ats);
}
}