Heres my notes on how to adding enhanced labeling to 2.4.3
Might be useful for developers creating the current round of inspire based
metadata editors...
Labeling enhancement
problem case :-
We want to show specific labels and descriptions/help in our gemini2
/inspire editor.
For example we have 3 elements mapped to gmd:title.
<gmd:specification>
<gmd:CI_Citation>
<gmd:title>
</gmd:title>
</gmd:CI_Citation>
</gmd:specification>
<gmd:citation>
<gmd:CI_Citation>
<gmd:title>
</gmd:title>
</gmd:CI_Citation>
</gmd:citation>
<gmd:thesaurusName>
<gmd:CI_Citation>
<gmd:title>
</gmd:title>
</gmd:CI_Citation>
</gmd:thesaurusName>
In the current labeling system in 2.4.3 these would all map to
<element name="gmd:title" >
<label>Title</label>
<description>Name by which the cited resource is known</description>
<condition>mandatory</condition>
</element>
In the trunk the labeling system can map a label with the help of the
immediate parent node.
<element name="gmd:title" context="gmd:CI_Citation" >
<label>Citation Title</label>
<description>Citation Title Description Help</description>
<condition>mandatory</condition>
</element>
However our requirement needs to be even more fine grained.
We need to add a context and a parentContext to the labeling system like
this
<element name="gmd:title" context="gmd:CI_Citation"
parentContext="gmd:citation">
<label>Citation Title</label>
<description>Citation Title Description Help</description>
<condition>mandatory</condition>
</element>
<element name="gmd:title" context="gmd:CI_Citation"
parentContext="gmd:specification">
<label>Specification Title</label>
<description>Specification Title Description Help</description>
<condition>mandatory</condition>
</element>
<element name="gmd:title" context="gmd:CI_Citation"
parentContext="gmd:thesaurusName">
<label>Thesaurus Title</label>
<description>Thesaurus Title Description Help</description>
<condition>mandatory</condition>
</element>
Code changes made.
Metadata.xsl
1.
Update the helplinkurl template to include the 2 additional contexts
<!--
-->
<!-- returns the help url -->
<!--
-->
<xsl:template name="getHelpLink">
<xsl:param name="name"/>
<xsl:param name="schema"/>
<xsl:choose>
<xsl:when test="contains($name,'_ELEMENT')">
<xsl:value-of select="''"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($schema,'|', $name ,'|',
name(parent::node()) ,'|', name(../../.) ,'|',../@gco:isoType)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
2. Update the getTitle template so we can use the 2 additional contexts
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- utility templates -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!--
Returns the title of an element. If the schema is an ISO profil then
search:
* the ISO profil help first
* with context (ie. context is the class where the element is defined)
* with no context
and if not found search the iso19139 main help.
If not iso based, search in corresponding schema.
If not found return the element name between "".
-->
<xsl:template name="getTitle">
<xsl:param name="name"/>
<xsl:param name="schema"/>
<xsl:variable name="context" select="name(parent::node())"/>
<xsl:variable name="contextIsoType" select="parent::node()/@gco:isoType"/>
<xsl:variable name="parentContext" select="name(../../.)"/>
<xsl:if test="$name='gmd:title'" >
<xsl:value-of select="'dfgdg'"></xsl:value-of>
</xsl:if>
<xsl:variable name="title">
<xsl:choose>
<xsl:when test="starts-with($schema,'iso19139')">
<xsl:variable name="testschematitleWithContext"
select="string(/root/gui/*[name(.)=$schema]
/element[@name=$name and (@context=$context or
@context=$contextIsoType)]/label)"/>
<!-- Name with context in current schema -->
<xsl:variable name="schematitleWithContext" >
<xsl:choose>
<xsl:when test="/root/gui/*[name(.)=$schema]
/element[@name=$name and (@context=$context and
@parentContext=$parentContext)]">
<xsl:value-of select="string(/root/gui/*[name(.)=$schema]
/element[@name=$name and @context=$context and
@parentContext=$parentContext]
/label)"></xsl:value-of>
</xsl:when>
<xsl:when test="/root/gui/*[name(.)=$schema]
/element[@name=$name and (@context=$context or
@context=$contextIsoType)]">
<xsl:value-of select="string(/root/gui/*[name(.)=$schema]
/element[@name=$name and (@context=$context or
@context=$contextIsoType)]
/label)"></xsl:value-of>
</xsl:when>
</xsl:choose>
</xsl:variable>
<!-- Name with context in base schema -->
<xsl:variable name="schematitleWithContextIso"
select="string(/root/gui/iso19139/element[@name=$name and
(@context=$context or @context=$contextIsoType)]
/label)"/>
<!-- Name in current schema -->
<xsl:variable name="schematitle"
select="string(/root/gui/*[name(.)=$schema]/element[@name=$name and
not(@context)]/label)"/>
<xsl:choose>
<xsl:when test="normalize-space($schematitle)='' and
normalize-space($schematitleWithContext)='' and
normalize-space($schematitleWithContextIso)=''">
<xsl:value-of
select="string(/root/gui/iso19139/element[@name=$name]/label)"/>
</xsl:when>
<xsl:when test="normalize-space($schematitleWithContext)='' and
normalize-space($schematitleWithContextIso)=''">
<xsl:value-of select="$schematitle"/>
</xsl:when>
<xsl:when test="normalize-space($schematitleWithContext)=''">
<xsl:value-of select="$schematitleWithContextIso"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$schematitleWithContext"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<!-- otherwise just get the title out of the approriate schema help file
-->
<xsl:otherwise>
<xsl:value-of
select="string(/root/gui/*[name(.)=$schema]/element[@name=$name]/label)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="normalize-space($title)!=''">
<xsl:value-of select="$title"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$name"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
3. For the ajax Help popup.
Update the javascript simpletooltip.js to pass the additional contexts to
the java service
function toolTip(spanId) {
var elem = $(spanId);
if (elem.childElements().length == 0) {
var tokens = elem.getAttribute('id').split('|');
var schema = tokens[0].substring(5);
var name = tokens[1];
var context = tokens[2];
var parentContext = tokens[3];
var isoType = tokens[4];
var request = str.substitute(toolTipRequestTemp, {
SCHEMA : schema,
NAME : name,
CONTEXT : context,
PARENT_CONTEXT : parentContext,
ISOTYPE : isoType
});
ker.send('xml.schema.info', request, ker.wrap(this,
function(xmlRes) {
if (xmlRes.nodeName == 'error') {
ker.showError(translate('cannotGetTooltip'), xmlRes);
} else {
var htmlTip = getHtmlTip(xmlRes
.getElementsByTagName('element')[0]);
tip = document.createElement('div');
tip.className = 'toolTipOverlay';
tip.innerHTML = htmlTip;
elem.appendChild(tip);
}
}));
} else {
childs = elem.childElements();
childs[0].toggle();
}
}
4 Update the templateTipRequest in simpletooltip.js
var toolTipRequestTemp = '<request
xmlns:gmd="http://www.isotc211.org/2005/gmd"'
+ ' xmlns:gts="http://www.isotc211.org/2005/gts"'
+ ' xmlns:srv="http://www.isotc211.org/2005/srv"'
+ ' xmlns:gml="http://www.opengis.net/gml"'
+ ' xmlns:gfc="http://www.isotc211.org/2005/gfc"'
+ ' xmlns:gco="http://www.isotc211.org/2005/gco"'
+ ' xmlns:dct="http://purl.org/dc/terms/"'
+ ' xmlns:xlink="http://www.w3.org/1999/xlink"'
+ ' xmlns:dc ="http://purl.org/dc/elements/1.1/">'
+ ' <element schema="{SCHEMA}" name="{NAME}" context="{CONTEXT}"
isoType="{ISOTYPE}" parentContext="{PARENT_CONTEXT}"/>'
'</request>';
5. Update the java org.fao.geonet.services.schema.Info.java service to make
use of the contexts
//=============================================================================
//=== Copyright (C) 2001-2007 Food and Agriculture Organization of the
//=== United Nations (FAO-UN), United Nations World Food Programme (WFP)
//=== and United Nations Environment Programme (UNEP)
//===
//=== This program is free software; you can redistribute it and/or modify
//=== it under the terms of the GNU General Public License as published by
//=== the Free Software Foundation; either version 2 of the License, or (at
//=== your option) any later version.
//===
//=== This program is distributed in the hope that it will be useful, but
//=== WITHOUT ANY WARRANTY; without even the implied warranty of
//=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//=== General Public License for more details.
//===
//=== You should have received a copy of the GNU General Public License
//=== along with this program; if not, write to the Free Software
//=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
USA
//===
//=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
//=== Rome - Italy. email: geonetwork@anonymised.com
//==============================================================================
package org.fao.geonet.services.schema;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import jeeves.exceptions.BadInputEx;
import jeeves.exceptions.BadParameterEx;
import jeeves.exceptions.OperationAbortedEx;
import jeeves.interfaces.Service;
import jeeves.server.ServiceConfig;
import jeeves.server.context.ServiceContext;
import jeeves.utils.Util;
import jeeves.utils.XmlFileCacher;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.kernel.DataManager;
import org.jdom.Element;
import org.jdom.Namespace;
//=============================================================================
public class Info implements Service {
//
--------------------------------------------------------------------------
// ---
// --- Init
// ---
//
--------------------------------------------------------------------------
public void init(String appPath, ServiceConfig params) throws Exception {
this.appPath = appPath;
}
//
--------------------------------------------------------------------------
// ---
// --- Service
// ---
//
--------------------------------------------------------------------------
public Element exec(Element params, ServiceContext context)
throws Exception {
GeonetContext gc = (GeonetContext) context
.getHandlerContext(Geonet.CONTEXT_NAME);
DataManager dm = gc.getDataManager();
String langCode = context.getLanguage();
Element response = new Element("response");
for (Object o : params.getChildren()) {
Element elem = (Element) o;
String name = elem.getName();
if (name.equals("element"))
response.addContent(handleElement(dm, langCode, elem));
else if (name.equals("codelist"))
response.addContent(handleCodelist(dm, langCode, elem));
else
throw new BadParameterEx("element", name);
}
return response;
}
//
--------------------------------------------------------------------------
// ---
// --- Private methods
// ---
//
--------------------------------------------------------------------------
private Element handleElement(DataManager dm, String langCode, Element
elem)
throws Exception {
return handleObject(dm, langCode, elem, "labels.xml");
}
//
--------------------------------------------------------------------------
private Element handleCodelist(DataManager dm, String langCode, Element
elem)
throws Exception {
return handleObject(dm, langCode, elem, "codelists.xml");
}
//
--------------------------------------------------------------------------
private Element handleObject(DataManager dm, String langCode, Element elem,
String fileName) throws BadInputEx, OperationAbortedEx {
String schema = Util.getAttrib(elem, "schema");
String name = Util.getAttrib(elem, "name");
String context = Util.getAttrib(elem, "context", "");
String parentContext = Util.getAttrib(elem, "parentContext", "");
String isoType = Util.getAttrib(elem, "isoType", "");
name = normalizeNamespace(elem, name);
context = normalizeNamespace(elem, context);
parentContext = normalizeNamespace(elem, parentContext);
isoType = normalizeNamespace(elem, isoType);
if (name == null)
return buildError(elem, UNKNOWN_NAMESPACE);
if (!dm.existsSchema(schema))
return buildError(elem, UNKNOWN_SCHEMA);
return getHelp(dm, langCode, elem, fileName, schema, name, context,
parentContext,
isoType);
}
private Element getHelp(DataManager dm, String langCode, Element elem,
String fileName, String schema, String name, String context, String
parentContext,
String isoType) throws BadInputEx, OperationAbortedEx {
File file = getFile(langCode, schema, fileName);
if (file == null)
throw new OperationAbortedEx("File not found for : " + schema + "/"
+ fileName);
XmlFileCacher xfc = cache.get(file);
if (xfc == null) {
xfc = new XmlFileCacher(file);
cache.put(file, xfc);
}
try {
Element entries = xfc.get();
for (Object o : entries.getChildren()) {
Element currElem = (Element) o;
String currName = currElem.getAttributeValue("name");
String currContext = currElem.getAttributeValue("context");
String currParentContext = currElem.getAttributeValue("parentContext");
currName = normalizeNamespace(entries, currName);
if (currName == null)
throw new OperationAbortedEx("No namespace found for : "
+ currName);
if (currContext != null && context != null && isoType != null) {
currContext = normalizeNamespace(entries, currContext);
if (name.equals(currName)
&& (context.equals(currContext) || isoType
.equals(currContext)))
return (Element) currElem.clone();
}
else if(name.equals(currName)
&& context.equals(currContext) &&
parentContext.equals(currParentContext) ){
return (Element) currElem.clone();
}
}
for (Object o : entries.getChildren()) {
Element currElem = (Element) o;
String currName = currElem.getAttributeValue("name");
String currContext = currElem.getAttributeValue("context");
currName = normalizeNamespace(entries, currName);
if (currName == null)
throw new OperationAbortedEx("No namespace found for : "
+ currName);
if( name.equals(currName) && context.equals(currContext)){
return (Element) currElem.clone();
}
}
for (Object o : entries.getChildren()) {
Element currElem = (Element) o;
String currName = currElem.getAttributeValue("name");
currName = normalizeNamespace(entries, currName);
if (currName == null)
throw new OperationAbortedEx("No namespace found for : "
+ currName);
if( name.equals(currName)){
return (Element) currElem.clone();
}
}
if (schema.contains("iso19139") && !(schema.equals("iso19139"))) {
return getHelp(dm, langCode, elem, fileName, "iso19139", name,
context, parentContext, isoType);
} else
return buildError(elem, NOT_FOUND);
} catch (Exception e) {
throw new OperationAbortedEx("Can't load xml file : " + file
+ " element name:" + name, e);
}
}
//
--------------------------------------------------------------------------
private String normalizeNamespace(Element elem, String name) {
int pos = name.indexOf(":");
if (pos == -1)
return name;
String prefix = name.substring(0, pos);
Namespace ns = elem.getNamespace(prefix);
if (ns == null)
return null;
return ns.getURI() + name.substring(pos);
}
//
--------------------------------------------------------------------------
private File getFile(String langCode, String schema, String fileName) {
File file = new File(appPath + "xml/schemas/" + schema + "/loc/"
+ langCode + "/" + fileName);
if (file.exists())
return file;
// --- let's try the default language 'en'
file = new File(appPath + "xml/schemas/" + schema + "/loc/"
+ Geonet.DEFAULT_LANGUAGE + "/" + fileName);
if (file.exists())
return file;
return null;
}
//
--------------------------------------------------------------------------
private Element buildError(Element elem, String error) {
elem = (Element) elem.clone();
elem.setAttribute("error", error);
return elem;
}
//
--------------------------------------------------------------------------
// ---
// --- Variables
// ---
//
--------------------------------------------------------------------------
private static final String UNKNOWN_SCHEMA = "unknown-schema";
private static final String UNKNOWN_NAMESPACE = "unknown-namespace";
private static final String NOT_FOUND = "not-found";
//
--------------------------------------------------------------------------
private String appPath;
private Map<File, XmlFileCacher> cache = new HashMap<File,
XmlFileCacher>();
}
//
6. Update the css style style sheets. In geonetwork.css to get the box.
div.toolTipOverlay {
background: #fff;
max-width: 600px!important;
height: auto;
font-weight: normal;
position: absolute;
border-style: solid;
margin: 2px;
padding: 2px;
}
7. Update the labels.xml file with the new finer grained labels and help
<element name="gmd:title" context="gmd:CI_Citation"
parentContext="gmd:citation">
<label>Citation Title</label>
<description>Citation Title Description Help</description>
<condition>mandatory</condition>
</element>
<element name="gmd:title" context="gmd:CI_Citation"
parentContext="gmd:specification">
<label>Specification Title</label>
<description>Specification Title Description Help</description>
<condition>mandatory</condition>
</element>
<element name="gmd:title" context="gmd:CI_Citation"
parentContext="gmd:thesaurusName">
<label>Thesaurus Title</label>
<description>Thesaurus Title Description Help</description>
<condition>mandatory</condition>
</element>
--
View this message in context: http://osgeo-org.1803224.n2.nabble.com/Labelling-question-tp4962074p4973245.html
Sent from the GeoNetwork developer mailing list archive at Nabble.com.