Ruby on Rails implementation similar to Java enums - java

Details (Flavor Enum)
public enum Flavor {
SWEET("sugar", 10),
SOUR("vinegar", 20),
private final String ingredient;
private final int price;
private Flavor(String ingredient, int price) {
this.ingredient = ingredient;
this.price = price;
}
public String getIngredient() {
return ingredient;
}
public int getPrice(){
return price;
}
}
Current implementation in ruby code.
module Drink
class Flavor
FLAVORS = {
sweet: {
ingredient: 'sugar',
price: 10,
},
sour: {
ingredient: 'vinegar',
price: 20,
}
}.freeze
def self.get(flavor)
APPS[:flavor]
end
end
end
Comparison between Java code VS Ruby
The above ruby code works just fine when we only need ingredient and price attributes but is lacking if I need to fetch the sweet or sour value. Example of comparison below.
Using Java enum
In Java, I can directly use the enum when I need to query for db entries flavored sweet or sour like below
//in another service
//this will be passed around into different service and/or repositories
//with just this assignment, I have access to the actual enum, the ingredient, and price
Enum flavor = Flavor.SWEET
//flavor is passed into the repository class
//I can just use the flavor directly to fetch drinks
drinkRepository.findByFlavor(flavor);
In ruby on rails
Using the same use-case as the above, this is not possible in ruby.
The below code will not work since Drink::Flavor.get(:sweet) will return an object with properties namely ingredient and price, which is not the value I needed to query from db.
# in a different class
# this will be passed around into different class
# this assignment will only provide me ingredient and the price
# WITHOUT the actual `sweet` value
flavor = Drink::Flavor.get(:sweet)
# in a different service class, I'm aiming to implement the below.
# this is not working since flavor value is not `sweet` or `sour`
DrinkRepository.find_by(flavor: flavor)
Question:
How can I make the above ruby code work, without adding new field/attribute flavor for each object in the hash of FLAVORS in my ruby class?

Calling the constant from the file, you need to pass in the argument and convert it into a symbol.
:flavor is not the same as flavor.to_sym in your case because if declared as a symbol, it won't have the data passed in the params of self.get.
Here's an implementation:
module Drink
class Flavor
FLAVORS = {
sweet: {
ingredient: 'sugar',
price: 10,
},
sour: {
ingredient: 'vinegar',
price: 20,
}
}.freeze
def self.get(flavor)
FLAVORS[flavor.to_sym]
end
end
end
Then you can call Drink::Flavor.get(:sweet) which will yield the JSON for the 'sweet' object. Another good thing about this implementation is you can pass in a symbol or a string Drink::Flavor.get('sweet') and it will still work.

Related

How to refer to java fields or getters ? (variable column excel sheet)

