package edu.kit.pse.ws2013.routekit.profiles; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; /** * A vehicle profile. */ public class Profile implements Cloneable { /** * The name of the profile. */ private String name; /** * The type of the vehicle. */ private VehicleType vehicleType; /** * The height of the vehicle, in centimeters. */ private int height; /** * The width of the vehicle, in centimeters. */ private int width; /** * The weight of the vehicle, in kilograms. */ private int weight; /** * The average speed of the vehicle on a highway, in kilometers per hour. */ private int speedHighway; /** * The average speed of the vehicle on an ordinary (country) road, in * kilometers per hour. */ private int speedRoad; /** * If the profile is a default profile or not. */ private boolean isDefault; public static final Profile defaultCar = new Profile("PKW (Standard)", VehicleType.Car, 160, 160, 1400, 120, 80, true); public static final Profile defaultTruck = new Profile("LKW (Standard)", VehicleType.Truck, 350, 240, 20000, 80, 80, true); /** * Creates a new non-default {@link Profile} with the specified parameters. * * @param name * The name of the profile. * @param vehicleType * The type of the vehicle. * @param height * The height of the vehicle, in centimeters. * @param width * The width of the vehicle, in centimeters. * @param weight * The weight of the vehicle, in kilograms. * @param speedHighway * The average speed of the vehicle on a highway, in kilometers * per hour. * @param speedRoad * The average speed of the vehicle on an ordinary (country) * road, in kilometers per hour. */ public Profile(String name, VehicleType vehicleType, int height, int width, int weight, int speedHighway, int speedRoad) { this(name, vehicleType, height, width, weight, speedHighway, speedRoad, false); } /** * Creates a new {@link Profile} with the specified parameters. * * @param name * The name of the profile. * @param vehicleType * The type of the vehicle. * @param height * The height of the vehicle, in centimeters. * @param width * The width of the vehicle, in centimeters. * @param weight * The weight of the vehicle, in kilograms. * @param speedHighway * The average speed of the vehicle on a highway, in kilometers * per hour. * @param speedRoad * The average speed of the vehicle on an ordinary (country) * road, in kilometers per hour. * @param isDefault * If the profile is a default profile or not. */ private Profile(String name, VehicleType vehicleType, int height, int width, int weight, int speedHighway, int speedRoad, boolean isDefault) { this.name = name; this.vehicleType = vehicleType; this.height = height; this.width = width; this.weight = weight; this.speedHighway = speedHighway; this.speedRoad = speedRoad; this.isDefault = isDefault; } /** * Creates and returns a non-default copy of this profile. */ @Override public Profile clone() { return new Profile(name, vehicleType, height, width, weight, speedHighway, speedRoad); } @Override public String toString() { return name; } /** * Saves the profile to the specified file using the Java {@link Properties} * format. * * @param file * The file to which the profile should be saved. * @throws IOException * If the file can’t be written. * @see #load(File) */ public void save(File file) throws IOException { Properties p = new Properties(); p.setProperty("name", name); p.setProperty("vehicleType", vehicleType.name()); p.setProperty("height", Integer.toString(height)); p.setProperty("width", Integer.toString(width)); p.setProperty("weight", Integer.toString(weight)); p.setProperty("speedHighway", Integer.toString(speedHighway)); p.setProperty("speedRoad", Integer.toString(speedRoad)); try (FileWriter writer = new FileWriter(file)) { p.store(new FileWriter(file), null); } } /** * Loads a profile from the specified file and returns it. * * @param file * The file from which the profile should be loaded. * @return A new profile with the values from the file. * @throws IOException * If the file can’t be read or parsed. * @throws FileNotFoundException * If the file doesn’t exist. * @see #save(File) */ public static Profile load(File file) throws FileNotFoundException, IOException { Properties p = new Properties(); try (FileReader reader = new FileReader(file)) { p.load(reader); } String name = p.getProperty("name"); VehicleType vehicleType = VehicleType.valueOf(p .getProperty("vehicleType")); Integer height = parseIntElseNull(p.getProperty("height")); Integer width = parseIntElseNull(p.getProperty("width")); Integer weight = parseIntElseNull(p.getProperty("weight")); Integer speedHighway = parseIntElseNull(p.getProperty("speedHighway")); Integer speedRoad = parseIntElseNull(p.getProperty("speedRoad")); if (name == null) { throw new IOException( "name missing or cannot be parsed in profile file '" + file + "'"); } if (vehicleType == null) { throw new IOException( "vehicleType missing or cannot be parsed in profile file '" + file + "'"); } if (width == null) { throw new IOException( "width missing or cannot be parsed in profile file '" + file + "'"); } if (height == null) { throw new IOException( "height missing or cannot be parsed in profile file '" + file + "'"); } if (weight == null) { throw new IOException( "weight missing or cannot be parsed in profile file '" + file + "'"); } if (speedHighway == null) { throw new IOException( "speedHighway missing or cannot be parsed in profile file '" + file + "'"); } if (speedRoad == null) { throw new IOException( "speedRoad missing or cannot be parsed in profile file '" + file + "'"); } return new Profile(name, vehicleType, height, width, weight, speedHighway, speedRoad); } private static Integer parseIntElseNull(String s) { try { return new Integer(s); } catch (NumberFormatException e) { return null; } } /** * <p> * Indicates if the profile is a default profile. * </p> * <p> * Default profiles are different than normal profiles in that it’s not * allowed to set their values. * </p> * * @return {@code true} if the profile is a default profile, else * {@code false}. */ public boolean isDefault() { return isDefault; } /** * Gets the name of the profile. * * @return The name of the profile. */ public String getName() { return name; } /** * <p> * Sets the name of the profile. * </p> * <p> * Note that this is not allowed for {@link #isDefault() default} profiles. * </p> * * @param name * The name of the profile. */ public void setName(String name) { if (isDefault()) { throw new IllegalStateException( "Can't set parameter of a default profile!"); } this.name = name; } /** * Gets the type of the vehicle. * * @return The type of the vehicle. */ public VehicleType getVehicleType() { return vehicleType; } /** * <p> * Sets the type of the vehicle. * </p> * <p> * Note that this is not allowed for {@link #isDefault() default} profiles. * </p> * * @param name * The type of the vehicle. */ public void setVehicleType(VehicleType vehicleType) { if (isDefault()) { throw new IllegalStateException( "Can't set parameter of a default profile!"); } this.vehicleType = vehicleType; } /** * Gets the height of the vehicle, in centimeters. * * @return The height of the vehicle, in centimeters. */ public int getHeight() { return height; } /** * <p> * Sets the height of the vehicle, in centimeters. * </p> * <p> * Note that this is not allowed for {@link #isDefault() default} profiles. * </p> * * @param name * The height of the vehicle, in centimeters. */ public void setHeight(int height) { if (isDefault()) { throw new IllegalStateException( "Can't set parameter of a default profile!"); } this.height = height; } /** * Gets the width of the vehicle, in centimeters. * * @return The width of the vehicle, in centimeters. */ public int getWidth() { return width; } /** * <p> * Sets the width of the vehicle, in centimeters. * </p> * <p> * Note that this is not allowed for {@link #isDefault() default} profiles. * </p> * * @param name * The width of the vehicle, in centimeters. */ public void setWidth(int width) { if (isDefault()) { throw new IllegalStateException( "Can't set parameter of a default profile!"); } this.width = width; } /** * Gets the weight of the vehicle, in kilograms. * * @return The weight of the vehicle, in kilograms. */ public int getWeight() { return weight; } /** * <p> * Sets the weight of the vehicle, in kilograms. * </p> * <p> * Note that this is not allowed for {@link #isDefault() default} profiles. * </p> * * @param name * The weight of the vehicle, in kilograms. */ public void setWeight(int weight) { if (isDefault()) { throw new IllegalStateException( "Can't set parameter of a default profile!"); } this.weight = weight; } /** * Gets the average speed of the vehicle on a highway, in kilometers per * hour. * * @return The average speed of the vehicle on a highway, in kilometers per * hour. */ public int getSpeedHighway() { return speedHighway; } /** * <p> * Sets the average speed of the vehicle on a highway, in kilometers per * hour. * </p> * <p> * Note that this is not allowed for {@link #isDefault() default} profiles. * </p> * * @param name * The average speed of the vehicle on a highway, in kilometers * per hour. */ public void setSpeedHighway(int speedHighway) { if (isDefault()) { throw new IllegalStateException( "Can't set parameter of a default profile!"); } this.speedHighway = speedHighway; } /** * Gets the average speed of the vehicle on an ordinary (country) road, in * kilometers per hour. * * @return The average speed of the vehicle on an ordinary (country) road, * in kilometers per hour. */ public int getSpeedRoad() { return speedRoad; } /** * <p> * Sets the average speed of the vehicle on an ordinary (country) road, in * kilometers per hour. * </p> * <p> * Note that this is not allowed for {@link #isDefault() default} profiles. * </p> * * @param name * The average speed of the vehicle on an ordinary (country) * road, in kilometers per hour. */ public void setSpeedRoad(int speedRoad) { if (isDefault()) { throw new IllegalStateException( "Can't set parameter of a default profile!"); } this.speedRoad = speedRoad; } /** * Indicates whether this profile is equal to the given object. If * {@code obj} is a {@code Profile}, then this is equivalent to * <code>equals(obj, true)</code>, i. e. the profiles must be either * both {@link #isDefault() default} or both non-default. * * @return {@code true} if the two profiles are equal, {@code false} * otherwise. * @see #equals(Profile, boolean) */ @Override public boolean equals(Object obj) { if (obj instanceof Profile) { return equals((Profile) obj, true); } return false; } /** * Indicates whether this profile is equal to the given profile. * * @param other * The other profile. * @param checkDefault * Whether to include the {@link #isDefault() default} property * in the check or not. For example, * <code>defaultCar.equals(defaultCar.clone(), true)</code> is * {@code false} because the {@link #clone() clone} isn’t a * default profile, but * <code>defaultCar.equals(defaultCar.clone(), false)</code> is * {@code true}. * @return {@code true} if the two profiles are equal, {@code false} * otherwise. */ public boolean equals(Profile other, boolean checkDefault) { if (!this.name.equals(other.name)) { return false; } if (!this.vehicleType.equals(other.vehicleType)) { return false; } if (this.height != other.height) { return false; } if (this.width != other.width) { return false; } if (this.weight != other.weight) { return false; } if (this.speedHighway != other.speedHighway) { return false; } if (this.speedRoad != other.speedRoad) { return false; } if (checkDefault && this.isDefault != other.isDefault) { return false; } return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((vehicleType == null) ? 0 : vehicleType.hashCode()); result = prime * result + height; result = prime * result + width; result = prime * result + weight; result = prime * result + speedHighway; result = prime * result + speedRoad; result = prime * result + (isDefault ? 1231 : 1237); return result; } }