- The Case for Low-Touch Programming
- Some I18N Requirements
- Apache Axis and I18N
- GUI Elements and I18N
- I18N Using Aspects: An Order Management Program
- The Order Management Program Structure
- Date Modification
- Conclusions
The Order Management Program Structure
The program consists of four classes:
- OrderManagement.java
- Order.java
- StockItem.java
- Charging.java
To build the program, you can use the file OrderManagement.lst (an ApsectJ artifact that simply lists the files for compilation) and run the following commands (provided here for readers not familiar with AspectJ):
ajc -argfile OrderManagement.lst set classpath=.;%classpath%;Charging.class;Order.class; OrderManagement.class;StockItem.class;
I implemented the charging code as an aspect, to illustrate how significant production-time functionality can be added with aspects. The Charging aspect is also where I do the I18N coding. To make the code a little easier to follow, I've broken the aspect code into two blocks. The first block defines the pointcut:
public aspect Charging { pointcut startCharging(Order order): target(order) && call(void Order.completeOrder()); after(Order order): startCharging(order) { System.out.println("Now in the after code"); calculateTotalCharge(order); }
This code defines the Charging aspect and the conditions under which it executes. The pointcut exists to pick out execution join points as well as to expose context data. My pointcut is called StartCharging and it operates against instances of the Order class. The pointcut runs when its signature is matched—that is, when the completeOrder() method is called.
Once the pointcut executes, the after code is called, at which point the method calculateTotalCharge() is invoked. The latter executes the I18N code:
public double Order.totalCharge = 0; public double calculateTotalCharge(Order order) { System.out.println("Date of order origination " + order.dateOfOrderCreation); DateFormat df = DateFormat.getDateInstance(); try { System.out.println(df.format(order.dateOfOrderCreation)); } catch(Exception e) { System.out.println("Exception occurred: " + e.getMessage()); System.exit(-1); } Enumeration e = order.orderItems.elements(); while (e.hasMoreElements()) { StockItem aStockItem = (StockItem)e.nextElement(); order.totalCharge += aStockItem.itemFinancialValue; } System.out.println("Calculated order value " + order.totalCharge); return order.totalCharge; } public double getTotalCharge(Order order) { NumberFormat moneyFormatter2 = NumberFormat.getCurrencyInstance(Locale.US); System.out.println("Retrieved order value " + moneyFormatter2.format(order.totalCharge)); return order.totalCharge; } }
The key elements of the aspect are the data member called Order.totalCharge, and the two methods called calculateTotalCharge() and getTotalCharge(), respectively. The first method is used to calculate the total value of the items in the order, and the second method allows for this summed value to be retrieved.
As you saw in the earlier listing, the value of the order is 670.576. To add a dollar symbol, the following changes are required to the Charging.java class. First, add two new imports:
import java.text.NumberFormat; import java.util.Locale;
Then make the following change to getTotalCharge():
public long getTotalCharge(Order order) { NumberFormat moneyFormatter2 = NumberFormat.getCurrencyInstance(Locale.US); System.out.println("Retrieved order value " + moneyFormatter2.format(order.totalCharge)); return order.totalCharge; }
When you build and run the program, here is the modified output:
Created an instance of StockItem Created another instance of StockItem Now routing the order to billing Now in the after code Date of order origination Fri Jul 07 12:07:49 BST 2006 Jul 7, 2006 Calculated order value 670.576 Order is complete, ready for reporting Retrieved order value $670.58 Order has a value of 670.576
Of course, production code most likely would read locale-specific data from some form of persistent storage. The important point here is that the use of aspects helps achieve LTP.
You can see the dollar symbol in the second-to-last line. Notice also that the figure now has only two decimal places and has been rounded up to $670.58. This is pretty much standard practice except with some specialized applications, such as stock price–reporting software, where more precision is required. The last line in the listing indicates that the unrounded value has been retained; that is, the display on the second-to-last line is for informational purposes only.