This is more of a "Design" or "Conception" sort of question.
So I have a simple problem; I want to print some workers info in an Excel sheet.
But I want to do it in a way that is easy to change in the future, let me explain : for now, people just want to see last name, first name and address in that excel table. But, what if all of a sudden they want more ? Or less ? How to add or remove a column (that actually refers to a field in the Worker class) hassle free ?
In a simple picutre, I want a simple system to go from this (these would be excel sheets) :
| first name | age | job |
-----------------------------------
| joe | 26 | developer |
| mary | 25 | tester |
to this :
| first name | last name | status | adress |
---------------------------------------------------------
| joe | johnson | employee | 8 sun street |
| mary | hoover | bos | 6 moon street |
So my class is Worker, I thought about making a class that is called WorkerTabular that would have a List of java.lang.reflect.Field references in it, and then I can check, but I don't want to break the encapsulation, that would kind of defeat the purpose of making an "easily variable system", if all of a sudden we tie to the implementation and oversee getters. So instead I thought of storing the references to the getter methods in this List of columns. But how would I call that function reference I stored on an instance of Worker?
Something like (using the builder pattern) WorkerTabular().addColumn(Worker::getName).addColumn(Worker::getHiringDate) and then, in a third class like ExcelMaker do something like worker.call(Worker::getName) to get the name.
I want to keep things as segregated as possible to make a truly reusable thing, by leaving the Worker Entity untouched, encapsulating the tabular data we want in the WorkerTabular, and the actual work of making the Excel stuffs in the ExcelMaker class.
Am I missing a well known pattern to do all this ? After all, making a kind of "variable excel sheet" must not be a new problem.
In other languages like Javascript, I can kind of see how that would be done, WorkerTabular would be made with that builder pattern just that it's a List of Strings, and then in ExcelMaker we would just do worker[listElement] while iterating on the list of attributes we chose to be in the Excel sheet. But in Java, I can't really see a clean and "Javaic" way to do it.
I'm sorry if I'm asking a stupid question.
EDIT 1 :
Thanks to Justin Albano for his nice answer :).
You really nailed it I think with the usage of the interface, even the fact that not every field is a String can be handled in the Implementation of TableEntry, by doing the conversion there (Dates to Strings, Ints to Strings, etc). There is a bit of coupling between TableEntry and Worker, but it's kept there and TableBuilder can really just concentrate of it's job of iterating over the List of Strings and build the Excel file.
I'm having a bit of trouble figuring out how to add a "columns titles" line to the TableBuilder, but I guess I'll just do it like this :
class TableBuilder {
List<String> columnTitles;
String tableTitle;
bytes[] build(List<TableEntry> lte) {
// make first row, make title & iterate over entries
// then do miscellaneous things like set the correct merged region for title, etc
}
}
And initialize those fields with a static factory or builder.
Actually this problem arose :
there are two types of Workers, and they have two fields : email and work_email.
A type of worker has both, and the other type has only work_email. So with my implementation I'm screwed ! I would have to put BOTH fields in the Excel table,
and one would be empty for the other type of worker, and people would complain !
Or I would need to split the function generating the Excel file in two thus duplicating a lot of code, or handle this little weird case in the function making it really ugly.
With the implementation with Entry interface to represent data, I can get around this easy ! I get the feeling that it's a bit "overengineered" and certainly my colleagues won't like stumbling through this implementation I think (the codebase is more of a "straight to the point and ugly don't matter" kind of thing), but it's also very clean I feel.
Moreover, the class TableBuilder could build an excel file for any Thing, as long as an implementation class of ThingEntry has been made. That's pretty sweet !
Maybe the only real "issue" I see with it is that 2n objects need to be created now, versus just the n of the 'ugly' implementation. But I feel that in 2018 that's not too big of an issue, right ?
A simple way to allow the internal representation of Worker to vary independently of the tabular representation of the Worker is to create a separate class for its representation. For example, given the following definition of Worker
public class Worker {
private final String firstName;
private final int age;
private final String job;
public Worker(String firstName, int age, String job) {
this.firstName = firstName;
this.age = age;
this.job = job;
}
public String getFirstName() {
return firstName;
}
public String getAge() {
return age;
}
public String getJob() {
return job;
}
}
the following wrapper can be created:
public interface TableEntry {
public List<String> getColumnValues();
}
public class WorkerTableEntry implements TableEntry {
private final Worker worker;
public WorkerEntry(Worker worker) {
this.worker = worker;
}
#Override
public List<String> getColumnValues() {
List<String> columns = new ArrayList<>();
columns.add(worker.getFirstName());
columns.add(String.valueOf(worker.getAge()));
columns.add(worker.getJob());
return columns;
}
}
This would now allow another class, TableBuilder to depend only on the TableEntry interface, not the internals of Worker:
public class TableBuilder {
public String buildTable(List<TableEntry> entries) {
// Print header
for (TableEntry entry: entries) {
List<String> columns = entry.getColumnValues();
// Print each column
}
}
}
Then the TableBuilder can be called as follows:
List<Worker> workers = ...
List<TableEntry> entries = new ArrayList<>();
for (Worker worker: workers) {
entries.add(new WorkerTableEntry(worker));
}
TableBuilder builder = new TableBulder();
builder.buildTable(entries);
This ensures that if the fields or methods of Worker change, its representation in the table does not necessarily change; and vice-versa, if the representation in the table needs to change, that the Worker class does not necessarily need to change (the two are independent). If other tables need to be built, you can simply create more implementations of TableEntry and reuse the TableBuilder class.
If you wanted to store the getters of the Worker class as the means of building the table, you can do so, although doing so is a bit more complicated. At its most basic level, the getters are Supplier<String> objects, meaning that take no arguments but produce a single String value. For example, you can develop a VariableTableEntry in the following manner:
public class VariableTableEntry {
private List<Supplier<String>> columnSuppliers;
public void addColumn(Supplier<String> supplier) {
columnSuppliers.add(supplier);
}
public String getRow() {
for (Supplier<String> columnSupplier: columnSuppliers) {
String columnValue = columnSupplier.get();
// Print each column
}
}
}
The difficult part is that not every getter will return a String. Some, like getAge(), will return an int. To be able to print those getter references as a String, a conversion would have to be performed (this method would be present in the VariableTableEntry class):
public void addIntColumn(Supplier<Integer> supplier) {
addColumn(() -> String.valueOf(supplier.get()));
}
This essential just wraps the supplied getter in a lambda expression that returns a String instead of an Integer/int. This process would be repeated for each of the other primitive values. Any Object (such as Worker) can be handled by deferring to toString:
public void addObjectColumn(Supplier<Object> supplier) {
addColumn(() -> supplier.get().toString());
}
If I have understood correctly, then Worker is your POJO and you are trying to create the list of POJOs and dumping in the excel sheet..So, what's the issue if person can add/remove the attributes in that bean class and corresponding getters/setters?

