views:

154

answers:

6

I'm about creating a java class for parsing and storing the content of a simple CSS stylesheet. This class will be used to paint a non-html object using the CSS selectors. My naive approach is to basically use a

Map<String,Map<String,Object>>

to store this stylesheet. Would it be any (clever) other way for storing this information ?

A: 

This should be quite enough if you: 1. plan on building up class hierarchy around your "Object", e.g. "Color", "BackgroundInformation" etc, since there is a lot of possibilites of what can appear on the right side 2. I think you should replace first "String" with some Object which is able to parse the CSS selectors and build up logic around it, similar to (1)

MilanAleksic
+1  A: 

I would recommend something like:

Map<String, Map<String, CSSValue>>

Where CSSValue is an abstract class or interface that you will extend with things like CSSColor, CSSNumber, CSSString, CSSList<CSSValue>.

This will make your code much cleaner.

jjnguy
+4  A: 

the question of course is: why?

A CSS parser (at least a robust one) is non-trivial. You'd need to cater for things like imports, @media, browser-specific directives and so on. But I gather you're not after something that robust.

So what are you after?

Object is too general for the value too. Have some common base class and then subclasses to represent:

  • Single values (number plus optional units of measurement, including percentages);
  • Lists of strings (eg font-family);
  • Composite/complex values (such as border and background support);
  • URLs;
  • Enumerated values (eg collapse or separate for border-collapse); and
  • so on.

That is, assuming you want to validate the result.

cletus
Thanks, that's an interesting comment
Pierre
+1  A: 

That is an extremely naive solution. Here are the flaws with it I can think of off the top of my head:

  • If you use String as for the CSS selector, it will be difficult to determine whether it is a valid selector for a given item. Better to wrap that functionality up in a class.
  • The built-in maps will only you give you one one matching element, but the very point of CSS is that you can cascade multiple styles that all apply to one element. You need a way to retrieve all matching styles.
  • Using Object is a bad idea. Create an interface or abstract class to extend all of your styles from. You'll have less type-casting and have the added benefit of being able to push down the shared functionality.

In all, I'd do something like CSSMap<CSSSelector, List<CSSStyle>>.

Pesto
+1  A: 

You're modelling this as a Map, but it's not a Map. You need a CSS object that contains (say) CSSSelectors and CSSStyles and all the surrounding functionality.

It will provide extra functionality such as determining how styles cascade. handling different measurements, validating inputs etc. All the functionality associated with CSS sheets would go in this object. Perhaps parsing a .css as part of it's construction (we'll get into discussions about factories if we're not careful).

The underlying implementation may involve a Map, but I think you need to think first about what this object is required to do.

If (however) you simply have a Map, then there's no additional functionality. Or rather, where does it go?

Brian Agnew
+1  A: 

I don't think it makes sense to pretend you're using CSS; you're not. CSS selectors are much, much more complex that what you describe, and even if you could use a real CSS parser/matcher you'd probably run into a lot of open questions and contradictions trying to apply real CSS to your non-HTML data.

So what you want is a small subset of CSS-like functionality, i.e. only direct selectors. For that, your nested map structure is OK, though as Pesto and jjnguy said it would be better to go for more type safety.

The remaining question, which only you can answer is: does it really make sense to represent the styling information in a pseudo-CSS syntax that you'll have to write your own parser for? Who will write the styling information? Are they familiar with CSS? If yes, won't they be irritated at not being able to use more complex selectors? If no, why go through all the effort to make it look like CSS? Why not use something simpler like a properties file, or if you want more structure, something with existing parsers, like XML or JSON?

Michael Borgwardt