You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by an...@apache.org on 2008/03/25 17:48:53 UTC

svn commit: r640893 - in /lenya/trunk/src/modules/lucene: ./ config/cocoon-xconf/ java/src/org/apache/cocoon/components/search/ java/src/org/apache/cocoon/components/search/components/impl/ java/src/org/apache/cocoon/transformation/ java/src/org/apache...

Author: andreas
Date: Tue Mar 25 09:48:47 2008
New Revision: 640893

URL: http://svn.apache.org/viewvc?rev=640893&view=rev
Log:
Adding all meta data and the fields 'uuid' and 'language' to the Lucene index.

Added:
    lenya/trunk/src/modules/lucene/config/cocoon-xconf/metaDataFieldRegistry.xconf
    lenya/trunk/src/modules/lucene/config/cocoon-xconf/queryString-module.xconf
    lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/
    lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/
    lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/MetaDataFieldRegistry.java
    lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/QueryStringModule.java
    lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/impl/
    lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/impl/MetaDataFieldRegistryImpl.java
    lenya/trunk/src/modules/lucene/xslt/metadata2index.xsl
Modified:
    lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/Index.java
    lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/AbstractIndexer.java
    lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/DefaultIndexerImpl.java
    lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/IndexManagerImpl.java
    lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/transformation/LuceneIndexTransformer2.java
    lenya/trunk/src/modules/lucene/sitemap.xmap
    lenya/trunk/src/modules/lucene/xslt/index.xsl
    lenya/trunk/src/modules/lucene/xslt/search2html.xsl

Added: lenya/trunk/src/modules/lucene/config/cocoon-xconf/metaDataFieldRegistry.xconf
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/config/cocoon-xconf/metaDataFieldRegistry.xconf?rev=640893&view=auto
==============================================================================
--- lenya/trunk/src/modules/lucene/config/cocoon-xconf/metaDataFieldRegistry.xconf (added)
+++ lenya/trunk/src/modules/lucene/config/cocoon-xconf/metaDataFieldRegistry.xconf Tue Mar 25 09:48:47 2008
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<!-- $Id: doctypes.xconf 164635 2005-04-25 20:01:43Z tschlabach $ -->
+
+<xconf xpath="/cocoon"
+  unless="/cocoon/copmonent[@role = 'org.apache.lenya.modules.lucene.MetaDataFieldRegistry']">
+
+  <component role="org.apache.lenya.modules.lucene.MetaDataFieldRegistry"
+    class="org.apache.lenya.modules.lucene.impl.MetaDataFieldRegistryImpl"/>
+
+</xconf>

Added: lenya/trunk/src/modules/lucene/config/cocoon-xconf/queryString-module.xconf
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/config/cocoon-xconf/queryString-module.xconf?rev=640893&view=auto
==============================================================================
--- lenya/trunk/src/modules/lucene/config/cocoon-xconf/queryString-module.xconf (added)
+++ lenya/trunk/src/modules/lucene/config/cocoon-xconf/queryString-module.xconf Tue Mar 25 09:48:47 2008
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<!-- $Id: doctypes.xconf 164635 2005-04-25 20:01:43Z tschlabach $ -->
+
+<xconf xpath="/cocoon/input-modules" unless="/cocoon/input-modules/component-instance[@name = 'queryString']">
+
+  <component-instance logger="core.modules.input.queryString" name="queryString"
+    class="org.apache.lenya.modules.lucene.QueryStringModule"/>
+  
+</xconf>

Modified: lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/Index.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/Index.java?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/Index.java (original)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/Index.java Tue Mar 25 09:48:47 2008
@@ -28,6 +28,7 @@
 import org.apache.cocoon.components.search.components.Indexer;
 import org.apache.cocoon.components.search.fieldmodel.DateFieldDefinition;
 import org.apache.cocoon.components.search.fieldmodel.FieldDefinition;
+import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexReader;
@@ -164,7 +165,11 @@
             analyzerM = (AnalyzerManager) this.manager
                     .lookup(AnalyzerManager.ROLE);
 
-            indexer.setAnalyzer(analyzerM.getAnalyzer(getDefaultAnalyzerID()));
+            String analyzerId = getDefaultAnalyzerID();
+            if (analyzerId != null) {
+                Analyzer analyzer = analyzerM.getAnalyzer(analyzerId);
+                indexer.setAnalyzer(analyzer);
+            }
             indexer.setIndex(directory);
 
             return indexer;