Java class: limit instance variable to one of several possible values, depending on other instance variables

I am sorry for the vague question. I am not sure what I'm looking for here.
I have a Java class, let's call it Bar. In that class is an instance variable, let's call it foo. foo is a String.
foo cannot just have any value. There is a long list of strings, and foo must be one of them.
Then, for each of those strings in the list I would like the possibility to set some extra conditions as to whether that specific foo can belong in that specific type of Bar (depending on other instance variables in that same Bar).
What approach should I take here? Obviously, I could put the list of strings in a static class somewhere and upon calling setFoo(String s) check whether s is in that list. But that would not allow me to check for extra conditions - or I would need to put all that logic for every value of foo in the same method, which would get ugly quickly.
Is the solution to make several hundred classes for every possible value of foo and insert in each the respective (often trivial) logic to determine what types of Bar it fits? That doesn't sound right either.
What approach should I take here?
Here's a more concrete example, to make it more clear what I am looking for. Say there is a Furniture class, with a variable material, which can be lots of things, anything from mahogany to plywood. But there is another variable, upholstery, and you can make furniture containing cotton of plywood but not oak; satin furniture of oak but not walnut; other types of fabric go well with any material; et cetera.
I wouldn't suggest creating multiple classes/templates for such a big use case. This is very opinion based but I'll take a shot at answering as best as I can.
In such a case where your options can be numerous and you want to keep a maintainable code base, the best solution is to separate the values and the logic. I recommend that you store your foo values in a database. At the same time, keep your client code as clean and small as possible. So that it doesn't need to filter through the data to figure out which data is valid. You want to minimize dependency to data in your code. Think of it this way: tomorrow you might need to add a new material to your material list. Do you want to modify all your code for that? Or do you want to just add it to your database and everything magically works? Obviously the latter is a better option. Here is an example on how to design such a system. Of course, this can vary based on your use case or variables but it is a good guideline. The basic rule of thumb is: your code should have as little dependency to data as possible.
Let's say you want to create a Bar which has to have a certain foo. In this case, I would create a database for BARS which contains all the possible Bars. Example:
ID NAME FOO
1 Door 1,4,10
I will also create a database FOOS which contains the details of each foo. For example:
ID NAME PROPERTY1 PROPERTY2 ...
1 Oak Brown Soft
When you create a Bar:
Bar door = new Bar(Bar.DOOR);
in the constructor you would go to the BARS table and query the foos. Then you would query the FOOS table and load all the material and assign them to the field inside your new object.
This way whenever you create a Bar the material can be changed and loaded from DB without changing any code. You can add as many types of Bar as you can and change material properties as you goo. Your client code however doesn't change much.
You might ask why do we create a database for FOOS and refer to it's ids in the BARS table? This way, you can modify the properties of each foo as much as you want. Also you can share foos between Bars and vice versa but you only need to change the db once. cross referencing becomes a breeze. I hope this example explains the idea clearly.
You say:
Is the solution to make several hundred classes for every possible
value of foo and insert in each the respective (often trivial) logic
to determine what types of Bar it fits? That doesn't sound right
either.
Why not have separate classes for each type of Foo? Unless you need to define new types of Foo without changing the code you can model them as plain Java classes. You can go with enums as well but it does not really give you any advantage since you still need to update the enum when adding a new type of Foo.
In any case here is type safe approach that guarantees compile time checking of your rules:
public static interface Material{}
public static interface Upholstery{}
public static class Oak implements Material{}
public static class Plywood implements Material{}
public static class Cotton implements Upholstery{}
public static class Satin implements Upholstery{}
public static class Furniture<M extends Material, U extends Upholstery>{
private M matrerial = null;
private U upholstery = null;
public Furniture(M matrerial, U upholstery){
this.matrerial = matrerial;
this.upholstery = upholstery;
}
public M getMatrerial() {
return matrerial;
}
public U getUpholstery() {
return upholstery;
}
}
public static Furniture<Plywood, Cotton> cottonFurnitureWithPlywood(Plywood plywood, Cotton cotton){
return new Furniture<>(plywood, cotton);
}
public static Furniture<Oak, Satin> satinFurnitureWithOak(Oak oak, Satin satin){
return new Furniture<>(oak, satin);
}
It depends on what you really want to achieve. Creating objects and passing them around will not magically solve your domain-specific problems.
If you cannot think of any real behavior to add to your objects (except the validation), then it might make more sense to just store your data and read them into memory whenever you want. Even treat rules as data.
Here is an example:
public class Furniture {
String name;
Material material;
Upholstery upholstery;
//getters, setters, other behavior
public Furniture(String name, Material m, Upholstery u) {
//Read rule files from memory or disk and do all the checks
//Do not instantiate if validation does not pass
this.name = name;
material = m;
upholstery = u;
}
}
To specify rules, you will then create three plain text files (e.g. using csv format). File 1 will contain valid values for material, file 2 will contain valid values for upholstery, and file 3 will have a matrix format like the following:
upholstery\material plywood mahogany oak
cotton 1 0 1
satin 0 1 0
to check if a material goes with an upholstery or not, just check the corresponding row and column.
Alternatively, if you have lots of data, you can opt for a database system along with an ORM. Rule tables then can be join tables and come with extra nice features a DBMS may provide (like easy checking for duplicate values). The validation table could look something like:
MaterialID UpholsteryID Compatability_Score
plywood cotton 1
oak satin 0
The advantage of using this approach is that you quickly get a working application and you can decide what to do as you add new behavior to your application. And even if it gets way more complex in the future (new rules, new data types, etc) you can use something like the repository pattern to keep your data and business logic decoupled.
Notes about Enums:
Although the solution suggested by #Igwe Kalu solves the specific case described in the question, it is not scalable. What if you want to find what material goes with a given upholstery (the reverse case)? You will need to create another enum which does not add anything meaningful to the program, or add complex logic to your application.
This is a more detailed description of the idea I threw out there in the comment:
Keep Furniture a POJO, i.e., just hold the data, no behavior or rules implemented in it.
Implement the rules in separate classes, something along the lines of:
interface FurnitureRule {
void validate(Furniture furniture) throws FurnitureRuleException;
}
class ValidMaterialRule implements FurnitureRule {
// this you can load in whatever way suitable in your architecture -
// from enums, DB, an XML file, a JSON file, or inject via Spring, etc.
private Set<String> validMaterialNames;
#Overload
void validate(Furniture furniture) throws FurnitureRuleException {
if (!validMaterialNames.contains(furniture.getMaterial()))
throws new FurnitureRuleException("Invalid material " + furniture.getMaterial());
}
}
class UpholsteryRule implements FurnitureRule {
// Again however suitable to implement/config this
private Map<String, Set<String>> validMaterialsPerUpholstery;
#Overload
void validate(Furniture furniture) throws FurnitureRuleException {
Set<String> validMaterialNames = validMaterialsPerUpholstery.get(furniture.getUpholstery();
if (validMaterialNames != null && !validMaterialNames.contains(furniture.getMaterial()))
throws new FurnitureRuleException("Invalid material " + furniture.getMaterial() + " for upholstery " + furniture.getUpholstery());
}
}
// and more complex rules if you need to
Then have some service along the lines of FurnitureManager. It's the "gatekeeper" for all Furniture creation/updates:
class FurnitureManager {
// configure these via e.g. Spring.
private List<FurnitureRule> rules;
public void updateFurniture(Furniture furniture) throws FurnitureRuleException {
rules.forEach(rule -> rule.validate(furniture))
// proceed to persist `furniture` in the database or whatever else you do with a valid piece of furniture.
}
}
material should be of type Enum.
public enum Material {
MAHOGANY,
TEAK,
OAK,
...
}
Furthermore you can have a validator for Furniture that contains the logic which types of Furniture make sense, and then call that validator in every method that can change the material or upholstery variable (typically only your setters).
public class Furniture {
private Material material;
private Upholstery upholstery; //Could also be String depending on your needs of course
public void setMaterial(Material material) {
if (FurnitureValidator.isValidCombination(material, this.upholstery)) {
this.material = material;
}
}
...
private static class FurnitureValidator {
private static boolean isValidCombination(Material material, Upholstery upholstery) {
switch(material) {
case MAHOGANY: return upholstery != Upholstery.COTTON;
break;
//and so on
}
}
}
}
We often are oblivious of the power inherent in enum types. The Java™ Tutorials clearly states "you should use enum types any time you need to represent a fixed set of constants."
How do you simply make the best of enum in resolving the challenge you presented? - Here goes:
public enum Material {
MAHOGANY( "satin", "velvet" ),
PLYWOOD( "leather" ),
// possibly many other materials and their matching fabrics...
OAK( "some other fabric - 0" ),
WALNUT( "some other fabric - 0", "some other fabric - 1" );
private final String[] listOfSuitingFabrics;
Material( String... fabrics ) {
this.listOfSuitingFabrics = fabrics;
}
String[] getListOfSuitingFabrics() {
return Arrays.copyOf( listOfSuitingFabrics );
}
public String toString() {
return name().substring( 0, 1 ) + name().substring( 1 );
}
}
Let's test it:
public class TestMaterial {
for ( Material material : Material.values() ) {
System.out.println( material.toString() + " go well with " + material.getListOfSuitingFabrics() );
}
}
Probably the approach I'd use (because it involves the least amount of code and it's reasonably fast) is to "flatten" the hierarchical logic into a one-dimensional Set of allowed value combinations. Then when setting one of the fields, validate that the proposed new combination is valid. I'd probably just use a Set of concatenated Strings for simplicity. For the example you give above, something like this:
class Furniture {
private String wood;
private String upholstery;
/**
* Set of all acceptable values, with each combination as a String.
* Example value: "plywood:cotton"
*/
private static final Set<String> allowed = new HashSet<>();
/**
* Load allowed values in initializer.
*
* TODO: load allowed values from DB or config file
* instead of hard-wiring.
*/
static {
allowed.add("plywood:cotton");
...
}
public void setWood(String wood) {
if (!allowed.contains(wood + ":" + this.upholstery)) {
throw new IllegalArgumentException("bad combination of materials!");
}
this.wood = wood;
}
public void setUpholstery(String upholstery) {
if (!allowed.contains(this.wood + ":" + upholstery)) {
throw new IllegalArgumentException("bad combination of materials!");
}
this.upholstery = upholstery;
}
public void setMaterials(String wood, String upholstery) {
if (!allowed.contains(wood + ":" + upholstery)) {
throw new IllegalArgumentException("bad combination of materials!");
}
this.wood = wood;
this.upholstery = upholstery;
}
// getters
...
}
The disadvantage of this approach compared to other answers is that there is no compile-time type checking. For example, if you try to set the wood to plywoo instead of plywood you won’t know about your error until runtime. In practice this disadvantage is negligible since presumably the options will be chosen by a user through a UI (or through some other means), so you won’t know what they are until runtime anyway. Plus the big advantage is that the code will never have to be changed so long as you’re willing to maintain a list of allowed combinations externally. As someone with 30 years of development experience, take my word for it that this approach is far more maintainable.
With the above code, you'll need to use setMaterials before using setWood or setUpholstery, since the other field will still be null and therefore not an allowed combination. You can initialize the class's fields with default materials to avoid this if you want.

