Changeset 24393


Ignore:
Timestamp:
2011-08-12T09:57:26+12:00 (13 years ago)
Author:
sjm84
Message:

Adding in the server-side code for the Document Maker as well as several other enhancements

Location:
main/trunk/greenstone3/src/java/org/greenstone/gsdl3
Files:
5 added
16 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/Action.java

    r24254 r24393  
    7777    }
    7878
    79     protected void extractMetadataNames(Element format, HashSet meta_names) {
     79    protected void extractMetadataNames(Element format, HashSet meta_names) {
    8080    //NodeList nodes = format.getElementsByTagNameNS("metadata", "http://www.greenstone.org/configformat");
    8181    NodeList metadata_nodes = format.getElementsByTagName("gsf:metadata");
     
    9090                metadata.append("all");
    9191                metadata.append(GSConstants.META_RELATION_SEP);
    92             } else if (all.equals("offset")) { // multiple is no longer boolean.
    93         // Can be "true", "false" or it can be "offset" (when requested to use mdoffset)
    94                 metadata.append("offset");
    95                 metadata.append(GSConstants.META_RELATION_SEP);
    96             } // if multiple=false, then get first value for the metadata
     92            }
    9793            if (!select.equals("")) {
    9894                metadata.append(select);
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/action/GS2BrowseAction.java

    r24254 r24393  
    272272        Element d = this.doc.createElement(GSXML.DOC_NODE_ELEM);
    273273        d.setAttribute(GSXML.NODE_ID_ATT, ((Element)doc_nodes.item(c)).getAttribute(GSXML.NODE_ID_ATT));
    274         if(((Element)doc_nodes.item(c)).hasAttribute(GSXML.NODE_MDOFFSET_ATT)) {
    275             d.setAttribute(GSXML.NODE_MDOFFSET_ATT, ((Element)doc_nodes.item(c)).getAttribute(GSXML.NODE_MDOFFSET_ATT));
    276         }
    277274        doc_list.appendChild(d);
    278275        }
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/collection/Collection.java

    r24361 r24393  
    2323import org.greenstone.gsdl3.service.*;
    2424
    25 
    2625// java XML classes we're using
    27 import org.w3c.dom.Document; 
    28 import org.w3c.dom.Node; 
    29 import org.w3c.dom.Element; 
    30 import org.w3c.dom.NodeList; 
     26import org.w3c.dom.Document;
     27import org.w3c.dom.Node;
     28import org.w3c.dom.Element;
     29import org.w3c.dom.NodeList;
    3130
    3231import java.io.*;
     
    4948
    5049/**
    51  * Represents a collection in Greenstone. A collection is an extension of
    52  * a ServiceCluster - it has local data that the services use.
    53  *
     50 * Represents a collection in Greenstone. A collection is an extension of a
     51 * ServiceCluster - it has local data that the services use.
     52 * 
    5453 * @author <a href="mailto:[email protected]">Katherine Don</a>
    5554 * @see ModuleInterface
    5655 */
    57 public class Collection
    58     extends ServiceCluster {
    59 
    60     static Logger logger = Logger.getLogger(org.greenstone.gsdl3.collection.Collection.class.getName());
    61 
    62     /** is this collection being tidied */
    63     protected boolean useBook = false;
    64     /** is this collection public or private */
    65     protected boolean is_public = true;
    66 
    67     /** does this collection provide the OAI service */
    68     protected boolean has_oai = true;
    69     /** time when this collection was built */
    70     protected long lastmodified = 0;
    71     /** earliestDatestamp of this collection. Necessary for OAI */
    72     protected long earliestDatestamp = 0;
    73 
    74 
    75     /** An element containing the serviceRackList element of buildConfig.xml, used to determine whether it contains
    76      *  the OAIPMH serviceRack
    77      */
    78     //protected Element service_rack_list = null;
    79    
    80     protected XMLTransformer transformer = null;
    81     /** same as setClusterName */
    82     public void setCollectionName(String name) {
    83     setClusterName(name);
    84     }
    85 
    86     public Collection() {
    87     super();
    88     this.description = this.doc.createElement(GSXML.COLLECTION_ELEM);
    89    
    90     }
    91    
    92     /**
    93      * Configures the collection.
    94      *
    95      * gsdlHome and collectionName must be set before configure is called.
    96      *
    97      * the file buildcfg.xml is located in gsdlHome/collect/collectionName
    98      * collection metadata is obtained, and services loaded.
    99      *
    100      * @return true/false on success/fail
    101      */
    102     public boolean configure() {
    103    
    104     if (this.site_home == null || this.cluster_name== null) {
    105         logger.error("Collection: site_home and collection_name must be set before configure called!");
    106         return false;
    107     }
    108    
    109     Element coll_config_xml = loadCollConfigFile();
    110     Element build_config_xml = loadBuildConfigFile();
    111    
    112     if (coll_config_xml==null||build_config_xml==null) {
    113         return false;
    114     }
    115    
    116     // get the collection type attribute
    117     Element search = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.SEARCH_ELEM);
    118     if(search!=null) {
    119       col_type = search.getAttribute(GSXML.TYPE_ATT);
    120     }
    121    
    122     // process the metadata and display items
    123     findAndLoadInfo(coll_config_xml, build_config_xml);
    124    
    125     // now do the services
    126     configureServiceRacks(coll_config_xml, build_config_xml);
    127 
    128     return true;
    129    
    130     }
    131 
    132     public boolean useBook() {
    133         return useBook;
    134     }
    135    
    136     public boolean isPublic() {
    137     return is_public;
    138     }
    139     // Not used anymore by the OAIReceptionist to find out the earliest datestamp
    140     // amongst all oai collections in the repository. May be useful generally.
    141     public long getLastmodified() {
    142       return lastmodified;
    143     }
    144     //used by the OAIReceptionist to find out the earliest datestamp amongst all oai collections in the repository
    145     public long getEarliestDatestamp() {
    146     return earliestDatestamp;
    147     }
    148 
    149     /** whether the service_map in ServiceCluster.java contains the service 'OAIPMH'
    150      *  11/06/2007 xiao
    151      */
    152     public boolean hasOAI() {
    153       return has_oai;
    154     }
    155     /**
    156      * load in the collection config file into a DOM Element
    157      */   
    158     protected Element loadCollConfigFile() {
    159 
    160     File coll_config_file = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name));
    161    
    162     if (!coll_config_file.exists()) {
    163         logger.error("Collection: couldn't configure collection: "+this.cluster_name+", "+coll_config_file+" does not exist");
    164         return null;
    165     }
    166     // get the xml for both files
    167     Document coll_config_doc = this.converter.getDOM(coll_config_file, CONFIG_ENCODING);
    168     Element coll_config_elem = null;
    169     if (coll_config_doc != null) {
    170         coll_config_elem = coll_config_doc.getDocumentElement();
    171     }
    172     return coll_config_elem;
    173 
    174     }
    175    
    176     /**
    177      * load in the collection build config file into a DOM Element
    178      */       
    179     protected Element loadBuildConfigFile() {
    180    
    181     File build_config_file = new File(GSFile.collectionBuildConfigFile(this.site_home, this.cluster_name));
    182     if (!build_config_file.exists()) {
    183         logger.error("Collection: couldn't configure collection: "+this.cluster_name+", "+build_config_file+" does not exist");
    184         return null;
    185     }
    186     Document build_config_doc = this.converter.getDOM(build_config_file, CONFIG_ENCODING);
    187     Element build_config_elem = null;
    188     if (build_config_doc != null) {
    189         build_config_elem = build_config_doc.getDocumentElement();
    190     }
    191 
    192     lastmodified = build_config_file.lastModified();
    193  
    194     return build_config_elem;
    195     }
    196 
    197     /**
    198      * find the metadata and display elems from the two config files and add it to the appropriate lists
    199      */
    200     protected boolean findAndLoadInfo(Element coll_config_xml,
    201                       Element build_config_xml){
    202              
    203       // metadata
    204       Element meta_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
    205       addMetadata(meta_list);
    206       meta_list = (Element)GSXML.getChildByTagName(build_config_xml, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
    207       addMetadata(meta_list);
    208      
    209       meta_list = this.doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
    210       GSXML.addMetadata(this.doc, meta_list, "httpPath", this.site_http_address+"/collect/"+this.cluster_name);
    211       addMetadata(meta_list);
    212      
    213       // display stuff
    214       Element display_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER);
    215       if (display_list != null) {
    216         resolveMacros(display_list);
    217         addDisplayItems(display_list);
    218       }
    219      
    220       //check whether the html are tidy or not
    221       Element import_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.IMPORT_ELEM);
    222       if (import_list != null) {
    223         Element plugin_list = (Element)GSXML.getChildByTagName(import_list, GSXML.PLUGIN_ELEM+GSXML.LIST_MODIFIER);
    224         addPlugins(plugin_list);
    225         if (plugin_list != null){
    226           Element plugin_elem = (Element)GSXML.getNamedElement(plugin_list, GSXML.PLUGIN_ELEM, GSXML.NAME_ATT, "HTMLPlugin");
    227           if (plugin_elem != null) {
    228             //get the option
    229             Element option_elem = (Element)GSXML.getNamedElement(plugin_elem, GSXML.PARAM_OPTION_ELEM, GSXML.NAME_ATT, "-use_realistic_book");
    230             if (option_elem != null) {
    231               useBook = true;
    232             }
    233           }
    234         }
    235       }
    236       meta_list = this.doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
    237       if (useBook == true)
    238         GSXML.addMetadata(this.doc, meta_list, "tidyoption", "tidy");
    239       else
    240         GSXML.addMetadata(this.doc, meta_list, "tidyoption", "untidy");
    241       addMetadata(meta_list);
    242      
    243       // check whether we are public or not
    244       if (meta_list != null) {
    245         Element meta_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "public");
    246         if (meta_elem != null) {
    247           String value = GSXML.getValue(meta_elem).toLowerCase().trim();
    248           if (value.equals("false")) {
    249             is_public = false;
    250           }
    251         }
    252       }
    253       return true;
    254 
    255     }
    256 
    257   protected boolean configureServiceRacks(Element coll_config_xml,
    258                       Element build_config_xml){
    259     clearServices();
    260     Element service_list = (Element)GSXML.getChildByTagName(build_config_xml, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
    261     configureServiceRackList(service_list, coll_config_xml);
    262        
    263     // collection Config may also contain manually added service racks
    264     service_list = (Element)GSXML.getChildByTagName(coll_config_xml, GSXML.SERVICE_CLASS_ELEM+GSXML.LIST_MODIFIER);
    265     if (service_list != null) {
    266       configureServiceRackList(service_list, build_config_xml);
    267      
    268       // Check for oai
    269       Element oai_service_rack = GSXML.getNamedElement(service_list, GSXML.SERVICE_CLASS_ELEM, OAIXML.NAME, OAIXML.OAIPMH);
    270       if (oai_service_rack == null) {
    271     has_oai = false;
    272     logger.info("No oai for collection: " + this.cluster_name);
    273    
    274       } else {
    275     has_oai = true;
    276    
    277     // extract earliestDatestamp from the buildconfig.xml for OAI
    278     Element metadata_list = (Element)GSXML.getChildByTagName(build_config_xml, GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
    279 
    280     if(metadata_list != null) {
    281         NodeList children = metadata_list.getElementsByTagName(GSXML.METADATA_ELEM);
    282                // can't do getChildNodes(), because whitespace, such as newlines, creates Text nodes
    283         for (int i = 0; i < children.getLength(); i++) {
    284         Element metadata = (Element)children.item(i);
    285         if(metadata.getAttribute(GSXML.NAME_ATT).equals(OAIXML.EARLIEST_DATESTAMP)) {
    286             String earliestDatestampStr = GSXML.getValue(metadata);
    287             if(!earliestDatestampStr.equals("")) {
    288             earliestDatestamp = Long.parseLong(earliestDatestampStr);
    289             }
    290             break; // found a metadata element with name=earliestDatestamp in buildconfig
    291         }
    292         }
    293     }
    294    
    295     // If at the end of this, there is no value for earliestDatestamp, print out a warning
    296     logger.warn("No earliestDatestamp in buildConfig.xml for collection: " + this.cluster_name + ". Defaulting to 0.");
    297 
    298       }
    299     } else { // no list of services (no ServiceRackList), so no oai_service_rack either
    300     // explicitly set has_oai to false here, since it's initialised to true by default
    301     has_oai = false;
    302     }
    303     return true;
    304   }
    305  
    306   protected boolean resolveMacros(Element display_list) {
    307     if (display_list==null) return false;
    308     NodeList displaynodes = display_list.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
    309     if (displaynodes.getLength()>0) {
    310         String http_site = this.site_http_address;
    311         String http_collection = this.site_http_address +"/collect/"+this.cluster_name;
    312         for(int k=0; k<displaynodes.getLength(); k++) {
    313         Element d = (Element) displaynodes.item(k);
    314         String text = GSXML.getNodeText(d);
    315         text = StringUtils.replace(text, "_httpsite_", http_site);
    316         text = StringUtils.replace(text, "_httpcollection_", http_collection);
    317         GSXML.setNodeText(d, text);
    318         }
    319     }
    320     return true;
    321     }
    322     /**
    323      * do a configure on only part of the collection
    324      */
    325     protected boolean configureSubset(String subset) {
    326 
    327     // need the coll config files
    328     Element coll_config_elem = loadCollConfigFile();
    329     Element build_config_elem = loadBuildConfigFile();
    330     if (coll_config_elem == null||build_config_elem == null) {
    331         // wont be able to do any of the requests
    332         return false;
    333     }   
    334    
    335     if (subset.equals(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER)) {
    336       return configureServiceRacks(coll_config_elem, build_config_elem);
    337     }
    338 
    339     if (subset.equals(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER) || subset.equals(GSXML.DISPLAY_TEXT_ELEM+GSXML.LIST_MODIFIER) || subset.equals(GSXML.PLUGIN_ELEM+GSXML.LIST_MODIFIER)) {
    340         return findAndLoadInfo(coll_config_elem, build_config_elem);
    341        
    342     }
    343    
    344     logger.error("Collection: cant process system request, configure "+subset);
    345     return false;
    346     }
    347 
    348  /** handles requests made to the ServiceCluster itself
    349      *
    350      * @param req - the request Element- <request>
    351      * @return the result Element - should be <response>
    352      */
    353     protected Element processMessage(Element request) {
    354 
    355     Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
    356     response.setAttribute(GSXML.FROM_ATT, this.cluster_name);
    357     String type = request.getAttribute(GSXML.TYPE_ATT);
    358     String lang = request.getAttribute(GSXML.LANG_ATT);
    359     response.setAttribute(GSXML.TYPE_ATT, type);
    360 
    361     logger.debug("Collection received a message, attempting to process");
    362 
    363     if (type.equals(GSXML.REQUEST_TYPE_FORMAT_STRING)) {
    364         logger.error("Received format string request");
    365 
    366         String subaction = request.getAttribute("subaction");
    367         logger.error("Subaction is " + subaction);
    368 
    369         String service = request.getAttribute("service");
    370         logger.error("Service is " + service);
    371 
    372         String classifier = null;
    373         if(service.equals("ClassifierBrowse"))
    374         {
    375             classifier = request.getAttribute("classifier");
    376             logger.error("Classifier is " + classifier);
    377         }
    378 
    379         //logger.error("Format string: " + format_string);
    380         logger.error("Config file location = " + GSFile.collectionConfigFile(this.site_home, this.cluster_name));
    381 
    382         // check for version file
    383 
    384         String directory = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name)).getParent() + File.separator;
    385         logger.error("Directory is " + directory);
    386 
    387         String version_filename = "";
    388         if(service.equals("ClassifierBrowse"))
    389             version_filename = directory + "browse_"+classifier+"_format_statement_version.txt";
    390         else
    391             version_filename = directory + "query_format_statement_version.txt";
    392 
    393         File version_file = new File(version_filename);
    394         logger.error("Version filename is " + version_filename);
    395 
    396 
    397         if(subaction.equals("update"))
    398         {
    399             Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM);
    400             //String format_string = GSXML.getNodeText(format_element);
    401             Element format_statement = (Element) format_element.getFirstChild();
    402 
    403 
    404             String version_number = "1";
    405             BufferedWriter writer;
    406 
    407             try{
    408 
    409                 if(version_file.exists())
    410                 {
    411                     // Read version
    412                     BufferedReader reader = new BufferedReader(new FileReader(version_filename));
    413                     version_number = reader.readLine();
    414                     int aInt = Integer.parseInt(version_number) + 1;
    415                     version_number = Integer.toString(aInt);
    416                     reader.close();
    417                 }
    418                 else{
    419                     // Create
    420                     version_file.createNewFile();
    421                     writer = new BufferedWriter(new FileWriter(version_filename));
    422                     writer.write(version_number);
    423                     writer.close();
    424                 }
    425 
    426                 // Write version file
    427                 String format_statement_filename = "";
    428 
    429                 if(service.equals("ClassifierBrowse"))
    430                     format_statement_filename = directory + "browse_"+classifier+"_format_statement_v" + version_number + ".txt";
    431                 else
    432                     format_statement_filename = directory + "query_format_statement_v" + version_number + ".txt";
    433 
    434                 logger.error("Format statement filename is " + format_statement_filename);
    435 
    436                 // Write format statement
    437                 String format_string = this.converter.getString(format_statement); //GSXML.xmlNodeToString(format_statement);
    438                 writer = new BufferedWriter(new FileWriter(format_statement_filename));
    439                 writer.write(format_string);
    440                 writer.close();
    441 
    442                 // Update version number
    443                 writer = new BufferedWriter(new FileWriter(version_filename));
    444                 writer.write(version_number);
    445                 writer.close();
    446 
    447             } catch (IOException e) {
    448                 logger.error("IO Exception "+e);
    449             }
    450         }
    451 
    452         if(subaction.equals("saveDocument"))
    453         {
    454             int k;
    455             Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM);
    456             //String format_string = GSXML.getNodeText(format_element);
    457             // Get display tag
    458             Element display_format = (Element) format_element.getFirstChild();
    459 
    460             logger.error("I have received a save document request");
    461             String format_string = GSXML.xmlNodeToString(display_format);
    462             logger.error("Param="+format_string);
    463             String collection_config = directory + "collectionConfig.xml";
    464             Document config = this.converter.getDOM(new File(collection_config), "UTF-8");
    465 
    466             Node current_node = GSXML.getChildByTagName(config, "CollectionConfig");
    467 
    468             // Get display child
    469             if(GSXML.getChildByTagName(current_node, "display") == null)
    470             {
    471                 logger.error("ERROR: does not have a display child");
    472                 // well then create a format tag
    473                 Element display_tag = config.createElement("display");
    474                 current_node = (Node) current_node.appendChild(display_tag);
    475                 //current_node = (Node) format_tag;
    476             }
    477 
    478             else{
    479                 current_node = GSXML.getChildByTagName(current_node, "display");
    480             }
    481 
    482             if(GSXML.getChildByTagName(current_node, "format") == null)
    483             {
    484                 logger.error("ERROR: does not have a format child");
    485                 // well then create a format tag
    486                 Element format_tag = config.createElement("format");
    487                 current_node.appendChild(format_tag);
    488                 //current_node = (Node) format_tag;
    489             }
    490 
    491 
    492             current_node.replaceChild(config.importNode(display_format,true), GSXML.getChildByTagName(current_node, "format"));
    493 
    494             logger.error(GSXML.xmlNodeToString(current_node));
    495 
    496             logger.error("Convert config to string");
    497             String new_config = this.converter.getString(config);
    498 
    499             new_config = StringUtils.replace(new_config, "&lt;", "<");
    500             new_config = StringUtils.replace(new_config, "&gt;", ">");
    501             new_config = StringUtils.replace(new_config, "&quot;", "\"");
    502 
    503             try{
    504                 // Write to file (not original! for now)
    505                 BufferedWriter writer = new BufferedWriter(new FileWriter(collection_config+".new"));
    506                 writer.write(new_config);
    507                 writer.close();
    508                 logger.error("All is happy with collection saveDocument");
    509             } catch (IOException e) {
    510                 logger.error("IO Exception "+e);
    511             }
    512         }
    513 
    514         if(subaction.equals("save"))
    515         {
    516             logger.error("SAVE format statement");
    517 
    518             Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM);
    519             //String format_string = GSXML.getNodeText(format_element);
    520             Element format_statement = (Element) format_element.getFirstChild();
    521 
    522             try{
    523 
    524                 // open collectionConfig.xml and read in to w3 Document
    525                 String collection_config = directory + "collectionConfig.xml";
    526                 Document config = this.converter.getDOM(new File(collection_config), "UTF-8");
    527            
    528                 //String tag_name = "";
    529                 int k;
    530                 int index;
    531                 Element elem;
    532                 // Try importing entire tree to this.doc so we can add and remove children at ease
    533                 //Node current_node = this.doc.importNode(GSXML.getChildByTagName(config, "CollectionConfig"),true);
    534                 Node current_node = GSXML.getChildByTagName(config, "CollectionConfig");
    535                 NodeList current_node_list;
    536    
    537                 logger.error("Service is "+service);
    538 
    539                 if(service.equals("ClassifierBrowse"))
    540                 {
    541                     //tag_name = "browse";
    542                     // if CLX then need to look in <classifier> X then <format>
    543                     // default is <browse><format>
    544 
    545                     logger.error("Looking for browse");
    546                     current_node = GSXML.getChildByTagName(current_node, "browse");
    547 
    548                     // find CLX
    549                     if(classifier != null)
    550                     {
    551                         logger.error("Classifier is not null");
    552                         logger.error("Classifier is "+classifier);
    553                         current_node_list = GSXML.getChildrenByTagName(current_node, "classifier");
    554                         index = Integer.parseInt(classifier.substring(2)) - 1;
    555                         logger.error("classifier index is "+index);
    556                         // index should be given by X-1
    557                         current_node = current_node_list.item(index);
    558                         // what if classifier does not have a format tag?
    559                         if(GSXML.getChildByTagName(current_node, "format") == null)
    560                         {
    561                             logger.error("ERROR: valid classifier but does not have a format child");
    562                             // well then create a format tag
    563                             Element format_tag = config.createElement("format");
    564                             current_node.appendChild(format_tag);
    565                             //current_node = (Node) format_tag;
    566                         }
    567                     }
    568                     else{
    569                         logger.error("Classifier is null");
    570                         // To support all classifiers, set classifier to null?  There is the chance here that the format tag does not exist
    571                         if(GSXML.getChildByTagName(current_node, "format") == null)
    572                         {
    573                             logger.error("ERROR: classifier does not have a format child");
    574                             // well then create a format tag
    575                             Element format_tag = config.createElement("format");
    576                             current_node.appendChild(format_tag);
    577                             //current_node = (Node) format_tag;
    578                         }
    579                     }
    580                 }
    581                 else if(service.equals("AllClassifierBrowse"))
    582                 {
    583                     logger.error("Looking for browse");
    584                     current_node = GSXML.getChildByTagName(current_node, "browse");
    585                     if(GSXML.getChildByTagName(current_node, "format") == null)
    586                     {
    587                         logger.error("ERROR AllClassifierBrowse: all classifiers do not have a format child");
    588                         // well then create a format tag
    589                         Element format_tag = config.createElement("format");
    590                         current_node.appendChild(format_tag);
    591                         //current_node = (Node) format_tag;
    592                     }
    593                 }
    594                 else
    595                 {
    596                     // look in <format> with no attributes
    597                     logger.error("I presume this is search");
    598            
    599                     current_node_list = GSXML.getChildrenByTagName(current_node, "search");
    600                     for(k=0; k<current_node_list.getLength(); k++)
    601                     {
    602                         current_node = current_node_list.item(k);
    603                         // if current_node has no attributes then break
    604                         elem = (Element) current_node;
    605                         if(elem.hasAttribute("name")==false)
    606                             break;
    607                     }
    608                 }
    609 
    610                 current_node.replaceChild(config.importNode(format_statement,true), GSXML.getChildByTagName(current_node, "format"));
    611 
    612                 // Now convert config document to string for writing to file
    613                 logger.error("Convert config to string");
    614                 String new_config = this.converter.getString(config);
    615 
    616                 new_config = StringUtils.replace(new_config, "&lt;", "<");
    617                 new_config = StringUtils.replace(new_config, "&gt;", ">");
    618                 new_config = StringUtils.replace(new_config, "&quot;", "\"");
    619    
    620                 // Write to file (not original! for now)
    621                 BufferedWriter writer = new BufferedWriter(new FileWriter(collection_config+".new"));
    622                 writer.write(new_config);
    623                 writer.close();
    624                 logger.error("All is happy with collection");
    625 
    626              } catch( Exception ex ) {
    627                 logger.error("There was an exception "+ex);
    628 
    629                 StringWriter sw = new StringWriter();
    630                 PrintWriter pw = new PrintWriter(sw, true);
    631                 ex.printStackTrace(pw);
    632                 pw.flush();
    633                 sw.flush();
    634                 logger.error(sw.toString());
    635             }
    636 
    637         }
    638     }
    639     else { // unknown type
    640         return super.processMessage(request);
    641 
    642     }
    643     return response;
    644     }
     56public class Collection extends ServiceCluster
     57{
     58
     59    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.collection.Collection.class.getName());
     60
     61    /** is this collection being tidied */
     62    protected boolean useBook = false;
     63    /** is this collection public or private */
     64    protected boolean is_public = true;
     65
     66    /** does this collection provide the OAI service */
     67    protected boolean has_oai = true;
     68    /** time when this collection was built */
     69    protected long lastmodified = 0;
     70    /** earliestDatestamp of this collection. Necessary for OAI */
     71    protected long earliestDatestamp = 0;
     72
     73    /**
     74     * An element containing the serviceRackList element of buildConfig.xml,
     75     * used to determine whether it contains the OAIPMH serviceRack
     76     */
     77    //protected Element service_rack_list = null;
     78
     79    protected XMLTransformer transformer = null;
     80
     81    /** same as setClusterName */
     82    public void setCollectionName(String name)
     83    {
     84        setClusterName(name);
     85    }
     86
     87    public Collection()
     88    {
     89        super();
     90        this.description = this.doc.createElement(GSXML.COLLECTION_ELEM);
     91
     92    }
     93
     94    /**
     95     * Configures the collection.
     96     *
     97     * gsdlHome and collectionName must be set before configure is called.
     98     *
     99     * the file buildcfg.xml is located in gsdlHome/collect/collectionName
     100     * collection metadata is obtained, and services loaded.
     101     *
     102     * @return true/false on success/fail
     103     */
     104    public boolean configure()
     105    {
     106
     107        if (this.site_home == null || this.cluster_name == null)
     108        {
     109            logger.error("Collection: site_home and collection_name must be set before configure called!");
     110            return false;
     111        }
     112
     113        Element coll_config_xml = loadCollConfigFile();
     114        Element build_config_xml = loadBuildConfigFile();
     115
     116        if (coll_config_xml == null || build_config_xml == null)
     117        {
     118            return false;
     119        }
     120
     121        // get the collection type attribute
     122        Element search = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.SEARCH_ELEM);
     123        if (search != null)
     124        {
     125            col_type = search.getAttribute(GSXML.TYPE_ATT);
     126        }
     127       
     128        Element browse = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.INFODB_ELEM);
     129        if (browse != null)
     130        {
     131            db_type = browse.getAttribute(GSXML.TYPE_ATT);
     132        }
     133        else
     134        {
     135            db_type = "gdbm"; //Default database type
     136        }
     137
     138        // process the metadata and display items
     139        findAndLoadInfo(coll_config_xml, build_config_xml);
     140
     141        // now do the services
     142        configureServiceRacks(coll_config_xml, build_config_xml);
     143
     144        return true;
     145
     146    }
     147
     148    public boolean useBook()
     149    {
     150        return useBook;
     151    }
     152
     153    public boolean isPublic()
     154    {
     155        return is_public;
     156    }
     157
     158    // Not used anymore by the OAIReceptionist to find out the earliest datestamp
     159    // amongst all oai collections in the repository. May be useful generally.
     160    public long getLastmodified()
     161    {
     162        return lastmodified;
     163    }
     164
     165    //used by the OAIReceptionist to find out the earliest datestamp amongst all oai collections in the repository
     166    public long getEarliestDatestamp()
     167    {
     168        return earliestDatestamp;
     169    }
     170
     171    /**
     172     * whether the service_map in ServiceCluster.java contains the service
     173     * 'OAIPMH' 11/06/2007 xiao
     174     */
     175    public boolean hasOAI()
     176    {
     177        return has_oai;
     178    }
     179
     180    /**
     181     * load in the collection config file into a DOM Element
     182     */
     183    protected Element loadCollConfigFile()
     184    {
     185
     186        File coll_config_file = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name));
     187
     188        if (!coll_config_file.exists())
     189        {
     190            logger.error("Collection: couldn't configure collection: " + this.cluster_name + ", " + coll_config_file + " does not exist");
     191            return null;
     192        }
     193        // get the xml for both files
     194        Document coll_config_doc = this.converter.getDOM(coll_config_file, CONFIG_ENCODING);
     195        Element coll_config_elem = null;
     196        if (coll_config_doc != null)
     197        {
     198            coll_config_elem = coll_config_doc.getDocumentElement();
     199        }
     200        return coll_config_elem;
     201
     202    }
     203
     204    /**
     205     * load in the collection build config file into a DOM Element
     206     */
     207    protected Element loadBuildConfigFile()
     208    {
     209
     210        File build_config_file = new File(GSFile.collectionBuildConfigFile(this.site_home, this.cluster_name));
     211        if (!build_config_file.exists())
     212        {
     213            logger.error("Collection: couldn't configure collection: " + this.cluster_name + ", " + build_config_file + " does not exist");
     214            return null;
     215        }
     216        Document build_config_doc = this.converter.getDOM(build_config_file, CONFIG_ENCODING);
     217        Element build_config_elem = null;
     218        if (build_config_doc != null)
     219        {
     220            build_config_elem = build_config_doc.getDocumentElement();
     221        }
     222
     223        lastmodified = build_config_file.lastModified();
     224
     225        return build_config_elem;
     226    }
     227
     228    /**
     229     * find the metadata and display elems from the two config files and add it
     230     * to the appropriate lists
     231     */
     232    protected boolean findAndLoadInfo(Element coll_config_xml, Element build_config_xml)
     233    {
     234
     235        // metadata
     236        Element meta_list = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
     237        addMetadata(meta_list);
     238        meta_list = (Element) GSXML.getChildByTagName(build_config_xml, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
     239        addMetadata(meta_list);
     240
     241        meta_list = this.doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
     242        GSXML.addMetadata(this.doc, meta_list, "httpPath", this.site_http_address + "/collect/" + this.cluster_name);
     243        addMetadata(meta_list);
     244
     245        // display stuff
     246        Element display_list = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER);
     247        if (display_list != null)
     248        {
     249            resolveMacros(display_list);
     250            addDisplayItems(display_list);
     251        }
     252
     253        //check whether the html are tidy or not
     254        Element import_list = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.IMPORT_ELEM);
     255        if (import_list != null)
     256        {
     257            Element plugin_list = (Element) GSXML.getChildByTagName(import_list, GSXML.PLUGIN_ELEM + GSXML.LIST_MODIFIER);
     258            addPlugins(plugin_list);
     259            if (plugin_list != null)
     260            {
     261                Element plugin_elem = (Element) GSXML.getNamedElement(plugin_list, GSXML.PLUGIN_ELEM, GSXML.NAME_ATT, "HTMLPlugin");
     262                if (plugin_elem != null)
     263                {
     264                    //get the option
     265                    Element option_elem = (Element) GSXML.getNamedElement(plugin_elem, GSXML.PARAM_OPTION_ELEM, GSXML.NAME_ATT, "-use_realistic_book");
     266                    if (option_elem != null)
     267                    {
     268                        useBook = true;
     269                    }
     270                }
     271            }
     272        }
     273        meta_list = this.doc.createElement(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
     274        if (useBook == true)
     275            GSXML.addMetadata(this.doc, meta_list, "tidyoption", "tidy");
     276        else
     277            GSXML.addMetadata(this.doc, meta_list, "tidyoption", "untidy");
     278        addMetadata(meta_list);
     279
     280        // check whether we are public or not
     281        if (meta_list != null)
     282        {
     283            Element meta_elem = (Element) GSXML.getNamedElement(metadata_list, GSXML.METADATA_ELEM, GSXML.NAME_ATT, "public");
     284            if (meta_elem != null)
     285            {
     286                String value = GSXML.getValue(meta_elem).toLowerCase().trim();
     287                if (value.equals("false"))
     288                {
     289                    is_public = false;
     290                }
     291            }
     292        }
     293        return true;
     294
     295    }
     296
     297    protected boolean configureServiceRacks(Element coll_config_xml, Element build_config_xml)
     298    {
     299        clearServices();
     300        Element service_list = (Element) GSXML.getChildByTagName(build_config_xml, GSXML.SERVICE_CLASS_ELEM + GSXML.LIST_MODIFIER);
     301        configureServiceRackList(service_list, coll_config_xml);
     302
     303        // collection Config may also contain manually added service racks
     304        service_list = (Element) GSXML.getChildByTagName(coll_config_xml, GSXML.SERVICE_CLASS_ELEM + GSXML.LIST_MODIFIER);
     305        if (service_list != null)
     306        {
     307            configureServiceRackList(service_list, build_config_xml);
     308
     309            // Check for oai
     310            Element oai_service_rack = GSXML.getNamedElement(service_list, GSXML.SERVICE_CLASS_ELEM, OAIXML.NAME, OAIXML.OAIPMH);
     311            if (oai_service_rack == null)
     312            {
     313                has_oai = false;
     314                logger.info("No oai for collection: " + this.cluster_name);
     315
     316            }
     317            else
     318            {
     319                has_oai = true;
     320
     321                // extract earliestDatestamp from the buildconfig.xml for OAI
     322                Element metadata_list = (Element) GSXML.getChildByTagName(build_config_xml, GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER);
     323
     324                if (metadata_list != null)
     325                {
     326                    NodeList children = metadata_list.getElementsByTagName(GSXML.METADATA_ELEM);
     327                    // can't do getChildNodes(), because whitespace, such as newlines, creates Text nodes
     328                    for (int i = 0; i < children.getLength(); i++)
     329                    {
     330                        Element metadata = (Element) children.item(i);
     331                        if (metadata.getAttribute(GSXML.NAME_ATT).equals(OAIXML.EARLIEST_DATESTAMP))
     332                        {
     333                            String earliestDatestampStr = GSXML.getValue(metadata);
     334                            if (!earliestDatestampStr.equals(""))
     335                            {
     336                                earliestDatestamp = Long.parseLong(earliestDatestampStr);
     337                            }
     338                            break; // found a metadata element with name=earliestDatestamp in buildconfig
     339                        }
     340                    }
     341                }
     342
     343                // If at the end of this, there is no value for earliestDatestamp, print out a warning
     344                logger.warn("No earliestDatestamp in buildConfig.xml for collection: " + this.cluster_name + ". Defaulting to 0.");
     345
     346            }
     347        }
     348        else
     349        { // no list of services (no ServiceRackList), so no oai_service_rack either
     350            // explicitly set has_oai to false here, since it's initialised to true by default
     351            has_oai = false;
     352        }
     353        return true;
     354    }
     355
     356    protected boolean resolveMacros(Element display_list)
     357    {
     358        if (display_list == null)
     359            return false;
     360        NodeList displaynodes = display_list.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
     361        if (displaynodes.getLength() > 0)
     362        {
     363            String http_site = this.site_http_address;
     364            String http_collection = this.site_http_address + "/collect/" + this.cluster_name;
     365            for (int k = 0; k < displaynodes.getLength(); k++)
     366            {
     367                Element d = (Element) displaynodes.item(k);
     368                String text = GSXML.getNodeText(d);
     369                text = StringUtils.replace(text, "_httpsite_", http_site);
     370                text = StringUtils.replace(text, "_httpcollection_", http_collection);
     371                GSXML.setNodeText(d, text);
     372            }
     373        }
     374        return true;
     375    }
     376
     377    /**
     378     * do a configure on only part of the collection
     379     */
     380    protected boolean configureSubset(String subset)
     381    {
     382
     383        // need the coll config files
     384        Element coll_config_elem = loadCollConfigFile();
     385        Element build_config_elem = loadBuildConfigFile();
     386        if (coll_config_elem == null || build_config_elem == null)
     387        {
     388            // wont be able to do any of the requests
     389            return false;
     390        }
     391
     392        if (subset.equals(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER))
     393        {
     394            return configureServiceRacks(coll_config_elem, build_config_elem);
     395        }
     396
     397        if (subset.equals(GSXML.METADATA_ELEM + GSXML.LIST_MODIFIER) || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER) || subset.equals(GSXML.PLUGIN_ELEM + GSXML.LIST_MODIFIER))
     398        {
     399            return findAndLoadInfo(coll_config_elem, build_config_elem);
     400
     401        }
     402
     403        logger.error("Collection: cant process system request, configure " + subset);
     404        return false;
     405    }
     406
     407    /**
     408     * handles requests made to the ServiceCluster itself
     409     *
     410     * @param req
     411     *            - the request Element- <request>
     412     * @return the result Element - should be <response>
     413     */
     414    protected Element processMessage(Element request)
     415    {
     416
     417        Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
     418        response.setAttribute(GSXML.FROM_ATT, this.cluster_name);
     419        String type = request.getAttribute(GSXML.TYPE_ATT);
     420        String lang = request.getAttribute(GSXML.LANG_ATT);
     421        response.setAttribute(GSXML.TYPE_ATT, type);
     422
     423        logger.error("Collection received a message, attempting to process");
     424
     425        if (type.equals(GSXML.REQUEST_TYPE_FORMAT_STRING))
     426        {
     427            logger.error("Received format string request");
     428
     429            String subaction = request.getAttribute("subaction");
     430            logger.error("Subaction is " + subaction);
     431
     432            String service = request.getAttribute("service");
     433            logger.error("Service is " + service);
     434
     435            String classifier = null;
     436            if (service.equals("ClassifierBrowse"))
     437            {
     438                classifier = request.getAttribute("classifier");
     439                logger.error("Classifier is " + classifier);
     440            }
     441
     442            //logger.error("Format string: " + format_string);
     443            logger.error("Config file location = " + GSFile.collectionConfigFile(this.site_home, this.cluster_name));
     444
     445            // check for version file
     446
     447            String directory = new File(GSFile.collectionConfigFile(this.site_home, this.cluster_name)).getParent() + File.separator;
     448            logger.error("Directory is " + directory);
     449
     450            String version_filename = "";
     451            if (service.equals("ClassifierBrowse"))
     452                version_filename = directory + "browse_" + classifier + "_format_statement_version.txt";
     453            else
     454                version_filename = directory + "query_format_statement_version.txt";
     455
     456            File version_file = new File(version_filename);
     457            logger.error("Version filename is " + version_filename);
     458
     459            if (subaction.equals("update"))
     460            {
     461                Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM);
     462                //String format_string = GSXML.getNodeText(format_element);
     463                Element format_statement = (Element) format_element.getFirstChild();
     464
     465                String version_number = "1";
     466                BufferedWriter writer;
     467
     468                try
     469                {
     470
     471                    if (version_file.exists())
     472                    {
     473                        // Read version
     474                        BufferedReader reader = new BufferedReader(new FileReader(version_filename));
     475                        version_number = reader.readLine();
     476                        int aInt = Integer.parseInt(version_number) + 1;
     477                        version_number = Integer.toString(aInt);
     478                        reader.close();
     479                    }
     480                    else
     481                    {
     482                        // Create
     483                        version_file.createNewFile();
     484                        writer = new BufferedWriter(new FileWriter(version_filename));
     485                        writer.write(version_number);
     486                        writer.close();
     487                    }
     488
     489                    // Write version file
     490                    String format_statement_filename = "";
     491
     492                    if (service.equals("ClassifierBrowse"))
     493                        format_statement_filename = directory + "browse_" + classifier + "_format_statement_v" + version_number + ".txt";
     494                    else
     495                        format_statement_filename = directory + "query_format_statement_v" + version_number + ".txt";
     496
     497                    logger.error("Format statement filename is " + format_statement_filename);
     498
     499                    // Write format statement
     500                    String format_string = this.converter.getString(format_statement); //GSXML.xmlNodeToString(format_statement);
     501                    writer = new BufferedWriter(new FileWriter(format_statement_filename));
     502                    writer.write(format_string);
     503                    writer.close();
     504
     505                    // Update version number
     506                    writer = new BufferedWriter(new FileWriter(version_filename));
     507                    writer.write(version_number);
     508                    writer.close();
     509
     510                }
     511                catch (IOException e)
     512                {
     513                    logger.error("IO Exception " + e);
     514                }
     515            }
     516
     517            if (subaction.equals("saveDocument"))
     518            {
     519                int k;
     520                Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM);
     521                //String format_string = GSXML.getNodeText(format_element);
     522                // Get display tag
     523                Element display_format = (Element) format_element.getFirstChild();
     524
     525                logger.error("I have received a save document request");
     526                String format_string = GSXML.xmlNodeToString(display_format);
     527                logger.error("Param=" + format_string);
     528                String collection_config = directory + "collectionConfig.xml";
     529                Document config = this.converter.getDOM(new File(collection_config), "UTF-8");
     530
     531                Node current_node = GSXML.getChildByTagName(config, "CollectionConfig");
     532
     533                // Get display child
     534                if (GSXML.getChildByTagName(current_node, "display") == null)
     535                {
     536                    logger.error("ERROR: does not have a display child");
     537                    // well then create a format tag
     538                    Element display_tag = config.createElement("display");
     539                    current_node = (Node) current_node.appendChild(display_tag);
     540                    //current_node = (Node) format_tag;
     541                }
     542
     543                else
     544                {
     545                    current_node = GSXML.getChildByTagName(current_node, "display");
     546                }
     547
     548                if (GSXML.getChildByTagName(current_node, "format") == null)
     549                {
     550                    logger.error("ERROR: does not have a format child");
     551                    // well then create a format tag
     552                    Element format_tag = config.createElement("format");
     553                    current_node.appendChild(format_tag);
     554                    //current_node = (Node) format_tag;
     555                }
     556
     557                current_node.replaceChild(config.importNode(display_format, true), GSXML.getChildByTagName(current_node, "format"));
     558
     559                logger.error(GSXML.xmlNodeToString(current_node));
     560
     561                logger.error("Convert config to string");
     562                String new_config = this.converter.getString(config);
     563
     564                new_config = StringUtils.replace(new_config, "&lt;", "<");
     565                new_config = StringUtils.replace(new_config, "&gt;", ">");
     566                new_config = StringUtils.replace(new_config, "&quot;", "\"");
     567
     568                try
     569                {
     570                    // Write to file (not original! for now)
     571                    BufferedWriter writer = new BufferedWriter(new FileWriter(collection_config + ".new"));
     572                    writer.write(new_config);
     573                    writer.close();
     574                    logger.error("All is happy with collection saveDocument");
     575                }
     576                catch (IOException e)
     577                {
     578                    logger.error("IO Exception " + e);
     579                }
     580            }
     581
     582            if (subaction.equals("save"))
     583            {
     584                logger.error("SAVE format statement");
     585
     586                Element format_element = (Element) GSXML.getChildByTagName(request, GSXML.FORMAT_STRING_ELEM);
     587                //String format_string = GSXML.getNodeText(format_element);
     588                Element format_statement = (Element) format_element.getFirstChild();
     589
     590                try
     591                {
     592
     593                    // open collectionConfig.xml and read in to w3 Document
     594                    String collection_config = directory + "collectionConfig.xml";
     595                    Document config = this.converter.getDOM(new File(collection_config), "UTF-8");
     596
     597                    //String tag_name = "";
     598                    int k;
     599                    int index;
     600                    Element elem;
     601                    // Try importing entire tree to this.doc so we can add and remove children at ease
     602                    //Node current_node = this.doc.importNode(GSXML.getChildByTagName(config, "CollectionConfig"),true);
     603                    Node current_node = GSXML.getChildByTagName(config, "CollectionConfig");
     604                    NodeList current_node_list;
     605
     606                    logger.error("Service is " + service);
     607
     608                    if (service.equals("ClassifierBrowse"))
     609                    {
     610                        //tag_name = "browse";
     611                        // if CLX then need to look in <classifier> X then <format>
     612                        // default is <browse><format>
     613
     614                        logger.error("Looking for browse");
     615                        current_node = GSXML.getChildByTagName(current_node, "browse");
     616
     617                        // find CLX
     618                        if (classifier != null)
     619                        {
     620                            logger.error("Classifier is not null");
     621                            logger.error("Classifier is " + classifier);
     622                            current_node_list = GSXML.getChildrenByTagName(current_node, "classifier");
     623                            index = Integer.parseInt(classifier.substring(2)) - 1;
     624                            logger.error("classifier index is " + index);
     625                            // index should be given by X-1
     626                            current_node = current_node_list.item(index);
     627                            // what if classifier does not have a format tag?
     628                            if (GSXML.getChildByTagName(current_node, "format") == null)
     629                            {
     630                                logger.error("ERROR: valid classifier but does not have a format child");
     631                                // well then create a format tag
     632                                Element format_tag = config.createElement("format");
     633                                current_node.appendChild(format_tag);
     634                                //current_node = (Node) format_tag;
     635                            }
     636                        }
     637                        else
     638                        {
     639                            logger.error("Classifier is null");
     640                            // To support all classifiers, set classifier to null?  There is the chance here that the format tag does not exist
     641                            if (GSXML.getChildByTagName(current_node, "format") == null)
     642                            {
     643                                logger.error("ERROR: classifier does not have a format child");
     644                                // well then create a format tag
     645                                Element format_tag = config.createElement("format");
     646                                current_node.appendChild(format_tag);
     647                                //current_node = (Node) format_tag;
     648                            }
     649                        }
     650                    }
     651                    else if (service.equals("AllClassifierBrowse"))
     652                    {
     653                        logger.error("Looking for browse");
     654                        current_node = GSXML.getChildByTagName(current_node, "browse");
     655                        if (GSXML.getChildByTagName(current_node, "format") == null)
     656                        {
     657                            logger.error("ERROR AllClassifierBrowse: all classifiers do not have a format child");
     658                            // well then create a format tag
     659                            Element format_tag = config.createElement("format");
     660                            current_node.appendChild(format_tag);
     661                            //current_node = (Node) format_tag;
     662                        }
     663                    }
     664                    else
     665                    {
     666                        // look in <format> with no attributes
     667                        logger.error("I presume this is search");
     668
     669                        current_node_list = GSXML.getChildrenByTagName(current_node, "search");
     670                        for (k = 0; k < current_node_list.getLength(); k++)
     671                        {
     672                            current_node = current_node_list.item(k);
     673                            // if current_node has no attributes then break
     674                            elem = (Element) current_node;
     675                            if (elem.hasAttribute("name") == false)
     676                                break;
     677                        }
     678                    }
     679
     680                    current_node.replaceChild(config.importNode(format_statement, true), GSXML.getChildByTagName(current_node, "format"));
     681
     682                    // Now convert config document to string for writing to file
     683                    logger.error("Convert config to string");
     684                    String new_config = this.converter.getString(config);
     685
     686                    new_config = StringUtils.replace(new_config, "&lt;", "<");
     687                    new_config = StringUtils.replace(new_config, "&gt;", ">");
     688                    new_config = StringUtils.replace(new_config, "&quot;", "\"");
     689
     690                    // Write to file (not original! for now)
     691                    BufferedWriter writer = new BufferedWriter(new FileWriter(collection_config + ".new"));
     692                    writer.write(new_config);
     693                    writer.close();
     694                    logger.error("All is happy with collection");
     695
     696                }
     697                catch (Exception ex)
     698                {
     699                    logger.error("There was an exception " + ex);
     700
     701                    StringWriter sw = new StringWriter();
     702                    PrintWriter pw = new PrintWriter(sw, true);
     703                    ex.printStackTrace(pw);
     704                    pw.flush();
     705                    sw.flush();
     706                    logger.error(sw.toString());
     707                }
     708
     709            }
     710        }
     711        else
     712        { // unknown type
     713            return super.processMessage(request);
     714
     715        }
     716        return response;
     717    }
    645718
    646719}
    647 
    648 
    649 
    650 
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/AbstractBrowse.java

    r24254 r24393  
    574574     * <docNode nodeId='xxx' nodeType='leaf' docType='hierarchy'/>
    575575     */
    576     protected Element createDocNode(String node_id, int offset) {
     576    protected Element createDocNode(String node_id) {
    577577    Element node = this.doc.createElement(GSXML.DOC_NODE_ELEM);
    578578    node.setAttribute(GSXML.NODE_ID_ATT, node_id);
     
    587587    String node_type = getNodeType(node_id, doc_type); 
    588588    node.setAttribute(GSXML.NODE_TYPE_ATT, node_type);
    589    
    590     // mdoffset information stored in DB determines which of multiple values for
    591     // a metadata needs to be displayed when a classifier is built on that metadata
    592     node.setAttribute(GSXML.NODE_MDOFFSET_ATT, Integer.toString(offset));
    593589    return node;
    594590    }
     
    625621    ArrayList child_ids = getChildrenIds(node_id);
    626622    if (child_ids==null) return;
    627    
    628     // get a list of all mdoffsets at this point
    629     ArrayList child_offsets = getOffsetsForChildrenIds(node_id);
    630     // make sure that if it's doesn't match up with child_ids in length,
    631     // it is padded with 0s to make up the length
    632     if(child_offsets == null) {
    633         child_offsets = new ArrayList(child_ids.size());
    634     }
    635     if(child_offsets.size() < child_ids.size()) {
    636         Integer zero = new Integer(0);
    637         for(int i = child_offsets.size()-1; i < child_ids.size(); i++) {
    638         child_offsets.add(zero);
    639         }
    640     }
    641 
    642623    for (int i=0; i< child_ids.size(); i++) {
    643624        String child_id = (String)child_ids.get(i);
    644         int child_offset = ((Integer)child_offsets.get(i)).intValue(); // counts both docnodes and classnodes at the childlevel, is this right?
    645625        Element child_elem;
    646626        if (isDocumentId(child_id)) {
    647         child_elem = createDocNode(child_id, child_offset);
     627        child_elem = createDocNode(child_id);
    648628        } else {
    649629        child_elem = createClassifierNode(child_id);
     
    704684    }
    705685
    706     /** Override to get a list of mdoffsets of children. Return null if no children or if no mdoffsets for them */
    707     protected ArrayList getOffsetsForChildrenIds(String node_id) {
    708     return null;
    709     }
    710 
    711686    /** if id ends in .fc, .pc etc, then translate it to the correct id */
    712687    abstract protected String translateId(String node_id);
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java

    r24334 r24393  
    241241        Element request_node = (Element) request_nodes.item(i);
    242242        String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
    243 
    244         // make a custom copy of metadata_names_list for each docID, since mdoffset value varies for each doc
    245         ArrayList customised_metadata_names_list = new ArrayList(metadata_names_list.size());
    246         int mdoffset = 0;
    247         if(request_node.hasAttribute(GSXML.NODE_MDOFFSET_ATT)) {
    248         String offset = request_node.getAttribute(GSXML.NODE_MDOFFSET_ATT);
    249         mdoffset = Integer.parseInt(offset);
    250         }   
    251         for(int x = 0; x < metadata_names_list.size(); x++) {
    252         String metaname = (String)metadata_names_list.get(x);
    253         if(metaname.indexOf("offset" + GSConstants.META_RELATION_SEP) != -1) {
    254             // append offset number to the metaname
    255             metaname = metaname.replace("offset"+GSConstants.META_RELATION_SEP, "offset"+mdoffset+GSConstants.META_RELATION_SEP);
    256         }
    257         customised_metadata_names_list.add(x, metaname);           
    258         }
    259        
    260243       
    261244        boolean is_external_link = false;
     
    289272        if (!is_external_link){
    290273        try {
    291             Element metadata_list = getMetadataList(node_id, all_metadata, customised_metadata_names_list);
     274            Element metadata_list = getMetadataList(node_id, all_metadata, metadata_names_list);
    292275            request_node.appendChild(metadata_list);
    293276        } catch (GSException e) {       
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java

    r24254 r24393  
    4141import java.util.Iterator;
    4242import java.util.ArrayList;
    43 import java.util.regex.Matcher;
    44 import java.util.regex.Pattern;
    4543
    4644import org.apache.log4j.*;
     
    198196       
    199197    } else {
    200         // prepare regex to work with mdoffset: looking for <offset\d*_>
    201         Pattern pattern = Pattern.compile("offset[0-9]*" + GSConstants.META_RELATION_SEP);
    202 
    203198        for (int i=0; i<metadata_names.size(); i++) {
    204199                String meta_name = (String) metadata_names.get(i);
    205200        String value = getMetadata(node_id, info, meta_name, lang);
    206 
    207         // Remove the occurrence (if any) in this metaname of the mdoffset number in the pattern <offset\d*_>
    208         // Leaving string "offset" in at this point: it will be handled in config_format.xsl's gsf:metadata template match
    209         Matcher matcher = pattern.matcher(meta_name);
    210         meta_name = matcher.replaceFirst("offset" + GSConstants.META_RELATION_SEP);
    211             //replaceFirst(""); // if removing the occurrence (if any) of entire pattern <offset\d*_> in input     
    212 
    213201        GSXML.addMetadata(this.doc, metadata_list, meta_name, value);
    214202        }
     
    329317    protected String getMetadata(String node_id, DBInfo info,
    330318                 String metadata, String lang) {
    331     String multiple = "false"; // multiple can now be "true", "false" or "offset<number>". It's no longer a boolean
     319    boolean multiple = false;
    332320    String relation = "";
    333321    String separator = ", ";
     
    358346    metadata = metadata.substring(pos+1);
    359347    // check for all on the front
    360     if (temp.equals("all") || temp.startsWith("offset")) { // multiple can now be "true", "false" or "offset"
    361         multiple = temp; // multiple=true;
     348    if (temp.equals("all")) {
     349        multiple=true;     
    362350        pos = metadata.indexOf(GSConstants.META_RELATION_SEP);
    363351        if (pos ==-1) {
     
    411399    StringBuffer result = new StringBuffer();
    412400
    413     if (multiple.equals("false")) {
     401    if (!multiple) {
    414402        result.append(this.macro_resolver.resolve(relation_info.getInfo(metadata), lang, MacroResolver.SCOPE_META, relation_id));
    415     } else if(multiple.startsWith("offset")) { // multiple = offset
    416         String offset = multiple.substring("offset".length(), multiple.length());
    417         int offsetVal = offset.equals("") ? 0 : Integer.parseInt(offset);
    418         String value = relation_info.getInfoOffset(metadata, offsetVal); // what if this metadata is not the one we need to get the offset for? MDTYPE!
    419            // at the moment, do we assume the user will specify retrieving the offset only for such metadata as has an offset?
    420            // At least, getInfoOffset will return the firstelement if the offset exceeds the bounds of the values for this metadata key
    421 
    422         result.append(this.macro_resolver.resolve(value, lang, MacroResolver.SCOPE_META, relation_id));
    423        
    424     } else { // multiple = true, we have multiple meta     
     403    } else {
     404        // we have multiple meta
    425405        Vector values = relation_info.getMultiInfo(metadata);
    426         if (values != null) {
     406        if (values != null) {
    427407        boolean first = true;
    428408        for (int i=0; i<values.size(); i++) {
     
    435415        }
    436416        }
    437         logger.info(result);
     417          logger.info(result);
    438418    }
    439419    // if not ancestors, then this is all we do
     
    448428        relation_info = this.coll_db.getInfo(relation_id);
    449429        if (relation_info == null) return result.toString();
    450         if (multiple.equals("false")) { //if (!multiple)
     430        if (!multiple) {
    451431        result.insert(0, separator);
    452432        result.insert(0, this.macro_resolver.resolve(relation_info.getInfo(metadata), lang, MacroResolver.SCOPE_META, relation_id));
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/GS2Browse.java

    r24254 r24393  
    175175
    176176    }
    177     /** returns a list of the mdoffset values in order for the children, null is
    178       * returned if there are no children or if the mdoffset field is empty */
    179     protected ArrayList getOffsetsForChildrenIds(String node_id) {
    180     DBInfo info = this.coll_db.getInfo(node_id);
    181     if (info == null) {
    182         return null;
    183     }
    184    
    185     ArrayList childrenOffsets = new ArrayList();
    186    
    187     String offset = info.getInfo("mdoffset").trim();
    188     if(offset.equals("")) {
    189         return null;
    190     }
    191     StringTokenizer st = new StringTokenizer(offset, ";");
    192     while (st.hasMoreTokens()) {
    193         String val = st.nextToken().trim();
    194         childrenOffsets.add(Integer.valueOf(val));
    195     }
    196     return childrenOffsets;
    197     }
    198 
    199177    /** returns the node id of the parent node, null if no parent */
    200178    protected String getParentId(String node_id){
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/ServiceRack.java

    r21781 r24393  
    2424
    2525// xml classes
    26 import org.w3c.dom.Node; 
    27 import org.w3c.dom.NodeList; 
    28 import org.w3c.dom.Element; 
    29 import org.w3c.dom.Document; 
     26import org.w3c.dom.Node;
     27import org.w3c.dom.NodeList;
     28import org.w3c.dom.Element;
     29import org.w3c.dom.Document;
    3030import org.xml.sax.InputSource;
    3131import javax.xml.parsers.*;
     
    4545/**
    4646 * ServiceRack - abstract base class for services
    47  *
    48  * A ServiceRack provides one or more Services.
    49  * This base class implements the process method.
    50  *Each service is invoked
    51  * by a method called process<service name> which takes one parameter - the xml request Element, and returns an XML response Element.
    52  * for example, the TextQuery service would be invoked by
     47 *
     48 * A ServiceRack provides one or more Services. This base class implements the
     49 * process method. Each service is invoked by a method called process<service
     50 * name> which takes one parameter - the xml request Element, and returns an XML
     51 * response Element. for example, the TextQuery service would be invoked by
    5352 * processTextQuery(Element request)
    54  *
     53 * 
    5554 * @author Katherine Don
    5655 */
    57 public abstract class ServiceRack
    58     implements ModuleInterface
     56public abstract class ServiceRack implements ModuleInterface
    5957{
    6058
    61      static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.ServiceRack.class.getName());
    62 
    63     /** the absolute address of the site home */
    64     protected String site_home =null;
    65     /** the http address of the site home */
    66     protected String site_http_address =null;
    67 
    68     protected String library_name = null;
    69     /** the name of the cluster (or collection) that this service
    70     belongs to - if any */
    71     protected String cluster_name = null;
    72 
    73     /** some services can talk back to the message router */
    74     protected MessageRouter router = null;
    75 
    76     /** a converter class to create Documents etc */
    77     protected XMLConverter converter = null;
    78 
    79     /** the original config info - if need to store it */
    80     protected Element config_info = null;
    81 
    82     /** XML element for describe requests - the container doc */
    83     protected Document doc = null;
    84 
    85     /** XML element for describe requests - list of supported services
    86     - this is static     */
    87     protected Element short_service_info = null;
    88 
    89     /** XML element for stylesheet requests - map of service name to format
    90     elem */
    91     protected HashMap format_info_map = null;
    92 
    93     /** A class loader that knows about the collection resources directory
    94      *  can put properties files, dtds etc  in here */
    95     CollectionClassLoader class_loader = null;
    96    
    97     /** sets the cluster name */
    98     public void setClusterName(String cluster_name) {
    99     this.cluster_name = cluster_name;
    100     }
    101     /** sets the collect name */
    102     public void setCollectionName(String coll_name) {
    103     setClusterName(coll_name);
    104     }
    105 
    106     public void cleanUp() {}
    107    
    108     /** sets the site home */
    109     public void setSiteHome(String site_home) {
    110     this.site_home = site_home;
    111     }
    112     /** sets the site http address */
    113     public void setSiteAddress(String site_address) {
    114     this.site_http_address = site_address;
    115     }
    116 
    117     public void setLibraryName(String library_name) {
    118     this.library_name = library_name;
    119     }
    120     public String getLibraryName() {
    121     return this.library_name;
    122     }
    123     /** sets the message router */
    124     public void setMessageRouter(MessageRouter m) {
    125        this.router = m;
    126        setLibraryName(m.getLibraryName());
    127     }
    128 
    129     /** the no-args constructor */
    130     public ServiceRack() {
    131     this.converter = new XMLConverter();
    132     this.doc = this.converter.newDOM();
    133     this.short_service_info = this.doc.createElement(GSXML.SERVICE_ELEM+GSXML.LIST_MODIFIER);
    134     this.format_info_map = new HashMap();
    135     }
    136    
    137 
    138     /** configure the service module
    139      *
    140      * @param info the XML node <serviceRack name="XXX"/> with name equal
    141      * to the class name (of the subclass)
    142      *
    143      * must configure short_service_info_ and service_info_map_
    144      * @return true if configured ok
    145      * must be implemented in subclasses
    146      */
    147     public boolean configure(Element info) {
    148     return configure(info, null);
    149     }
    150    
    151     public boolean configure(Element info, Element extra_info) {
    152     // set up the class loader
    153     this.class_loader = new CollectionClassLoader(this.getClass().getClassLoader(), this.site_home, this.cluster_name);
    154     return true;
    155     }
    156 
    157     /**
    158      * Process an XML document - convenience method that uses Strings rather than Elements. just calls process(Element).
    159      *
    160      * @param xml_in the Document to process - a string
    161      * @return the resultant document as a string - contains any error messages
    162      * @see String
    163      */
    164     public String process(String xml_in) {
    165    
    166     Document doc = this.converter.getDOM(xml_in);
    167     if (doc == null) {
    168         logger.error("Couldn't parse request");
    169         logger.error(xml_in);
    170         return null;
    171     }
    172     Node res = process(doc);
    173     return this.converter.getString(res);
    174    
    175     }
    176 
    177     /** process an XML request in DOM form
    178      *
    179      * @param message the Node node containing the request
    180      * should be <message>
    181      * @return an Node with the result XML
    182      * @see Node/Element
    183      */
    184     public Node process(Node message_node) {
    185 
    186     Element message = this.converter.nodeToElement(message_node);
    187 
    188     NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM);
    189     Document mess_doc = message.getOwnerDocument();
    190     Element mainResult = this.doc.createElement(GSXML.MESSAGE_ELEM);
    191     if (requests.getLength()==0) {
    192         // no requests
    193         return mainResult; // empty message for now
    194     }
    195 
    196     for (int i=0; i<requests.getLength(); i++) {
    197         Element request = (Element)requests.item(i);
    198    
    199         String type = request.getAttribute(GSXML.TYPE_ATT);
    200         if (type.equals(GSXML.REQUEST_TYPE_DESCRIBE)) {
    201         Element response = processDescribe(request);
    202         if (response !=null) {
    203             mainResult.appendChild(this.doc.importNode(response, true));
    204         }
    205        
    206         } else if (type.equals(GSXML.REQUEST_TYPE_FORMAT)) {
    207         Element response = processFormat(request);
    208             mainResult.appendChild(this.doc.importNode(response, true));
    209        
    210            
    211         } else {
    212         // other type of request, must be processed by the subclass -
    213         // send to the service method
    214         StringBuffer error_string = new StringBuffer();
    215         String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));       
    216         Element response = null;
    217         try {
    218             Class c = this.getClass();
    219             Class []params = {Class.forName("org.w3c.dom.Element")};
    220            
    221             String method_name = "process"+to;
    222             Method m = null;
    223             while (c != null) {
    224            
    225             try {
    226                 m = c.getDeclaredMethod(method_name, params);
    227                 // if this has worked, break
    228                 break;
    229             } catch (NoSuchMethodException e) {
    230                 c = c.getSuperclass();
    231             } catch (SecurityException e) {
    232                 logger.error("security exception for finding method "+method_name);
    233                 error_string.append("ServiceRack.process: security exception for finding method "+method_name);
     59    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.service.ServiceRack.class.getName());
     60
     61    /** the absolute address of the site home */
     62    protected String site_home = null;
     63    /** the http address of the site home */
     64    protected String site_http_address = null;
     65
     66    protected String library_name = null;
     67    /**
     68     * the name of the cluster (or collection) that this service belongs to - if
     69     * any
     70     */
     71    protected String cluster_name = null;
     72
     73    /** some services can talk back to the message router */
     74    protected MessageRouter router = null;
     75
     76    /** a converter class to create Documents etc */
     77    protected XMLConverter converter = null;
     78
     79    /** the original config info - if need to store it */
     80    protected Element config_info = null;
     81
     82    /** XML element for describe requests - the container doc */
     83    protected Document doc = null;
     84
     85    /**
     86     * XML element for describe requests - list of supported services - this is
     87     * static
     88     */
     89    protected Element short_service_info = null;
     90
     91    /**
     92     * XML element for stylesheet requests - map of service name to format elem
     93     */
     94    protected HashMap format_info_map = null;
     95
     96    /**
     97     * A class loader that knows about the collection resources directory can
     98     * put properties files, dtds etc in here
     99     */
     100    CollectionClassLoader class_loader = null;
     101
     102    /** sets the cluster name */
     103    public void setClusterName(String cluster_name)
     104    {
     105        this.cluster_name = cluster_name;
     106    }
     107
     108    /** sets the collect name */
     109    public void setCollectionName(String coll_name)
     110    {
     111        setClusterName(coll_name);
     112    }
     113
     114    public void cleanUp()
     115    {
     116    }
     117
     118    /** sets the site home */
     119    public void setSiteHome(String site_home)
     120    {
     121        this.site_home = site_home;
     122    }
     123
     124    /** sets the site http address */
     125    public void setSiteAddress(String site_address)
     126    {
     127        this.site_http_address = site_address;
     128    }
     129
     130    public void setLibraryName(String library_name)
     131    {
     132        this.library_name = library_name;
     133    }
     134
     135    public String getLibraryName()
     136    {
     137        return this.library_name;
     138    }
     139
     140    /** sets the message router */
     141    public void setMessageRouter(MessageRouter m)
     142    {
     143        this.router = m;
     144        setLibraryName(m.getLibraryName());
     145    }
     146
     147    /** the no-args constructor */
     148    public ServiceRack()
     149    {
     150        this.converter = new XMLConverter();
     151        this.doc = this.converter.newDOM();
     152        this.short_service_info = this.doc.createElement(GSXML.SERVICE_ELEM + GSXML.LIST_MODIFIER);
     153        this.format_info_map = new HashMap();
     154    }
     155
     156    /**
     157     * configure the service module
     158     *
     159     * @param info
     160     *            the XML node <serviceRack name="XXX"/> with name equal to the
     161     *            class name (of the subclass)
     162     *
     163     *            must configure short_service_info_ and service_info_map_
     164     * @return true if configured ok must be implemented in subclasses
     165     */
     166    public boolean configure(Element info)
     167    {
     168        return configure(info, null);
     169    }
     170
     171    public boolean configure(Element info, Element extra_info)
     172    {
     173        // set up the class loader
     174        this.class_loader = new CollectionClassLoader(this.getClass().getClassLoader(), this.site_home, this.cluster_name);
     175        return true;
     176    }
     177
     178    /**
     179     * Process an XML document - convenience method that uses Strings rather
     180     * than Elements. just calls process(Element).
     181     *
     182     * @param xml_in
     183     *            the Document to process - a string
     184     * @return the resultant document as a string - contains any error messages
     185     * @see String
     186     */
     187    public String process(String xml_in)
     188    {
     189
     190        Document doc = this.converter.getDOM(xml_in);
     191        if (doc == null)
     192        {
     193            logger.error("Couldn't parse request");
     194            logger.error(xml_in);
     195            return null;
     196        }
     197        Node res = process(doc);
     198        return this.converter.getString(res);
     199
     200    }
     201
     202    /**
     203     * process an XML request in DOM form
     204     *
     205     * @param message
     206     *            the Node node containing the request should be <message>
     207     * @return an Node with the result XML
     208     * @see Node/Element
     209     */
     210    public Node process(Node message_node)
     211    {
     212
     213        Element message = this.converter.nodeToElement(message_node);
     214
     215        NodeList requests = message.getElementsByTagName(GSXML.REQUEST_ELEM);
     216        Document mess_doc = message.getOwnerDocument();
     217        Element mainResult = this.doc.createElement(GSXML.MESSAGE_ELEM);
     218        if (requests.getLength() == 0)
     219        {
     220            // no requests
     221            return mainResult; // empty message for now
     222        }
     223
     224        for (int i = 0; i < requests.getLength(); i++)
     225        {
     226            Element request = (Element) requests.item(i);
     227
     228            String type = request.getAttribute(GSXML.TYPE_ATT);
     229            if (type.equals(GSXML.REQUEST_TYPE_DESCRIBE))
     230            {
     231                Element response = processDescribe(request);
     232                if (response != null)
     233                {
     234                    mainResult.appendChild(this.doc.importNode(response, true));
     235                }
     236
    234237            }
    235             } // while
    236             if (m != null) {
    237             Object []args = {request};
    238             try {
    239                 response = (Element)m.invoke(this, args);
    240                
    241             } catch (Exception e) {
    242               logger.error("Trying to call a processService type method (process"+to+") on a subclass("+this.getClass().getName()+"), but an exception happened:"+e.toString(), e);
    243                
    244                 error_string.append("Trying to call a processService type method (process"+to+") on a subclass("+this.getClass().getName()+"), but an exception happened:"+e.toString());
     238            else if (type.equals(GSXML.REQUEST_TYPE_FORMAT))
     239            {
     240                Element response = processFormat(request);
     241                mainResult.appendChild(this.doc.importNode(response, true));
     242
    245243            }
    246             } else {
    247             logger.error("method "+method_name+" not found for class "+this.getClass().getName());
    248             error_string.append("ServiceRack.process: method "+method_name+" not found for class "+this.getClass().getName());
    249             }
    250            
    251         } catch (ClassNotFoundException e) {
    252             logger.error("Element class not found");
    253             error_string.append("Element class not found");
    254         }
    255         if (response !=null) {
    256             mainResult.appendChild(this.doc.importNode(response, true));
    257         } else {
    258             // add in a dummy response
    259             logger.error("adding in an error element\n");
    260             response = this.doc.createElement(GSXML.RESPONSE_ELEM);
    261             GSXML.addError(this.doc, response, error_string.toString());
    262             mainResult.appendChild(response);
    263            
    264         }
    265  
    266         } // else process request
    267     } // for each request
    268    
    269     return mainResult;
    270        
    271     }
    272 
    273  
    274 
    275     /** process method for describe requests
    276      */
    277     protected Element processDescribe(Element request) {
    278    
    279     Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
    280     response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_DESCRIBE);
    281    
    282     String lang = request.getAttribute(GSXML.LANG_ATT);
    283     String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
    284     if (to.equals("")) { // return the service list
    285         response.appendChild(getServiceList(lang));
    286         return response;
    287     }
    288     response.setAttribute(GSXML.FROM_ATT, to);
    289     Element param_list = (Element)GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
    290     Element description = null;
    291     if (param_list == null) {
    292         description = getServiceDescription(to, lang, null);
    293     } else {
    294         NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
    295         for (int i=0; i<params.getLength(); i++) {
    296        
    297         Element param = (Element)params.item(i);
    298         // Identify the structure information desired
    299         if (param.getAttribute(GSXML.NAME_ATT).equals(GSXML.SUBSET_PARAM )) {
    300             String info = param.getAttribute(GSXML.VALUE_ATT);
    301             if (description == null) {
    302              description = getServiceDescription(to, lang, info);
    303             } else {
    304             Element temp = getServiceDescription(to, lang, info);
    305             GSXML.mergeElements(description, temp);
    306             }
    307         }
    308         }
    309     }
    310     if (description != null) { // may be null if non-existant service
    311         response.appendChild(description);
    312     }
    313     return response;
    314    
    315     }
    316 
    317     /** process method for stylesheet requests
    318      */
    319     protected Element processFormat(Element request) {
    320     Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
    321     response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_FORMAT);
    322    
    323     String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
    324    
    325     if (to.equals("")) { // serviceRack query - is this appropriate??
    326         return response;
    327     }
    328    
    329    
    330     // describe a particular service   
    331     if (this.format_info_map.containsKey(to)) {
    332         response.appendChild(getServiceFormat(to));
    333         response.setAttribute(GSXML.FROM_ATT, to);
    334         return response;
    335     }
    336     // else no format info
    337     logger.error("ServiceRack describe request: no format info for "+to+".");
    338     return response;
    339     }   
    340    
    341     /** returns the service list for the subclass */
    342     protected Element getServiceList(String lang) {
    343     // for now, it is static and has no language stuff
    344     return (Element) this.short_service_info.cloneNode(true);
    345     }
    346    
    347     /** returns a specific service description */
    348     abstract protected Element getServiceDescription(String service, String lang, String subset);
    349 
    350     protected Element getServiceFormat(String service) {
    351     Element format = (Element)((Element)this.format_info_map.get(service)).cloneNode(true);
    352     return format;
    353     }
    354 
    355     /** overloaded version for no args case */
    356     protected String getTextString(String key, String lang) {
    357     return getTextString(key, lang, null, null);
    358     }
    359 
    360     protected String getTextString(String key, String lang, String dictionary) {
    361     return getTextString(key, lang, dictionary, null);
    362     }
    363     protected String getTextString(String key, String lang, String [] args) {
    364     return getTextString(key, lang, null, args);
    365     }
    366    
    367     /** getTextString - retrieves a language specific text string for the given
    368 key and locale, from the specified resource_bundle (dictionary)
    369     */
    370     protected String getTextString(String key, String lang, String dictionary, String[] args) {
    371 
    372     // we want to use the collection class loader in case there are coll specific files
    373     if (dictionary != null) {
    374         // just try the one specified dictionary
    375         Dictionary dict = new Dictionary(dictionary, lang, this.class_loader);
    376         String result = dict.get(key, args);
    377         if (result == null) { // not found
    378         return "_"+key+"_";
    379         }
    380         return result;
    381     }
    382 
    383     // now we try class names for dictionary names
    384     String class_name = this.getClass().getName();
    385     class_name = class_name.substring(class_name.lastIndexOf('.')+1);
    386     Dictionary dict = new Dictionary(class_name, lang, this.class_loader);
    387     String result = dict.get(key, args);
    388     if (result != null) {
    389         return result;
    390     }
    391 
    392     // we have to try super classes
    393     Class c = this.getClass().getSuperclass();
    394     while (result == null && c != null) {
    395         class_name = c.getName();
    396         class_name = class_name.substring(class_name.lastIndexOf('.')+1);
    397         if (class_name.equals("ServiceRack")) {
    398         // this is as far as we go
    399         break;
    400         }
    401         dict = new Dictionary(class_name, lang, this.class_loader);
    402         result = dict.get(key, args);
    403         c = c.getSuperclass();
    404     }
    405     if (result == null) {
    406         return "_"+key+"_";
    407     }
    408     return result;
    409    
    410     }
    411 
    412     protected String getMetadataNameText(String key, String lang) {
    413 
    414     String properties_name = "metadata_names";
    415     Dictionary dict = new Dictionary(properties_name, lang);
    416    
    417     String result = dict.get(key);
    418     if (result == null) { // not found
    419         return null;
    420     }
    421     return result;
    422     }
     244            else
     245            {
     246                // other type of request, must be processed by the subclass -
     247                // send to the service method
     248                StringBuffer error_string = new StringBuffer();
     249                String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
     250                Element response = null;
     251                try
     252                {
     253                    Class c = this.getClass();
     254                    Class[] params = { Class.forName("org.w3c.dom.Element") };
     255
     256                    String method_name = "process" + to;
     257                    Method m = null;
     258                    while (c != null)
     259                    {
     260
     261                        try
     262                        {
     263                            m = c.getDeclaredMethod(method_name, params);
     264                            // if this has worked, break
     265                            break;
     266                        }
     267                        catch (NoSuchMethodException e)
     268                        {
     269                            c = c.getSuperclass();
     270                        }
     271                        catch (SecurityException e)
     272                        {
     273                            logger.error("security exception for finding method " + method_name);
     274                            error_string.append("ServiceRack.process: security exception for finding method " + method_name);
     275                        }
     276                    } // while
     277                    if (m != null)
     278                    {
     279                        Object[] args = { request };
     280                        try
     281                        {
     282                            response = (Element) m.invoke(this, args);
     283
     284                        }
     285                        catch (Exception e)
     286                        {
     287                            logger.error("Trying to call a processService type method (process" + to + ") on a subclass(" + this.getClass().getName() + "), but an exception happened:" + e.toString(), e);
     288
     289                            error_string.append("Trying to call a processService type method (process" + to + ") on a subclass(" + this.getClass().getName() + "), but an exception happened:" + e.toString());
     290                        }
     291                    }
     292                    else
     293                    {
     294                        logger.error("method " + method_name + " not found for class " + this.getClass().getName());
     295                        error_string.append("ServiceRack.process: method " + method_name + " not found for class " + this.getClass().getName());
     296                    }
     297
     298                }
     299                catch (ClassNotFoundException e)
     300                {
     301                    logger.error("Element class not found");
     302                    error_string.append("Element class not found");
     303                }
     304                if (response != null)
     305                {
     306                    mainResult.appendChild(this.doc.importNode(response, true));
     307                }
     308                else
     309                {
     310                    // add in a dummy response
     311                    logger.error("adding in an error element\n");
     312                    response = this.doc.createElement(GSXML.RESPONSE_ELEM);
     313                    GSXML.addError(this.doc, response, error_string.toString());
     314                    mainResult.appendChild(response);
     315
     316                }
     317
     318            } // else process request
     319        } // for each request
     320
     321        return mainResult;
     322
     323    }
     324
     325    /**
     326     * process method for describe requests
     327     */
     328    protected Element processDescribe(Element request)
     329    {
     330
     331        Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
     332        response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_DESCRIBE);
     333
     334        String lang = request.getAttribute(GSXML.LANG_ATT);
     335        String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
     336        if (to.equals(""))
     337        { // return the service list
     338            response.appendChild(getServiceList(lang));
     339            return response;
     340        }
     341        response.setAttribute(GSXML.FROM_ATT, to);
     342        Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
     343        Element description = null;
     344        if (param_list == null)
     345        {
     346            description = getServiceDescription(to, lang, null);
     347        }
     348        else
     349        {
     350            NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
     351            for (int i = 0; i < params.getLength(); i++)
     352            {
     353
     354                Element param = (Element) params.item(i);
     355                // Identify the structure information desired
     356                if (param.getAttribute(GSXML.NAME_ATT).equals(GSXML.SUBSET_PARAM))
     357                {
     358                    String info = param.getAttribute(GSXML.VALUE_ATT);
     359                    if (description == null)
     360                    {
     361                        description = getServiceDescription(to, lang, info);
     362                    }
     363                    else
     364                    {
     365                        Element temp = getServiceDescription(to, lang, info);
     366                        GSXML.mergeElements(description, temp);
     367                    }
     368                }
     369            }
     370        }
     371        if (description != null)
     372        { // may be null if non-existant service
     373            response.appendChild(description);
     374        }
     375        return response;
     376
     377    }
     378
     379    /**
     380     * process method for stylesheet requests
     381     */
     382    protected Element processFormat(Element request)
     383    {
     384        Element response = this.doc.createElement(GSXML.RESPONSE_ELEM);
     385        response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_FORMAT);
     386
     387        String to = GSPath.getFirstLink(request.getAttribute(GSXML.TO_ATT));
     388
     389        if (to.equals(""))
     390        { // serviceRack query - is this appropriate??
     391            return response;
     392        }
     393
     394        // describe a particular service   
     395        if (this.format_info_map.containsKey(to))
     396        {
     397            response.appendChild(getServiceFormat(to));
     398            response.setAttribute(GSXML.FROM_ATT, to);
     399            return response;
     400        }
     401        // else no format info
     402        logger.error("ServiceRack describe request: no format info for " + to + ".");
     403        return response;
     404    }
     405
     406    /** returns the service list for the subclass */
     407    protected Element getServiceList(String lang)
     408    {
     409        // for now, it is static and has no language stuff
     410        return (Element) this.short_service_info.cloneNode(true);
     411    }
     412
     413    /** returns a specific service description */
     414    abstract protected Element getServiceDescription(String service, String lang, String subset);
     415
     416    protected Element getServiceFormat(String service)
     417    {
     418        Element format = (Element) ((Element) this.format_info_map.get(service)).cloneNode(true);
     419        return format;
     420    }
     421
     422    /** overloaded version for no args case */
     423    protected String getTextString(String key, String lang)
     424    {
     425        return getTextString(key, lang, null, null);
     426    }
     427
     428    protected String getTextString(String key, String lang, String dictionary)
     429    {
     430        return getTextString(key, lang, dictionary, null);
     431    }
     432
     433    protected String getTextString(String key, String lang, String[] args)
     434    {
     435        return getTextString(key, lang, null, args);
     436    }
     437
     438    /**
     439     * getTextString - retrieves a language specific text string for the given
     440     * key and locale, from the specified resource_bundle (dictionary)
     441     */
     442    protected String getTextString(String key, String lang, String dictionary, String[] args)
     443    {
     444
     445        // we want to use the collection class loader in case there are coll specific files
     446        if (dictionary != null)
     447        {
     448            // just try the one specified dictionary
     449            Dictionary dict = new Dictionary(dictionary, lang, this.class_loader);
     450            String result = dict.get(key, args);
     451            if (result == null)
     452            { // not found
     453                return "_" + key + "_";
     454            }
     455            return result;
     456        }
     457
     458        // now we try class names for dictionary names
     459        String class_name = this.getClass().getName();
     460        class_name = class_name.substring(class_name.lastIndexOf('.') + 1);
     461        Dictionary dict = new Dictionary(class_name, lang, this.class_loader);
     462        String result = dict.get(key, args);
     463        if (result != null)
     464        {
     465            return result;
     466        }
     467
     468        // we have to try super classes
     469        Class c = this.getClass().getSuperclass();
     470        while (result == null && c != null)
     471        {
     472            class_name = c.getName();
     473            class_name = class_name.substring(class_name.lastIndexOf('.') + 1);
     474            if (class_name.equals("ServiceRack"))
     475            {
     476                // this is as far as we go
     477                break;
     478            }
     479            dict = new Dictionary(class_name, lang, this.class_loader);
     480            result = dict.get(key, args);
     481            c = c.getSuperclass();
     482        }
     483        if (result == null)
     484        {
     485            return "_" + key + "_";
     486        }
     487        return result;
     488
     489    }
     490
     491    protected String getMetadataNameText(String key, String lang)
     492    {
     493
     494        String properties_name = "metadata_names";
     495        Dictionary dict = new Dictionary(properties_name, lang);
     496
     497        String result = dict.get(key);
     498        if (result == null)
     499        { // not found
     500            return null;
     501        }
     502        return result;
     503    }
    423504}
    424 
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/DBInfo.java

    r24254 r24393  
    2222import java.util.HashMap;
    2323import java.util.Set;
    24 /** class to hold info from a gdbm (or equiv) query
    25  * maps a String key to a list of Strings (values)
    26  * at the moment, the user must know if something has a single value or not
     24
     25/**
     26 * class to hold info from a gdbm (or equiv) query maps a String key to a list
     27 * of Strings (values) at the moment, the user must know if something has a
     28 * single value or not
    2729 */
    28 public class DBInfo {
     30public class DBInfo
     31{
     32    protected HashMap info_map_;
    2933
    30     protected HashMap info_map_;
     34    public DBInfo()
     35    {
     36        info_map_ = new HashMap();
     37    }
    3138
    32     public DBInfo() {
    33     info_map_ = new HashMap();
    34     }
     39    // methods for keys that can have a single value
    3540
    36     // methods for keys that can have a single value
     41    /** set the value for a key - replaces any existing value */
     42    public void setInfo(String key, String value)
     43    {
     44        Vector v = new Vector();
     45        v.add(value);
     46        info_map_.put(key, v);
     47    }
    3748
    38     /** set the value for a key - replaces any existing value */
    39     public void setInfo(String key, String value) {
    40     Vector v = new Vector();
    41     v.add(value);
    42     info_map_.put(key, v);
    43     }
     49    /**
     50     * get the value - used for keys that have one value, otherwise just returns
     51     * the first one
     52     */
     53    public String getInfo(String key)
     54    {
     55        Vector items = (Vector) info_map_.get(key);
     56        if (items == null)
     57        {
     58            return "";
     59        }
     60        return (String) items.firstElement();
     61    }
    4462
    45     /** get the value - used for keys that have one value, otherwise just
    46      * returns the first one */
    47     public String getInfo(String key) {
    48     Vector items = (Vector)info_map_.get(key);
    49     if (items==null) {
    50         return "";
     63    // methods for keys that can have multiple values
     64
     65    /** add a value to a key - for keys that can have multiple values */
     66    public void addInfo(String key, String value)
     67    {
     68        Vector v = (Vector) info_map_.get(key);
     69        if (v == null)
     70        {
     71            v = new Vector();
     72        }
     73        v.add(value);
     74        info_map_.put(key, v);
    5175    }
    52     return (String)items.firstElement();
    53     }
    5476
    55     /** get the value for the key at offset. If offset out of bounds,
    56      * just return the first one. */
    57     public String getInfoOffset(String key, int offset) {
    58     Vector items = (Vector)info_map_.get(key);
    59     if (items==null) {
    60         return "";
     77    /**
     78     * return a vector of all values associated with a key
     79     *
     80     * @return Vector of Strings
     81     */
     82    public Vector getMultiInfo(String key)
     83    {
     84        return (Vector) info_map_.get(key);
    6185    }
    62     if(offset >= 0 && offset < items.size()) {
    63         return (String)items.get(offset);
    64     } // else
    65     return (String)items.firstElement();
    66     }
    6786
     87    /** returns a list of all the keys in the info */
     88    public Set getKeys()
     89    {
     90        return info_map_.keySet();
     91    }
    6892
    69     // methods for keys that can have multiple values
    70    
    71     /** add a value to a key - for keys that can have multiple values */
    72     public void addInfo(String key, String value) {
    73     Vector v = (Vector)info_map_.get(key);
    74     if (v==null) {
    75         v = new Vector();
     93    /** returns the Info as a string */
     94    public String toString()
     95    {
     96        return info_map_.toString();
     97
    7698    }
    77     v.add(value);
    78     info_map_.put(key, v);
    79     }
    80     /** return a vector of all values associated with a key
    81      * @return Vector of Strings
    82      */
    83     public Vector getMultiInfo(String key) {
    84     return (Vector)info_map_.get(key);
    85     }
    86 
    87     /** returns a list of all the keys in the info */
    88     public Set getKeys() {
    89     return info_map_.keySet();
    90     }
    91     /** returns the Info as a string */
    92     public String toString() {
    93     return info_map_.toString();
    94 
    95     }
    9699}
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/FlatDatabaseWrapper.java

    r16797 r24393  
    3737  /** returns the value associated with the key */
    3838  public String getValue(String key);
     39 
     40  /** sets the given key to the given value in the database */
     41  public boolean setValue(String key, String value);
     42 
     43  /** deletes the given key from the database */
     44  public boolean deleteKey(String key);
    3945
    4046  /** returns a string of key-value entries that can be
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GDBMWrapper.java

    r21912 r24393  
    2828import java.io.File;
    2929
    30 /** java wrapper class for gdbm - uses Java-GDBM written by Martin Pool
    31  * replaces gdbmclass in the old version
     30/**
     31 * java wrapper class for gdbm - uses Java-GDBM written by Martin Pool replaces
     32 * gdbmclass in the old version
    3233 */
    3334
    34 public class GDBMWrapper
    35   implements FlatDatabaseWrapper {
    36 
    37   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GDBMWrapper.class.getName());
    38  
    39   /* GdbmFile modes:
    40      READER - read access, many readers may share the database
    41      WRITER - read/write access, exclusive access
    42      WRCREAT - read/write access, create db if doesn't exist
    43      NEWDB - read/write access, db should be replaced if exists
    44   */
    45    
    46    
    47     protected GdbmFile db_=null;
    48    
    49   /** open the database filename, with mode mode - uses the constants
    50       above, eg GdbmFile.WRITER */
    51   public boolean openDatabase(String filename, int mode) {
    52     // need to convert mode to GdbmFile mode
    53     if (mode == READ) {
    54       mode = GdbmFile.READER;
    55     } else if (mode == WRITE) {
    56       mode = GdbmFile.WRITER;
    57     }   else {
    58       logger.error ("invalid mode, "+mode+ ", opening db for reading only");
    59       mode = GdbmFile.READER;
    60     }
    61     try {
    62     if (db_!=null) {
    63         db_.close();
    64     }
    65 
    66     // The java version of the C++ code in common-src/src/lib/gdbmclass.cpp
    67     if(mode == GdbmFile.READER) {
    68       // Looking to read in the database
    69       // we now use gdb extension. Check for ldb/bdb in case of legacy collection
    70       // if not (first time) then generate using txt2db
    71         if (!new File(filename).exists()) {
    72           logger.warn("Database file " + filename + " does not exist. Looking for ldb/bdb version");
    73           int extension = filename.lastIndexOf('.');
    74           String filename_head = filename.substring(0, extension);
    75           filename = filename_head + ".ldb";
    76           if (!new File(filename).exists()) {
    77         filename = filename_head + ".bdb";
     35public class GDBMWrapper implements FlatDatabaseWrapper
     36{
     37
     38    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GDBMWrapper.class.getName());
     39
     40    /*
     41     * GdbmFile modes: READER - read access, many readers may share the database
     42     * WRITER - read/write access, exclusive access WRCREAT - read/write access,
     43     * create db if doesn't exist NEWDB - read/write access, db should be
     44     * replaced if exists
     45     */
     46
     47    protected GdbmFile db_ = null;
     48
     49    /**
     50     * open the database filename, with mode mode - uses the constants above, eg
     51     * GdbmFile.WRITER
     52     */
     53    public boolean openDatabase(String filename, int mode)
     54    {
     55        // need to convert mode to GdbmFile mode
     56        if (mode == READ)
     57        {
     58            mode = GdbmFile.READER;
     59        }
     60        else if (mode == WRITE)
     61        {
     62            mode = GdbmFile.WRITER;
     63        }
     64        else
     65        {
     66            logger.error("invalid mode, " + mode + ", opening db for reading only");
     67            mode = GdbmFile.READER;
     68        }
     69        try
     70        {
     71            if (db_ != null)
     72            {
     73                db_.close();
     74            }
     75
     76            // The java version of the C++ code in common-src/src/lib/gdbmclass.cpp
     77            if (mode == GdbmFile.READER)
     78            {
     79                // Looking to read in the database
     80                // we now use gdb extension. Check for ldb/bdb in case of legacy collection
     81                // if not (first time) then generate using txt2db
     82                if (!new File(filename).exists())
     83                {
     84                    logger.warn("Database file " + filename + " does not exist. Looking for ldb/bdb version");
     85                    int extension = filename.lastIndexOf('.');
     86                    String filename_head = filename.substring(0, extension);
     87                    filename = filename_head + ".ldb";
     88                    if (!new File(filename).exists())
     89                    {
     90                        filename = filename_head + ".bdb";
     91
     92                        if (!new File(filename).exists())
     93                        {
     94                            logger.warn("ldb/bdb version of database file " + filename + " does not exist. Looking for txtgz version of db file.");
     95                            // put the filename back to gdb
     96                            filename = filename_head + ".gdb";
     97                            // need to generate architecture native GDBM file using txt2db
     98
     99                            // replace sought after gdbm filename ext with ".txt.gz"
     100
     101                            String txtgzFilename = filename_head + ".txt.gz";
     102                            if (new File(txtgzFilename).exists())
     103                            {
     104                                // Test to make sure Perl is on the path
     105                                // On Linux, the output of the test goes to STDOUT so redirect it to STDERR
     106                                String cmdTest = "perl -v 2>&1";
     107                                //String cmdTest = "echo %PATH%";
     108                                int returnValue = Processing.runProcess(cmdTest);
     109                                if (returnValue != 0)
     110                                {
     111                                    logger.error("Tried to find Perl. Return exit value of running " + cmdTest + ": " + returnValue + ", (expected this to be 0)");
     112                                    logger.error("Check that Perl is set in your PATH environment variable.");
     113                                    //log.error("At present, PATH=" + System.getenv("PATH"));
     114                                }
     115
     116                                String cmd = "perl -S txtgz-to-gdbm.pl \"" + txtgzFilename + "\" \"" + filename + "\"";
     117                                returnValue = Processing.runProcess(cmd);
     118                                // For some reason, launching this command with gsdl_system() still returns 1
     119                                // even when it returns 0 when run from the command-line. We can check whether
     120                                // we succeeded by looking at whether the output database file was created.
     121                                if (returnValue != 0)
     122                                {
     123                                    logger.warn("Warning, non-zero return value on running command \"" + cmd + "\": " + returnValue);
     124                                    if (!new File(filename).exists())
     125                                    {
     126                                        logger.error("Tried to run command \"" + cmd + "\", but it failed");
     127                                    }
     128                                }
     129                            }
     130                        }
     131                    }
     132
     133                }
     134            }
     135
     136            db_ = new GdbmFile(filename, mode);
     137        }
     138        catch (GdbmException e)
     139        { // the database wasn't opened or created
     140            logger.error("couldn't open database " + filename);
     141            return false;
     142        }
     143        db_.setKeyPacking(new StringPacking());
     144        db_.setValuePacking(new StringPacking());
     145        return true;
     146    }
     147
     148    /** close the database associated with this wrapper */
     149    public void closeDatabase()
     150    {
     151        try
     152        {
     153            if (db_ != null)
     154            {
     155                db_.close();
     156                db_ = null;
     157                if (System.getProperty("os.name").startsWith("Windows"))
     158                {
     159                    //Hack: force Windows to let go of the gdb file
     160                    System.gc();
     161                }
     162            }
     163        }
     164        catch (GdbmException e)
     165        {
     166            // should never get here - close never actually throws an exception
     167            logger.error("error on close()");
     168        }
     169    }
     170
     171    public String getValue(String key)
     172    {
     173        if (db_ == null)
     174        {
     175            return null;
     176        }
     177        String s_info;
     178        try
     179        {
     180            try
     181            {
     182                // The key is UTF8: do db lookup using the UTF8 version of key
     183                s_info = (String) db_.fetch(key.getBytes("UTF-8"));
     184            }
     185            catch (UnsupportedEncodingException e)
     186            {
     187                logger.warn("utf8 key for " + key + " unrecognised. Retrying with default encoding.");
     188                // retry db lookup using default encoding of key instead of UTF8
     189                s_info = (String) db_.fetch(key);
     190            }
     191        }
     192        catch (GdbmException e)
     193        {
     194            logger.error("couldn't get record");
     195            return null;
     196        }
     197        if (s_info == null)
     198        {
     199            // record not present
     200            logger.error("key " + key + " not present in db");
     201            return null;
     202        }
     203        return s_info;
     204    }
     205
     206    /**
     207     * sets the given key to the given value in the database
     208     */
     209    public boolean setValue(String key, String value)
     210    {
     211        if (db_ == null || !db_.isWritable())
     212        {
     213            logger.error("GDBM database is either null or not writable");
     214            return false;
     215        }
    78216       
    79         if (!new File(filename).exists()) {
    80         logger.warn("ldb/bdb version of database file " + filename + " does not exist. Looking for txtgz version of db file.");
    81         // put the filename back to gdb
    82         filename = filename_head + ".gdb";
    83         // need to generate architecture native GDBM file using txt2db
     217        try
     218        {
     219            db_.store(key, value);
     220        }
     221        catch (GdbmException ex)
     222        {
     223            logger.error("Error storing " + key + " = " + value + " in GDBM database");
     224            logger.error("Error message is: " + ex.getMessage());
     225            return false;
     226        }
     227        return true;
     228    }
     229
     230    /**
     231     * deletes the entry for given key
     232     */
     233    public boolean deleteKey(String key)
     234    {
     235        if (db_ == null)
     236        {
     237            logger.error("GDBM database is null");
     238            return false;
     239        }
    84240       
    85         // replace sought after gdbm filename ext with ".txt.gz"
     241        try
     242        {
     243            db_.delete(key);
     244        }
     245        catch (GdbmException ex)
     246        {
     247            logger.error("Error deleting key " + key + " from the database");
     248            logger.error("Error message is: " + ex.getMessage());
     249            return false;
     250        }
    86251       
    87         String txtgzFilename = filename_head + ".txt.gz";
    88         if(new File(txtgzFilename).exists()) {         
    89             // Test to make sure Perl is on the path
    90             // On Linux, the output of the test goes to STDOUT so redirect it to STDERR
    91             String cmdTest = "perl -v 2>&1";           
    92             //String cmdTest = "echo %PATH%";
    93             int returnValue = Processing.runProcess(cmdTest);
    94             if (returnValue != 0) {
    95             logger.error("Tried to find Perl. Return exit value of running "
    96                      + cmdTest + ": " +  returnValue + ", (expected this to be 0)");
    97             logger.error("Check that Perl is set in your PATH environment variable.");
    98             //log.error("At present, PATH=" + System.getenv("PATH"));
    99             }
    100            
    101             String cmd = "perl -S txtgz-to-gdbm.pl \"" + txtgzFilename + "\" \"" + filename + "\"";
    102             returnValue = Processing.runProcess(cmd);
    103             // For some reason, launching this command with gsdl_system() still returns 1
    104             // even when it returns 0 when run from the command-line. We can check whether
    105             // we succeeded by looking at whether the output database file was created.
    106             if (returnValue != 0) {
    107             logger.warn("Warning, non-zero return value on running command \"" + cmd + "\": " + returnValue);
    108             if (!new File(filename).exists()) {
    109                 logger.error("Tried to run command \"" + cmd + "\", but it failed");
    110             }
    111             }           
    112         }
    113         }
    114           }
    115          
    116         }
    117     }
    118 
    119     db_ = new GdbmFile(filename, mode);
    120     } catch ( GdbmException e) { // the database wasn't opened or created
    121     logger.error("couldn't open database "+filename);
    122     return false;
    123     }
    124     db_.setKeyPacking(new StringPacking());
    125     db_.setValuePacking(new StringPacking());
    126     return true;
    127   }
    128  
    129   /** close the database associated with this wrapper */
    130   public void closeDatabase() {
    131     try {
    132       if (db_ != null) {
    133        db_.close();
    134        db_ = null;
    135         if(System.getProperty("os.name").startsWith("Windows")) {
    136             //Hack: force Windows to let go of the gdb file
    137             System.gc();
    138         }
    139       }
    140     } catch (GdbmException e) {
    141       // should never get here - close never actually throws an exception
    142       logger.error("error on close()");
    143     }
    144   }
    145 
    146   public String getValue(String key) {
    147     if (db_==null) {
    148       return null;
    149     }
    150     String s_info;
    151     try {
    152     try {
    153         // The key is UTF8: do db lookup using the UTF8 version of key
    154         s_info = (String)db_.fetch(key.getBytes("UTF-8"));
    155     } catch(UnsupportedEncodingException e) {
    156         logger.warn("utf8 key for " + key
    157              + " unrecognised. Retrying with default encoding.");
    158         // retry db lookup using default encoding of key instead of UTF8
    159         s_info = (String)db_.fetch(key);
    160     }
    161     } catch (GdbmException e) {
    162       logger.error("couldn't get record");
    163       return null;
    164     }
    165     if (s_info==null) {
    166       // record not present
    167       logger.error("key "+key+" not present in db");
    168       return null;
    169     }
    170     return s_info;
    171   }
    172 
    173   /** sets the key value as info
    174    * TODO - not implemented yet */
    175   public boolean setValue (String key, String value) {
    176     if (db_==null) {
    177       return false;
    178     }
    179     return false;
    180   }
    181   /** deletes the entry for key
    182    * TODO - not implemented yet */
    183   public boolean deleteKey(String key) {
    184     if (db_==null) {
    185       return false;
    186     }
    187     return false;
    188   }
    189 
    190     /** returns a string of key-value entries that
    191      *  can be printed for debugging purposes. */
    192     public String displayAllEntries() {
    193     StringBuffer output = new StringBuffer();
    194     try{
    195         java.util.Enumeration e = db_.keys();
    196         while(e.hasMoreElements()) {
    197         Object key = e.nextElement();
    198         Object value = db_.fetch(key);
    199 
    200         output.append("key href: ");
    201         output.append((String)key);
    202         output.append("\tvalue ID: ");
    203         output.append((String)value);
    204         output.append("\n");
    205         //logger.warn("key: " + key + "\tvalue: " + value);
    206 
    207         String urlkey = java.net.URLEncoder.encode((String)key, "UTF8");
    208         output.append("URL encoded key: " + urlkey);
    209         //logger.warn("URL encoded key: " + urlkey);
    210         }
    211     } catch(UnsupportedEncodingException e) {
    212         logger.warn("Trouble converting key to UTF-8.");
    213     } catch(Exception e) {
    214         logger.warn("Exception encountered when trying to displayAllEntries():" + e);
    215     }
    216     return output.toString();
    217     }
     252        return true;
     253    }
     254
     255    /**
     256     * returns a string of key-value entries that can be printed for debugging
     257     * purposes.
     258     */
     259    public String displayAllEntries()
     260    {
     261        StringBuffer output = new StringBuffer();
     262        try
     263        {
     264            java.util.Enumeration e = db_.keys();
     265            while (e.hasMoreElements())
     266            {
     267                Object key = e.nextElement();
     268                Object value = db_.fetch(key);
     269
     270                output.append("key href: ");
     271                output.append((String) key);
     272                output.append("\tvalue ID: ");
     273                output.append((String) value);
     274                output.append("\n");
     275                //logger.warn("key: " + key + "\tvalue: " + value);
     276
     277                String urlkey = java.net.URLEncoder.encode((String) key, "UTF8");
     278                output.append("URL encoded key: " + urlkey);
     279                //logger.warn("URL encoded key: " + urlkey);
     280            }
     281        }
     282        catch (UnsupportedEncodingException e)
     283        {
     284            logger.warn("Trouble converting key to UTF-8.");
     285        }
     286        catch (Exception e)
     287        {
     288            logger.warn("Exception encountered when trying to displayAllEntries():" + e);
     289        }
     290        return output.toString();
     291    }
    218292}
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java

    r24254 r24393  
    11/*
    2  *    GSXML.java
    3  *    Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
    4  *
    5  *    This program is free software; you can redistribute it and/or modify
    6  *    it under the terms of the GNU General Public License as published by
    7  *    the Free Software Foundation; either version 2 of the License, or
    8  *    (at your option) any later version.
    9  *
    10  *    This program is distributed in the hope that it will be useful,
    11  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  *    GNU General Public License for more details.
    14  *
    15  *    You should have received a copy of the GNU General Public License
    16  *    along with this program; if not, write to the Free Software
    17  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    18  */
     2*    GSXML.java
     3*    Copyright (C) 2008 New Zealand Digital Library, http://www.nzdl.org
     4*
     5*    This program is free software; you can redistribute it and/or modify
     6*    it under the terms of the GNU General Public License as published by
     7*    the Free Software Foundation; either version 2 of the License, or
     8*    (at your option) any later version.
     9*
     10*    This program is distributed in the hope that it will be useful,
     11*    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13*    GNU General Public License for more details.
     14*
     15*    You should have received a copy of the GNU General Public License
     16*    along with this program; if not, write to the Free Software
     17*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18*/
    1919package org.greenstone.gsdl3.util;
    2020
     
    2626import org.w3c.dom.Text;
    2727
    28 
    2928import javax.xml.transform.TransformerFactory;
    3029import javax.xml.transform.Transformer;
     
    4645/** various functions for extracting info out of GS XML */
    4746public class GSXML {
    48  
    49   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName());
    50  
    51   // greenstone xml elements
    52   public static final String MESSAGE_ELEM = "message";
    53   public static final String REQUEST_ELEM = "request";
    54   public static final String RESPONSE_ELEM = "response";
    55   public static final String COLLECTION_ELEM = "collection";
    56   public static final String SERVICE_ELEM = "service";
    57   public static final String CLUSTER_ELEM = "serviceCluster";
    58   public static final String SITE_ELEM = "site";
    59   public static final String PARAM_ELEM = "param";
    60   public static final String PARAM_OPTION_ELEM = "option";
    61   public static final String CONTENT_ELEM = "content";
    62   public static final String RESOURCE_ELEM = "resource";
    63   public static final String DOCUMENT_ELEM = "document";
    64   public static final String METADATA_ELEM = "metadata";
    65   public static final String SERVICE_CLASS_ELEM = "serviceRack";
    66   public static final String CLASSIFIER_ELEM = "classifier";
    67   public static final String APPLET_ELEM = "applet";
    68   public static final String APPLET_DATA_ELEM = "appletData";
    69   public static final String CONFIGURE_ELEM = "configure";
    70   public static final String STATUS_ELEM = "status";
    71   public static final String ERROR_ELEM = "error";
    72   public static final String DEFAULT_ELEM = "default";
    73   public static final String STYLESHEET_ELEM = "format";//"stylesheet"; // any additional stylesheet stuff is carried in the message inside this elem
    74   public static final String FORMAT_ELEM = "format"; // config files use format - should we use this instead of stylesheet??
    75   public static final String TERM_ELEM = "term";
    76   public static final String STOPWORD_ELEM = "stopword";
    77   public static final String SYSTEM_ELEM = "system";
    78   public static final String FORMAT_STRING_ELEM = "formatString";
    79  
    80   //config file elems
    81   public static final String COLLECTION_CONFIG_ELEM = "collectionConfig";
    82   public static final String COLLECTION_BUILD_ELEM = "buildConfig";
    83   public static final String COLLECTION_INIT_ELEM = "collectionInit";
    84   public static final String RECOGNISE_ELEM = "recognise";
    85   public static final String DOC_TYPE_ELEM = "docType";
    86   public static final String SEARCH_ELEM = "search";
    87   public static final String INFODB_ELEM = "infodb";
    88   public static final String INDEX_ELEM = "index";
    89   public static final String INDEX_STEM_ELEM = "indexStem";
    90   public static final String INDEX_OPTION_ELEM = "indexOption";
    91   public static final String BROWSE_ELEM = "browse";
    92   public static final String DISPLAY_ELEM = "display";
    93   public static final String LEVEL_ELEM = "level";
    94 
    95   public static final String DBINFO_ELEM = "dbInfo";
    96   public static final String DBNAME_ATT = "dbname"; 
    97   public static final String DBPATH_ATT = "dbpath";
    98   public static final String SQLSTATE_ATT = "sqlstate";
    99   public static final String DATABASE_TYPE_ELEM = "databaseType";
    100   public static final String SHORTNAME_ATT = "shortname";
    101   public static final String NOTIFY_ELEM = "notify";
    102   public static final String NOTIFY_HOST_ATT = "host";
    103 
    104    
    105 
    106   // elems for the pages to be processed by xslt
    107   public final static String PAGE_ELEM = "page";
    108   public final static String CONFIGURATION_ELEM = "config";
    109   public final static String PAGE_REQUEST_ELEM = "pageRequest";
    110   public final static String PAGE_RESPONSE_ELEM = "pageResponse";
    111   public final static String PAGE_EXTRA_ELEM = "pageExtra";
    112  
    113   //public final static String DESCRIPTION_ELEM = "description";
    114  
    115   public static final String  ACTION_ELEM = "action";
    116   public static final String  SUBACTION_ELEM = "subaction";
    117  
    118   // add on to another elem type to get a list of that type
    119   public static final String LIST_MODIFIER = "List";
    120  
    121   // greenstone xml attributes
    122   public static final String NAME_ATT = "name";
    123   public static final String TO_ATT = "to";
    124   public static final String USER_ID_ATT = "uid";
    125   public static final String FROM_ATT = "from";
    126   public static final String LANG_ATT = "lang";
    127   public static final String TYPE_ATT = "type";
    128   public static final String DB_TYPE_ATT = "dbType";
    129   public static final String VALUE_ATT = "value";
    130   public static final String DEFAULT_ATT = "default";
    131   public static final String INFO_ATT = "info";
    132   public static final String ACTION_ATT = "action";
    133   public static final String SUBACTION_ATT = "subaction";
    134   public static final String OUTPUT_ATT = "output";
    135   public static final String ADDRESS_ATT = "address";
    136   public static final String LOCAL_SITE_ATT = "localSite";
    137   public static final String LOCAL_SITE_NAME_ATT = "localSiteName";
    138   public static final String STATUS_ERROR_CODE_ATT = "code";
    139   public static final String STATUS_PROCESS_ID_ATT = "pid";
    140   public static final String PARAM_SHORTNAME_ATT = "shortname";
    141   public static final String PARAM_IGNORE_POS_ATT = "ignore";
    142   public static final String CLASSIFIER_CONTENT_ATT = "content";
    143   public static final String ERROR_TYPE_ATT = "type";
    144   public static final String COLLECT_TYPE_ATT = "ct";
    145   public static final String HIDDEN_ATT = "hidden";
    146  
    147   // document stuff
    148   public static final String DOC_TYPE_ATT = "docType";
    149   public static final String DOC_NODE_ELEM = "documentNode";
    150   public static final String NODE_CONTENT_ELEM = "nodeContent";
    151   public static final String NODE_STRUCTURE_ELEM = "nodeStructure";
    152   public static final String NODE_ID_ATT = "nodeID";
    153   public static final String NODE_NAME_ATT = "nodeName";
    154   public static final String NODE_TYPE_ATT = "nodeType";
    155   public static final String NODE_RANK_ATT = "rank";
    156   public static final String NODE_TYPE_ROOT = "root";
    157   public static final String NODE_TYPE_INTERNAL = "internal";
    158   public static final String NODE_TYPE_LEAF = "leaf";
    159   public static final String NODE_MDOFFSET_ATT = "mdoffset";
    160  
    161   public static final String DOC_TYPE_SIMPLE = "simple";
    162   public static final String DOC_TYPE_PAGED = "paged";
    163   public static final String DOC_TYPE_HIERARCHY = "hierarchy";
    164 
    165   public static final String SESSION_EXPIRATION = "session_expiration";
    166   public static final String USER_SESSION_CACHE_ATT = "user_session_cache";
    167 
    168   // classifier stuff
    169   public static final String CLASS_NODE_ELEM = "classifierNode";
    170   public static final String CLASS_NODE_ORIENTATION_ATT = "orientation";
    171  
    172   // parameter types
    173   public static final String PARAM_TYPE_INTEGER = "integer";
    174   public static final String PARAM_TYPE_BOOLEAN = "boolean";
    175   public static final String PARAM_TYPE_ENUM_START = "enum";
    176   public static final String PARAM_TYPE_ENUM_SINGLE = "enum_single";
    177   public static final String PARAM_TYPE_ENUM_MULTI = "enum_multi";
    178   public static final String PARAM_TYPE_STRING = "string";
    179   public static final String PARAM_TYPE_TEXT = "text";
    180   public static final String PARAM_TYPE_MULTI = "multi";
    181   public static final String PARAM_TYPE_FILE = "file";
    182   public static final String PARAM_TYPE_INVISIBLE = "invisible";
    183   // stuff for text strings
    184   public static final String DISPLAY_TEXT_ELEM = "displayItem";
    185   // the following are used for the name attributes
    186   public static final String DISPLAY_TEXT_NAME = "name";
    187   public static final String DISPLAY_TEXT_SUBMIT = "submit";
    188   public static final String DISPLAY_TEXT_DESCRIPTION = "description";
    189  
    190   // request types
    191   // get the module description
    192   public static final String REQUEST_TYPE_DESCRIBE = "describe";
    193   // startup a process
    194   public static final String REQUEST_TYPE_PROCESS = "process";
    195   // get the status of an ongoing process
    196   public static final String REQUEST_TYPE_STATUS = "status";
    197   // system type request - eg reload a collection
    198   public static final String REQUEST_TYPE_SYSTEM = "system";
    199   // page requests to the Receptionist/Actions
    200   public static final String REQUEST_TYPE_PAGE = "page"; // used to be cgi
    201   // get any format info for a service
    202   public static final String REQUEST_TYPE_FORMAT = "format";
    203   // modify the requests
    204   public static final String REQUEST_TYPE_MESSAGING = "messaging";
    205   // save the format string
    206   public static final String REQUEST_TYPE_FORMAT_STRING = "formatString";
    207  
    208   // service types
    209   public static final String SERVICE_TYPE_QUERY = "query";
    210   public static final String SERVICE_TYPE_RETRIEVE = "retrieve";
    211   public static final String SERVICE_TYPE_BROWSE = "browse";
    212   public static final String SERVICE_TYPE_APPLET = "applet";
    213   public static final String SERVICE_TYPE_PROCESS = "process";
    214   public static final String SERVICE_TYPE_ENRICH = "enrich";
    215   public static final String SERVICE_TYPE_OAI = "oai";
    216   public static final String FLAX_PAGE = "flaxPage";
    217   public static final String FLAX_PAGE_GENERATION = "FlaxPageGeneration"; 
    218  
    219   // system command types and attributes
    220   public static final String SYSTEM_TYPE_CONFIGURE = "configure";
    221   public static final String SYSTEM_TYPE_ACTIVATE = "activate";
    222   public static final String SYSTEM_TYPE_DEACTIVATE = "deactivate";
    223  
    224   public static final String SYSTEM_SUBSET_ATT = "subset";
    225   public static final String SYSTEM_MODULE_TYPE_ATT = "moduleType";
    226   public static final String SYSTEM_MODULE_NAME_ATT = "moduleName";
    227  
    228   // communicator types
    229   public static final String COMM_TYPE_SOAP_JAVA = "soap";
    230  
    231   // error types
    232   public static final String ERROR_TYPE_SYNTAX = "syntax";
    233   public static final String ERROR_TYPE_SYSTEM = "system";
    234   public static final String ERROR_TYPE_INVALID_ID = "invalid_id";
    235   public static final String ERROR_TYPE_OTHER = "other";
    236  
    237   // some system wide param names
    238   public static final String SUBSET_PARAM = "subset";
    239  
    240   //for plugin
    241   public static final String PLUGIN_ELEM = "plugin";
    242   public static final String IMPORT_ELEM = "import";
    243  
    244   //for authentication
    245    public static final String AUTHEN_NODE_ELEM="authenticationNode";
    246    public static final String USER_NODE_ELEM="userNode";
    247 
    248    //for configure action results
    249    public static final String SUCCESS = "success";
    250    public static final String ERROR = "error";
    251    
    252   /** takes a list of elements, and returns an array of strings
    253    * of the values of attribute att_name */
    254   public static String [] getAttributeValuesFromList(Element list,
    255     String att_name) {
    256    
    257     NodeList children = list.getChildNodes();
    258    
    259     int num_nodes = children.getLength();
    260     String []ids = new String[num_nodes];
    261     for (int i=0; i<num_nodes; i++) {
    262       Element e = (Element)children.item(i);
    263       String id = e.getAttribute(att_name);
    264       ids[i] = id;
    265     }
    266    
    267     return ids;
    268   }
    269  
    270   public static HashMap extractParams(Element xml, boolean deep) {
    271     return extractParams(xml, deep, null);
    272   }
    273 
    274   /** takes a paramList element, and gets a HashMap of name-value pairs
    275    * if deep=true, extracts embedded params, otherwise just top level
    276    * params*/
    277   public static HashMap extractParams(Element xml, boolean deep, String toFind) {
    278    
    279     if (!xml.getNodeName().equals(PARAM_ELEM+LIST_MODIFIER)) {
    280       logger.error("paramList element should have been passed to extractParams, instead it was "+xml.getNodeName());
    281       return null;
    282     }
    283    
    284     NodeList params = null;
    285     if (deep) { // get all the nested ones
    286       params = xml.getElementsByTagName(PARAM_ELEM);
    287     } else { // just get the top  level ones
    288       params = xml.getChildNodes();
    289     }
    290     HashMap param_map = new HashMap();
    291     for (int i=0; i<params.getLength(); i++) {
    292       if (params.item(i).getNodeName().equals(PARAM_ELEM)) {
    293         Element param = (Element)params.item(i);
    294         String name=param.getAttribute(NAME_ATT);
    295         String value=getValue(param); //att or content
    296 
    297     // For only one parameter
    298     if(toFind != null && name.equals(toFind)) {
    299         param_map.put(name, value);
     47
     48    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName());
     49
     50    // greenstone xml elements
     51    public static final String MESSAGE_ELEM = "message";
     52    public static final String REQUEST_ELEM = "request";
     53    public static final String RESPONSE_ELEM = "response";
     54    public static final String COLLECTION_ELEM = "collection";
     55    public static final String SERVICE_ELEM = "service";
     56    public static final String CLUSTER_ELEM = "serviceCluster";
     57    public static final String SITE_ELEM = "site";
     58    public static final String PARAM_ELEM = "param";
     59    public static final String PARAM_OPTION_ELEM = "option";
     60    public static final String CONTENT_ELEM = "content";
     61    public static final String RESOURCE_ELEM = "resource";
     62    public static final String DOCUMENT_ELEM = "document";
     63    public static final String METADATA_ELEM = "metadata";
     64    public static final String SERVICE_CLASS_ELEM = "serviceRack";
     65    public static final String CLASSIFIER_ELEM = "classifier";
     66    public static final String APPLET_ELEM = "applet";
     67    public static final String APPLET_DATA_ELEM = "appletData";
     68    public static final String CONFIGURE_ELEM = "configure";
     69    public static final String STATUS_ELEM = "status";
     70    public static final String ERROR_ELEM = "error";
     71    public static final String DEFAULT_ELEM = "default";
     72    public static final String STYLESHEET_ELEM = "format";//"stylesheet"; // any additional stylesheet stuff is carried in the message inside this elem
     73    public static final String FORMAT_ELEM = "format"; // config files use format - should we use this instead of stylesheet??
     74    public static final String TERM_ELEM = "term";
     75    public static final String STOPWORD_ELEM = "stopword";
     76    public static final String SYSTEM_ELEM = "system";
     77    public static final String FORMAT_STRING_ELEM = "formatString";
     78
     79    //config file elems
     80    public static final String COLLECTION_CONFIG_ELEM = "collectionConfig";
     81    public static final String COLLECTION_BUILD_ELEM = "buildConfig";
     82    public static final String COLLECTION_INIT_ELEM = "collectionInit";
     83    public static final String RECOGNISE_ELEM = "recognise";
     84    public static final String DOC_TYPE_ELEM = "docType";
     85    public static final String SEARCH_ELEM = "search";
     86    public static final String INFODB_ELEM = "infodb";
     87    public static final String INDEX_ELEM = "index";
     88    public static final String INDEX_STEM_ELEM = "indexStem";
     89    public static final String INDEX_OPTION_ELEM = "indexOption";
     90    public static final String BROWSE_ELEM = "browse";
     91    public static final String DISPLAY_ELEM = "display";
     92    public static final String LEVEL_ELEM = "level";
     93
     94    public static final String DBINFO_ELEM = "dbInfo";
     95    public static final String DBNAME_ATT = "dbname"; 
     96    public static final String DBPATH_ATT = "dbpath";
     97    public static final String SQLSTATE_ATT = "sqlstate";
     98    public static final String DATABASE_TYPE_ELEM = "databaseType";
     99    public static final String SHORTNAME_ATT = "shortname";
     100    public static final String NOTIFY_ELEM = "notify";
     101    public static final String NOTIFY_HOST_ATT = "host";
     102   
     103    //doc.xml file elems
     104    public static final String DOCXML_SECTION_ELEM = "Section";
     105    public static final String DOCXML_DESCRIPTION_ELEM = "Description";
     106    public static final String DOCXML_METADATA_ELEM = "Metadata";
     107    public static final String DOCXML_CONTENT_ELEM = "Content";
     108
     109    // elems for the pages to be processed by xslt
     110    public final static String PAGE_ELEM = "page";
     111    public final static String CONFIGURATION_ELEM = "config";
     112    public final static String PAGE_REQUEST_ELEM = "pageRequest";
     113    public final static String PAGE_RESPONSE_ELEM = "pageResponse";
     114    public final static String PAGE_EXTRA_ELEM = "pageExtra";
     115
     116    //public final static String DESCRIPTION_ELEM = "description";
     117
     118    public static final String  ACTION_ELEM = "action";
     119    public static final String  SUBACTION_ELEM = "subaction";
     120
     121    // add on to another elem type to get a list of that type
     122    public static final String LIST_MODIFIER = "List";
     123
     124    // greenstone xml attributes
     125    public static final String COLLECTION_ATT = "collection";
     126    public static final String NAME_ATT = "name";
     127    public static final String TO_ATT = "to";
     128    public static final String USER_ID_ATT = "uid";
     129    public static final String FROM_ATT = "from";
     130    public static final String LANG_ATT = "lang";
     131    public static final String TYPE_ATT = "type";
     132    public static final String DB_TYPE_ATT = "dbType";
     133    public static final String VALUE_ATT = "value";
     134    public static final String DEFAULT_ATT = "default";
     135    public static final String INFO_ATT = "info";
     136    public static final String ACTION_ATT = "action";
     137    public static final String SUBACTION_ATT = "subaction";
     138    public static final String OUTPUT_ATT = "output";
     139    public static final String ADDRESS_ATT = "address";
     140    public static final String LOCAL_SITE_ATT = "localSite";
     141    public static final String LOCAL_SITE_NAME_ATT = "localSiteName";
     142    public static final String STATUS_ERROR_CODE_ATT = "code";
     143    public static final String STATUS_PROCESS_ID_ATT = "pid";
     144    public static final String PARAM_SHORTNAME_ATT = "shortname";
     145    public static final String PARAM_IGNORE_POS_ATT = "ignore";
     146    public static final String CLASSIFIER_CONTENT_ATT = "content";
     147    public static final String ERROR_TYPE_ATT = "type";
     148    public static final String COLLECT_TYPE_ATT = "ct";
     149    public static final String HIDDEN_ATT = "hidden";
     150
     151    // document stuff
     152    public static final String DOC_TYPE_ATT = "docType";
     153    public static final String DOC_NODE_ELEM = "documentNode";
     154    public static final String NODE_CONTENT_ELEM = "nodeContent";
     155    public static final String NODE_STRUCTURE_ELEM = "nodeStructure";
     156    public static final String NODE_ID_ATT = "nodeID";
     157    public static final String NODE_NAME_ATT = "nodeName";
     158    public static final String NODE_TYPE_ATT = "nodeType";
     159    public static final String NODE_RANK_ATT = "rank";
     160    public static final String NODE_TYPE_ROOT = "root";
     161    public static final String NODE_TYPE_INTERNAL = "internal";
     162    public static final String NODE_TYPE_LEAF = "leaf";
     163
     164    public static final String DOC_TYPE_SIMPLE = "simple";
     165    public static final String DOC_TYPE_PAGED = "paged";
     166    public static final String DOC_TYPE_HIERARCHY = "hierarchy";
     167
     168    public static final String SESSION_EXPIRATION = "session_expiration";
     169    public static final String USER_SESSION_CACHE_ATT = "user_session_cache";
     170
     171    // classifier stuff
     172    public static final String CLASS_NODE_ELEM = "classifierNode";
     173    public static final String CLASS_NODE_ORIENTATION_ATT = "orientation";
     174
     175    // parameter types
     176    public static final String PARAM_TYPE_INTEGER = "integer";
     177    public static final String PARAM_TYPE_BOOLEAN = "boolean";
     178    public static final String PARAM_TYPE_ENUM_START = "enum";
     179    public static final String PARAM_TYPE_ENUM_SINGLE = "enum_single";
     180    public static final String PARAM_TYPE_ENUM_MULTI = "enum_multi";
     181    public static final String PARAM_TYPE_STRING = "string";
     182    public static final String PARAM_TYPE_TEXT = "text";
     183    public static final String PARAM_TYPE_MULTI = "multi";
     184    public static final String PARAM_TYPE_FILE = "file";
     185    public static final String PARAM_TYPE_INVISIBLE = "invisible";
     186    // stuff for text strings
     187    public static final String DISPLAY_TEXT_ELEM = "displayItem";
     188    // the following are used for the name attributes
     189    public static final String DISPLAY_TEXT_NAME = "name";
     190    public static final String DISPLAY_TEXT_SUBMIT = "submit";
     191    public static final String DISPLAY_TEXT_DESCRIPTION = "description";
     192
     193    // request types
     194    // get the module description
     195    public static final String REQUEST_TYPE_DESCRIBE = "describe";
     196    // startup a process
     197    public static final String REQUEST_TYPE_PROCESS = "process";
     198    // get the status of an ongoing process
     199    public static final String REQUEST_TYPE_STATUS = "status";
     200    // system type request - eg reload a collection
     201    public static final String REQUEST_TYPE_SYSTEM = "system";
     202    // page requests to the Receptionist/Actions
     203    public static final String REQUEST_TYPE_PAGE = "page"; // used to be cgi
     204    // get any format info for a service
     205    public static final String REQUEST_TYPE_FORMAT = "format";
     206    // modify the requests
     207    public static final String REQUEST_TYPE_MESSAGING = "messaging";
     208    // save the format string
     209    public static final String REQUEST_TYPE_FORMAT_STRING = "formatString";
     210
     211    // service types
     212    public static final String SERVICE_TYPE_QUERY = "query";
     213    public static final String SERVICE_TYPE_RETRIEVE = "retrieve";
     214    public static final String SERVICE_TYPE_BROWSE = "browse";
     215    public static final String SERVICE_TYPE_APPLET = "applet";
     216    public static final String SERVICE_TYPE_PROCESS = "process";
     217    public static final String SERVICE_TYPE_ENRICH = "enrich";
     218    public static final String SERVICE_TYPE_OAI = "oai";
     219    public static final String FLAX_PAGE = "flaxPage";
     220    public static final String FLAX_PAGE_GENERATION = "FlaxPageGeneration"; 
     221
     222    // system command types and attributes
     223    public static final String SYSTEM_TYPE_CONFIGURE = "configure";
     224    public static final String SYSTEM_TYPE_ACTIVATE = "activate";
     225    public static final String SYSTEM_TYPE_DEACTIVATE = "deactivate";
     226
     227    public static final String SYSTEM_SUBSET_ATT = "subset";
     228    public static final String SYSTEM_MODULE_TYPE_ATT = "moduleType";
     229    public static final String SYSTEM_MODULE_NAME_ATT = "moduleName";
     230
     231    // communicator types
     232    public static final String COMM_TYPE_SOAP_JAVA = "soap";
     233
     234    // error types
     235    public static final String ERROR_TYPE_SYNTAX = "syntax";
     236    public static final String ERROR_TYPE_SYSTEM = "system";
     237    public static final String ERROR_TYPE_INVALID_ID = "invalid_id";
     238    public static final String ERROR_TYPE_OTHER = "other";
     239
     240    // some system wide param names
     241    public static final String SUBSET_PARAM = "subset";
     242
     243    //for plugin
     244    public static final String PLUGIN_ELEM = "plugin";
     245    public static final String IMPORT_ELEM = "import";
     246
     247    //for authentication
     248    public static final String AUTHEN_NODE_ELEM="authenticationNode";
     249    public static final String USER_NODE_ELEM="userNode";
     250
     251    //for configure action results
     252    public static final String SUCCESS = "success";
     253    public static final String ERROR = "error";
     254
     255    /** takes a list of elements, and returns an array of strings
     256* of the values of attribute att_name */
     257    public static String [] getAttributeValuesFromList(Element list,
     258    String att_name) {
     259       
     260        NodeList children = list.getChildNodes();
     261       
     262        int num_nodes = children.getLength();
     263        String []ids = new String[num_nodes];
     264        for (int i=0; i<num_nodes; i++) {
     265            Element e = (Element)children.item(i);
     266            String id = e.getAttribute(att_name);
     267            ids[i] = id;
     268        }
     269       
     270        return ids;
     271    }
     272
     273    public static HashMap extractParams(Element xml, boolean deep) {
     274        return extractParams(xml, deep, null);
     275    }
     276
     277    /** takes a paramList element, and gets a HashMap of name-value pairs
     278* if deep=true, extracts embedded params, otherwise just top level
     279* params*/
     280    public static HashMap extractParams(Element xml, boolean deep, String toFind) {
     281       
     282        if (!xml.getNodeName().equals(PARAM_ELEM+LIST_MODIFIER)) {
     283            logger.error("paramList element should have been passed to extractParams, instead it was "+xml.getNodeName());
     284            return null;
     285        }
     286       
     287        NodeList params = null;
     288        if (deep) { // get all the nested ones
     289            params = xml.getElementsByTagName(PARAM_ELEM);
     290        } else { // just get the top  level ones
     291            params = xml.getChildNodes();
     292        }
     293        HashMap param_map = new HashMap();
     294        for (int i=0; i<params.getLength(); i++) {
     295            if (params.item(i).getNodeName().equals(PARAM_ELEM)) {
     296                Element param = (Element)params.item(i);
     297                String name=param.getAttribute(NAME_ATT);
     298                String value=getValue(param); //att or content
     299
     300                // For only one parameter
     301                if(toFind != null && name.equals(toFind)) {
     302                    param_map.put(name, value);
     303                    return param_map;
     304                }       
     305                else if(toFind != null)
     306                continue;
     307
     308                int pos = name.indexOf('.');
     309                if (pos == -1) { // a base param
     310                    param_map.put(name, value);
     311                } else { // a namespaced param
     312                   
     313                    String namespace = name.substring(0, pos);
     314                    name = name.substring(pos+1);
     315                    HashMap map = (HashMap)param_map.get(namespace);
     316                    if (map == null) {
     317                        map = new HashMap();
     318                        param_map.put(namespace, map);
     319                    }
     320                    map.put(name, value);
     321                }
     322            }
     323        }
    300324        return param_map;
    301     }       
    302     else if(toFind != null)
    303         continue;
    304 
    305         int pos = name.indexOf('.');
    306         if (pos == -1) { // a base param
    307           param_map.put(name, value);
    308         } else { // a namespaced param
    309          
    310           String namespace = name.substring(0, pos);
    311           name = name.substring(pos+1);
    312           HashMap map = (HashMap)param_map.get(namespace);
    313           if (map == null) {
    314             map = new HashMap();
    315             param_map.put(namespace, map);
    316           }
    317           map.put(name, value);
    318         }
    319       }
    320     }
    321     return param_map;
    322   }
    323  
    324   /** gets the value att or the text content */
    325   public static String getValue(Element e) {
    326     String val = e.getAttribute(VALUE_ATT);
    327     if (val ==null || val.equals("")) {
    328       // have to get it out of the text
    329       val=getNodeText(e);
    330      
    331     } else {
    332       // unescape the xml stuff
    333       val = unXmlSafe(val);
    334     }
    335     return val;
    336   }
    337  
    338   /** extracts the text out of a node */
    339   public static Node getNodeTextNode(Element param) {
    340     param.normalize();
    341     Node n = param.getFirstChild();
    342     while (n!=null && n.getNodeType() !=Node.TEXT_NODE) {
    343       n=n.getNextSibling();
    344     }
    345     return n;
    346   }
    347  
    348   /** extracts the text out of a node */
    349   public static String getNodeText(Element param) {
    350     Node text_node = getNodeTextNode(param);
    351     if (text_node == null) {
    352       return "";
    353     }
    354     return text_node.getNodeValue();
    355   }
    356  
    357   public static void setNodeText(Element elem, String text) {
    358     Node old_text_node = getNodeTextNode(elem);
    359     if (old_text_node != null) {
    360       elem.removeChild(old_text_node);
    361     }
    362     Text t = elem.getOwnerDocument().createTextNode(text);
    363     elem.appendChild(t);
    364   }
    365  
    366   /** add text to a document/subsection  element */
    367   public static boolean addDocText(Document owner, Element doc, String text) {
    368    
    369     Element content = owner.createElement(NODE_CONTENT_ELEM);
    370     Text t = owner.createTextNode(text);
    371     content.appendChild(t);
    372     doc.appendChild(content);
    373     return true;
    374   }
    375  
    376   /** add an error message, unknown error type */
    377   public static boolean addError(Document owner, Element doc, String text) {
    378     return addError(owner, doc, text, ERROR_TYPE_OTHER);
    379   }
    380   /** add an error message */
    381   public static boolean addError(Document owner, Element doc, String text,
    382     String error_type) {
    383    
    384     Element content = owner.createElement(ERROR_ELEM);
    385     content.setAttribute(ERROR_TYPE_ATT, error_type);
    386     Text t = owner.createTextNode(text);
    387     content.appendChild(t);
    388     doc.appendChild(content);
    389     return true;
    390   }
    391  
    392   /** add an error message */
    393   public static boolean addError(Document owner, Element doc, Throwable error) {
    394     return addError(owner, doc, error, ERROR_TYPE_OTHER);
    395   }
    396  
    397   /** add an error message */
    398   public static boolean addError(Document owner, Element doc,
    399     Throwable error, String error_type) {
    400     error.printStackTrace();
    401     return addError(owner, doc, error.toString(), error_type);
    402   }
    403  
    404   public static Element createMetadataParamList(Document owner, Vector meta_values) {
    405    
    406     Element meta_param_list = owner.createElement(PARAM_ELEM+LIST_MODIFIER);
    407     Iterator i = meta_values.iterator();
    408     while(i.hasNext()) {
    409       String next = (String)i.next();
    410       Element meta_param = owner.createElement(PARAM_ELEM);
    411       meta_param_list.appendChild(meta_param);
    412       meta_param.setAttribute(NAME_ATT, "metadata");
    413       meta_param.setAttribute(VALUE_ATT, next);
    414     }
    415     return meta_param_list;
    416   }
    417  
    418   /** adds a metadata elem to a list */
    419   public static boolean addMetadata(Document owner, Element list,
    420     String meta_name, String meta_value) {
    421     if (meta_value==null || meta_value.equals("")) {
    422       return false;
    423     }
    424     Element data = owner.createElement(METADATA_ELEM);
    425     data.setAttribute(NAME_ATT, meta_name);
    426     Text t = owner.createTextNode(meta_value);
    427     data.appendChild(t);
    428     list.appendChild(data);
    429     return true;
    430    
    431   }
    432  
    433   /** copies the metadata out of the metadataList of 'from' into
    434    * the metadataList of 'to' */
    435   public static boolean mergeMetadataLists(Node to, Node from) {
    436     Node from_meta = getChildByTagName(from, METADATA_ELEM+LIST_MODIFIER);
    437     if  (from_meta == null) { // nothing to copy
    438       return true;
    439     }
    440     return mergeMetadataFromList(to, from_meta);
    441   }
    442  
    443 
    444   /** copies the metadata out of the meta_list metadataList  into
    445    * the metadataList of 'to' */
    446   public static boolean mergeMetadataFromList(Node to, Node meta_list) {
    447     if (meta_list == null) return false;
    448     Node to_meta = getChildByTagName(to, METADATA_ELEM+LIST_MODIFIER);
    449     Document to_owner = to.getOwnerDocument();
    450     if (to_meta == null) {
    451       to.appendChild(to_owner.importNode(meta_list, true));
    452       return true;
    453     }
    454     // copy individual metadata elements
    455     NodeList meta_items = ((Element)meta_list).getElementsByTagName(METADATA_ELEM);
    456     for (int i=0; i<meta_items.getLength(); i++) {
    457       to_meta.appendChild(to_owner.importNode(meta_items.item(i),true));
    458     }
    459     return true;
    460   }
    461  
    462   /** copies all the children from from to to */
    463   public static boolean mergeElements(Element to, Element from) {
    464    
    465     Document owner = to.getOwnerDocument();
    466     Node child = from.getFirstChild();
    467     while (child != null) {
    468       to.appendChild(owner.importNode(child, true));
    469       child = child.getNextSibling();
    470     }
    471     return true;
    472   }
    473   /** returns the (first) element child of the node n */
    474   public static Element getFirstElementChild(Node n) {
    475    
    476     Node child = n.getFirstChild();
    477     while (child!=null) {
    478       if (child.getNodeType() == Node.ELEMENT_NODE) {
    479         return (Element)child;
    480       }
    481       child = child.getNextSibling();
    482     }
    483     return null; //no element child found
    484   }
    485   /** returns the (first) child element with the given name */
    486   public static Node getChildByTagName(Node n, String name) {
    487       if(n != null) { // this line is an attempted solution to the NullPointerException mentioned
    488       // in trac bug ticket #225. If n is null can't do n.getFirstChild() below. As per bug #225:
    489       // GSXML.getNodeByPath() is called by GS2BrowseAction, which then calls this method.
    490       // If n is null, null will be returned which GS2BrowseAction already checks for. It's here
    491       // that the NullPointerException was thrown.
    492  
    493       Node child = n.getFirstChild();
    494       while (child!=null) {
    495           if (child.getNodeName().equals(name)) {
    496           return child;
    497           }
    498           child = child.getNextSibling();
    499       }
    500       }
    501       return null; //not found
    502   }
    503  
    504   /** returns the (nth) child element with the given name
    505    * index numbers start at 0 */
    506   public static Node getChildByTagNameIndexed(Node n, String name, int index) {
    507     if (index == -1) {
    508       return getChildByTagName(n, name);
    509     }
    510     int count = 0;
    511     Node child = n.getFirstChild();
    512     while (child!=null) {
    513       if (child.getNodeName().equals(name)) {
    514         if (count == index) {
    515           return child;
    516         } else {
    517           count++;
    518         }
    519       }
    520       child = child.getNextSibling();
    521     }
    522     return null; //not found
    523   }
    524  
    525   /** takes an xpath type expression of the form name/name/...
    526    * and returns the first node that matches, or null if not found */
    527   public static Node getNodeByPath(Node n, String path) {
    528    
    529     String link = GSPath.getFirstLink(path);
    530     path = GSPath.removeFirstLink(path);
    531     while (!link.equals("")) {
    532       n = getChildByTagName(n, link);
    533       if (n==null) {
    534         return null;
    535       }
    536       link = GSPath.getFirstLink(path);
    537       path = GSPath.removeFirstLink(path);
    538     }
    539     return n;
    540   }
    541  
    542   /** takes an xpath type expression of the form name/name/...
    543    * and returns the first node that matches, or null if not found
    544    * can include [i] indices. index numbers start at 0 */
    545   public static Node getNodeByPathIndexed(Node n, String path) {
    546    
    547     String link = GSPath.getFirstLink(path);
    548     int index = GSPath.getIndex(link);
    549     if (index != -1) {
    550       link = GSPath.removeIndex(link);
    551     }
    552     path = GSPath.removeFirstLink(path);
    553     while (!link.equals("")) {
    554       n = getChildByTagNameIndexed(n, link, index);
    555       if (n==null) {
    556         return null;
    557       }
    558       link = GSPath.getFirstLink(path);
    559       index = GSPath.getIndex(link);
    560       if (index != -1) {
    561         link = GSPath.removeIndex(link);
    562       }
    563       path = GSPath.removeFirstLink(path);
    564     }
    565     return n;
    566   }
    567  
    568   public static HashMap getChildrenMap(Node n) {
    569    
    570     HashMap map= new HashMap();
    571     Node child = n.getFirstChild();
    572     while (child!=null) {
    573       String name = child.getNodeName();
    574       map.put(name, child);
    575       child = child.getNextSibling();
    576     }
    577     return map;
    578   }
    579  
    580   public static NodeList getChildrenByTagName(Node n, String name) {
    581     MyNodeList node_list = new MyNodeList();
    582     Node child = n.getFirstChild();
    583     while (child!=null) {
    584       if (child.getNodeName().equals(name)) {
    585         node_list.addNode(child);
    586       }
    587       child = child.getNextSibling();
    588     }
    589     return node_list;
    590   }
    591  
    592  
    593   /** Duplicates an element, but gives it a new name */
    594   public static Element duplicateWithNewName(Document owner, Element element,
    595     String element_name, boolean with_attributes) {
    596     return duplicateWithNewNameNS(owner, element, element_name, null, with_attributes);
    597   }
    598  
    599   /** Duplicates an element, but gives it a new name */
    600   public static Element duplicateWithNewNameNS(Document owner,
    601     Element element,
    602     String element_name,
    603     String namespace_uri,
    604     boolean with_attributes) {
    605     Element duplicate;
    606     if (namespace_uri == null) {
    607       duplicate = owner.createElement(element_name);
    608     } else {
    609       duplicate = owner.createElementNS(namespace_uri, element_name);
    610     }
    611     // Copy element attributes
    612     if (with_attributes) {
    613       NamedNodeMap attributes = element.getAttributes();
    614       for (int i = 0; i < attributes.getLength(); i++) {
    615         Node attribute = attributes.item(i);
    616         duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
    617       }
    618     }
    619    
    620     // Copy element children
    621     NodeList children = element.getChildNodes();
    622     for (int i = 0; i < children.getLength(); i++) {
    623       Node child = children.item(i);
    624       duplicate.appendChild(owner.importNode(child, true));
    625     }
    626    
    627     return duplicate;
    628   }
    629  
    630   public static void copyAllChildren(Element to, Element from) {
    631    
    632     Document to_doc = to.getOwnerDocument();
    633     Node child = from.getFirstChild();
    634     while (child != null) {
    635       to.appendChild(to_doc.importNode(child, true));
    636       child = child.getNextSibling();
    637     }
    638   }
    639   /** returns a basic request message */
    640   public static  Element createBasicRequest(Document owner,
    641     String request_type, String to,
    642     String lang,
    643     String uid) {
    644     Element request = owner.createElement(REQUEST_ELEM);
    645     request.setAttribute(TYPE_ATT, request_type);
    646     request.setAttribute(LANG_ATT, lang);
    647     request.setAttribute(TO_ATT, to);
    648     request.setAttribute(USER_ID_ATT, uid);
    649     return request;
    650   }
    651  
    652   public static Element createTextElement(Document owner, String elem_name,
    653     String text) {
    654     Element e = owner.createElement(elem_name);
    655     Text t = owner.createTextNode(text);
    656     e.appendChild(t);
    657     return e;
    658    
    659   }
    660  
    661   public static Element createTextElement(Document owner, String elem_name,
    662             String text, String att_name, String att_value) {
    663             Element e = owner.createElement(elem_name);
    664             e.setAttribute(att_name, att_value);
    665             Text t = owner.createTextNode(text);
    666             e.appendChild(t);
    667             return e;
    668            
    669           }
    670          
    671   public static Element createDisplayTextElement(Document owner,
    672     String text_name,
    673     String text) {
    674     Element e = owner.createElement(DISPLAY_TEXT_ELEM);
    675     e.setAttribute(NAME_ATT, text_name);
    676     Text t = owner.createTextNode(text);
    677     e.appendChild(t);
    678     return e;
    679    
    680   }
    681  
    682  
    683   public static Element createParameter(Document owner, String name,
    684     String value) {
    685     Element param = owner.createElement(PARAM_ELEM);
    686     param.setAttribute(NAME_ATT, name);
    687     param.setAttribute(VALUE_ATT, value);
    688     return param;
    689   }
    690  
    691   public static void addParametersToList(Document owner, Element param_list,
    692     HashMap params) {
    693     if (params == null)
     325    }
     326
     327    /** gets the value att or the text content */
     328    public static String getValue(Element e) {
     329        String val = e.getAttribute(VALUE_ATT);
     330        if (val ==null || val.equals("")) {
     331            // have to get it out of the text
     332            val=getNodeText(e);
     333           
     334        } else {
     335            // unescape the xml stuff
     336            val = unXmlSafe(val);
     337        }
     338        return val;
     339    }
     340
     341    /** extracts the text out of a node */
     342    public static Node getNodeTextNode(Element param) {
     343        param.normalize();
     344        Node n = param.getFirstChild();
     345        while (n!=null && n.getNodeType() !=Node.TEXT_NODE) {
     346            n=n.getNextSibling();
     347        }
     348        return n;
     349    }
     350
     351    /** extracts the text out of a node */
     352    public static String getNodeText(Element param) {
     353        Node text_node = getNodeTextNode(param);
     354        if (text_node == null) {
     355            return "";
     356        }
     357        return text_node.getNodeValue();
     358    }
     359
     360    public static void setNodeText(Element elem, String text) {
     361        Node old_text_node = getNodeTextNode(elem);
     362        if (old_text_node != null) {
     363            elem.removeChild(old_text_node);
     364        }
     365        Text t = elem.getOwnerDocument().createTextNode(text);
     366        elem.appendChild(t);
     367    }
     368
     369    /** add text to a document/subsection  element */
     370    public static boolean addDocText(Document owner, Element doc, String text) {
     371       
     372        Element content = owner.createElement(NODE_CONTENT_ELEM);
     373        Text t = owner.createTextNode(text);
     374        content.appendChild(t);
     375        doc.appendChild(content);
     376        return true;
     377    }
     378
     379    /** add an error message, unknown error type */
     380    public static boolean addError(Document owner, Element doc, String text) {
     381        return addError(owner, doc, text, ERROR_TYPE_OTHER);
     382    }
     383    /** add an error message */
     384    public static boolean addError(Document owner, Element doc, String text,
     385    String error_type) {
     386       
     387        Element content = owner.createElement(ERROR_ELEM);
     388        content.setAttribute(ERROR_TYPE_ATT, error_type);
     389        Text t = owner.createTextNode(text);
     390        content.appendChild(t);
     391        doc.appendChild(content);
     392        return true;
     393    }
     394
     395    /** add an error message */
     396    public static boolean addError(Document owner, Element doc, Throwable error) {
     397        return addError(owner, doc, error, ERROR_TYPE_OTHER);
     398    }
     399
     400    /** add an error message */
     401    public static boolean addError(Document owner, Element doc,
     402    Throwable error, String error_type) {
     403        error.printStackTrace();
     404        return addError(owner, doc, error.toString(), error_type);
     405    }
     406
     407    public static Element createMetadataParamList(Document owner, Vector meta_values) {
     408       
     409        Element meta_param_list = owner.createElement(PARAM_ELEM+LIST_MODIFIER);
     410        Iterator i = meta_values.iterator();
     411        while(i.hasNext()) {
     412            String next = (String)i.next();
     413            Element meta_param = owner.createElement(PARAM_ELEM);
     414            meta_param_list.appendChild(meta_param);
     415            meta_param.setAttribute(NAME_ATT, "metadata");
     416            meta_param.setAttribute(VALUE_ATT, next);
     417        }
     418        return meta_param_list;
     419    }
     420
     421    /** adds a metadata elem to a list */
     422    public static boolean addMetadata(Document owner, Element list,
     423    String meta_name, String meta_value) {
     424        if (meta_value==null || meta_value.equals("")) {
     425            return false;
     426        }
     427        Element data = owner.createElement(METADATA_ELEM);
     428        data.setAttribute(NAME_ATT, meta_name);
     429        Text t = owner.createTextNode(meta_value);
     430        data.appendChild(t);
     431        list.appendChild(data);
     432        return true;
     433       
     434    }
     435
     436    /** copies the metadata out of the metadataList of 'from' into
     437* the metadataList of 'to' */
     438    public static boolean mergeMetadataLists(Node to, Node from) {
     439        Node from_meta = getChildByTagName(from, METADATA_ELEM+LIST_MODIFIER);
     440        if  (from_meta == null) { // nothing to copy
     441            return true;
     442        }
     443        return mergeMetadataFromList(to, from_meta);
     444    }
     445
     446
     447    /** copies the metadata out of the meta_list metadataList  into
     448* the metadataList of 'to' */
     449    public static boolean mergeMetadataFromList(Node to, Node meta_list) {
     450        if (meta_list == null) return false;
     451        Node to_meta = getChildByTagName(to, METADATA_ELEM+LIST_MODIFIER);
     452        Document to_owner = to.getOwnerDocument();
     453        if (to_meta == null) {
     454            to.appendChild(to_owner.importNode(meta_list, true));
     455            return true;
     456        }
     457        // copy individual metadata elements
     458        NodeList meta_items = ((Element)meta_list).getElementsByTagName(METADATA_ELEM);
     459        for (int i=0; i<meta_items.getLength(); i++) {
     460            to_meta.appendChild(to_owner.importNode(meta_items.item(i),true));
     461        }
     462        return true;
     463    }
     464
     465    /** copies all the children from from to to */
     466    public static boolean mergeElements(Element to, Element from) {
     467       
     468        Document owner = to.getOwnerDocument();
     469        Node child = from.getFirstChild();
     470        while (child != null) {
     471            to.appendChild(owner.importNode(child, true));
     472            child = child.getNextSibling();
     473        }
     474        return true;
     475    }
     476    /** returns the (first) element child of the node n */
     477    public static Element getFirstElementChild(Node n) {
     478       
     479        Node child = n.getFirstChild();
     480        while (child!=null) {
     481            if (child.getNodeType() == Node.ELEMENT_NODE) {
     482                return (Element)child;
     483            }
     484            child = child.getNextSibling();
     485        }
     486        return null; //no element child found
     487    }
     488    /** returns the (first) child element with the given name */
     489    public static Node getChildByTagName(Node n, String name) {
     490        if(n != null) { // this line is an attempted solution to the NullPointerException mentioned
     491            // in trac bug ticket #225. If n is null can't do n.getFirstChild() below. As per bug #225:
     492            // GSXML.getNodeByPath() is called by GS2BrowseAction, which then calls this method.
     493            // If n is null, null will be returned which GS2BrowseAction already checks for. It's here
     494            // that the NullPointerException was thrown.
     495
     496            Node child = n.getFirstChild();
     497            while (child!=null) {
     498                if (child.getNodeName().equals(name)) {
     499                    return child;
     500                }
     501                child = child.getNextSibling();
     502            }
     503        }
     504        return null; //not found
     505    }
     506
     507    /** returns the (nth) child element with the given name
     508* index numbers start at 0 */
     509    public static Node getChildByTagNameIndexed(Node n, String name, int index) {
     510        if (index == -1) {
     511            return getChildByTagName(n, name);
     512        }
     513        int count = 0;
     514        Node child = n.getFirstChild();
     515        while (child!=null) {
     516            if (child.getNodeName().equals(name)) {
     517                if (count == index) {
     518                    return child;
     519                } else {
     520                    count++;
     521                }
     522            }
     523            child = child.getNextSibling();
     524        }
     525        return null; //not found
     526    }
     527
     528    /** takes an xpath type expression of the form name/name/...
     529* and returns the first node that matches, or null if not found */
     530    public static Node getNodeByPath(Node n, String path) {
     531       
     532        String link = GSPath.getFirstLink(path);
     533        path = GSPath.removeFirstLink(path);
     534        while (!link.equals("")) {
     535            n = getChildByTagName(n, link);
     536            if (n==null) {
     537                return null;
     538            }
     539            link = GSPath.getFirstLink(path);
     540            path = GSPath.removeFirstLink(path);
     541        }
     542        return n;
     543    }
     544
     545    /** takes an xpath type expression of the form name/name/...
     546* and returns the first node that matches, or null if not found
     547* can include [i] indices. index numbers start at 0 */
     548    public static Node getNodeByPathIndexed(Node n, String path) {
     549       
     550        String link = GSPath.getFirstLink(path);
     551        int index = GSPath.getIndex(link);
     552        if (index != -1) {
     553            link = GSPath.removeIndex(link);
     554        }
     555        path = GSPath.removeFirstLink(path);
     556        while (!link.equals("")) {
     557            n = getChildByTagNameIndexed(n, link, index);
     558            if (n==null) {
     559                return null;
     560            }
     561            link = GSPath.getFirstLink(path);
     562            index = GSPath.getIndex(link);
     563            if (index != -1) {
     564                link = GSPath.removeIndex(link);
     565            }
     566            path = GSPath.removeFirstLink(path);
     567        }
     568        return n;
     569    }
     570
     571    public static HashMap getChildrenMap(Node n) {
     572       
     573        HashMap map= new HashMap();
     574        Node child = n.getFirstChild();
     575        while (child!=null) {
     576            String name = child.getNodeName();
     577            map.put(name, child);
     578            child = child.getNextSibling();
     579        }
     580        return map;
     581    }
     582
     583    public static NodeList getChildrenByTagName(Node n, String name) {
     584        MyNodeList node_list = new MyNodeList();
     585        Node child = n.getFirstChild();
     586        while (child!=null) {
     587            if (child.getNodeName().equals(name)) {
     588                node_list.addNode(child);
     589            }
     590            child = child.getNextSibling();
     591        }
     592        return node_list;
     593    }
     594
     595
     596    /** Duplicates an element, but gives it a new name */
     597    public static Element duplicateWithNewName(Document owner, Element element,
     598    String element_name, boolean with_attributes) {
     599        return duplicateWithNewNameNS(owner, element, element_name, null, with_attributes);
     600    }
     601
     602    /** Duplicates an element, but gives it a new name */
     603    public static Element duplicateWithNewNameNS(Document owner,
     604    Element element,
     605    String element_name,
     606    String namespace_uri,
     607    boolean with_attributes) {
     608        Element duplicate;
     609        if (namespace_uri == null) {
     610            duplicate = owner.createElement(element_name);
     611        } else {
     612            duplicate = owner.createElementNS(namespace_uri, element_name);
     613        }
     614        // Copy element attributes
     615        if (with_attributes) {
     616            NamedNodeMap attributes = element.getAttributes();
     617            for (int i = 0; i < attributes.getLength(); i++) {
     618                Node attribute = attributes.item(i);
     619                duplicate.setAttribute(attribute.getNodeName(), attribute.getNodeValue());
     620            }
     621        }
     622       
     623        // Copy element children
     624        NodeList children = element.getChildNodes();
     625        for (int i = 0; i < children.getLength(); i++) {
     626            Node child = children.item(i);
     627            duplicate.appendChild(owner.importNode(child, true));
     628        }
     629       
     630        return duplicate;
     631    }
     632
     633    public static void copyAllChildren(Element to, Element from) {
     634       
     635        Document to_doc = to.getOwnerDocument();
     636        Node child = from.getFirstChild();
     637        while (child != null) {
     638            to.appendChild(to_doc.importNode(child, true));
     639            child = child.getNextSibling();
     640        }
     641    }
     642    /** returns a basic request message */
     643    public static  Element createBasicRequest(Document owner,
     644    String request_type, String to,
     645    String lang,
     646    String uid) {
     647        Element request = owner.createElement(REQUEST_ELEM);
     648        request.setAttribute(TYPE_ATT, request_type);
     649        request.setAttribute(LANG_ATT, lang);
     650        request.setAttribute(TO_ATT, to);
     651        request.setAttribute(USER_ID_ATT, uid);
     652        return request;
     653    }
     654   
     655    public static Element createBasicResponse(Document owner, String from)
    694656    {
    695         return;
     657        Element response = owner.createElement(GSXML.RESPONSE_ELEM);
     658        response.setAttribute(GSXML.FROM_ATT, from);
     659        response.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
     660        return response;
    696661    }
    697662   
    698     Set items = params.entrySet();
    699     Iterator i = items.iterator();
    700     while(i.hasNext()) {
    701       Map.Entry m = (Map.Entry)i.next();
    702       param_list.appendChild(createParameter(owner, (String)m.getKey(), (String)m.getValue()));
    703     }
    704    
    705   }
    706  
    707   public static Element createParameterDescription(Document owner,
    708     String id,
    709     String display_name,
    710     String type,
    711     String default_value,
    712     String []option_ids,
    713     String []option_names) {
    714    
    715    
    716     Element p = owner.createElement(PARAM_ELEM);
    717     p.setAttribute(NAME_ATT, id);
    718     p.setAttribute(TYPE_ATT, type);
    719     p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
    720    
    721     if (default_value != null) {
    722       p.setAttribute(DEFAULT_ATT, default_value);
    723     }
    724     if (option_ids!=null && option_names!=null) {
    725       for (int i=0; i<option_ids.length; i++) {
    726         Element e = owner.createElement(PARAM_OPTION_ELEM);
    727         e.setAttribute(NAME_ATT, option_ids[i]);
    728         e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, option_names[i]));
    729         p.appendChild(e);
    730       }
    731     }
    732     return p;
    733   }
    734   public static Element createParameterDescription2(Document owner,
    735     String id,
    736     String display_name,
    737     String type,
    738     String default_value,
    739     ArrayList option_ids,
    740     ArrayList option_names) {
    741    
    742    
    743     Element p = owner.createElement(PARAM_ELEM);
    744     p.setAttribute(NAME_ATT, id);
    745     p.setAttribute(TYPE_ATT, type);
    746     p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
    747     if (default_value != null) {
    748       p.setAttribute(DEFAULT_ATT, default_value);
    749     }
    750     if (option_ids!=null && option_names!=null) {
    751       for (int i=0; i<option_ids.size(); i++) {
    752         Element e = owner.createElement(PARAM_OPTION_ELEM);
    753         e.setAttribute(NAME_ATT, (String)option_ids.get(i));
    754         e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, (String)option_names.get(i)));
    755         p.appendChild(e);
    756       }
    757     }
    758     return p;
    759   }
    760  
    761  
    762   /** returns the element parent/node_name[@attribute_name='attribute_value']
    763    */
    764   public static Element getNamedElement(Element parent, String node_name,
    765     String attribute_name,
    766     String attribute_value) {
    767    
    768     NodeList children = parent.getChildNodes();
    769     for (int i=0; i<children.getLength(); i++) {
    770       Node child = children.item(i);
    771       if (child.getNodeName().equals(node_name)) {
    772         if (((Element)child).getAttribute(attribute_name).equals(attribute_value))
    773           return (Element)child;
    774       }
    775     }
    776     // not found
    777     return null;
    778   }
    779   /** returns a NodeList of elements: ancestor/node_name[@attribute_name='attribute_value']
    780    */
    781   public static NodeList getNamedElements(Element ancestor, String node_name, String attribute_name, String attribute_value) {
    782         MyNodeList node_list = new MyNodeList();
    783         NodeList children = ancestor.getElementsByTagName(node_name);
    784        
     663    public static Element createMetadataElement(Document owner, String name, String value)
     664    {
     665        Element metaElem = owner.createElement(GSXML.METADATA_ELEM);
     666        metaElem.setAttribute(GSXML.NAME_ATT, name);
     667        metaElem.setAttribute(GSXML.VALUE_ATT, value);
     668        return metaElem;
     669    }
     670
     671    public static Element createTextElement(Document owner, String elem_name,
     672    String text) {
     673        Element e = owner.createElement(elem_name);
     674        Text t = owner.createTextNode(text);
     675        e.appendChild(t);
     676        return e;
     677       
     678    }
     679
     680    public static Element createTextElement(Document owner, String elem_name,
     681    String text, String att_name, String att_value) {
     682        Element e = owner.createElement(elem_name);
     683        e.setAttribute(att_name, att_value);
     684        Text t = owner.createTextNode(text);
     685        e.appendChild(t);
     686        return e;
     687       
     688    }
     689   
     690    public static Element createDisplayTextElement(Document owner,
     691    String text_name,
     692    String text) {
     693        Element e = owner.createElement(DISPLAY_TEXT_ELEM);
     694        e.setAttribute(NAME_ATT, text_name);
     695        Text t = owner.createTextNode(text);
     696        e.appendChild(t);
     697        return e;
     698       
     699    }
     700
     701
     702    public static Element createParameter(Document owner, String name,
     703    String value) {
     704        Element param = owner.createElement(PARAM_ELEM);
     705        param.setAttribute(NAME_ATT, name);
     706        param.setAttribute(VALUE_ATT, value);
     707        return param;
     708    }
     709
     710    public static void addParametersToList(Document owner, Element param_list,
     711    HashMap params) {
     712        if (params == null)
     713        {
     714            return;
     715        }
     716       
     717        Set items = params.entrySet();
     718        Iterator i = items.iterator();
     719        while(i.hasNext()) {
     720            Map.Entry m = (Map.Entry)i.next();
     721            param_list.appendChild(createParameter(owner, (String)m.getKey(), (String)m.getValue()));
     722        }
     723       
     724    }
     725
     726    public static Element createParameterDescription(Document owner,
     727    String id,
     728    String display_name,
     729    String type,
     730    String default_value,
     731    String []option_ids,
     732    String []option_names) {
     733       
     734       
     735        Element p = owner.createElement(PARAM_ELEM);
     736        p.setAttribute(NAME_ATT, id);
     737        p.setAttribute(TYPE_ATT, type);
     738        p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
     739       
     740        if (default_value != null) {
     741            p.setAttribute(DEFAULT_ATT, default_value);
     742        }
     743        if (option_ids!=null && option_names!=null) {
     744            for (int i=0; i<option_ids.length; i++) {
     745                Element e = owner.createElement(PARAM_OPTION_ELEM);
     746                e.setAttribute(NAME_ATT, option_ids[i]);
     747                e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, option_names[i]));
     748                p.appendChild(e);
     749            }
     750        }
     751        return p;
     752    }
     753    public static Element createParameterDescription2(Document owner,
     754    String id,
     755    String display_name,
     756    String type,
     757    String default_value,
     758    ArrayList option_ids,
     759    ArrayList option_names) {
     760       
     761       
     762        Element p = owner.createElement(PARAM_ELEM);
     763        p.setAttribute(NAME_ATT, id);
     764        p.setAttribute(TYPE_ATT, type);
     765        p.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, display_name));
     766        if (default_value != null) {
     767            p.setAttribute(DEFAULT_ATT, default_value);
     768        }
     769        if (option_ids!=null && option_names!=null) {
     770            for (int i=0; i<option_ids.size(); i++) {
     771                Element e = owner.createElement(PARAM_OPTION_ELEM);
     772                e.setAttribute(NAME_ATT, (String)option_ids.get(i));
     773                e.appendChild(createDisplayTextElement(owner, GSXML.DISPLAY_TEXT_NAME, (String)option_names.get(i)));
     774                p.appendChild(e);
     775            }
     776        }
     777        return p;
     778    }
     779
     780
     781    /** returns the element parent/node_name[@attribute_name='attribute_value']
     782*/
     783    public static Element getNamedElement(Element parent, String node_name,
     784    String attribute_name,
     785    String attribute_value) {
     786       
     787        NodeList children = parent.getChildNodes();
     788        for (int i=0; i<children.getLength(); i++) {
     789            Node child = children.item(i);
     790            if (child.getNodeName().equals(node_name)) {
     791                if (((Element)child).getAttribute(attribute_name).equals(attribute_value))
     792                return (Element)child;
     793            }
     794        }
     795        // not found
     796        return null;
     797    }
     798    /** returns a NodeList of elements: ancestor/node_name[@attribute_name='attribute_value']
     799*/
     800    public static NodeList getNamedElements(Element ancestor, String node_name, String attribute_name, String attribute_value) {
     801        MyNodeList node_list = new MyNodeList();
     802        NodeList children = ancestor.getElementsByTagName(node_name);
     803       
    785804        if(children != null && children.getLength() > 0) {
    786805           
     
    789808                if (child.getNodeName().equals(node_name)) {
    790809                    if (((Element)child).getAttribute(attribute_name).equals(attribute_value))
    791                         node_list.addNode(child);
     810                    node_list.addNode(child);
    792811                }           
    793812            }           
    794         }
    795         return node_list;
    796   }
    797  
    798   public static int SORT_TYPE_STRING = 0;
    799   public static int SORT_TYPE_INT = 1;
    800   public static int SORT_TYPE_FLOAT = 2;
    801  
    802   // sort type:
    803   public static Element insertIntoOrderedList(Element parent_node,
    804     String node_name,
    805     Element start_from_elem,
    806     Element new_elem, String sort_att,
    807     boolean descending) {
    808     if (new_elem == null) return null;
    809     Element cloned_elem = (Element)parent_node.getOwnerDocument().importNode(new_elem, true);
    810     if (start_from_elem == null) {
    811       parent_node.appendChild(cloned_elem);
    812       return cloned_elem;
    813     }
    814    
    815     Node current_node = start_from_elem;
    816     String insert_att = cloned_elem.getAttribute(sort_att);
    817     String list_att = start_from_elem.getAttribute(sort_att);
    818     while ((!descending && list_att.compareTo(insert_att)<0) || (descending && list_att.compareTo(insert_att)>0)) {
    819       current_node = current_node.getNextSibling();
    820       if (current_node == null) break; // end of the list
    821       if (!current_node.getNodeName().equals(node_name)) {
    822         continue; // not a valid node
    823       }
    824       list_att = ((Element)current_node).getAttribute(sort_att);
    825     }
    826    
    827     parent_node.insertBefore(cloned_elem, current_node);
    828     return cloned_elem;
    829   }
    830  
    831  
    832   /** Returns the appropriate language element from a display elem,
    833    * display is the containing element, name is the name of the element to
    834    * look for, lang is the preferred language, lang_default is the fall back
    835    * lang if neither lang is found, will return the first one it finds*/
    836   public static String getDisplayText(Element display, String name,
    837     String lang, String lang_default) {
    838    
    839     String def = null;
    840     String first = null;
    841     NodeList elems = display.getElementsByTagName(DISPLAY_TEXT_ELEM);
    842     if (elems.getLength() == 0) return "";
    843     for (int i=0; i<elems.getLength(); i++) {
    844       Element e = (Element)elems.item(i);
    845       String n = e.getAttribute(NAME_ATT);
    846       if (name.equals(n)) {
    847         String l = e.getAttribute(LANG_ATT);
    848         if (lang.equals(l)) {
    849           return getNodeText(e);
    850         } else if (lang_default.equals(l)) {
    851           def = getNodeText(e);
    852         } else if (first == null) {
    853           first = getNodeText(e);
    854         }
    855       } else {
    856         continue;
    857       }
    858     }
    859    
    860     if (def != null) {
    861       return def;
    862     }
    863     if (first != null) {
    864       return first;
    865     }
    866     return "";
    867   }
    868  
    869   // replaces < > " ' & in the original with their entities
    870   public static String xmlSafe(String original) {
    871    
    872     StringBuffer filtered = new StringBuffer(original.length());
    873     char c;
    874     for (int i=0; i<original.length(); i++) {
    875       c = original.charAt(i);
    876       if (c == '>') {
    877         filtered.append("&gt;");
    878       } else if (c == '<') {
    879         filtered.append("&lt;");
    880       } else if (c == '"') {
    881         filtered.append("&quot;");
    882       } else if (c == '&') {
    883         filtered.append("&amp;");
    884       } else if (c == '\'') {
    885         filtered.append("&apos;");
    886       } else {
    887         filtered.append(c);
    888       }
    889     }
    890     return filtered.toString();
    891   }
    892  
    893  
    894   // replaces < > " ' & entities with their originals
    895   public static String unXmlSafe(String original) {
    896    
    897     StringBuffer filtered = new StringBuffer(original.length());
    898     char c;
    899     for (int i=0; i<original.length(); i++) {
    900       c = original.charAt(i);
    901       if (c == '&') {
    902         int pos = original.indexOf(";", i);
    903         String entity = original.substring(i+1, pos);
    904         if (entity.equals("gt")) {
    905           filtered.append(">");
    906         } else if (entity.equals("lt")) {
    907           filtered.append("<");
    908         } else if (entity.equals("apos")) {
    909           filtered.append("'");
    910         } else if (entity.equals("amp")) {
    911           filtered.append("&");
    912         } else if (entity.equals("quot")) {
    913           filtered.append("\"");
    914         } else {
    915           filtered.append("&"+entity+";");
    916         }
    917         i = pos;
    918       } else {
    919         filtered.append(c);
    920       }
    921     }
    922     return filtered.toString();
    923   }
    924  
    925   public static void printXMLNode(Node e, boolean printText) {
    926     printXMLNode(e, 0, printText) ;
    927   }
    928  
    929   public static String xmlNodeToString(Node e){
    930     StringBuffer sb = new StringBuffer("");
    931     xmlNodeToString(sb,e,0);
    932     return sb.toString();
    933   }
    934  
    935   private static void xmlNodeToString(StringBuffer sb, Node e, int depth){
    936    
    937     for (int i=0 ; i<depth ; i++)
    938       sb.append(' ') ;
    939    
    940     if (e.getNodeType() == Node.TEXT_NODE){
    941       sb.append("text") ;
    942       return ;
    943     }
    944    
    945     sb.append('<');
    946     sb.append(e.getNodeName());
    947     NamedNodeMap attrs = e.getAttributes();
    948     if(attrs != null)
    949     {
    950         for (int i = 0; i < attrs.getLength(); i++) {
    951             Node attr = attrs.item(i);
    952             sb.append(' ');
    953             sb.append(attr.getNodeName());
    954             sb.append("=\"");
    955             sb.append(attr.getNodeValue());
    956             sb.append('"');
    957         }
    958     }
    959    
    960     NodeList children = e.getChildNodes();
    961    
    962     if (children == null || children.getLength() == 0)
    963       sb.append("/>\n") ;
    964     else {
    965      
    966       sb.append(">\n") ;
    967      
    968       int len = children.getLength();
    969       for (int i = 0; i < len; i++) {
    970         xmlNodeToString(sb,children.item(i), depth + 1);
    971       }
    972      
    973       for (int i=0 ; i<depth ; i++)
    974         sb.append(' ') ;
    975      
    976       sb.append("</" + e.getNodeName() + ">\n");
    977     }
    978    
    979    
    980   }
    981  
    982   public static void printXMLNode(Node e, int depth, boolean printText) { //recursive method call using DOM API...
    983    
    984     if(e == null){return;}
    985    
    986     for (int i=0 ; i<depth ; i++)
    987       System.out.print(' ') ;
    988    
    989     if (e.getNodeType() == Node.TEXT_NODE){
    990       if(printText){
    991         System.out.println(e.getNodeValue());
    992       }
    993       else {
    994         System.out.println("text");
    995       }
    996       return ;
    997     }
    998    
    999     System.out.print('<');
    1000     System.out.print(e.getNodeName());
    1001     NamedNodeMap attrs = e.getAttributes();
    1002    
    1003     if (attrs != null)
    1004     {
    1005         for (int i = 0; i < attrs.getLength(); i++) {
    1006             Node attr = attrs.item(i);
    1007             System.out.print(' ');
    1008             System.out.print(attr.getNodeName());
    1009             System.out.print("=\"");
    1010             System.out.print(attr.getNodeValue());
    1011             System.out.print('"');
    1012         }
    1013     }
    1014    
    1015     NodeList children = e.getChildNodes();
    1016    
    1017     if (children == null || children.getLength() == 0)
    1018       System.out.println("/>") ;
    1019     else {
    1020      
    1021       System.out.println('>') ;
    1022      
    1023       int len = children.getLength();
    1024       for (int i = 0; i < len; i++) {
    1025         printXMLNode(children.item(i), depth + 1, printText);
    1026       }
    1027      
    1028       for (int i=0 ; i<depth ; i++)
    1029         System.out.print(' ') ;
    1030      
    1031       System.out.println("</" + e.getNodeName() + ">");
    1032     }
    1033    
    1034   }
    1035 
    1036   public static void elementToLogAsString(Element e) {
    1037     try {
    1038       TransformerFactory tf = TransformerFactory.newInstance();
    1039       Transformer trans = tf.newTransformer();
    1040       StringWriter sw = new StringWriter();
    1041       trans.transform(new DOMSource(e), new StreamResult(sw));
    1042       System.err.println( sw.toString() ); // logger.info( sw.toString() );
    1043     } catch( Exception ex ) {
    1044       System.err.println( "couldn't write " + e + " to log" );
    1045     }
    1046 
    1047   }
     813        }
     814        return node_list;
     815    }
     816
     817    public static int SORT_TYPE_STRING = 0;
     818    public static int SORT_TYPE_INT = 1;
     819    public static int SORT_TYPE_FLOAT = 2;
     820
     821    // sort type:
     822    public static Element insertIntoOrderedList(Element parent_node,
     823    String node_name,
     824    Element start_from_elem,
     825    Element new_elem, String sort_att,
     826    boolean descending) {
     827        if (new_elem == null) return null;
     828        Element cloned_elem = (Element)parent_node.getOwnerDocument().importNode(new_elem, true);
     829        if (start_from_elem == null) {
     830            parent_node.appendChild(cloned_elem);
     831            return cloned_elem;
     832        }
     833       
     834        Node current_node = start_from_elem;
     835        String insert_att = cloned_elem.getAttribute(sort_att);
     836        String list_att = start_from_elem.getAttribute(sort_att);
     837        while ((!descending && list_att.compareTo(insert_att)<0) || (descending && list_att.compareTo(insert_att)>0)) {
     838            current_node = current_node.getNextSibling();
     839            if (current_node == null) break; // end of the list
     840            if (!current_node.getNodeName().equals(node_name)) {
     841                continue; // not a valid node
     842            }
     843            list_att = ((Element)current_node).getAttribute(sort_att);
     844        }
     845       
     846        parent_node.insertBefore(cloned_elem, current_node);
     847        return cloned_elem;
     848    }
     849
     850
     851    /** Returns the appropriate language element from a display elem,
     852* display is the containing element, name is the name of the element to
     853* look for, lang is the preferred language, lang_default is the fall back
     854* lang if neither lang is found, will return the first one it finds*/
     855    public static String getDisplayText(Element display, String name,
     856    String lang, String lang_default) {
     857       
     858        String def = null;
     859        String first = null;
     860        NodeList elems = display.getElementsByTagName(DISPLAY_TEXT_ELEM);
     861        if (elems.getLength() == 0) return "";
     862        for (int i=0; i<elems.getLength(); i++) {
     863            Element e = (Element)elems.item(i);
     864            String n = e.getAttribute(NAME_ATT);
     865            if (name.equals(n)) {
     866                String l = e.getAttribute(LANG_ATT);
     867                if (lang.equals(l)) {
     868                    return getNodeText(e);
     869                } else if (lang_default.equals(l)) {
     870                    def = getNodeText(e);
     871                } else if (first == null) {
     872                    first = getNodeText(e);
     873                }
     874            } else {
     875                continue;
     876            }
     877        }
     878       
     879        if (def != null) {
     880            return def;
     881        }
     882        if (first != null) {
     883            return first;
     884        }
     885        return "";
     886    }
     887
     888    // replaces < > " ' & in the original with their entities
     889    public static String xmlSafe(String original) {
     890       
     891        StringBuffer filtered = new StringBuffer(original.length());
     892        char c;
     893        for (int i=0; i<original.length(); i++) {
     894            c = original.charAt(i);
     895            if (c == '>') {
     896                filtered.append("&gt;");
     897            } else if (c == '<') {
     898                filtered.append("&lt;");
     899            } else if (c == '"') {
     900                filtered.append("&quot;");
     901            } else if (c == '&') {
     902                filtered.append("&amp;");
     903            } else if (c == '\'') {
     904                filtered.append("&apos;");
     905            } else {
     906                filtered.append(c);
     907            }
     908        }
     909        return filtered.toString();
     910    }
     911
     912
     913    // replaces < > " ' & entities with their originals
     914    public static String unXmlSafe(String original) {
     915       
     916        StringBuffer filtered = new StringBuffer(original.length());
     917        char c;
     918        for (int i=0; i<original.length(); i++) {
     919            c = original.charAt(i);
     920            if (c == '&') {
     921                int pos = original.indexOf(";", i);
     922                String entity = original.substring(i+1, pos);
     923                if (entity.equals("gt")) {
     924                    filtered.append(">");
     925                } else if (entity.equals("lt")) {
     926                    filtered.append("<");
     927                } else if (entity.equals("apos")) {
     928                    filtered.append("'");
     929                } else if (entity.equals("amp")) {
     930                    filtered.append("&");
     931                } else if (entity.equals("quot")) {
     932                    filtered.append("\"");
     933                } else {
     934                    filtered.append("&"+entity+";");
     935                }
     936                i = pos;
     937            } else {
     938                filtered.append(c);
     939            }
     940        }
     941        return filtered.toString();
     942    }
     943
     944    public static void printXMLNode(Node e, boolean printText) {
     945        printXMLNode(e, 0, printText) ;
     946    }
     947
     948    public static String xmlNodeToString(Node e){
     949        StringBuffer sb = new StringBuffer("");
     950        xmlNodeToString(sb,e,0);
     951        return sb.toString();
     952    }
     953
     954    private static void xmlNodeToString(StringBuffer sb, Node e, int depth){
     955       
     956        for (int i=0 ; i<depth ; i++)
     957        sb.append(' ') ;
     958       
     959        if (e.getNodeType() == Node.TEXT_NODE){
     960            sb.append("text") ;
     961            return ;
     962        }
     963       
     964        sb.append('<');
     965        sb.append(e.getNodeName());
     966        NamedNodeMap attrs = e.getAttributes();
     967        if(attrs != null)
     968        {
     969            for (int i = 0; i < attrs.getLength(); i++) {
     970                Node attr = attrs.item(i);
     971                sb.append(' ');
     972                sb.append(attr.getNodeName());
     973                sb.append("=\"");
     974                sb.append(attr.getNodeValue());
     975                sb.append('"');
     976            }
     977        }
     978       
     979        NodeList children = e.getChildNodes();
     980       
     981        if (children == null || children.getLength() == 0)
     982        sb.append("/>\n") ;
     983        else {
     984           
     985            sb.append(">\n") ;
     986           
     987            int len = children.getLength();
     988            for (int i = 0; i < len; i++) {
     989                xmlNodeToString(sb,children.item(i), depth + 1);
     990            }
     991           
     992            for (int i=0 ; i<depth ; i++)
     993            sb.append(' ') ;
     994           
     995            sb.append("</" + e.getNodeName() + ">\n");
     996        }
     997       
     998       
     999    }
     1000
     1001    public static void printXMLNode(Node e, int depth, boolean printText) { //recursive method call using DOM API...
     1002       
     1003        if(e == null){return;}
     1004       
     1005        for (int i=0 ; i<depth ; i++)
     1006        System.out.print(' ') ;
     1007       
     1008        if (e.getNodeType() == Node.TEXT_NODE){
     1009            if(printText){
     1010                System.out.println(e.getNodeValue());
     1011            }
     1012            else {
     1013                System.out.println("text");
     1014            }
     1015            return ;
     1016        }
     1017       
     1018        System.out.print('<');
     1019        System.out.print(e.getNodeName());
     1020        NamedNodeMap attrs = e.getAttributes();
     1021       
     1022        if (attrs != null)
     1023        {
     1024            for (int i = 0; i < attrs.getLength(); i++) {
     1025                Node attr = attrs.item(i);
     1026                System.out.print(' ');
     1027                System.out.print(attr.getNodeName());
     1028                System.out.print("=\"");
     1029                System.out.print(attr.getNodeValue());
     1030                System.out.print('"');
     1031            }
     1032        }
     1033       
     1034        NodeList children = e.getChildNodes();
     1035       
     1036        if (children == null || children.getLength() == 0)
     1037        System.out.println("/>") ;
     1038        else {
     1039           
     1040            System.out.println('>') ;
     1041           
     1042            int len = children.getLength();
     1043            for (int i = 0; i < len; i++) {
     1044                printXMLNode(children.item(i), depth + 1, printText);
     1045            }
     1046           
     1047            for (int i=0 ; i<depth ; i++)
     1048            System.out.print(' ') ;
     1049           
     1050            System.out.println("</" + e.getNodeName() + ">");
     1051        }   
     1052    }
     1053
     1054    public static void elementToLogAsString(Element e) {
     1055        try {
     1056            TransformerFactory tf = TransformerFactory.newInstance();
     1057            Transformer trans = tf.newTransformer();
     1058            StringWriter sw = new StringWriter();
     1059            trans.transform(new DOMSource(e), new StreamResult(sw));
     1060            System.err.println( sw.toString() );
     1061        } catch( Exception ex ) {
     1062            System.err.println( "couldn't write " + e + " to log" );
     1063        }
     1064    }
    10481065}
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/JDBMWrapper.java

    r22973 r24393  
    3636import jdbm.htree.HTree;
    3737
    38 public class JDBMWrapper
    39   implements FlatDatabaseWrapper {
    40  
    41   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.JDBMWrapper.class.getName());
    42 
    43     static String TNAME = "greenstone";
    44 
    45     RecordManager  recman_ = null;
    46     HTree          hashtable_;
    47 
    48     String db_filename_;
    49 
    50     static private PrintWriter utf8out = null;
    51 
    52     static
    53     {
    54         try {
    55             OutputStreamWriter osw = new OutputStreamWriter(System.out, "UTF-8");
    56             utf8out = new PrintWriter(osw, true);
    57         }
    58         catch (UnsupportedEncodingException e) {
    59             System.out.println(e);
    60         }
    61     }
    62 
    63 
    64   /** open database named filename, using mode */
    65   public boolean openDatabase(String db_filename, int mode) {
    66      
    67 
    68       if (db_filename.endsWith(".jdb")) {
    69       // remove file extension as JDBM does not expect it
    70       db_filename = db_filename.substring(0,db_filename.length()-4);
    71       }
    72 
    73       // Map the mode value into equivalent JDBM 'must_exist' value
    74       // currently this is very simple as there is only READ and WRITE
    75       // (no WRITER_CREATE)
    76       // => assume the database must exist
    77       boolean must_exist = true; // default
    78 
    79       if (recman_ != null) {
    80       String message = "openDatabase() called when the class already has a database open\n";
    81       message += "  Use closeDatabase before opening the next one.\n";
    82       message += "  Existing database file: " + db_filename_ + "\n";
    83       message += "  New database file:      " + db_filename + "\n";
    84       logger.warn(message);
    85       // consider closing it automatically?
    86       }
    87 
    88 
    89       try {
    90       // create or open a record manager
    91       Properties props = new Properties();
    92       recman_ = RecordManagerFactory.createRecordManager(db_filename, props);
    93      
    94       // load existing table (if exists) otherwise create new one
    95       long recid = recman_.getNamedObject(TNAME);
    96      
    97       if (recid != 0) {
    98           System.err.println("# Loading existing database table '" + TNAME +"' ...");
    99           hashtable_ = HTree.load(recman_, recid);
    100       }
    101       else {
    102          
    103           if (must_exist) {
    104           recman_.close();
    105           recman_ = null;
    106           db_filename_ = null;
    107 
    108           System.err.println("Database table '" + TNAME +"' does not exist.");
    109           throw new IOException();
    110           }
    111           else {
    112           System.err.println("# No database table '" + TNAME +"' to set.  Creating new one");
    113             hashtable_ = HTree.createInstance(recman_);
    114             recman_.setNamedObject(TNAME, hashtable_.getRecid());
    115         }
    116       }
    117       }
    118       catch (IOException e) {     
    119     logger.error("couldn't open database "+ db_filename);
    120     return false;
    121       }
    122 
    123       db_filename_ = db_filename;
    124 
    125       return true;
    126   }
    127 
    128 
    129   /** close the database associated with this wrapper */
    130   public void closeDatabase() {
    131       try {
    132       if (recman_ != null) {
    133           recman_.close();
    134           recman_ = null;
    135           db_filename_ = null;
    136       }
    137       }
    138       catch (IOException e) {     
    139     logger.error("Failed to close JDBM database");
    140       }
    141   }
    142 
    143   /** returns the value associated with the key */
    144   public String getValue(String key) {
    145 
    146       String val;
    147 
    148       try {
    149       val = (String) hashtable_.get(key);
    150        
    151       recman_.commit();
    152       }
    153       catch (IOException e) {     
    154     logger.error("Failed get key " + key + "from JDBM database");
    155     return null;
    156       }
    157 
    158       return val;
    159   }
    160 
    161   /** returns a string of key-value entries that can be
    162    *    printed for debugging purposes*/
    163   public String displayAllEntries() {
    164 
    165       StringBuffer keys = new StringBuffer();
    166 
    167       try {
    168       FastIterator   iter = hashtable_.keys();
    169       String         key  = (String) iter.next();
    170      
    171       String nl = System.getProperty("line.separator");
    172      
    173       while (key != null) {
    174           String val = (String) hashtable_.get(key);
    175           keys.append("[" + key + "]" + nl);
    176           keys.append(val + nl);
    177           // 70 hypens
    178           keys.append("----------------------------------------------------------------------" + nl);
    179           key = (String) iter.next();
    180       }
    181 
    182       recman_.commit();
    183       }
    184       catch (IOException e) {     
    185     logger.error("Failed get all keys and values from JDBM database");
    186     return null;
    187       }
    188        
    189       return keys.toString();
    190   }
     38public class JDBMWrapper implements FlatDatabaseWrapper
     39{
     40
     41    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.JDBMWrapper.class.getName());
     42
     43    static String TNAME = "greenstone";
     44
     45    RecordManager recman_ = null;
     46    HTree hashtable_;
     47
     48    String db_filename_;
     49
     50    static private PrintWriter utf8out = null;
     51
     52    static
     53    {
     54        try
     55        {
     56            OutputStreamWriter osw = new OutputStreamWriter(System.out, "UTF-8");
     57            utf8out = new PrintWriter(osw, true);
     58        }
     59        catch (UnsupportedEncodingException e)
     60        {
     61            System.out.println(e);
     62        }
     63    }
     64
     65    /** open database named filename, using mode */
     66    public boolean openDatabase(String db_filename, int mode)
     67    {
     68
     69        if (db_filename.endsWith(".jdb"))
     70        {
     71            // remove file extension as JDBM does not expect it
     72            db_filename = db_filename.substring(0, db_filename.length() - 4);
     73        }
     74
     75        // Map the mode value into equivalent JDBM 'must_exist' value
     76        // currently this is very simple as there is only READ and WRITE
     77        // (no WRITER_CREATE)
     78        // => assume the database must exist
     79        boolean must_exist = true; // default
     80
     81        if (recman_ != null)
     82        {
     83            String message = "openDatabase() called when the class already has a database open\n";
     84            message += "  Use closeDatabase before opening the next one.\n";
     85            message += "  Existing database file: " + db_filename_ + "\n";
     86            message += "  New database file:      " + db_filename + "\n";
     87            logger.warn(message);
     88            // consider closing it automatically?
     89        }
     90
     91        try
     92        {
     93            // create or open a record manager
     94            Properties props = new Properties();
     95            recman_ = RecordManagerFactory.createRecordManager(db_filename, props);
     96
     97            // load existing table (if exists) otherwise create new one
     98            long recid = recman_.getNamedObject(TNAME);
     99
     100            if (recid != 0)
     101            {
     102                System.err.println("# Loading existing database table '" + TNAME + "' ...");
     103                hashtable_ = HTree.load(recman_, recid);
     104            }
     105            else
     106            {
     107
     108                if (must_exist)
     109                {
     110                    recman_.close();
     111                    recman_ = null;
     112                    db_filename_ = null;
     113
     114                    System.err.println("Database table '" + TNAME + "' does not exist.");
     115                    throw new IOException();
     116                }
     117                else
     118                {
     119                    System.err.println("# No database table '" + TNAME + "' to set.  Creating new one");
     120                    hashtable_ = HTree.createInstance(recman_);
     121                    recman_.setNamedObject(TNAME, hashtable_.getRecid());
     122                }
     123            }
     124        }
     125        catch (IOException e)
     126        {
     127            logger.error("couldn't open database " + db_filename);
     128            return false;
     129        }
     130
     131        db_filename_ = db_filename;
     132
     133        return true;
     134    }
     135
     136    /** close the database associated with this wrapper */
     137    public void closeDatabase()
     138    {
     139        try
     140        {
     141            if (recman_ != null)
     142            {
     143                recman_.close();
     144                recman_ = null;
     145                db_filename_ = null;
     146            }
     147        }
     148        catch (IOException e)
     149        {
     150            logger.error("Failed to close JDBM database");
     151        }
     152    }
     153
     154    /** returns the value associated with the key */
     155    public String getValue(String key)
     156    {
     157
     158        String val;
     159
     160        try
     161        {
     162            val = (String) hashtable_.get(key);
     163           
     164            recman_.commit();
     165        }
     166        catch (IOException e)
     167        {
     168            logger.error("Failed get key " + key + "from JDBM database");
     169            return null;
     170        }
     171       
     172        return val;
     173    }
     174   
     175    /**
     176     * Sets the given key to the given value in the database
     177     */
     178    public boolean setValue(String key, String value)
     179    {
     180        try
     181        {
     182            hashtable_.put(key, value);
     183            recman_.commit();
     184        }
     185        catch (Exception ex)
     186        {
     187            logger.error("Failed to set " + key + " = " + value + " in the JDBM database");
     188            return false;
     189        }
     190        return true;
     191    }
     192
     193    /**
     194     * Deletes the given key (and corresponding value) from the database
     195     */
     196    public boolean deleteKey(String key)
     197    {
     198        try
     199        {
     200            hashtable_.remove(key);
     201            recman_.commit();
     202        }
     203        catch (Exception ex)
     204        {
     205            logger.error("Failed to delete key " + key + " in the JDBM database");
     206            return false;
     207        }
     208        return true;
     209    }
     210
     211    /**
     212     * returns a string of key-value entries that can be printed for debugging
     213     * purposes
     214     */
     215    public String displayAllEntries()
     216    {
     217
     218        StringBuffer keys = new StringBuffer();
     219
     220        try
     221        {
     222            FastIterator iter = hashtable_.keys();
     223            String key = (String) iter.next();
     224
     225            String nl = System.getProperty("line.separator");
     226
     227            while (key != null)
     228            {
     229                String val = (String) hashtable_.get(key);
     230                keys.append("[" + key + "]" + nl);
     231                keys.append(val + nl);
     232                // 70 hypens
     233                keys.append("----------------------------------------------------------------------" + nl);
     234                key = (String) iter.next();
     235            }
     236
     237            recman_.commit();
     238        }
     239        catch (IOException e)
     240        {
     241            logger.error("Failed get all keys and values from JDBM database");
     242            return null;
     243        }
     244
     245        return keys.toString();
     246    }
    191247}
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/SimpleCollectionDatabase.java

    r23791 r24393  
    1919package org.greenstone.gsdl3.util;
    2020
     21import java.util.Iterator;
     22import java.util.Set;
     23import java.util.Vector;
     24
    2125import org.apache.log4j.*;
    2226
    2327import org.apache.commons.lang3.StringUtils;
    2428
    25 public class SimpleCollectionDatabase implements OID.OIDTranslatable {
    26  
    27   static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.SimpleCollectionDatabase.class.getName());
    28 
    29   /* just read access, many readers can share a database */
    30   public final static int READ = FlatDatabaseWrapper.READ;
    31   /* read/write, exclusive access */
    32   public final static int WRITE = FlatDatabaseWrapper.WRITE;
    33  
    34   protected FlatDatabaseWrapper coll_db = null;
    35  
    36   public SimpleCollectionDatabase(String db_type) {
    37 
    38       // Access databaseWrapper through reflection (forName) so code
    39       // can be more dynamic as to the database backends that are
    40       // supported for this installation of Greenstone
    41 
    42       String dbwrap_name = db_type.toUpperCase() + "Wrapper";
    43       Class dbwrap_class = null;
    44 
    45       try {
    46       String full_dbwrap_name = "org.greenstone.gsdl3.util."+dbwrap_name;
    47       dbwrap_class = Class.forName(full_dbwrap_name);
    48       }
    49       catch(ClassNotFoundException e) {
    50       try {
    51           //try the dbwrap_name alone in case the package name is
    52           //already specified
    53           dbwrap_class = Class.forName(dbwrap_name);
    54       }
    55       catch(ClassNotFoundException ae) {
    56           logger.error("Couldn't create SimpleCollectionDatabase of type "+db_type);
    57           logger.info(ae.getMessage());
    58       }
    59       }
    60 
    61       try {
    62       this.coll_db = (FlatDatabaseWrapper)dbwrap_class.newInstance();
    63       }
    64       catch(Exception e) {
    65           logger.error("Failed to call the constructor "+dbwrap_name+"()");
    66       }
    67 
    68 
    69   }
    70  
    71   public boolean databaseOK() {
    72       // Previously failed to open database
    73       // Most likely cause is that this installation of Greenstone3 has not
    74       // been compiled with support for this database type
    75       return coll_db != null;
    76   }
    77 
    78   /** open the database filename, with mode mode - uses the FlatDatabaseWrapper modes */
    79   public boolean openDatabase(String filename, int mode){
    80     return this.coll_db.openDatabase(filename, mode);
    81   }
    82  
    83   /** close the database */
    84   public void closeDatabase() {
    85     this.coll_db.closeDatabase();
    86   }
    87  
    88   /** Returns a DBInfo structure of the key-value pairs associated with a
    89     particular main key in the database */
    90   public DBInfo getInfo(String main_key) {
    91       //   logger.warn("All the entries of the db are:");
    92       //   this.coll_db.displayAllEntries();
    93 
    94      
    95     if (this.coll_db==null) {
    96     // Most likely cause is that this installation of Greenstone3 has not
    97     // been compiled with support for this database type
    98     return null;
    99     }
    100 
    101     String key_info = this.coll_db.getValue(main_key);
    102     if (key_info == null || key_info.equals("")) {
    103       return null;
    104     }
    105    
    106     DBInfo info = new DBInfo();
    107    
    108     String [] lines = StringUtils.split(key_info, "\n");
    109     String key;
    110     String value;
    111     for (int i=0; i<lines.length; i++) {
    112       logger.debug("line:"+lines[i]);
    113       int a = lines[i].indexOf('<');
    114       int b= lines[i].indexOf('>');
    115       if (a==-1 || b==-1) {
    116     logger.error("bad format in db");
    117       }
    118       else {
    119     key=lines[i].substring(a+1, b);
    120     value=lines[i].substring(b+1);
    121     logger.debug("key="+key+", val="+value);
    122     info.addInfo(key, value);
    123 
    124       }
    125     }
    126     return info;
    127    
    128   }
    129  
    130   /** converts a greenstone OID to internal docnum */
    131   public String OID2Docnum(String OID) {
    132     DBInfo info = getInfo(OID);
    133     if (info != null) {
    134       return info.getInfo("docnum");
    135     }
    136     return null;
    137   }
    138    
    139   /** converts a greenstone OID to an internal docnum, returning a Long
    140    - convenience method*/
    141   public long OID2DocnumLong(String OID) {
    142     DBInfo info = getInfo(OID);
    143     if (info != null) {
    144       long real_num = Long.parseLong(info.getInfo("docnum"));
    145       return real_num;
    146     }
    147     return -1;
    148   }
    149 
    150 
    151   /** converts a docnum to greenstone OID */
    152   public String docnum2OID(String docnum) {
    153     DBInfo info = getInfo(docnum);
    154     if (info!=null){
    155       String oid = info.getInfo("section");
    156       return oid;
    157     } else{
    158       return null;
    159     }
    160   }
    161 
    162   /** converts a docnum to greenstone OID
    163       - convenience method */
    164   public String docnum2OID(long docnum) {
    165     return docnum2OID(Long.toString(docnum));
    166   }
    167 
    168   /** converts an external id to greenstone OID */
    169   public String externalId2OID(String extid) {
    170     DBInfo info = getInfo(extid);
    171     if (info != null) {
    172       String oid = info.getInfo("section");
    173       return oid;
    174     }
    175     return null;
    176   }
    177 
    178   /** After OID.translateOID() is through, this method processes OID further
    179    * to translate relative oids into proper oids:
    180    * .pr (parent), .rt (root) .fc (first child), .lc (last child),
    181    * .ns (next sibling), .ps (previous sibling)
    182    * .np (next page), .pp (previous page) : links sections in the order that you'd read the document
    183    * a suffix is expected to be present so test before using
    184    */
    185     public String processOID(String doc_id, String top, String suff, int sibling_num) {
    186     DBInfo info = getInfo(doc_id);
    187     if (info==null) {
    188       logger.info("info is null!!");
    189       return top;
    190     }
     29public class SimpleCollectionDatabase implements OID.OIDTranslatable
     30{
     31
     32    static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.SimpleCollectionDatabase.class.getName());
     33
     34    /* just read access, many readers can share a database */
     35    public final static int READ = FlatDatabaseWrapper.READ;
     36    /* read/write, exclusive access */
     37    public final static int WRITE = FlatDatabaseWrapper.WRITE;
     38
     39    protected FlatDatabaseWrapper coll_db = null;
     40
     41    public SimpleCollectionDatabase(String db_type)
     42    {
     43
     44        // Access databaseWrapper through reflection (forName) so code
     45        // can be more dynamic as to the database backends that are
     46        // supported for this installation of Greenstone
     47
     48        String dbwrap_name = db_type.toUpperCase() + "Wrapper";
     49        Class dbwrap_class = null;
     50
     51        try
     52        {
     53            String full_dbwrap_name = "org.greenstone.gsdl3.util." + dbwrap_name;
     54            dbwrap_class = Class.forName(full_dbwrap_name);
     55        }
     56        catch (ClassNotFoundException e)
     57        {
     58            try
     59            {
     60                //try the dbwrap_name alone in case the package name is
     61                //already specified
     62                dbwrap_class = Class.forName(dbwrap_name);
     63            }
     64            catch (ClassNotFoundException ae)
     65            {
     66                logger.error("Couldn't create SimpleCollectionDatabase of type " + db_type);
     67                logger.info(ae.getMessage());
     68            }
     69        }
     70
     71        try
     72        {
     73            this.coll_db = (FlatDatabaseWrapper) dbwrap_class.newInstance();
     74        }
     75        catch (Exception e)
     76        {
     77            logger.error("Failed to call the constructor " + dbwrap_name + "()");
     78        }
     79
     80    }
     81
     82    public boolean databaseOK()
     83    {
     84        // Previously failed to open database
     85        // Most likely cause is that this installation of Greenstone3 has not
     86        // been compiled with support for this database type
     87        return coll_db != null;
     88    }
     89
     90    /**
     91     * open the database filename, with mode mode - uses the FlatDatabaseWrapper
     92     * modes
     93     */
     94    public boolean openDatabase(String filename, int mode)
     95    {
     96        return this.coll_db.openDatabase(filename, mode);
     97    }
     98
     99    /** close the database */
     100    public void closeDatabase()
     101    {
     102        this.coll_db.closeDatabase();
     103    }
     104
     105    /**
     106     * Returns a DBInfo structure of the key-value pairs associated with a
     107     * particular main key in the database
     108     */
     109    public DBInfo getInfo(String main_key)
     110    {
     111        //   logger.warn("All the entries of the db are:");
     112        //   this.coll_db.displayAllEntries();
     113
     114        if (this.coll_db == null)
     115        {
     116            // Most likely cause is that this installation of Greenstone3 has not
     117            // been compiled with support for this database type
     118            return null;
     119        }
     120
     121        String key_info = this.coll_db.getValue(main_key);
     122        if (key_info == null || key_info.equals(""))
     123        {
     124            return null;
     125        }
     126       
     127        DBInfo info = new DBInfo();
     128
     129        String[] lines = StringUtils.split(key_info, "\n");
     130        String key;
     131        String value;
     132        for (int i = 0; i < lines.length; i++)
     133        {
     134            logger.debug("line:" + lines[i]);
     135            int a = lines[i].indexOf('<');
     136            int b = lines[i].indexOf('>');
     137            if (a == -1 || b == -1)
     138            {
     139                logger.error("bad format in db");
     140            }
     141            else
     142            {
     143                key = lines[i].substring(a + 1, b);
     144                value = lines[i].substring(b + 1);
     145                logger.debug("key=" + key + ", val=" + value);
     146                info.addInfo(key, value);
     147            }
     148        }
     149       
     150        return info;
     151    }
    191152   
    192     String contains = info.getInfo("contains");
    193     if (contains.equals("")) {
    194       // something is wrong
    195       return top;
    196     }
    197     contains = StringUtils.replace(contains, "\"", doc_id);
    198     String [] children = StringUtils.split(contains, ";");
    199     if (suff.equals("fc")) {
    200       return children[0];
    201     } else if (suff.equals("lc")) {
    202       return children[children.length-1];
    203     } else {
    204       if (suff.equals("ss")) {
    205     return children[sibling_num-1];
    206       }
    207       // find the position that we are at.
    208       int i=0;
    209       while (i<children.length) {
    210     if (children[i].equals(top)) {
    211       break;
    212     }
    213     i++;
    214       }
    215        
    216       if (suff.equals("ns")) {
    217     if (i==children.length-1) {
    218       return children[i];
    219     }
    220     return children[i+1];
    221       } else if (suff.equals("ps")) {
    222     if (i==0) {
    223       return children[i];
    224     }
    225     return children[i-1];
    226       }
    227     }
     153    public boolean setInfo(String mainKey, DBInfo info)
     154    {
     155        StringBuilder valueToAdd = new StringBuilder();
     156        Iterator i = info.getKeys().iterator();
     157        while (i.hasNext())
     158        {
     159            String currentKey = (String)i.next();
     160            Vector currentValues = (Vector)info.getMultiInfo(currentKey);
     161           
     162            if(currentValues.size() == 0)
     163            {
     164                valueToAdd.append("<" + currentKey + ">\n");
     165                continue;
     166            }
     167           
     168            for(int j = 0; j < currentValues.size(); j++)
     169            {
     170                valueToAdd.append("<" + currentKey + ">" + currentValues.get(j) + "\n");
     171            }
     172        }
     173       
     174        //Remove the final \n
     175        if (valueToAdd.length() > 0)
     176        {
     177            valueToAdd.delete(valueToAdd.length() - 1, valueToAdd.length());
     178        }
     179       
     180        return this.coll_db.setValue(mainKey, valueToAdd.toString());
     181    }
    228182   
    229     return top;
    230     } 
     183    public String getValue(String key)
     184    {
     185        return this.coll_db.getValue(key);
     186    }
     187   
     188    public boolean setValue(String key, String value)
     189    {
     190        return this.coll_db.setValue(key, value);
     191    }
     192   
     193    public boolean deleteKey(String key)
     194    {
     195        return this.coll_db.deleteKey(key);
     196    }
     197
     198    /** converts a greenstone OID to internal docnum */
     199    public String OID2Docnum(String OID)
     200    {
     201        DBInfo info = getInfo(OID);
     202        if (info != null)
     203        {
     204            return info.getInfo("docnum");
     205        }
     206        return null;
     207    }
     208
     209    /**
     210     * converts a greenstone OID to an internal docnum, returning a Long -
     211     * convenience method
     212     */
     213    public long OID2DocnumLong(String OID)
     214    {
     215        DBInfo info = getInfo(OID);
     216        if (info != null)
     217        {
     218            long real_num = Long.parseLong(info.getInfo("docnum"));
     219            return real_num;
     220        }
     221        return -1;
     222    }
     223
     224    /** converts a docnum to greenstone OID */
     225    public String docnum2OID(String docnum)
     226    {
     227        DBInfo info = getInfo(docnum);
     228        if (info != null)
     229        {
     230            String oid = info.getInfo("section");
     231            return oid;
     232        }
     233        else
     234        {
     235            return null;
     236        }
     237    }
     238
     239    /**
     240     * converts a docnum to greenstone OID - convenience method
     241     */
     242    public String docnum2OID(long docnum)
     243    {
     244        return docnum2OID(Long.toString(docnum));
     245    }
     246
     247    /** converts an external id to greenstone OID */
     248    public String externalId2OID(String extid)
     249    {
     250        DBInfo info = getInfo(extid);
     251        if (info != null)
     252        {
     253            String oid = info.getInfo("section");
     254            return oid;
     255        }
     256        return null;
     257    }
     258
     259    /**
     260     * After OID.translateOID() is through, this method processes OID further to
     261     * translate relative oids into proper oids: .pr (parent), .rt (root) .fc
     262     * (first child), .lc (last child), .ns (next sibling), .ps (previous
     263     * sibling) .np (next page), .pp (previous page) : links sections in the
     264     * order that you'd read the document a suffix is expected to be present so
     265     * test before using
     266     */
     267    public String processOID(String doc_id, String top, String suff, int sibling_num)
     268    {
     269        DBInfo info = getInfo(doc_id);
     270        if (info == null)
     271        {
     272            logger.info("info is null!!");
     273            return top;
     274        }
     275
     276        String contains = info.getInfo("contains");
     277        if (contains.equals(""))
     278        {
     279            // something is wrong
     280            return top;
     281        }
     282        contains = StringUtils.replace(contains, "\"", doc_id);
     283        String[] children = StringUtils.split(contains, ";");
     284        if (suff.equals("fc"))
     285        {
     286            return children[0];
     287        }
     288        else if (suff.equals("lc"))
     289        {
     290            return children[children.length - 1];
     291        }
     292        else
     293        {
     294            if (suff.equals("ss"))
     295            {
     296                return children[sibling_num - 1];
     297            }
     298            // find the position that we are at.
     299            int i = 0;
     300            while (i < children.length)
     301            {
     302                if (children[i].equals(top))
     303                {
     304                    break;
     305                }
     306                i++;
     307            }
     308
     309            if (suff.equals("ns"))
     310            {
     311                if (i == children.length - 1)
     312                {
     313                    return children[i];
     314                }
     315                return children[i + 1];
     316            }
     317            else if (suff.equals("ps"))
     318            {
     319                if (i == 0)
     320                {
     321                    return children[i];
     322                }
     323                return children[i - 1];
     324            }
     325        }
     326
     327        return top;
     328    }
    231329}
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java

    r24361 r24393  
    177177            // Use the TransformerFactory to process the stylesheet Source and generate a Transformer.
    178178            Transformer transformer = this.t_factory.newTransformer(new DOMSource(stylesheet));
    179             logger.debug("XMLTransformer transformer is " + transformer);
     179            logger.error("XMLTransformer transformer is " + transformer);
    180180            transformer.setErrorListener(new TransformErrorListener());
    181181            if (parameters != null) {
  • main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/XSLTUtil.java

    r24219 r24393  
    138138    }
    139139    public static String getInterfaceText(String interface_name, String lang, String key, String args_str) {
     140   
     141    key = key.replaceAll("__INTERFACE_NAME__", interface_name);
     142       
    140143    String [] args = null;
    141144    if (args_str!=null && !args_str.equals("")) {
Note: See TracChangeset for help on using the changeset viewer.