Modified: lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/AbstractIndexer.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/AbstractIndexer.java?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/AbstractIndexer.java (original)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/AbstractIndexer.java Tue Mar 25 09:48:47 2008
@@ -222,12 +222,12 @@
      */
     public void optimize() throws IndexException {
         // optimize index
-        try {
+        //try {
             this.switchToADD_MODE(false);
-            add_writer.optimize();
-        } catch (IOException ex) {
-            throw new IndexException("optimization error", ex);
-        }
+            //add_writer.optimize();
+        //} catch (IOException ex) {
+        //    throw new IndexException("optimization error", ex);
+        //}
     }
 
     /*

Modified: lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/DefaultIndexerImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/DefaultIndexerImpl.java?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/DefaultIndexerImpl.java (original)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/DefaultIndexerImpl.java Tue Mar 25 09:48:47 2008
@@ -90,7 +90,7 @@
             flushBufferedDocs();
         }
         bufferSize = defaultMaxBufDocs;
-        this.optimize();
+        //this.optimize();
         super.release();
     }
 

Modified: lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/IndexManagerImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/IndexManagerImpl.java?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/IndexManagerImpl.java (original)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/components/search/components/impl/IndexManagerImpl.java Tue Mar 25 09:48:47 2008
@@ -43,11 +43,16 @@
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.excalibur.source.SourceUtil;
 import org.apache.lenya.cms.cocoon.components.context.ContextUtility;
+import org.apache.lenya.cms.metadata.Element;
+import org.apache.lenya.cms.metadata.ElementSet;
+import org.apache.lenya.cms.metadata.MetaDataException;
+import org.apache.lenya.cms.metadata.MetaDataRegistry;
 import org.apache.lenya.cms.publication.DocumentFactory;
 import org.apache.lenya.cms.publication.DocumentUtil;
 import org.apache.lenya.cms.publication.Publication;
 import org.apache.lenya.cms.publication.PublicationException;
 import org.apache.lenya.cms.publication.PublicationManager;
+import org.apache.lenya.modules.lucene.MetaDataFieldRegistry;
 
 /**
  * Index Manager Component. Configure and Manage the differents indexes.
@@ -106,7 +111,8 @@
     /**
      * type of the field: "text, "keyword", "date" (see
      * 
-     * @see org.apache.cocoon.components.search.fieldmodel.FieldDefinition class)
+     * @see org.apache.cocoon.components.search.fieldmodel.FieldDefinition
+     *      class)
      */
     public static final String TYPE_ATTRIBUTE = "type";
 
