views:

52

answers:

1

On a project I'm working on, there is an existing messaging system that sends in-app messages and emails. All the messages are currently hard-coded, with placeholders for specific variables (name, date, stuff like that).

An upcoming requirement for the project is to make all these messages configurable. The details aren't hugely important, all that matters are these points:

1) The messages should be able to take any object from our ORM and replace portions of the content of the message with values from the object. For example, something like ${User.FirstName} or ${Customer.IsEnabled}, etc.

2) The messages need to be editable by the system admins easily. So compiling stuff in (unless it's done on the fly) is a no-go.

3) Ideally, there will be a way for me to verify that the message is "valid", and can be parsed properly. Not a requirement (I intend make a sandbox for them to play in anyway), but it would be nice.

Anyone have any suggestions for the best way to go about this?

+1  A: 

You really need to divide the problem into some discrete sub-problems:

  1. Implement a mechanism to load templates from some type of configuration file or database.
  2. Implement a mechanism to parse the templates and extract the substitution markers from them.
  3. Implement a mechanism that interprets and evaluates substitution markers against objects in your program dynamically.
  4. Optionally, implement a mechanism that allows substitution markers to be statically evaluated either during compilation or at application startup.

So, here's some advice on each of the sub-problems:

Template Repository: I would consider going with a simple mechanism initially, but one that would allow you sys admins to make changes without risking messing anything else up. I would probably rule out web/app config files for this reason - and use either a settings file or (if your app already uses it) a database table. You may want to give each template a stable internal identifier as well as a customizable name. The code would rely on the stable identifier while the name is just a convenient way for admins to organize these templates.

Parsing Markers: This is one place where regular expressions seem to be a reasonable choice. It's not terribly difficult to parse out patterns of the form $(...) correctly.

Interpreting/Evaluating Markers: This is one of the more complicated parts of your problem. Unless performance is of paramount concern, I would probably use reflection and a bit of string manipulation to do the job. If you can constraint the substitution markers to only ever refer to public properties of your ORM objects, that would make life a lot simpler too. You could then just split the string based on '.' characters and then use iterative logic to fetch the value of the corresponding property until you get to the final value.

Compile/Runtime Validation: This is a tall order. You definitely want to get all of the other pieces working first. Once you do, one way of implementing this may be to load all templates at app startup, visit each one and make sure that the markers in the templates all exist in the object types in your ORM. Since it looks like you are already prefixing the object type name into the marker, this should be possible. Unfortunately, you probably can't reuse the same logic that evaluates markers to validate them - since for validation you don't have instances of the types - just their type information.

LBushkin
Thanks LBushkin. This is pretty close to the approach I was considering. I'm debating using a plain XML file vs the database simply because it'll be easier to diagnose XML later if something blows up, but the parsing via reflection was spot on with my thoughts. The ORM has fairly sensible naming, so that should be feasible for the admins too. Thanks for your thoughts!
jvenema