package org.greenstone.gsdl3.gs3build; import java.util.Date; import java.util.Calendar; import java.util.List; import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import java.util.Iterator; import java.util.GregorianCalendar; import java.io.File; import java.io.IOException; import java.net.URL; import javax.xml.parsers.*; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.greenstone.gsdl3.gs3build.collection.*; import org.greenstone.gsdl3.gs3build.classifier.*; import org.greenstone.gsdl3.gs3build.indexers.*; import org.greenstone.gsdl3.gs3build.util.GS3SQLConnection; import org.greenstone.gsdl3.gs3build.util.GS3SQLConnectionFactory; import org.greenstone.gsdl3.gs3build.util.DOMUtils; /** * Store and hold collection-level configuration information for a collection. * This should be used by BuildManager to work out which classes, etc. to load * at build time, and as a repository for the collection-level metadata, and * a means of loading and saving the same to a file or database, as is seen * fit in the final development of gs3. */ public class CollectionManager { GregorianCalendar lastBuildDate; // pretty obvious String adminEmail; // the email address of the administrator of the // collection int buildDocNo; // used to generate document identifiers CollectionMetadata metadata; // collection-level metadata GS3SQLConnection database; // the database to store everything in String collectionHome; String collectionName; class CollectionClassifier { File file; String type; List fields; String sort; public CollectionClassifier(String type, Node node) { this.type = type; this.fields = new ArrayList(); NodeList children = node.getChildNodes(); for (int c = 0; c < children.getLength(); c ++) { Node child = children.item(c); if (child.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { String name = child.getNodeName(); if (name.equals("file")) { NamedNodeMap atts = children.item(c).getAttributes(); Node attribute = atts.getNamedItem("URL"); String urlString = attribute.getNodeValue(); if (urlString == null) continue; this.file = new File(urlString); } else if (name.equals("field")) { String fieldName = DOMUtils.getNodeChildText(children.item(c)); this.fields.add(fieldName.toString()); } else if (name.equals("sort")) { String sortName = DOMUtils.getNodeChildText(children.item(c)); this.sort = sortName; } } } } public ClassifierInterface getClassifier() { if (this.type == null) { return null; } if (this.type.toLowerCase().equals("hierarchy")) { return new HierarchyClassifier(this.file, this.fields, this.sort); } else if (this.type.toLowerCase().equals("azlist")) { return new AZListClassifier(this.fields); } return null; } } /** * Create the collection manager for a given collection * * @param String the name of the collection */ public CollectionManager(String collection) { String collectRoot = System.getProperty("GSDL3HOME"); this.database = GS3SQLConnectionFactory.createConnection(collection); /* if (this.database != null) { this.database.clearCollection(collection); this.database = null; } */ if (this.database == null) { this.database = GS3SQLConnectionFactory.createConnection("test"); this.database.initCollection(collection); } this.metadata = new CollectionMetadata(); if (collectRoot == null) { System.out.println("Unable to locate GSDL3HOME"); // System.exit(1); return; } if (collectRoot.endsWith(System.getProperty("file.separator"))) { this.collectionHome = collectRoot + "web/sites/localsite/collect" + System.getProperty("file.separator") + collection; } else { this.collectionHome = collectRoot + System.getProperty("file.separator") + "web/sites/localsite/collect" + System.getProperty("file.separator") + collection; } this.collectionName = collection; File buildDirectory = new File(this.collectionHome, "building"); if (!buildDirectory.exists()) { buildDirectory.mkdir(); } File archiveDirectory = new File(this.collectionHome, "archives"); if (!archiveDirectory.exists()) { archiveDirectory.mkdir(); } this.buildDocNo = 1; } private void configureBrowsers(BuildManager buildManager, Node node) { CollectionClassifier classifier = null; NodeList children = node.getChildNodes(); for (int c = 0; c < children.getLength(); c ++) { // assume that non-element children are irrelevant if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) { continue; } String name = children.item(c).getNodeName(); System.out.println(name); if (name.equals("classifier")) { NamedNodeMap atts = children.item(c).getAttributes(); Node attribute = atts.getNamedItem("type"); if (attribute == null) { continue; } String type = attribute.getNodeValue(); classifier = new CollectionClassifier(type, children.item(c)); System.out.println("Found classifier " + type); // attach the classifier ClassifierInterface classify = classifier.getClassifier(); buildManager.getClassifierManager().addClassifier(classify); } } } public void configureCollection(BuildManager buildManager) { File collectionConfig = new File(collectionHome, "/etc/collectionConfig.xml"); // get the File and read it in try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(collectionConfig); // TODO: report an error if (document == null) { } // now parse the manager file... Element rootElement = document.getDocumentElement(); if (rootElement.getTagName() != "collectionConfig") { // TODO: throw exception } System.out.println("Configuring collection"); NodeList children = rootElement.getChildNodes(); for (int c = 0; c < children.getLength(); c ++) { // assume that non-element children are irrelevant if (children.item(c).getNodeType() != org.w3c.dom.Node.ELEMENT_NODE) { continue; } String name = children.item(c).getNodeName(); // the name is a plugin element if (name.equals("search")) { // pick up attributes from the tag now... NamedNodeMap searchAttributes = children.item(c).getAttributes(); Node searchAttribute = searchAttributes.getNamedItem("type"); String searchType = searchAttribute.getNodeValue(); searchAttribute = searchAttributes.getNamedItem("name"); String searchName = null; if (searchAttribute != null) { searchName = searchAttribute.getNodeValue(); } // create the pertinent indexer... IndexerInterface indexer = IndexerFactory.makeIndexer(searchType, searchName); if (indexer == null) { continue; } // configure the indexer indexer.configure(children.item(c)); // install it into the build manager buildManager.addIndexer(indexer); } else if (name.equals("browse")) { this.configureBrowsers(buildManager, children.item(c)); } // TODO: other elements - make a factory-method approach here... else { } } } catch (FactoryConfigurationError e) { System.out.println(e); } catch (ParserConfigurationException ex) { System.out.println(ex); } catch (SAXException ex) { System.out.println(ex); } catch (IOException ex) { System.out.println(ex); } System.out.println("<<>>>"); } public String getEtcDirectory() { return this.collectionHome + File.separator + "etc"; } public String getImportDirectory() { return this.collectionHome + File.separator + "import"; } public String getBuildDirectory() { return this.collectionHome + File.separator + "building"; } public String getArchiveDirectory() { return this.collectionHome + File.separator + "archives"; } public GS3SQLConnection getDatabase() { return this.database; } public void startBuild() { GregorianCalendar today = new GregorianCalendar(); if (this.lastBuildDate != null) { // if the build date is different to the last build date, then reset the build // document number if (today.get(Calendar.YEAR) != this.lastBuildDate.get(Calendar.YEAR) || today.get(Calendar.MONTH) != this.lastBuildDate.get(Calendar.MONTH) || today.get(Calendar.DAY_OF_MONTH) != this.lastBuildDate.get(Calendar.DAY_OF_MONTH)) { this.buildDocNo = 1; } } this.lastBuildDate = today; } public void endBuild() { Date startDate = this.lastBuildDate.getTime(); Date date = new Date(); long startTime = startDate.getTime(); long endTime = date.getTime(); long difference = ((endTime - startTime) + 500) / 1000; System.out.println("Build completed"); System.out.println("---------------"); System.out.println("Total Documents: " + this.getCollectionMetadata("gsdl3", "documentCount")); System.out.println("Total Time : " + (difference / 60) + " min. " + (difference % 60) + " secs."); } public String getNextDocumentID() { StringBuffer ID = new StringBuffer(); int value; ID.append(lastBuildDate.get(Calendar.YEAR)); // the use of month is a little odd, hence the following // code. Calendar.MONTH yields 0 = January, 1 = February, // etc. hence there is a '+1' added to the month to make // it into January = 1, etc., and the padding is altered // correspondingly. value = lastBuildDate.get(Calendar.MONTH); if (value < 9) { ID.append("0"); } ID.append(value + 1); value = lastBuildDate.get(Calendar.DAY_OF_MONTH); if (value < 10) ID.append("0"); ID.append(value); value = this.buildDocNo; this.buildDocNo ++; ID.append(":"); ID.append(Integer.toString(value)); return ID.toString(); } public int getDocumentNumber() { this.buildDocNo ++; return this.buildDocNo - 1; } /** * Get the collection metadata item in the given namespace * * @param String the namespace * @param String the label of the metadata */ public String getCollectionMetadata(String namespace, String label) { return this.metadata.getCollectionMetadata(namespace, label).get(0).toString(); } /** * Set the collection metadata item in the given namespace * * @param String the namespace * @param String the label * @param String the value */ public void setCollectionMetadata(String namespace, String label, String value) { this.metadata.setCollectionMetadata(namespace, label, value); } }