Better way to write many if statements in Java?

So I have this homework where I need to build a vending machine, and I assigned a coordinate to every product (A1, A2, A3..) and when the user enters the coin value I have to calculate if he can buy the product that he chose and if yes calculate the change, since i'm still new to programming I now have ended up with many statements like this
if ("a1".equals(choice)) {
System.out.println("You chose SNICKERS!");
if (money < 50) {
System.out.println("This is not enough money to buy this product");
} else if (money >= 50) {
System.out.println(" Price = 50 Your change = " + (money - 50));
}
}
where the only things changing are the coordinates (a1, a2, a3, a4, b1, b2 and so on) and the prices. What would be a better way to do this?
You could use a more OO approach.
Make a class called Product:
class Product {
private String name;
private int price;
public String getName() { return name; }
public int getPrice() { return price; }
public Product(String name, int price) {
this.name = name;
this.price = price;
}
}
Then, create a HashMap<String, Product> and add all your products and their coordinates in:
HashMap<String, Product> productMap = new HashMap<>();
productMap.put("A1", new Product("Snickers", 50));
productMap.put("A2", new Product("Something else", 40));
// do this for every coordinate...
Now, you can just use this code:
Product chosenProduct = productMap.get(choice);
System.out.println("You chose " + chosenProduct.getName() + "!");
if (money < chosenProduct.getPrice()) {
System.out.println("This is not enough money to buy this product");
} else {
System.out.println(" Price = " + chosenProduct.getPrice() + " Your change = " + (money - chosenProduct.getPrice()));
}
This is a common moment in programming and you're right to think there's a better way to go about it.
In your particular case, where you have a similar structure of code in many places, you should try using a function. Try writing a private function in the same class that takes in some of the parameters that change. Depending on the level of complexity you end up with you might end up with a large function with a lot of parameters which isn't great either. Regardless, writing a function is probably the first place you should go when you encounter this situation.
Secondarily, consider what this segment of code is doing. Making a generic function to replace the whole code segment might not be ideal but could you easily write a function to do a small part of it? If so, is it now easy to make the rest into another function? Keep track of any variances you have across your many similar code segments, if any, and try to create functions that address those variations.
Finally, depending on what is in scope for your current level of programming, you might be able to create data structure to help with the identification of the choice. For example, maybe you could make a map where you could store each of the choices and an associated object that contains all of the data you need to respond to the user (i.e. cost, item name, etc.). With that kind of approach you can pre-populate all of those options in a straightforward manner and have your code simply look up the set of data associated with the choice and call of function to print the necessary output.
Ultimately, how you go about this and future situations like it is highly dependent upon what your level of experience with programming, how many choices there are, and how complex the data associated with each choice is.
Continue to trust your instincts though, they will serve you well.
Switch case is the desired functionality.
switch(choice) {
case 'a' : <some code>
break;
case 'b': <some other code>
break;
default: <if none of the choices matched>
}
The only caveat is that your choice value has to be a char or an int
EDIT:
This was a bad answer from my side. Clearly, you need a more cleaner way to write your vending machine.
A good way to structure it would be to first create a Product class which can store the name and the price of the product.
class Product {
private String name;
private String price;
// Implement a constructor and an equals() method to equate two
// instances of product
}
You could then create a function (which could be used in your main()) which takes the text input from your user and map it to an actual product.
public static Main(String[] args) {
// ...
private Product processUserInput(String productName) {
// Add logic to process the string and return a Product
}
// ...
}
Then you could add a function that would process the Product and the amount the user has and return the change remaining or maybe -1 if the product costs more than the available amount.
public static Main(String[] args) {
// ...
private int processUserProductChoice(Product product, int amountAvailable) {
// Add logic to process the product and amount
// Probably use switch case now.
}
// ...
}