@@ -126,8 +132,8 @@
     public static final String INDEX_CONF_FILE = "search/lucene_index.xml";
 
     /**
-     * check the config file each time the getIndex is called to update if necessary the
-     * configuration
+     * check the config file each time the getIndex is called to update if
+     * necessary the configuration
      */
     // public static final String CHECK_ATTRIBUTE = "check";
     /**
@@ -135,7 +141,8 @@
      */
     // public static final String CONFIG_ATTRIBUTE = "config";
     /**
-     * Check or not the configuration file (automatic update if the file is changed)
+     * Check or not the configuration file (automatic update if the file is
+     * changed)
      */
     // private boolean check;
     /**
@@ -147,7 +154,7 @@
     private Map indexMap;
 
     protected Map indexes() {
-        if(this.indexMap == null) {
+        if (this.indexMap == null) {
             this.indexMap = new HashMap();
             loadIndexes();
         }
@@ -259,8 +266,8 @@
      * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
      */
     public void configure(Configuration configuration) throws ConfigurationException {
-        this.indexerRole = configuration.getChild(INDEXER_ELEMENT)
-                .getAttribute(INDEXER_ROLE_ATTRIBUTE);
+        this.indexerRole = configuration.getChild(INDEXER_ELEMENT).getAttribute(
+                INDEXER_ROLE_ATTRIBUTE);
     }
 
     /**
@@ -283,6 +290,8 @@
      */
     private void addIndexes(Configuration configuration) throws ConfigurationException {
         AnalyzerManager analyzerManager = null;
+        MetaDataFieldRegistry registry = null;
+
         Configuration[] confs = configuration.getChildren(INDEX_ELEMENT);
 
         if (confs.length == 0) {
@@ -290,20 +299,33 @@
         }
         try {
             analyzerManager = (AnalyzerManager) this.manager.lookup(AnalyzerManager.ROLE);
+            registry = (MetaDataFieldRegistry) this.manager.lookup(MetaDataFieldRegistry.ROLE);
 
             // configure each index
             for (int i = 0; i < confs.length; i++) {
                 String id = confs[i].getAttribute(ID_ATTRIBUTE);
-                String analyzerid = confs[i].getAttribute(INDEX_DEFAULTANALZER_ATTRIBUTE);
-                String directory = confs[i].getAttribute(INDEX_DIRECTORY_ATTRIBUTE);
-                if (!analyzerManager.exist(analyzerid)) {
+                String analyzerid = confs[i].getAttribute(INDEX_DEFAULTANALZER_ATTRIBUTE, null);
+                if (analyzerid != null && !analyzerManager.exist(analyzerid)) {
                     throw new ConfigurationException("Analyzer " + analyzerid + " no found");
                 }
 
-                Configuration[] fields = confs[i].getChild(STRUCTURE_ELEMENT)
-                        .getChildren(FIELD_ELEMENT);
+                String directory = confs[i].getAttribute(INDEX_DIRECTORY_ATTRIBUTE);
+
+                Configuration[] fields = confs[i].getChild(STRUCTURE_ELEMENT).getChildren(
+                        FIELD_ELEMENT);
 
                 IndexStructure docdecl = new IndexStructure();
+
+                addMetaDataFieldDefinitions(registry, docdecl);
+                
+                FieldDefinition uuidDef = FieldDefinition.create("uuid", FieldDefinition.KEYWORD);
+                uuidDef.setStore(true);
+                docdecl.addFieldDef(uuidDef);
+
+                FieldDefinition langDef = FieldDefinition.create("language", FieldDefinition.KEYWORD);
+                langDef.setStore(true);
+                docdecl.addFieldDef(langDef);
+
                 for (int j = 0; j < fields.length; j++) {
 
                     FieldDefinition fielddecl;
@@ -332,7 +354,8 @@
                     // field dateformat attribute
                     if (fielddecl.getType() == FieldDefinition.DATE) {
                         String dateformat_field = fields[j].getAttribute(DATEFORMAT_ATTRIBUTE);
-                        ((DateFieldDefinition) fielddecl).setDateFormat(new SimpleDateFormat(dateformat_field));
+                        ((DateFieldDefinition) fielddecl).setDateFormat(new SimpleDateFormat(
+                                dateformat_field));
                     }
 
                     this.getLogger().debug("field added: " + fielddecl);
@@ -351,7 +374,9 @@
                 if (index.setDirectory(directory)) {
                     this.getLogger().warn("directory " + directory + " was locked ");
                 }
-                index.setDefaultAnalyzerID(analyzerid);
+                if (analyzerid != null) {
+                    index.setDefaultAnalyzerID(analyzerid);
+                }
                 index.setStructure(docdecl);
                 index.setManager(manager);
 
@@ -367,7 +392,24 @@
             if (analyzerManager != null) {
                 this.manager.release(analyzerManager);
             }
+            if (registry != null) {
+                this.manager.release(registry);
+            }
+        }
+    }
+
+    protected void addMetaDataFieldDefinitions(MetaDataFieldRegistry registry,
+            IndexStructure indexStructure) throws MetaDataException {
+        String[] fieldNames = registry.getFieldNames();
+        for (int i = 0; i < fieldNames.length; i++) {
+            FieldDefinition fieldDef = FieldDefinition.create(fieldNames[i], FieldDefinition.TEXT);
+            fieldDef.setStore(false);
+            indexStructure.addFieldDef(fieldDef);
         }
+    }
+
+    public static String getUniversalName(String namespace, String elementName) {
+        return "{" + namespace + "}" + elementName;
     }
 
     /**

Modified: lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/transformation/LuceneIndexTransformer2.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/transformation/LuceneIndexTransformer2.java?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/transformation/LuceneIndexTransformer2.java (original)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/cocoon/transformation/LuceneIndexTransformer2.java Tue Mar 25 09:48:47 2008
@@ -17,6 +17,9 @@
 package org.apache.cocoon.transformation;
 
 import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.Map;
 
 import org.apache.avalon.excalibur.pool.Recyclable;
@@ -42,6 +45,7 @@
 import org.apache.lenya.ac.UserManager;
 import org.apache.lenya.cms.repository.RepositoryUtil;
 import org.apache.lenya.cms.repository.Session;
+import org.apache.lenya.modules.lucene.MetaDataFieldRegistry;
 import org.apache.lenya.notification.Message;
 import org.apache.lenya.notification.NotificationUtil;
 import org.apache.lucene.analysis.Analyzer;
@@ -208,6 +212,8 @@
 
     public static final int DELETING_PROCESS = 6;
 
+    protected static final String NAMESPACE_ATTRIBUTE = "namespace";
+
     // Runtime variables
     private int mergeFactor;
 
@@ -236,6 +242,8 @@
     private String uuid;
     private String language;
 
+    private MetaDataFieldRegistry registry;
+
     /**
      * Setup the transformer.
      */
@@ -356,11 +364,13 @@
 
             case IN_DOCUMENT_PROCESS:
                 if (LUCENE_FIELD_ELEMENT.equals(localName)) {
-
+                    final String namespace = atts.getValue(NAMESPACE_ATTRIBUTE);
+                    final String name = atts.getValue(LUCENE_FIELD_NAME_ATTRIBUTE);
+                    
                     // set the field name
-                    this.fieldname = atts.getValue(LUCENE_FIELD_NAME_ATTRIBUTE);
+                    this.fieldname = namespace == null ? name : getMetaDataFieldName(namespace, name);
                     if (this.fieldname == null || this.fieldname.equals("")) {
-                        handleError("<lucene:field> element must contain name attribut");
+                        handleError("<lucene:field> element must contain name attribute");
                     }
 
                     // clear the text buffer
@@ -385,6 +395,17 @@
         }
     }
 
+    protected String getMetaDataFieldName(String namespace, String elementName) {
+        if (this.registry == null) {
+            try {
+                this.registry = (MetaDataFieldRegistry) this.manager.lookup(MetaDataFieldRegistry.ROLE);
+            } catch (ServiceException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return this.registry.getFieldName(namespace, elementName);
+    }
+
     public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
 
         // getLogger().debug("END processing: "+processing+" "+localName);
@@ -399,7 +420,7 @@
                     this.processing = NO_PROCESSING;
                     super.endElement(namespaceURI, localName, qName);
                 } else {
-                    handleError("</lucene:" + LUCENE_DELETING_ELEMENT + " was expected!");
+                    handleUnexpectedClosingElement(localName, LUCENE_DELETING_ELEMENT);
                 }
                 break;
 
@@ -410,7 +431,7 @@
                     this.processing = NO_PROCESSING;
                     super.endElement(namespaceURI, localName, qName);
                 } else {
-                    handleError("</lucene:" + LUCENE_DELETING_ELEMENT + " was expected!");
+                    handleUnexpectedClosingElement(localName, LUCENE_DELETING_ELEMENT);
                 }
                 break;
 
@@ -434,7 +455,7 @@
                     super.endElement(namespaceURI, localName, qName);
                     this.processing = INDEX_PROCESS;
                 } else {
-                    handleError("</lucene:" + LUCENE_DOCUMENT_ELEMENT + " was expected!");
+                    handleUnexpectedClosingElement(localName, LUCENE_DOCUMENT_ELEMENT);
                 }
                 break;
 
@@ -454,7 +475,7 @@
                     super.endElement(namespaceURI, localName, qName);
                     this.processing = DELETE_PROCESS;
                 } else {
-                    handleError("</lucene:" + LUCENE_DOCUMENT_ELEMENT + " was expected!");
+                    handleUnexpectedClosingElement(localName, LUCENE_DOCUMENT_ELEMENT);
                 }
                 break;
 
