Hi Tapestry Users, tl;dr i print nice strings for enum values. i'm adding some logic which adds string display beautification. is this how/why i would create a service to inject my "enum-to-string-beautifier-helper-service" into page classes to use the methods in tml (forms).
Disclaimer: I'm not going for a gold medal for efficiency atm. Only 3 people will use my app. + you guys get to see how my head plugs away in tapestry :) I just want to know if I'm approaching this in a more or less okay way. I proudly admit(!!) that I have minimal repeated code that I want to reduce. 3 methods copy+pasted. I want to make a tapestry service out of it - a plain and boring converting string service for an enum with tiny logic involved (or added later). I have an entity - "Subnet" It has an enum field of type Netmask which looks like this: public enum Netmask{ MASK24("255.255.255.0 /24"), MASK25("255.255.255.0 /25"), MASK26("255.255.255.0 /26"), MASK27("255.255.255.0 /27"), MASK28("255.255.255.0 /28"), MASK29("255.255.255.0 /29"), MASK30("255.255.255.0 /30"), MASK31("255.255.255.0 /31"), MASK32("255.255.255.0 /32"); } This Netmask enum is used in a Select - i.e. when "creating a new subnet" and when "splitting a subnet" I allow only lesser subnet values to be displayed and therefore "select"-ed e.g. MASK24 > MASK25 > MASK26.....> MASK32 In my form for creation of a subnet, I've copy+pasted my handy utility string conversion methods to the "splitting a subnet" tapestry page class, therefore starting a maintenance headache. //this method is for select component text beautification public String convertNetmask(Netmask n){ switch(n){ case MASK24: return "255.255.255.0 /24"; case MASK25: return "255.255.255.128 /25"; case MASK26: return "255.255.255.192 /26"; case MASK27: return "255.255.255.224 /27"; case MASK28: return "255.255.255.240 /28"; case MASK29: return "255.255.255.248 /29"; case MASK30: return "255.255.255.252 /30"; case MASK31: return "255.255.255.254 /31"; case MASK32: return "255.255.255.255 /32"; default: return "NOT SET"; } } //this method is used when displaying in a table //the subnet's network address with mask e.g. "192.168.0.0 /24" public String convertNetmaskStrokeOnly(Netmask n){ switch(n){ case MASK24: return "/24"; case MASK25: return "/25"; case MASK26: return "/26"; case MASK27: return "/27"; case MASK28: return "/28"; case MASK29: return "/29"; case MASK30: return "/30"; case MASK31: return "/31"; case MASK32: return "/32"; default: return "NOT SET"; } In my tempaltes I have a template displaying Subnets (not a beandisplay) I like total control :) <td>${currentSubnet.networkAddress} ${convertNetmaskStrokeOnly(currentSubnet.mask)}</td> <td>${convertNetmask(currentSubnet.mask)}</td> This displays something like | 192.168.0.0 /24 | 255.255.255.0 /24 | | 192.168.100.0 /28 | 255.255.255.240 /28| It's a 6 or 7/10 for manageability/simplicity apart from code copy+paste for extra page classes introducing extra maintenance, but that is being quite generous. Now I've added the "splitting a subnet" part and I have this hideous method, which again is readable for a junior or perl/php/sys-admin type. public Netmask[] usableNetmasks(Netmask n) { Netmask[] for24 = {MASK25, MASK26, MASK27, MASK28, MASK29, MASK30, MASK31, MASK32}; Netmask[] for25 = {MASK26, MASK27, MASK28, MASK29, MASK30, MASK31, MASK32}; Netmask[] for26 = {MASK27, MASK28, MASK29, MASK30, MASK31, MASK32}; Netmask[] for27 = {MASK28, MASK29, MASK30, MASK31, MASK32}; Netmask[] for28 = {MASK29, MASK30, MASK31, MASK32}; Netmask[] for29 = {MASK30, MASK31, MASK32}; Netmask[] for30 = {MASK31, MASK32}; Netmask[] for31 = {MASK32}; Netmask[] for32 = {}; switch (n) { case MASK24: return for24; case MASK25: return for25; case MASK26: return for26; case MASK27: return for27; case MASK28: return for28; case MASK29: return for29; case MASK30: return for30; case MASK31: return for31; default: return for32; } } I use this method in a form's select (with a zone) like so: <tr> <td>Select</td> <td><t:label for="subnetMask"/><t:select t:id="subnetMask" t:model="usableNetmasks(addressSelected.mask)" t:zone="previewZone"/></td> </tr> And it works great! I'm now looking at reversing the splitting process = to join subnets together. I'm starting to see a pattern here. Whenever I want to do something with my subnets, I'm going to want to muck around with beautifying what a subnet looks like and massaging the model for display or something. Is this a valid (but maybe no super elegant) service to create....string conversion/display service for a netmask. e.g. some pseudo code public interface NetmaskDisplayHelper { String convertNetmask(Netmask n); String convertNetmaskStrokeOnly(Netmask n); String usableNetmasks(Netmask n); } public class NetmaskDisplayHelperImplByChris{ //copy+paste my repeated code here } then in AppModule do the binding binder.bind(NetmaskDisplayHelper.class, NetmaskDisplayHelperImplByChris.class); In the page classes @Inject the NetmaskDisplayHelper and from the templates somehow call the services, as per the tml snippets above. /HUGE-QUESTION-MARK! Thanks for reading!!! Feedback welcome. Condescending, patronising AND humourous comments accepted as well :) Cheers Chris P.S. I've gone down to MASK16, so if you know your networking - imagine a &*$%load of code I scroll past!! Apache net utils is bloody good too btw.