Reading information to a map

I'm learning about Sets and Maps in the Introduction to Java Programming book by Daniel Liang. My professor has assigned a problem in the back of the chapter that asks me to create a program that:
Queries the user for input on name
Queries the user for gender
Using these two criteria, and this/these website(s): http://cs.armstrong.edu/liang/data/babynamesranking2001.txt
... http://cs.armstrong.edu/liang/data/babynamesranking2010.txt
I have to be able to get the ranking.
I'm supposed to get this information into an array of 10 maps.
Each map corresponds with a .txt file/year. This is where I'm having problems with. How do I do this?
The (Int) rank of the student is the value of the map, and the key is the name (String) of the baby.
The way I was thinking was to create an array of maps or maybe a list of them. So like:
List<Map<Int, String>> or <Map<Int, String>[] myArray;
Yet even after that the issue of how I get all of this information from the .txt file to my maps is a hard one for me.
This is what I've come up so far. I can't say I'm happy with it. It doesn't even work when I try to start reading information is because I haven't specified the size of my array.
public class BabyNamesAndPopularity
{
public static void main (String[] args) throws IOException
{
Map<Integer, String>[] arrayOfMaps;
String myURL = "cs.armstrong.edu/liang/data/babynamesranking2001.txt";
java.net.URL url = new java.net.URL(myURL);
Scanner urlInput = new Scanner (url.openStream());
while(urlInput.hasNext())
{
...
}
}
}
Would it be viable to make a set OF MAPS? I was kind of thinking it would be better to make a set OF maps because of the fact that sets expand as needed (according to the load factor). I just need some general guidance. Unfortunately the CS program at my university (Francis Marion University in Florence, SC) is VERY small and we don't have any tutors for this stuff.
This answer rather vague, because of broad nature of question, and it may be more suitable for
programmers SE site. Still, you may find these two points worth something.
Instead of thinking in terms of 'raw' compound collections, such as lists of maps of sets or such, try to invent set of domain types, which would reflect your problem domain, and, as the next step, implement these types using suitable Java collections or arrays.
Unit-testing and incremental refinement. Instead of immediately starting with access to remote data (via java.net.URL), start with static source of data. Idea here is to have 'reliable' and easily accessible input data hand, which would allow you to write unit tests easily and w/o access to network or even to file system, using set of domain types from 1st point, above. As you write unit tests you can invent necessary domain types/methods names in unit tests at first, then implement these types/methods, then make unit tests pass.
For example, you may start by writing following unit test (I assume you know how to organize your Java project in your IDE, so unit test(s) can be run properly):
public class SingleFileProcessingTest {
private static String[] fileRawData;
#BeforeClass
public static void fillRawData() {
fileRawData = new String[2];
// values are from my head, resembling format from links you've posted
fileRawData[0] = "Jacob\t20000\tEmily\t19999";
fileRawData[1] = "Michael\t18000\tMadison\t17000";
}
#Test
public void test() {
Rankings rankings = new Rankings();
rankings.process(fileRawData);
assertEquals("Jacob", rankings.getTop().getName());
assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
assertEquals(18000, rankings.getScoreOf("Michael"));
assertEquals(4, rankings.getSize());
}
}
Of course, this won't even compile -- you need to type in code of Rankings class, code of class returned by getTop() or getScorerOfPosition(int) and so on. After you made this compile, you'll need to make test pass. But you get main idea here -- domain types and incremental refinement. And easily verifiable code w/o dependencies on file system or network. Just plain old java objects (POJOs). Code for working with external data sources can be added later on, after you get your POJOs right and make tests, which cover most parts of your use cases, pass.
UPDATE Actually, I've mixed up levels of abstraction in code above: proper Rankings class should not process raw data, this is better to be done in separate class, say, RankingsDataParser. With that, unit test, renamed to RankingsProcessingTest, will be:
public class RankingsProcessingTest {
#Test
public void test() {
Rankings rankings = new Rankings();
rankings.addScorer(new Scorer("Jacob", 20000));
rankings.addScorer(new Scorer("Emily", 19999));
rankings.addScorer(new Scorer("Michael", 18000));
rankings.addScorer(new Scorer("Madison", 17000));
assertEquals("Jacob", rankings.getTop().getName());
// assertEquals("Madison", rankings.getScorerOfPosition(4).getName());
// implementation of getScorerOfPosition(int) left as exercise :)
assertEquals(18000, rankings.getScoreOf("Michael"));
assertEquals(4, rankings.getSize());
}
}
With following initial implementation of Rankings and Scorer, this is actually compiles and passes:
class Scorer {
private final String name;
private final int rank;
Scorer(String name, int rank) {
this.name = name;
this.rank = rank;
}
public String getName() {
return name;
}
public int getRank() {
return rank;
}
}
class Rankings {
private final HashMap<String, Scorer> scorerByName = new HashMap<>();
private Scorer topScorer;
public Scorer getTop() {
return topScorer;
}
public void addScorer(Scorer scorer) {
if (scorerByName.get(scorer.getName()) != null)
throw new IllegalArgumentException("This version does not support duplicate names of scorers!");
if (topScorer == null || scorer.getRank() > topScorer.getRank()) {
topScorer = scorer;
}
scorerByName.put(scorer.getName(), scorer);
}
public int getSize() {
return scorerByName.size();
}
public int getScoreOf(String scorerName) {
return scorerByName.get(scorerName).getRank();
}
}
And unit test for parsing of raw data will start with following (how to download raw data should be responsibility of yet another class, to be developed and tested separately):
public class SingleFileProcessingTest {
private static String[] fileRawData;
#BeforeClass
public static void fillRawData() {
fileRawData = new String[2];
// values are from my head
fileRawData[0] = "Jacob\t20000\tEmily\t19999";
fileRawData[1] = "Michael\t18000\tMadison\t17000";
}
#Test
public void test() {
// uncomment, make compile, make pass
/*
RankingsDataParser parser = new RankingsDataParser();
parser.parse(fileRawData);
Rankings rankings = parser.getParsedRankings();
assertNotNull(rankings);
*/
}
}