@@ -462,30 +483,34 @@
                 if (LUCENE_FIELD_ELEMENT.equals(localName)) {
 
                     // create lucene field
-                    Field f = null;
                     try {
-                        f = index.createField(fieldname, fieldvalue.toString());
+                        Field f = index.createField(fieldname, fieldvalue.toString());
+                        f.setBoost(fieldboost);
+                        
+                        // add field to the lucene document
+                        bodyDocument.add(f);
+                        processing = IN_DOCUMENT_PROCESS;
                     } catch (IndexException ex) {
                         handleError(ex);
                     }
-                    f.setBoost(fieldboost);
-
-                    // add field to the lucene document
-                    bodyDocument.add(f);
-                    processing = IN_DOCUMENT_PROCESS;
                 } else {
-                    handleError("</lucene:" + LUCENE_FIELD_ELEMENT + " was expected!");
+                    handleUnexpectedClosingElement(localName, LUCENE_FIELD_ELEMENT);
                 }
                 break;
 
             default:
-                handleError("unknow element '" + LUCENE_FIELD_ELEMENT + "'!");
+                handleError("Inappropriate element '" + localName + "' in state '" + processing  + "'!");
             }
         } else {
             super.endElement(namespaceURI, localName, qName);
         }
     }
 
+    protected void handleUnexpectedClosingElement(String localName, String expectedLocalName)
+            throws SAXException {
+        handleError("</lucene:" + expectedLocalName + "> was expected instead of </lucene:" + localName + ">!");
+    }
+
     protected boolean canIndex() {
         return this.indexer != null;
     }
@@ -510,48 +535,18 @@
      */
     private void initIndexer(Attributes atts) throws SAXException {
 
-        String id = atts.getValue(LUCENE_INDEXING_INDEXID_ATTRIBUTE);
-        String analyzerid = atts.getValue(LUCENE_URI, LUCENE_INDEXING_ANALYZER_ATTRIBUTE);
-        String mergeF = atts.getValue(LUCENE_URI, LUCENE_INDEXING_MERGE_FACTOR_ATTRIBUTE);
-        String clear = atts.getValue(LUCENE_URI, LUCENE_INDEXING_CREATE_ATTRIBUTE);
+        final String indexId = atts.getValue(LUCENE_INDEXING_INDEXID_ATTRIBUTE);
+        final String mergeF = atts.getValue(LUCENE_URI, LUCENE_INDEXING_MERGE_FACTOR_ATTRIBUTE);
+        final String clear = atts.getValue(LUCENE_URI, LUCENE_INDEXING_CREATE_ATTRIBUTE);
         attrs = new AttributesImpl(atts);
 
-        // set the indexer
-        try {
-            IndexManager indexM = (IndexManager) manager.lookup(IndexManager.ROLE);
-            index = indexM.getIndex(id);
-            if (index == null) {
-                handleError("index [" + id + "] no found in the index definition");
-            }
-            indexer = index.getIndexer();
-            manager.release(indexM);
-        } catch (ServiceException ex1) {
-            handleError(ex1);
-
-        } catch (IndexException ex3) {
-            handleError("get Indexer error for index [" + id + "]", ex3);
-        }
-
-        // set a custum analyzer (default: the analyzer of the index)
-        if (analyzerid != null) {
-            Analyzer analyzer = null;
-            try {
-                AnalyzerManager analyzerM = (AnalyzerManager) manager.lookup(AnalyzerManager.ROLE);
-                analyzer = analyzerM.getAnalyzer(analyzerid);
-                indexer.setAnalyzer(analyzer);
-                manager.release(analyzerM);
-            } catch (ServiceException ex1) {
-                handleError(ex1);
-            } catch (ConfigurationException ex2) {
-                handleError("error setting analyzer for index [" + id + "]", ex2);
-            }
-        } else {
-
-            attrs.addAttribute(LUCENE_URI, LUCENE_INDEXING_ANALYZER_ATTRIBUTE,
-                    LUCENE_INDEXING_ANALYZER_ATTRIBUTE, "CDATA", index.getDefaultAnalyzerID());
-        }
+        setIndexer(indexId);
 
         if (canIndex()) {
+            
+            String analyzerId = atts.getValue(LUCENE_URI, LUCENE_INDEXING_ANALYZER_ATTRIBUTE);
+            setAnalyzer(analyzerId);
+            
             // set clear mode
             boolean new_index = (clear != null && clear.toLowerCase().equals("true")) ? true
                     : false;
@@ -571,11 +566,61 @@
 
             if (this.getLogger().isDebugEnabled()) {
                 this.getLogger().debug(
-                        "index " + id + " clear: " + new_index + " analyzerid: " + analyzerid
+                        "index " + indexId + " clear: " + new_index + " analyzerid: " + analyzerId
                                 + "mergefactor: " + mergeF);
             }
         }
     }
