Table of Contents
Display Items in Greenstone 3
DisplayItems are used in the collectionConfig.xml file to customise bits of text, in a language specific manner.
For example, they are used for:
- search field names
- classifier names
- collection name and description
Display Item format
Display items can be specified in several ways:
- Straight language dependent text: <displayItem name="name" lang="en">My Recipe Collection</displayItem>
- Dictionary lookup: <displayItem name="name" key="level.section"/> - This has an optional dictonary attribute, if you want to specify the dictionary file.
Note, main dictionaries are found in web/WEB-INF/classes, java source code is found in src/java/org/greenstone/gsdl3
Customising the search fields
Levels
<level name="section"/>
By default, the text for this will come from level.section in the ServiceRack.properties dictionary. We can customise it, e.g.
<level name="section"> <displayItem name="name" lang="fr">Chaptires</displayItem> <displayItem name="name" lang="en">Chapters</displayItem> <displayItem name="name" key="level.chapter"/> </level>
For english, the lang=en displayItem will be used, as it matches the current language. For languages where there is not a specific displayItem, it will use one with a key (if present). This key (level.chapter) is looked up in the ServiceRack.properties dictionary (for the approprate language). If it can find a value, then this will be used. If no value is found, then the first displayItem will be used as a default (in this case, the french version). If for some reason, no displayItem values are found (eg if only a key type one is present and the key hasn't been defined), then it will default to using level.section from the ServiceRack dictionary.
(See getDisplayText in service/ServiceRack.java, and getLevelData in service/AbstractGS2FieldSearch.java)
Indexes
Display values for indexes are done in a similar way to levels, except that the values are looked up in metadata_names.properties, rather than in the chain of servicename.properties.
<index name="Title"/>
No displayItems, so we look up Title.buttonname in metadata_names.
<index name="dc.Title,Title"> <displayItem name="name" key="Title.buttonname"/> <displayItem name="name" lang="en">book titles</displayItem> </index>
For English, we will display book titles. For other languages we will display the value from the dictionary for Title.buttonname.
Classifiers
The navigation tab for each classifier is also customisable. By default, the code will get the Title metadata for the classifier from the collection database (eg index/text/demo.gdb). It will look up this name + .buttonname to get the value for the tab. The Title metadata is set by the perl classifier code. It will use the -buttonname argument, or will generate one from the -metadata argument. For example List -metadata dc.Date,Date will just get "Date" as its Title.
DisplayItems can be used here too, in a similar way to the indexes and levels.
Understanding the Dictionaries
To get language specific strings in Java we use ResourceBundle dictionaries. If asked for a key from a specific dictionary in a specific language, Java will load the dictionary and look up the key. It has a chain of languages it tries. The specified language, a family related language (I think), the default language.
We use a custom classloader to find dictionary files (util/CollectionClassLoader.java). If the code is looking for eg ServiceRack.properties, it will first look in the current collection's resources folder. Otherwise it will look in the main classes area which is web/WEB-INF/classes. This enables a collection to customise the values without affecting other collections.
getTextString() (in services/ServiceRack.java) is the method we use to look something up in a dictionary.
In some cases, a dictionary name is passed in to getTextString() (e.g. metadata_names). In this case, we look for metadata_names dictionary using the CollectionClassLoader, and return the value from that dictionary. If no value is found, then we return nothing.
In the majority of cases, we will try various named dictionaries to try and find the key. It starts with the current class name, then tries up the class hierarchy until it gets to ServiceRack (which is the base class for all ServiceRacks. Once it gets to looking in ServiceRack.properties, it will try a key lookup of servicename.key, then just key itself.
In this way different services can override values. For example, if GS2MGPPSearch is looking up the value for level.section, the following shows the order of precedence (dictionary_file:key_name)
GS2MGPPSearch.properties:level.section
AbstractGS2FieldSearch.properties:level.section
AbstractGs2TextSearch.properties:level.section
ServiceRack.properties:GS2MGPPSearch.level.section
ServiceRack.properties:level.section