Enum saving in Hibernate

I am trying to save an Enum field to database but I am having a problem mapping the field to database. The code I have is as follows:
public enum InvoiceStatus {
PAID,
UNPAID;
}
and I am using this enum in one of my application classes as follows:
public class Invoice {
Enumerated(EnumType.ORDINAL)
#Column(name="INVOICE_STATUS", nullable = false, unique=false)
private InvoiceStatus invoiceStatus;
}
finally I let the app user select the Invoice Status from the view (JSP) using a drop down menu.
But I am not sure how to map the value received from the drop down menu selection to the Invoice Status field
I tried mapping the value received to short as follows, but it won't compile
invoice.setInvoiceStatus(Short.parseShort(request.getParameter("inbStatus")));
can someone please tell me how to map the data received from the view to the enum field?
Enum ordinal values are zero based indexes. In your case:
PAID = 0
UNPAID = 1
So the following code will return PAID:
int invoiceStatus = 0;
invoice.setInvoiceStatus(InvoiceStatus.values()[invoiceStatus]);
And the following code will return UNPAID:
int invoiceStatus = 1;
invoice.setInvoiceStatus(InvoiceStatus.values()[invoiceStatus]);
That means you should be able to do this way:
short invoiceStatus = Short.parseShort(request.getParameter("inbStatus"));
invoice.setInvoiceStatus(InvoiceStatus.values()[invoiceStatus]);
But only if inbStatus is 0 or 1. You should always validate user input for null and invalid values.
I see that u are using
Enumerated(EnumType.ORDINAL)
however after a while it could be quite difficult to troubleshoot if your enum will grow. Another issue with the ordinal is that you could refactor your code and change the order of the enum values and after that you could be in trouble. Mainly if it is a shared codebase and someone just decides to cleanup the code and "group the relevant enum constants together". If you'll use:
Enumerated(EnumType.STRING)
Directly the enum "name" will be inserted into the database. (Therefore you need Varchar type). If you want to present more user friendly version of your enum you could probably have:
public enum InvoiceStatus {
PAID(0, "Paid"), UNPAID(1, "Unpaid"), FAILED(2, "Failed"), PENDING(3, "Pending");
private int st;
private in uiLabel;
private InvoiceStatus(int st, String uiLabel){
this.st = st;
this.uiLabel = uiLabel;
}
private Map<String, InvoiceStatus> uiLabelMap = new HashMap<String, InvoiceStatus> ();
static {
for(InvoiceStatus status : values()) {
uiLableMap.put(status.getUiLabel(), status);
}
}
/** Returns the appropriate enum based on the String representation used in ui forms */
public InvoiceStatus fromUiLabel(String uiLabel) {
return uiLableMap.get(uiLabel); // plus some tweaks (null check or whatever)
}
//
// Same logic for the ORDINAL if you are keen to use it
//
}
Probably this could be also a solution for your problem, however i would really not use the ORDINAL based mapping. But just personal feeling.

Categories