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.

Reply via email to