+
+    protected void setIndexer(String indexId) throws SAXException {
+        IndexManager indexManager = null;
+        try {
+            indexManager = (IndexManager) manager.lookup(IndexManager.ROLE);
+            index = indexManager.getIndex(indexId);
+            if (index == null) {
+                handleError("index [" + indexId + "] no found in the index definition");
+            }
+            else {
+                indexer = index.getIndexer();
+                if (indexer == null) {
+                    handleError("Index [" + indexId + "] did return a null indexer.");
+                }
+            }
+        } catch (ServiceException ex1) {
+            handleError(ex1);
+        } catch (IndexException ex3) {
+            handleError("get Indexer error for index [" + indexId + "]", ex3);
+        } finally {
+            manager.release(indexManager);
+        }
+    }
+
+    /**
+     * Set a custum analyzer (default: the analyzer of the index).
+     * @param analyzerId The analyzer ID (may be null)
+     * @throws SAXException if an error occurs.
+     */
+    protected void setAnalyzer(String analyzerId) throws SAXException {
+        if (analyzerId == null) {
+            analyzerId = index.getDefaultAnalyzerID();
+        }
+        if (analyzerId != null) {
+            Analyzer analyzer = null;
+            AnalyzerManager analyzerManager = null;
+            try {
+                analyzerManager = (AnalyzerManager) manager.lookup(AnalyzerManager.ROLE);
+                analyzer = analyzerManager.getAnalyzer(analyzerId);
+                indexer.setAnalyzer(analyzer);
+            } catch (ServiceException ex1) {
+                handleError(ex1);
+            } catch (ConfigurationException ex2) {
+                handleError("error setting analyzer for index [" + this.index.getID() + "]", ex2);
+            }
+            finally {
+                manager.release(analyzerManager);
+            }
+        }
+    }
     
     void handleError(String message, Exception ex) throws SAXException {
         handleError(message + ": " + getExceptionMessage(ex));
@@ -588,7 +633,10 @@
     protected String getExceptionMessage(Exception ex) throws SAXException {
         String exMsg = ex.getMessage();
         String msg = exMsg == null ? "" : " (" + exMsg + ")";
-        return ex.getClass().getName() + msg;
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter printWriter = new PrintWriter(stringWriter);
+        ex.printStackTrace(printWriter);
+        return ex.getClass().getName() + msg + ", Stack trace: " + stringWriter.toString();
     }
 
     /**

Added: lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/MetaDataFieldRegistry.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/MetaDataFieldRegistry.java?rev=640893&view=auto
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/MetaDataFieldRegistry.java (added)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/MetaDataFieldRegistry.java Tue Mar 25 09:48:47 2008
@@ -0,0 +1,41 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lenya.modules.lucene;
+
+/**
+ * Map meta data elements to Lucene index fields.
+ */
+public interface MetaDataFieldRegistry {
+    
+    /**
+     * The Avalon service role.
+     */
+    String ROLE = MetaDataFieldRegistry.class.getName();
+
+    /**
+     * @param namespace The namespace URI of the meta data element set.
+     * @param elementName The name of the meta data element.
+     * @return The name of the corresponding Lucene index field.
+     */
+    String getFieldName(String namespace, String elementName);
+    
+    /**
+     * @return All field names.
+     */
+    String[] getFieldNames();
+
+}

Added: lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/QueryStringModule.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/QueryStringModule.java?rev=640893&view=auto
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/QueryStringModule.java (added)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/QueryStringModule.java Tue Mar 25 09:48:47 2008
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lenya.modules.lucene;
+
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Map;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.components.modules.input.AbstractInputModule;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.lenya.cms.metadata.Element;
+import org.apache.lenya.cms.metadata.ElementSet;
+import org.apache.lenya.cms.metadata.MetaDataRegistry;
+
+/**
+ * Creates a Lucene query string from a <em>queryString</em> request parameter
+ * which can be passed to the search generator.
+ */
+public class QueryStringModule extends AbstractInputModule implements Serviceable {
+
+    protected static final String PARAM_QUERY_STRING = "queryString";
+    protected static final String[] DEFAULT_FIELDS = { "body" };
+    
+    protected static final char[] ESCAPED_CHARACTERS = { '+', '-', '&', '|', '!', '(', ')', '{',
+        '}', '[', ']', '^', '"', '~', '*', '?', ':', '\\' };
+
+    private ServiceManager manager;
+
+    public Object getAttribute(String name, Configuration modeConf, Map objectModel)
+            throws ConfigurationException {
+
+        if (name.equals("queryString")) {
+            return getQueryString(objectModel);
+        } else {
+            throw new IllegalArgumentException("The attribute [" + name + "] is not supported.");
+        }
+
+    }
+
+    protected String getQueryString(Map objectModel) {
+        Request request = ObjectModelHelper.getRequest(objectModel);
+        String searchTerm = request.getParameter(PARAM_QUERY_STRING);
+        
+        if (searchTerm == null || searchTerm.trim().equals("")) {
+            return "";
+        }
+
+        StringBuffer queryString = new StringBuffer();
+
+        for (int i = 0; i < DEFAULT_FIELDS.length; i++) {
+            appendTerm(queryString, DEFAULT_FIELDS[i], searchTerm);
+        }
+
+        MetaDataRegistry registry = null;
+        MetaDataFieldRegistry fieldRegistry = null;
+        try {
+            registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
+            fieldRegistry = (MetaDataFieldRegistry) this.manager.lookup(MetaDataFieldRegistry.ROLE);
+            String[] namespaces = registry.getNamespaceUris();
+            for (int n = 0; n < namespaces.length; n++) {
+                ElementSet elementSet = registry.getElementSet(namespaces[n]);
+                Element[] elements = elementSet.getElements();
+                for (int e = 0; e < elements.length; e++) {
+                    if (elements[e].isSearchable()) {
+                        String field = fieldRegistry.getFieldName(namespaces[n], elements[e].getName());
+                        appendTerm(queryString, field, searchTerm);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (registry != null) {
+                this.manager.release(registry);
+            }
+            if (fieldRegistry != null) {
+                this.manager.release(fieldRegistry);
+            }
+        }
+        return queryString.toString();
+    }
+
+    protected boolean shallEscape(char c) {
+        for (int i = 0; i < ESCAPED_CHARACTERS.length; i++) {
+            if (ESCAPED_CHARACTERS[i] == c) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected String escape(final String prefix) {
+        StringBuilder builder = new StringBuilder();
+        StringCharacterIterator i = new StringCharacterIterator(prefix);
+        char c = i.current();
+        while (c != CharacterIterator.DONE) {
+            if (shallEscape(c)) {
+                builder.append('\\');
+            }
+            builder.append(c);
+            c = i.next();
+        }
+        return builder.toString();
+    }
+    
+    protected void appendTerm(StringBuffer queryString, String field, String searchTerm) {
+        if (queryString.length() > 0) {
+            queryString.append(" OR ");
+        }
+        String term = getTerm(field, searchTerm);
+        queryString.append(term);
+    }
+
+    protected String getTerm(String field, String searchTerm) {
+        return escape(field) + ":" + searchTerm;
+    }
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+}

Added: lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/impl/MetaDataFieldRegistryImpl.java
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/impl/MetaDataFieldRegistryImpl.java?rev=640893&view=auto
==============================================================================
--- lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/impl/MetaDataFieldRegistryImpl.java (added)
+++ lenya/trunk/src/modules/lucene/java/src/org/apache/lenya/modules/lucene/impl/MetaDataFieldRegistryImpl.java Tue Mar 25 09:48:47 2008
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lenya.modules.lucene.impl;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.lenya.cms.metadata.Element;
+import org.apache.lenya.cms.metadata.ElementSet;
+import org.apache.lenya.cms.metadata.MetaDataRegistry;
+import org.apache.lenya.modules.lucene.MetaDataFieldRegistry;
+import org.apache.lenya.util.Assert;
+
+public class MetaDataFieldRegistryImpl extends AbstractLogEnabled implements MetaDataFieldRegistry,
+        ThreadSafe, Serviceable {
+
+    private MetaDataRegistry registry;
+    private ServiceManager manager;
+    private Map namespace2prefix;
+
+    public String getFieldName(String namespace, String elementName) {
+        Assert.notNull("namespace", namespace);
+        Assert.notNull("element name", elementName);
+        initPrefixes();
+        Assert.isTrue("namespace [" + namespace + "] exists", this.namespace2prefix
+                .containsKey(namespace));
+        String prefix = (String) this.namespace2prefix.get(namespace);
+        return prefix + elementName;
+    }
+
+    protected MetaDataRegistry getRegistry() {
+        if (this.registry == null) {
+            try {
+                this.registry = (MetaDataRegistry) this.manager.lookup(MetaDataRegistry.ROLE);
+            } catch (ServiceException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return this.registry;
+    }
+
+    protected void initPrefixes() {
+        if (this.namespace2prefix == null) {
+            this.namespace2prefix = new HashMap();
+            MetaDataRegistry registry = getRegistry();
+            try {
+                String[] namespaces = registry.getNamespaceUris();
+                for (int n = 0; n < namespaces.length; n++) {
+                    String prefix = "{" + namespaces[n] + "}";
+                    this.namespace2prefix.put(namespaces[n], prefix);
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+    public String[] getFieldNames() {
+        MetaDataRegistry registry = getRegistry();
+        Set fieldNames = new HashSet();
+        try {
+            String[] namespaces = registry.getNamespaceUris();
+            for (int n = 0; n < namespaces.length; n++) {
+                ElementSet elementSet = registry.getElementSet(namespaces[n]);
+                Element[] elements = elementSet.getElements();
+                for (int e = 0; e < elements.length; e++) {
+                    String fieldName = getFieldName(namespaces[n], elements[e].getName());
+                    fieldNames.add(fieldName);
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return (String[]) fieldNames.toArray(new String[fieldNames.size()]);
+    }
+
+}

Modified: lenya/trunk/src/modules/lucene/sitemap.xmap
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/sitemap.xmap?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/sitemap.xmap (original)
+++ lenya/trunk/src/modules/lucene/sitemap.xmap Tue Mar 25 09:48:47 2008
@@ -93,36 +93,15 @@
       
       <!-- {1:pub}/{2:area}/{3:queryString} -->
       <map:match pattern="search-generator/*/*/*">
-        <map:select type="parameter">
-          <map:parameter name="parameter-selector-test" value="{3}"/>
-          <map:when test="">
-            <map:generate type="search">
-              <map:parameter name="index" value="{index-path:{1}-{2}}"/>
-              <map:parameter name="query" value=""/>
-            </map:generate>
-          </map:when>
-          <map:otherwise>
-            <map:generate type="search">
-              <map:parameter name="index" value="{index-path:{1}-{2}}"/>
-              <map:parameter name="query" value="title:{3} OR description:{3} OR subject:{3} OR body:{3}"/>
-            </map:generate>
-          </map:otherwise>
-        </map:select>
+        <map:generate type="search">
+          <map:parameter name="index" value="{index-path:{1}-{2}}"/>
+          <map:parameter name="query" value="{queryString:queryString}"/>
+        </map:generate>
         <map:serialize type="xml"/>
       </map:match>
       
-      <!-- {1:pub}/{2:area} -->
-      <map:match pattern="search/*/*.xml">
-        <map:generate src="cocoon:/search-generator/{1}/{2}/{request-param:queryString}"/>
-        <map:transform type="uuid2url">
-          <map:parameter name="pubId" value="{1}"/>
-          <map:parameter name="area" value="{2}"/>
-        </map:transform>
-        <map:serialize type="xml"/>
-      </map:match>
-
       <map:match pattern="search.xml">
-        <map:generate src="cocoon:/search/{page-envelope:publication-id}/{page-envelope:area}.xml"/>
+        <map:generate src="cocoon:/search-generator/{page-envelope:publication-id}/{page-envelope:area}/{request-param:queryString}"/>
         <map:transform src="fallback://lenya/modules/lucene/xslt/search2html.xsl">
           <map:parameter name="url" value="{page-envelope:document-url}"/>
           <map:parameter name="area" value="{page-envelope:area}"/>
@@ -131,14 +110,28 @@
           <map:parameter name="use-request-parameters" value="true"/>
           <map:parameter name="queryString" value="{request-param:queryString}"/>
         </map:transform>
+        <map:transform type="metaData">
+          <map:parameter name="pubid" value="{page-envelope:publication-id}"/>
+          <map:parameter name="area" value="{page-envelope:area}"/>
+        </map:transform>
         <map:transform type="cinclude"/>
         <map:transform type="uuid2url"/>
         <map:serialize type="xml"/>
       </map:match>
+      
+      <!-- index/{1:pub-id}/{2:area}/{3:uuid}/{4:language} -->
+      <map:match pattern="index-metadata/*/*/*/*">
+        <map:generate src="cocoon://modules/metadata/{1}/{2}/{3}/{4}"/>
+        <map:transform src="fallback://lenya/modules/lucene/xslt/metadata2index.xsl"/>
+        <map:serialize type="xml"/>
+      </map:match>
 
-      <!-- {pub-id}/{area}/{uuid}/{language} -->
+      <!-- {1:pub-id}/{2:area}/{3:uuid}/{4:language} -->
       <map:match pattern="index-document/*/*/*/*">
-        <map:generate src="{resource-type:{doc-info:{1}:{2}:{3}:{4}:resourceType}:format-luceneIndex}/{1}/{2}/{3}/{4}"/>
+        <map:aggregate element="index" ns="http://apache.org/cocoon/lucene/1.0">
+          <map:part src="lenya-document:{3},pub={1},area={2},lang={4}?format=luceneIndex" strip-root="true"/>
+          <map:part src="cocoon:/index-metadata/{1}/{2}/{3}/{4}"/>
+        </map:aggregate>
         <map:transform src="fallback://lenya/modules/lucene/xslt/index.xsl">
           <map:parameter name="index" value="{1}-{2}"/>
           <map:parameter name="uuid" value="{3}"/>

Modified: lenya/trunk/src/modules/lucene/xslt/index.xsl
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/xslt/index.xsl?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/xslt/index.xsl (original)
+++ lenya/trunk/src/modules/lucene/xslt/index.xsl Tue Mar 25 09:48:47 2008
@@ -14,6 +14,8 @@
   <xsl:template match="/lucene:index">
     <lucene:index indexid="{$index}" lucene:clear="false" lucene:merge-factor="100" lucene:analyzer="stopword_{$language}">
       <lucene:document uid="{$uuid}:{$language}">
+        <lucene:field name="uuid"><xsl:value-of select="$uuid"/></lucene:field>
+        <lucene:field name="language"><xsl:value-of select="$language"/></lucene:field>
         <xsl:apply-templates select="lucene:document/*"/>
       </lucene:document>
     </lucene:index>  

Added: lenya/trunk/src/modules/lucene/xslt/metadata2index.xsl
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/xslt/metadata2index.xsl?rev=640893&view=auto
==============================================================================
--- lenya/trunk/src/modules/lucene/xslt/metadata2index.xsl (added)
+++ lenya/trunk/src/modules/lucene/xslt/metadata2index.xsl Tue Mar 25 09:48:47 2008
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:lucene="http://apache.org/cocoon/lucene/1.0"
+  xmlns:meta="http://apache.org/cocoon/lenya/metadata/1.0"
+  >
+  
+  <xsl:template match="meta:metadata">
+    <lucene:document>
+      <xsl:apply-templates select="*/*"/>
+    </lucene:document>
+  </xsl:template>
+  
+  
+  <xsl:template match="*">
+    <lucene:field boost="0.5" namespace="{namespace-uri()}" name="{local-name()}"><xsl:value-of select="."/></lucene:field>
+  </xsl:template>
+  
+  
+</xsl:stylesheet>

Modified: lenya/trunk/src/modules/lucene/xslt/search2html.xsl
URL: http://svn.apache.org/viewvc/lenya/trunk/src/modules/lucene/xslt/search2html.xsl?rev=640893&r1=640892&r2=640893&view=diff
==============================================================================
--- lenya/trunk/src/modules/lucene/xslt/search2html.xsl (original)
+++ lenya/trunk/src/modules/lucene/xslt/search2html.xsl Tue Mar 25 09:48:47 2008
@@ -23,6 +23,7 @@
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:cinclude="http://apache.org/cocoon/include/1.0"
   xmlns:i18n="http://apache.org/cocoon/i18n/2.1"
+  xmlns:meta="http://apache.org/lenya/meta/1.0/"
   exclude-result-prefixes="cinclude search xhtml"
 >
 
@@ -123,27 +124,18 @@
   <xsl:template match="search:hit">
     <li class="search-result">
       <div class="search-result-rank"><xsl:value-of select="@rank + 1"/>. </div>
+      <xsl:variable name="uuid" select="search:field[@name='uuid']"/>
+      <xsl:variable name="language" select="search:field[@name='language']"/>
       <div class="search-result-title">
-        <xsl:variable name="titleField" select="search:field[attribute::name='title']"/>
-        <xsl:variable name="title">
-          <xsl:choose>
-            <xsl:when test="normalize-space($titleField) != ''">
-              <xsl:value-of select="$titleField"/>
-            </xsl:when>
-            <xsl:otherwise><i18n:text>No Title</i18n:text></xsl:otherwise>
-          </xsl:choose>
-        </xsl:variable>
-        <xsl:choose>
-          <xsl:when test="normalize-space(search:field[@name = 'uid']) != ''">
-            <a href="{$root}{search:field[attribute::name='uid']}"><xsl:value-of select="$title"/></a>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:value-of select="$title"/> (<i18n:text>not in site structure</i18n:text>)
-          </xsl:otherwise>
-        </xsl:choose>
-      <span class="search-result-score"> (<i18n:text>Score</i18n:text>: <xsl:value-of select="format-number( @score, '### %' )"/>)</span>
+        <a href="lenya-document:{$uuid},lang={$language}">
+          <meta:value element="title" ns="http://purl.org/dc/elements/1.1/" default="No Title"
+            i18n:attr="default" uuid="{$uuid}" lang="{$language}"/>
+        </a>
+        <span class="search-result-score"> (<i18n:text>Score</i18n:text>: <xsl:value-of select="format-number( @score, '### %' )"/>)</span>
+      </div>
+      <div class="search-result-description">
+        <meta:value element="description" ns="http://purl.org/dc/elements/1.1/" default="" uuid="{$uuid}" lang="{$language}"/>
       </div>
-      <div class="search-result-description"><xsl:value-of select="search:field[attribute::name='description']"/></div>
     </li>
   </xsl:template>
 



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org