From: <fxp...@us...> - 2011-03-10 12:41:39
|
Revision: 7447 http://geonetwork.svn.sourceforge.net/geonetwork/?rev=7447&view=rev Author: fxprunayre Date: 2011-03-10 12:41:30 +0000 (Thu, 10 Mar 2011) Log Message: ----------- Align to trunk r7446. Modified Paths: -------------- sandbox/GeoSource/trunk/src/main/added/web/pom.xml sandbox/GeoSource/trunk/src/main/added/web/src/main/java/org/fao/geonet/kernel/SchemaManager.java sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/WEB-INF/config-gui.xml sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/WEB-INF/schemaplugin-uri-catalog.xml sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/geonetwork.css sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xml/schemas/iso19139/present/metadata-iso19139-edit.xsl sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xml/schemas/iso19139/present/metadata-iso19139.xsl sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xml/schemas/iso19139/schema-suggestions.xml Added Paths: ----------- sandbox/GeoSource/trunk/src/main/added/web/src/main/java/org/fao/geonet/kernel/DataManager.java sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/images/harvesting/brgm.gif sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/loc/fr/xml/strings.xml Removed Paths: ------------- sandbox/GeoSource/trunk/src/main/added/web/src/main/java/org/fao/geonet/services/login/Login.java sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/scripts/editor/LogoSelectionPanel.js sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/scripts/editor/metadata-editor.js sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xml/schemas/iso19139/present/metadata-iso19139-geo.xsl sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xml/schemas/iso19139/present/metadata-iso19139-utils.xsl sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xml/schemas/iso19139/update-fixed-info.xsl sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xsl/geo/utils.xsl sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xsl/metadata.xsl sandbox/GeoSource/trunk/src/main/added/web/src/main/webapp/xsl/utils-fn.xsl Modified: sandbox/GeoSource/trunk/src/main/added/web/pom.xml =================================================================== --- sandbox/GeoSource/trunk/src/main/added/web/pom.xml 2011-03-10 12:36:47 UTC (rev 7446) +++ sandbox/GeoSource/trunk/src/main/added/web/pom.xml 2011-03-10 12:41:30 UTC (rev 7447) @@ -319,40 +319,6 @@ <artifactId>opendap</artifactId> <version>2.1</version> </dependency> - <dependency> -<!-- <groupId>activemq</groupId> - <artifactId>activemq-core</artifactId> ---> - <groupId>org.apache.activemq</groupId> - <artifactId>activemq-core</artifactId> - <version>5.4.2</version> - </dependency> - - <dependency> - <groupId>org.apache.xbean</groupId> - <artifactId>xbean-spring</artifactId> - <version>3.4</version> - </dependency> -<!-- <dependency> - <groupId>xmlbeans</groupId> - <artifactId>xmlbeans</artifactId> - <version>2.0-dev-2</version> - </dependency> - <dependency> - <groupId>net.java.dev.javacc</groupId> - <artifactId>javacc</artifactId> - <version>2.1</version> - </dependency> - <dependency> - <groupId>activecluster</groupId> - <artifactId>activecluster</artifactId> - <version>1.1-20050524.034300</version> - </dependency>--> -<dependency> - <groupId>javax.jms</groupId> - <artifactId>jms</artifactId> - <version>1.1</version> - </dependency> </dependencies> <build> @@ -381,7 +347,7 @@ <nomunge>false</nomunge> <jswarn>${minify.verbose}</jswarn> <excludes> - <exclude>apps/**/*.js</exclude> + <exclude>apps/**/*.*</exclude> <exclude>scripts/ext/**/*.js</exclude> <exclude>scripts/lib/*.js</exclude> </excludes> @@ -404,16 +370,13 @@ <include>${geonetwork.build.dir}/scripts/map/Control/ExtentBox.js</include> <include>${geonetwork.build.dir}/scripts/map/Control/ZoomWheel.js</include> - <include>${geonetwork.build.dir}/scripts/map/Control/WMSGetFeatureInfo.js</include> - <include>${geonetwork.build.dir}/scripts/map/Format/WMSCapabilities.js</include> - <include>${geonetwork.build.dir}/scripts/map/Format/WMSCapabilities_1_1_1.js</include> - <include>${geonetwork.build.dir}/scripts/map/lang/en.js</include> <include>${geonetwork.build.dir}/scripts/map/lang/de.js</include> <include>${geonetwork.build.dir}/scripts/map/lang/nl.js</include> <include>${geonetwork.build.dir}/scripts/map/lang/fr.js</include> - + <include>${geonetwork.build.dir}/scripts/map/lang/no.js</include> + <include>${geonetwork.build.dir}/scripts/map/Ext.ux/form/DateTime.js</include> <include>${geonetwork.build.dir}/scripts/map/widgets/tree/WMSListGenerator.js</include> Added: sandbox/GeoSource/trunk/src/main/added/web/src/main/java/org/fao/geonet/kernel/DataManager.java =================================================================== --- sandbox/GeoSource/trunk/src/main/added/web/src/main/java/org/fao/geonet/kernel/DataManager.java (rev 0) +++ sandbox/GeoSource/trunk/src/main/added/web/src/main/java/org/fao/geonet/kernel/DataManager.java 2011-03-10 12:41:30 UTC (rev 7447) @@ -0,0 +1,3309 @@ +//============================================================================== +//=== +//=== DataManager +//=== +//============================================================================= +//=== Copyright (C) 2001-2007 Food and Agriculture Organization of the +//=== United Nations (FAO-UN), United Nations World Food Programme (WFP) +//=== and United Nations Environment Programme (UNEP) +//=== +//=== This program is free software; you can redistribute it and/or modify +//=== it under the terms of the GNU General Public License as published by +//=== the Free Software Foundation; either version 2 of the License, or (at +//=== your option) any later version. +//=== +//=== This program is distributed in the hope that it will be useful, but +//=== WITHOUT ANY WARRANTY; without even the implied warranty of +//=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +//=== General Public License for more details. +//=== +//=== You should have received a copy of the GNU General Public License +//=== along with this program; if not, write to the Free Software +//=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +//=== +//=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2, +//=== Rome - Italy. email: geo...@os... +//============================================================================== + +package org.fao.geonet.kernel; + +import java.io.File; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Timer; +import java.util.TimerTask; +import java.util.UUID; +import java.util.Vector; +import java.sql.SQLException; + +import jeeves.constants.Jeeves; +import jeeves.exceptions.JeevesException; +import jeeves.exceptions.OperationNotAllowedEx; +import jeeves.resources.dbms.Dbms; +import jeeves.server.UserSession; +import jeeves.server.context.ServiceContext; +import jeeves.utils.Log; +import jeeves.utils.SerialFactory; +import jeeves.utils.Xml; +import jeeves.utils.Xml.ErrorHandler; +import jeeves.xlink.Processor; + +import org.fao.geonet.GeonetContext; +import org.fao.geonet.constants.Edit; +import org.fao.geonet.constants.Geonet; +import org.fao.geonet.constants.Params; +import org.fao.geonet.kernel.csw.domain.CswCapabilitiesInfo; +import org.fao.geonet.kernel.harvest.HarvestManager; +import org.fao.geonet.kernel.schema.MetadataSchema; +import org.fao.geonet.kernel.search.SearchManager; +import org.fao.geonet.kernel.search.spatial.Pair; +import org.fao.geonet.kernel.setting.SettingManager; +import org.fao.geonet.lib.Lib; +import org.fao.geonet.util.ISODate; +import org.jdom.Attribute; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.Namespace; +import org.jdom.Text; +import org.jdom.filter.ElementFilter; +import org.jdom.filter.Filter; + +//============================================================================= + +/** Handles all operations on metadata (select,insert,update,delete etc...) + */ + +public class DataManager +{ + //-------------------------------------------------------------------------- + //--- + //--- Constructor + //--- + //-------------------------------------------------------------------------- + + /** initializes the search manager and index not-indexed metadata + */ + + public DataManager(ServiceContext context, SchemaManager scm, SearchManager sm, AccessManager am, Dbms dbms, SettingManager ss, String baseURL, String htmlCacheDir, String dataDir, String appPath) throws Exception + { + searchMan = sm; + accessMan = am; + settingMan= ss; + schemaMan = scm; + editLib = new EditLib(schemaMan); + servContext=context; + + this.baseURL = baseURL; + this.dataDir = dataDir; + this.appPath = appPath; + + stylePath = context.getAppPath() + FS + Geonet.Path.STYLESHEETS + FS; + + + XmlSerializer.setSettingManager(ss); + + init(context, dbms, false); + } + + private synchronized void finishRebuilding() { rebuilding = false; } + + /** + * Init Data manager and refresh index if needed. + * Can also be called after GeoNetwork startup in order to rebuild the lucene + * index + * + * @param context + * @param dbms + * @param force Force reindexing all from scratch + * + **/ + public synchronized void init(ServiceContext context, Dbms dbms, Boolean force) throws Exception { + + if (rebuilding) throw new OperationNotAllowedEx("Index rebuilding already in progress"); + + // get all metadata from DB + Element result = dbms.select("SELECT id, changeDate FROM Metadata ORDER BY id ASC"); + + Log.debug(Geonet.DATA_MANAGER, "DB CONTENT:\n'"+ Xml.getString(result) +"'"); + + // get lastchangedate of all metadata in index + HashMap<String,String> docs = searchMan.getDocsChangeDate(); + + // set up results HashMap for post processing of records to be indexed + ArrayList<Integer> toIndex = new ArrayList<Integer>(); + + Log.debug(Geonet.DATA_MANAGER, "INDEX CONTENT:"); + + // index all metadata in DBMS if needed + for(int i = 0; i < result.getContentSize(); i++) { + // get metadata + Element record = (Element) result.getContent(i); + String id = record.getChildText("id"); + int iId = Integer.parseInt(id); + + Log.debug(Geonet.DATA_MANAGER, "- record ("+ id +")"); + + String idxLastChange = docs.get(id); + + // if metadata is not indexed index it + if (idxLastChange == null) { + Log.debug(Geonet.DATA_MANAGER, "- will be indexed"); + toIndex.add(iId); + + // else, if indexed version is not the latest index it + } else { + docs.remove(id); + + String lastChange = record.getChildText("changedate"); + + Log.debug(Geonet.DATA_MANAGER, "- lastChange: " + lastChange); + Log.debug(Geonet.DATA_MANAGER, "- idxLastChange: " + idxLastChange); + + // date in index contains 't', date in DBMS contains 'T' + if (force || !idxLastChange.equalsIgnoreCase(lastChange)) { + Log.debug(Geonet.DATA_MANAGER, "- will be indexed"); + toIndex.add(iId); + } + } + } + + // if anything to index then schedule it to be done after servlet is + // up so that any links to local fragments are resolvable + if ( toIndex.size() > 0 ) { + Timer t = new Timer(); + t.schedule(new IndexMetadataTask(context, toIndex), 10); + } + + if (docs.size() > 0) { // anything left? + Log.debug(Geonet.DATA_MANAGER, "INDEX HAS RECORDS THAT ARE NOT IN DB:"); + } + + // remove from index metadata not in DBMS + for ( String id : docs.keySet() ) + { + searchMan.delete("_id", id); + + Log.debug(Geonet.DATA_MANAGER, "- removed record (" + id + ") from index"); + } + } + + //-------------------------------------------------------------------------- + + public synchronized void rebuildIndexXLinkedMetadata(ServiceContext context) throws Exception { + + if (rebuilding) throw new OperationNotAllowedEx("Index rebuilding already in progress"); + + // get all metadata with XLinks + ArrayList<Integer> toIndex = searchMan.getDocsWithXLinks(); + + Log.debug(Geonet.DATA_MANAGER, "Will index "+toIndex.size()+" records with XLinks"); + if ( toIndex.size() > 0 ) { + // clean XLink Cache so that cache and index remain in sync + Processor.clearCache(); + + // execute indexing operation + Timer t = new Timer(); + t.schedule(new IndexMetadataTask(context, toIndex), 10); + } + } + + //-------------------------------------------------------------------------- + + class IndexMetadataTask extends TimerTask { + ServiceContext context; + ArrayList<Integer> toIndex; + + IndexMetadataTask(ServiceContext context, ArrayList<Integer> toIndex) { + this.context = context; + this.toIndex = toIndex; + } + + public void run() { + + try { + + // poll context to see whether servlet is up yet + while (!context.isServletInitialized()) { + Log.debug(Geonet.DATA_MANAGER, "Waiting for servlet to finish initializing.."); + Thread.sleep(10000); // sleep 10 seconds + } + + // servlet up so safe to index all metadata that needs indexing + + Dbms dbms = (Dbms) context.getResourceManager().openDirect(Geonet.Res.MAIN_DB); + startIndexGroup(); + try { + for ( Integer id : toIndex ) { + indexMetadataGroup(dbms, id.toString()); + } + } finally { + endIndexGroup(); + } + + //-- commit Dbms resource (which makes it available to pool again) + //-- to avoid exhausting Dbms pool + context.getResourceManager().close(Geonet.Res.MAIN_DB, dbms); + } catch (Exception e) { + e.printStackTrace(); + } finally { + finishRebuilding(); + } + } + } + + //-------------------------------------------------------------------------- + + public void indexMetadata(Dbms dbms, String id) throws Exception + { + + Log.debug(Geonet.DATA_MANAGER, "Indexing record (" + id + ")"); //DEBUG + + indexMetadata(dbms, id, searchMan, schemaMan, false); + } + + //-------------------------------------------------------------------------- + + public void startIndexGroup() throws Exception { + searchMan.startIndexGroup(); + } + + //-------------------------------------------------------------------------- + + public void endIndexGroup() throws Exception { + searchMan.endIndexGroup(); + } + + //-------------------------------------------------------------------------- + + public void indexMetadataGroup(Dbms dbms, String id) throws Exception { + Log.debug(Geonet.DATA_MANAGER, "Indexing record (" + id + ")"); //DEBUG + indexMetadata(dbms, id, searchMan, schemaMan, true); + } + + //-------------------------------------------------------------------------- + + public static void indexMetadata(Dbms dbms, String id, SearchManager sm, SchemaManager scm) throws Exception + { + indexMetadata(dbms, id, sm, scm, false); + } + + //-------------------------------------------------------------------------- + + public static void indexMetadata(Dbms dbms, String id, SearchManager sm, SchemaManager scm, boolean indexGroup) throws Exception + { + try + { + indexMetadataI(dbms, id, sm, scm, indexGroup); + } + catch (Exception e) + { + Log.error(Geonet.DATA_MANAGER, "The metadata document index with id="+id+" is corrupt/invalid - ignoring it. Error: " + e.getMessage()); + e.printStackTrace(); + } + } + + //-------------------------------------------------------------------------- + + private static void indexMetadataI(Dbms dbms, String id, SearchManager sm, SchemaManager schemaMan, boolean indexGroup) throws Exception + { + Vector<Element> moreFields = new Vector<Element>(); + + // get metadata, extracting and indexing any xlinks + Element md = XmlSerializer.selectNoXLinkResolver(dbms, "Metadata", id); + if (XmlSerializer.resolveXLinks()) { + List<Attribute> xlinks = Processor.getXLinks(md); + if (xlinks.size() > 0) { + moreFields.add(makeField("_hasxlinks", "1", true, true, false)); + StringBuilder sb = new StringBuilder(); + for (Attribute xlink : xlinks) { + sb.append(xlink.getValue()); sb.append(" "); + } + moreFields.add(makeField("_xlink", sb.toString(), true, true, false)); + Processor.detachXLink(md); + } else { + moreFields.add(makeField("_hasxlinks", "0", true, true, false)); + } + } else { + moreFields.add(makeField("_hasxlinks", "0", true, true, false)); + } + + // get metadata table fields + String root = md.getName(); + + String query ="SELECT schemaId, createDate, changeDate, source, isTemplate, title, uuid, "+ + "isHarvested, owner, groupOwner, popularity, rating FROM Metadata WHERE id = " + id; + + Element rec = dbms.select(query).getChild("record"); + + String schema = rec.getChildText("schemaid"); + String createDate = rec.getChildText("createdate"); + String changeDate = rec.getChildText("changedate"); + String source = rec.getChildText("source"); + String isTemplate = rec.getChildText("istemplate"); + String title = rec.getChildText("title"); + String uuid = rec.getChildText("uuid"); + String isHarvested= rec.getChildText("isharvested"); + String owner = rec.getChildText("owner"); + String groupOwner = rec.getChildText("groupowner"); + String popularity = rec.getChildText("popularity"); + String rating = rec.getChildText("rating"); + + Log.debug(Geonet.DATA_MANAGER, "record schema (" + schema + ")"); //DEBUG + Log.debug(Geonet.DATA_MANAGER, "record createDate (" + createDate + ")"); //DEBUG + + moreFields.add(makeField("_root", root, true, true, false)); + moreFields.add(makeField("_schema", schema, true, true, false)); + moreFields.add(makeField("_createDate", createDate, true, true, false)); + moreFields.add(makeField("_changeDate", changeDate, true, true, false)); + moreFields.add(makeField("_source", source, true, true, false)); + moreFields.add(makeField("_isTemplate", isTemplate, true, true, false)); + moreFields.add(makeField("_title", title, true, true, false)); + moreFields.add(makeField("_uuid", uuid, true, true, true)); + moreFields.add(makeField("_isHarvested", isHarvested, true, true, false)); + moreFields.add(makeField("_owner", owner, true, true, false)); + moreFields.add(makeField("_dummy", "0", false, true, false)); + moreFields.add(makeField("_popularity", popularity, true, true, false)); + moreFields.add(makeField("_rating", rating, true, true, false)); + + if (groupOwner != null) + moreFields.add(makeField("_groupOwner", groupOwner, true, true, false)); + + // get privileges + List operations = dbms.select("SELECT groupId, operationId FROM OperationAllowed "+ + "WHERE metadataId = " + id + " ORDER BY operationId ASC").getChildren(); + + for (Object operation1 : operations) { + Element operation = (Element) operation1; + String groupId = operation.getChildText("groupid"); + String operationId = operation.getChildText("operationid"); + + moreFields.add(makeField("_op" + operationId, groupId, true, true, false)); + } + // get categories + List categories = dbms.select("SELECT id, name FROM MetadataCateg, Categories "+ + "WHERE metadataId = " + id + " AND categoryId = id ORDER BY id").getChildren(); + + for (Object category1 : categories) { + Element category = (Element) category1; + String categoryName = category.getChildText("name"); + + moreFields.add(makeField("_cat", categoryName, true, true, false)); + } + + // getValidationInfo + // -1 : not evaluated + // 0 : invalid + // 1 : valid + List<Element> validationInfo = dbms.select("SELECT valType, status FROM Validation WHERE metadataId=?", new Integer(id)).getChildren(); + if (validationInfo.size() == 0) { + moreFields.add(makeField("_valid", "-1", true, true, false)); + } else { + String isValid = "1"; + for (Object elem : validationInfo) { + Element vi = (Element) elem; + String type = vi.getChildText("valtype"); + String status = vi.getChildText("status"); + if ("0".equals(status)) { + isValid = "0"; + } + moreFields.add(makeField("_valid_" + type, status, true, true, false)); + } + moreFields.add(makeField("_valid", isValid, true, true, false)); + } + if (indexGroup) { + sm.indexGroup(schemaMan.getSchemaDir(schema), md, id, moreFields, isTemplate, title); + } else { + sm.index(schemaMan.getSchemaDir(schema), md, id, moreFields, isTemplate, title); + } + } + + //-------------------------------------------------------------------------- + + public void rescheduleOptimizer(Calendar beginAt, int interval) throws Exception { + searchMan.rescheduleOptimizer(beginAt, interval); + } + + //-------------------------------------------------------------------------- + + public void disableOptimizer() throws Exception { + searchMan.disableOptimizer(); + } + + //-------------------------------------------------------------------------- + + private static Element makeField(String name, String value, boolean store, + boolean index, boolean token) + { + Element field = new Element("Field"); + + field.setAttribute("name", name); + field.setAttribute("string", value); + field.setAttribute("store", store+""); + field.setAttribute("index", index+""); + field.setAttribute("token", token+""); + + return field; + } + + //-------------------------------------------------------------------------- + //--- + //--- Schema management API + //--- + //-------------------------------------------------------------------------- + + public void setHarvestManager(HarvestManager hm) + { + harvestMan = hm; + } + + //-------------------------------------------------------------------------- + + public MetadataSchema getSchema(String name) + { + return schemaMan.getSchema(name); + } + + //-------------------------------------------------------------------------- + + public Set<String> getSchemas() + { + return schemaMan.getSchemas(); + } + + //-------------------------------------------------------------------------- + + public boolean existsSchema(String name) + { + return schemaMan.existsSchema(name); + } + + //-------------------------------------------------------------------------- + + public String getSchemaDir(String name) + { + return schemaMan.getSchemaDir(name); + } + + //-------------------------------------------------------------------------- + // Use this validate method for XML documents with dtd + public void validate(String schema, Document doc) throws Exception + { + Xml.validate(doc); + } + + //-------------------------------------------------------------------------- + // Use this validate method for XML documents with xsd validation + public void validate(String schema, Element md) throws Exception + { + String schemaLoc = md.getAttributeValue("schemaLocation", Geonet.XSI_NAMESPACE); + Log.debug(Geonet.DATA_MANAGER, "Extracted schemaLocation of "+schemaLoc); + if (schemaLoc == null) schemaLoc = ""; + + if (schema == null) { + // must use schemaLocation + Xml.validate(md); + } else { + // if schemaLocation use that + if (!schemaLoc.equals("")) { + Xml.validate(md); + // otherwise use supplied schema name + } else { + Xml.validate(getSchemaDir(schema) + Geonet.File.SCHEMA, md); + } + } + } + + //-------------------------------------------------------------------------- + + public Element validateInfo(String schema, Element md, ErrorHandler eh) throws Exception + { + String schemaLoc = md.getAttributeValue("schemaLocation", Geonet.XSI_NAMESPACE); + Log.debug(Geonet.DATA_MANAGER, "Extracted schemaLocation of "+schemaLoc); + if (schemaLoc == null) schemaLoc = ""; + + if (schema == null) { + // must use schemaLocation + return Xml.validateInfo(md, eh); + } else { + // if schemaLocation use that + if (!schemaLoc.equals("")) { + return Xml.validateInfo(md, eh); + // otherwise use supplied schema name + } else { + return Xml.validateInfo(getSchemaDir(schema) + Geonet.File.SCHEMA, md, eh); + } + } + } + /** + * Create XML schematron report. + */ + public Element doSchemaTronForEditor(String schema,Element md,String lang) throws Exception { + // enumerate the metadata xml so that we can report any problems found + // by the schematron_xml script to the geonetwork editor + editLib.enumerateTree(md); + + // get an xml version of the schematron errors and return for error display + Element schemaTronXmlReport = getSchemaTronXmlReport(schema, md, lang, null); + + // remove editing info added by enumerateTree + editLib.removeEditingInfo(md); + + return schemaTronXmlReport; + } + //-------------------------------------------------------------------------- + + public String getMetadataSchema(Dbms dbms, String id) throws Exception + { + List list = dbms.select("SELECT schemaId FROM Metadata WHERE id = " +id).getChildren(); + + if (list.size() == 0) + throw new IllegalArgumentException("Metadata not found for id : " +id); + else + { + // get metadata + Element record = (Element) list.get(0); + return record.getChildText("schemaid"); + } + } + + //-------------------------------------------------------------------------- + + public Element enumerateTree(Element md) throws Exception { + editLib.enumerateTree(md); + return md; + } + + + //-------------------------------------------------------------------------- + /** + * Create XML schematron report for each set of rules defined + * in schema directory. + * @param valTypeAndStatus + */ + private Element getSchemaTronXmlReport(String schema, Element md, String lang, HashMap<String, Integer[]> valTypeAndStatus) throws Exception { + // NOTE: this method assumes that you've run enumerateTree on the + // metadata + + MetadataSchema metadataSchema = getSchema(schema); + String[] rules = metadataSchema.getSchematronRules(); + + // Schematron report is composed of one or more report(s) + // for each set of rules. + Element schemaTronXmlOut = new Element("schematronerrors", + Edit.NAMESPACE); + + for (String rule : rules) { + // -- create a report for current rules. + // Identified by a rule attribute set to shematron file name + Log.debug(Geonet.DATA_MANAGER, " - rule:" + rule); + String ruleId = rule.substring(0, rule.indexOf(".xsl")); + Element report = new Element("report", Edit.NAMESPACE); + report.setAttribute("rule", ruleId, + Edit.NAMESPACE); + + String schemaTronXmlXslt = metadataSchema.getSchemaDir() + File.separator + + rule; + try { + Map<String,String> params = new HashMap<String,String>(); + params.put("lang", lang); + params.put("rule", rule); + params.put("dataDir", this.dataDir); + Element xmlReport = Xml.transform(md, schemaTronXmlXslt, params); + if (xmlReport != null) { + report.addContent(xmlReport); + } + // add results to persitent validation information + int firedRules = 0; + Iterator<Element> i = xmlReport.getDescendants(new ElementFilter ("fired-rule", Namespace.getNamespace("http://purl.oclc.org/dsdl/svrl"))); + while (i.hasNext()) { + i.next(); + firedRules ++; + } + int invalidRules = 0; + i = xmlReport.getDescendants(new ElementFilter ("failed-assert", Namespace.getNamespace("http://purl.oclc.org/dsdl/svrl"))); + while (i.hasNext()) { + i.next(); + invalidRules ++; + } + Integer[] results = {invalidRules!=0?0:1, firedRules, invalidRules}; + if (valTypeAndStatus != null) { + valTypeAndStatus.put(ruleId, results); + } + } catch (Exception e) { + Log.error(Geonet.DATA_MANAGER,"WARNING: schematron xslt "+schemaTronXmlXslt+" failed"); + e.printStackTrace(); + } + + // -- append report to main XML report. + schemaTronXmlOut.addContent(report); + } + + return schemaTronXmlOut; + } + + //-------------------------------------------------------------------------- + /** + * Valid the metadata record against its schema. + * For each error found, an xsderror attribute is added to + * the corresponding element trying to find the element + * based on the xpath return by the ErrorHandler. + * + */ + private synchronized Element getXSDXmlReport(String schema, Element md) throws Exception { + + // NOTE: this method assumes that enumerateTree has NOT been run on the + // metadata + ErrorHandler errorHandler = new ErrorHandler(); + errorHandler.setNs(Edit.NAMESPACE); + Element xsdErrors; + + try { + xsdErrors = validateInfo(schema, + md, errorHandler); + }catch (Exception e) { + xsdErrors = JeevesException.toElement(e); + return xsdErrors; + } + + if (xsdErrors != null) { + MetadataSchema mds = getSchema(schema); + List<Namespace> schemaNamespaces = mds.getSchemaNS(); + + //-- now get each xpath and evaluate it + //-- xsderrors/xsderror/{message,xpath} + List list = xsdErrors.getChildren(); + for (Object o : list) { + Element elError = (Element) o; + String xpath = elError.getChildText("xpath", Edit.NAMESPACE); + String message = elError.getChildText("message", Edit.NAMESPACE); + message = "\\n" + message; + + //-- get the element from the xpath and add the error message to it + Element elem = Xml.selectElement(md, xpath, schemaNamespaces); + if (elem != null) { + String existing = elem.getAttributeValue("xsderror",Edit.NAMESPACE); + if (existing != null) message = existing + message; + elem.setAttribute("xsderror",message,Edit.NAMESPACE); + } else { + Log.warning(Geonet.DATA_MANAGER,"WARNING: evaluating XPath "+xpath+" against metadata failed - XSD validation message: "+message+" will NOT be shown by the editor"); + } + } + } + return xsdErrors; + } + + //-------------------------------------------------------------------------- + + public AccessManager getAccessManager() + { + return accessMan; + } + + //-------------------------------------------------------------------------- + //--- + //--- General purpose API + //--- + //-------------------------------------------------------------------------- + + public String extractUUID(String schema, Element md) throws Exception + { + String styleSheet = getSchemaDir(schema) + Geonet.File.EXTRACT_UUID; + String uuid = Xml.transform(md, styleSheet).getText().trim(); + + Log.debug(Geonet.DATA_MANAGER, "Extracted UUID '"+ uuid +"' for schema '"+ schema +"'"); + + //--- needed to detach md from the document + md.detach(); + + return uuid; + } + + //-------------------------------------------------------------------------- + + public Element setUUID(String schema, String uuid, Element md) throws Exception + { + //--- setup environment + + Element env = new Element("env"); + env.addContent(new Element("uuid").setText(uuid)); + + //--- setup root element + + Element root = new Element("root"); + root.addContent(md.detach()); + root.addContent(env.detach()); + + //--- do an XSL transformation + + String styleSheet = getSchemaDir(schema) + Geonet.File.SET_UUID; + + return Xml.transform(root, styleSheet); + } + + @SuppressWarnings("unchecked") + public List<Element> getMetadataByHarvestingSource(Dbms dbms, String harvestingSource) throws Exception { + String query = "SELECT id FROM Metadata WHERE harvestUuid=?"; + return dbms.select(query, harvestingSource).getChildren(); + } + + //-------------------------------------------------------------------------- + + public Element extractSummary(Element md) throws Exception + { + String styleSheet = stylePath + Geonet.File.METADATA_BRIEF; + Element summary = Xml.transform(md, styleSheet); + + Log.debug(Geonet.DATA_MANAGER, "Extracted summary '\n"+Xml.getString(summary)); + + //--- needed to detach md from the document + md.detach(); + + return summary; + } + + //-------------------------------------------------------------------------- + + public String getMetadataId(Dbms dbms, String uuid) throws Exception + { + String query = "SELECT id FROM Metadata WHERE uuid=?"; + + List list = dbms.select(query, uuid).getChildren(); + + if (list.size() == 0) + return null; + + Element record = (Element) list.get(0); + + return record.getChildText("id"); + } + + //-------------------------------------------------------------------------- + + public String getMetadataId(ServiceContext srvContext, String uuid) throws Exception { + Dbms dbms = (Dbms) srvContext.getResourceManager().open(Geonet.Res.MAIN_DB); + String query = "SELECT id FROM Metadata WHERE uuid=?"; + List list = dbms.select(query, uuid).getChildren(); + if (list.size() == 0) + return null; + Element record = (Element) list.get(0); + return record.getChildText("id"); + } + //-------------------------------------------------------------------------- + + public String getMetadataUuid(Dbms dbms, String id) throws Exception + { + String query = "SELECT uuid FROM Metadata WHERE id=?"; + + List list = dbms.select(query, new Integer(id)).getChildren(); + + if (list.size() == 0) + return null; + + Element record = (Element) list.get(0); + + return record.getChildText("uuid"); + } + + //-------------------------------------------------------------------------- + + public String getMetadataTemplate(Dbms dbms, String id) throws Exception + { + String query = "SELECT istemplate FROM Metadata WHERE id=?"; + + List list = dbms.select(query, new Integer(id)).getChildren(); + + if (list.size() == 0) + return null; + + Element record = (Element) list.get(0); + + return record.getChildText("istemplate"); + } + + //-------------------------------------------------------------------------- + + public MdInfo getMetadataInfo(Dbms dbms, String id) throws Exception + { + String query = "SELECT id, uuid, schemaId, isTemplate, isHarvested, createDate, "+ + " changeDate, source, title, root, owner, groupOwner, displayOrder "+ + "FROM Metadata "+ + "WHERE id=?"; + + List list = dbms.select(query, new Integer(id)).getChildren(); + + if (list.size() == 0) + return null; + + Element record = (Element) list.get(0); + + MdInfo info = new MdInfo(); + + info.id = id; + info.uuid = record.getChildText("uuid"); + info.schemaId = record.getChildText("schemaid"); + info.isHarvested = "y".equals(record.getChildText("isharvested")); + info.createDate = record.getChildText("createdate"); + info.changeDate = record.getChildText("changedate"); + info.source = record.getChildText("source"); + info.title = record.getChildText("title"); + info.root = record.getChildText("root"); + info.owner = record.getChildText("owner"); + info.groupOwner = record.getChildText("groupowner"); + info.displayOrder = record.getChildText("displayOrder"); + + String temp = record.getChildText("istemplate"); + + if ("y".equals(temp)) + info.template = MdInfo.Template.TEMPLATE; + + else if ("s".equals(temp)) + info.template = MdInfo.Template.SUBTEMPLATE; + + else + info.template = MdInfo.Template.METADATA; + + return info; + } + + //-------------------------------------------------------------------------- + + public String getVersion(String id) + { + return editLib.getVersion(id); + } + + //-------------------------------------------------------------------------- + + public String getNewVersion(String id) + { + return editLib.getNewVersion(id); + } + + //-------------------------------------------------------------------------- + + public void setTemplate(Dbms dbms, int id, String isTemplate, String title) throws Exception + { + setTemplateExt(dbms, id, isTemplate, title); + indexMetadata(dbms, Integer.toString(id)); + } + + //-------------------------------------------------------------------------- + + public void setTemplateExt(Dbms dbms, int id, String isTemplate, String title) throws Exception + { + if (title == null) dbms.execute("UPDATE Metadata SET isTemplate=? WHERE id=?", isTemplate, id); + else dbms.execute("UPDATE Metadata SET isTemplate=?, title=? WHERE id=?", isTemplate, title, id); + } + + //-------------------------------------------------------------------------- + + public void setHarvested(Dbms dbms, int id, String harvestUuid) throws Exception + { + setHarvestedExt(dbms, id, harvestUuid); + indexMetadata(dbms, Integer.toString(id)); + } + + //-------------------------------------------------------------------------- + + public void setHarvestedExt(Dbms dbms, int id, String harvestUuid) throws Exception + { + String value = (harvestUuid != null) ? "y" : "n"; + if (harvestUuid == null) { + dbms.execute("UPDATE Metadata SET isHarvested=? WHERE id=?", value,id ); + } else { + dbms.execute("UPDATE Metadata SET isHarvested=?, harvestUuid=? WHERE id=?", value, harvestUuid, id); + } + } + + //-------------------------------------------------------------------------- + + public void setHarvestedExt(Dbms dbms, int id, String harvestUuid, String harvestUri) throws Exception + { + String value = (harvestUuid != null) ? "y" : "n"; + String query = "UPDATE Metadata SET isHarvested=?, harvestUuid=?, harvestUri=? WHERE id=?"; + + dbms.execute(query, value, harvestUuid, harvestUri, id); + } + + //--------------------------------------------------------------------------- + + public String getSiteURL() + { + String host = settingMan.getValue("system/server/host"); + String port = settingMan.getValue("system/server/port"); + String locServ = baseURL +"/"+ Jeeves.Prefix.SERVICE +"/en"; + + return "http://" + host + (port.equals("80") ? "" : ":" + port) + locServ; + } + + //-------------------------------------------------------------------------- + + public String autodetectSchema(Document doc) + { + return autodetectSchema(doc.getRootElement()); + } + + //-------------------------------------------------------------------------- + + public String autodetectSchema(Element md) + { + + Log.debug(Geonet.DATA_MANAGER, "Autodetect schema for metadata with :\n * root element:'" + md.getQualifiedName() + + "'\n * with namespace:'" + md.getNamespace() + + "\n * with additional namespaces:" + md.getAdditionalNamespaces().toString()); + String schema = schemaMan.autodetectSchema(md); + Log.debug(Geonet.DATA_MANAGER, "Schema detected was "+schema); + return schema; + } + + //-------------------------------------------------------------------------- + public void updateDisplayOrder(Dbms dbms, String id, String displayOrder) throws Exception { + String query = "UPDATE Metadata SET displayOrder = ? WHERE id = ?"; + dbms.execute(query, new Integer(displayOrder), new Integer(id)); + } + + //-------------------------------------------------------------------------- + + public void increasePopularity(ServiceContext srvContext, String id) throws Exception + { + GeonetContext gc = (GeonetContext) srvContext.getHandlerContext(Geonet.CONTEXT_NAME); + gc.getThreadPool().runTask(new IncreasePopularityTask(srvContext, id)); + } + + //-------------------------------------------------------------------------- + /** Allow to rate a metadata + * @param ipAddress IP address of the submitting client + * @param rating range should be 1..5 + */ + + public int rateMetadata(Dbms dbms, int id, String ipAddress, int rating) throws Exception + { + //--- first, update rating on the database + + String query = "UPDATE MetadataRating SET rating=? WHERE metadataId=? AND ipAddress=?"; + + int res = dbms.execute(query, rating, id, ipAddress); + + if (res == 0) + { + query = "INSERT INTO MetadataRating(metadataId, ipAddress, rating) VALUES(?,?,?)"; + dbms.execute(query, id, ipAddress, rating); + } + + //--- then, calculate new rating + + query = "SELECT sum(rating) as total FROM MetadataRating WHERE metadataId=?"; + List list = dbms.select(query, id).getChildren(); + + String sum = ((Element) list.get(0)).getChildText("total"); + + query = "SELECT count(*) as numr FROM MetadataRating WHERE metadataId=?"; + list = dbms.select(query, id).getChildren(); + + String count = ((Element) list.get(0)).getChildText("numr"); + + rating = (int)(Float.parseFloat(sum) / Float.parseFloat(count) + 0.5); + + Log.debug(Geonet.DATA_MANAGER, "Setting rating for id:"+ id +" --> rating is:"+rating); + + //--- finally, update metadata and reindex it + + query = "UPDATE Metadata SET rating=? WHERE id=?"; + dbms.execute(query, rating, id); + indexMetadata(dbms, Integer.toString(id)); + + return rating; + } + + //-------------------------------------------------------------------------- + //--- + //--- Metadata Insert API + //--- + //-------------------------------------------------------------------------- + + /** Create a new metadata duplicating an existing template + */ + + public String createMetadata(Dbms dbms, String templateId, String groupOwner, + SerialFactory sf, String source, int owner, + String parentUuid) throws Exception + { + String query = "SELECT schemaId, data FROM Metadata WHERE id="+ templateId; + + List listTempl = dbms.select(query).getChildren(); + + if (listTempl.size() == 0) + throw new IllegalArgumentException("Template id not found : " + templateId); + + Element el = (Element) listTempl.get(0); + + String schema = el.getChildText("schemaid"); + String data = el.getChildText("data"); + String uuid = UUID.randomUUID().toString(); + + //--- generate a new metadata id + int serial = sf.getSerial(dbms, "Metadata"); + + Element xml = updateFixedInfoNew(schema, Integer.toString(serial), Xml.loadString(data, false), uuid, parentUuid); + + //--- store metadata + + String id = XmlSerializer.insert(dbms, schema, xml, serial, source, uuid, owner, groupOwner); + + copyDefaultPrivForGroup(dbms, id, groupOwner); + + //--- store metadata categories copying them from the template + + List categList = dbms.select("SELECT categoryId FROM MetadataCateg WHERE metadataId = "+templateId).getChildren(); + + for (Object aCategList : categList) { + Element elRec = (Element) aCategList; + + String catId = elRec.getChildText("categoryid"); + + setCategory(dbms, id, catId); + } + + //--- index metadata and exit + + indexMetadata(dbms, id); + + return id; + } + + //-------------------------------------------------------------------------- + /** Adds a metadata in xml form (the xml should be validated). This method is + * used to add a metadata got from a remote site via a mef and the data has + * NOT been included. Note that neither permissions nor lucene indexes are + * updated. + */ + + public String insertMetadataExt(Dbms dbms, String schema, Element md, + SerialFactory sf, String source, String createDate, + String changeDate, String uuid, int owner, + String groupOwner ) throws Exception + { + //--- generate a new metadata id + int id = sf.getSerial(dbms, "Metadata"); + + return insertMetadataExt(dbms, schema, md, id, source, createDate, + changeDate, uuid, owner, groupOwner, "", "n"); + } + + //-------------------------------------------------------------------------- + /** Adds a metadata in xml form (the xml should be validated). This method is + * used to add a metadata got from a remote site via a mef and the data has + * been included. Note that neither permissions nor lucene indexes are + * updated. + */ + + public String insertMetadataExt(Dbms dbms, String schema, Element md, + SerialFactory sf, String source, String createDate, + String changeDate, String uuid, int owner, String groupOwner, + String isTemplate ) throws Exception + { + //--- generate a new metadata id + int id = sf.getSerial(dbms, "Metadata"); + + if (isTemplate.equals("n")) + md = updateFixedInfoExisting(schema, Integer.toString(id), md, uuid); + + return insertMetadataExt(dbms, schema, md, id, source, createDate, + changeDate, uuid, owner, groupOwner, "", isTemplate); + } + + //-------------------------------------------------------------------------- + /** @param source the source of the metadata. If null, the local siteId will be used + */ + + public String insertMetadataExt(Dbms dbms, String schema, Element md, int id, + String source, String createDate, String changeDate, + String uuid, int owner, String groupOwner, + String docType, String isTemplate) throws Exception + { + if (source == null) + source = getSiteID(); + + //--- force namespace prefix for iso19139 metadata + setNamespacePrefixUsingSchemas(md); + + //--- Note: we cannot index metadata here. Indexing is done in the harvesting part + + String record = XmlSerializer.insert(dbms, schema, md, id, source, uuid, createDate, + changeDate, isTemplate, null, owner, groupOwner, docType); + + // Notifies the metadata change to metatada notifier service + notifyMetadataChange(dbms, md, id + ""); + + return record; + } + + //-------------------------------------------------------------------------- + /** Adds a metadata in xml form (the xml should be validated). The group id is + * used to setup permissions. Internal metadata fields are updated. Default + * operations are set. + */ + + public String insertMetadata(Dbms dbms, String schema, String category, String groupId, Element xml, SerialFactory sf, String source, String uuid, int owner) throws Exception + { + return insertMetadata(dbms, schema, category, groupId, xml, sf, source, uuid, "n", null, owner); + } + + //-------------------------------------------------------------------------- + + public String insertMetadata(Dbms dbms, String schema, String category, String groupOwner, Element xml, SerialFactory sf, String source, String uuid, String isTemplate, String title, int owner) throws Exception + { + //--- generate a new metadata id + int serial = sf.getSerial(dbms, "Metadata"); + + //--- force namespace prefix for iso19139 metadata + setNamespacePrefixUsingSchemas(xml); + + if (isTemplate.equals("n")) + xml = updateFixedInfoExisting(schema, Integer.toString(serial), xml, uuid); + + //--- store metadata + + String id = XmlSerializer.insert(dbms, schema, xml, serial, source, uuid, isTemplate, title, owner, groupOwner); + + copyDefaultPrivForGroup(dbms, id, groupOwner); + if (category != null) + setCategory(dbms, id, category); + indexMetadata(dbms, id); + + // Notifies the metadata change to metatada notifier service + notifyMetadataChange(dbms, xml, id); + + return id; + } + + //-------------------------------------------------------------------------- + //--- + //--- Metadata Get API + //--- + //-------------------------------------------------------------------------- + + /** Retrieves a metadata (in xml) given its id with no geonet:info + */ + public Element getMetadataNoInfo(ServiceContext srvContext, String id) throws Exception + { + Element md = getMetadata(srvContext, id, false, false); + md.removeChild(Edit.RootChild.INFO, Edit.NAMESPACE); + return md; + } + + /** Retrieves a metadata (in xml) given its id; adds editing information + * if requested and does NOT include validation errors + */ + + public Element getMetadata(ServiceContext srvContext, String id, boolean forEditing) throws Exception + { + return getMetadata(srvContext, id, forEditing, false); + } + + /** Retrieves a metadata (in xml) given its id; adds editing information + * if requested and validation errors if requested + */ + public Element getMetadata(ServiceContext srvContext, String id, boolean forEditing, boolean withEditorValidationErrors) throws Exception + { + + Dbms dbms = (Dbms) srvContext.getResourceManager().open(Geonet.Res.MAIN_DB); + + boolean doXLinks = XmlSerializer.resolveXLinks(); + + Element md = XmlSerializer.selectNoXLinkResolver(dbms, "Metadata", id); + if (md == null) return null; + + String version = null; + + if (forEditing) { // copy in xlink'd fragments but leave xlink atts to editor + if (doXLinks) Processor.processXLink(md); + String schema = getMetadataSchema(dbms, id); + + if (withEditorValidationErrors) { + version = doValidate(srvContext.getUserSession(), dbms, schema, id, md, srvContext.getLanguage(), forEditing).two(); + } else { + editLib.expandElements(schema, md); + version = editLib.getVersionForEditing(schema, id, md); + } + } else { + if (doXLinks) Processor.detachXLink(md); + } + + md.addNamespaceDeclaration(Edit.NAMESPACE); + Element info = buildInfoElem(srvContext, id, version); + md.addContent(info); + + md.detach(); + return md; + } + + //-------------------------------------------------------------------------- + /** Retrieves a metadata element given it's ref + */ + + public Element getElementByRef(Element md, String ref) + { + return editLib.findElement(md, ref); + } + + //-------------------------------------------------------------------------- + /** Returns true if the metadata exists in the database + */ + public boolean existsMetadata(Dbms dbms, int id) throws Exception + { + //FIXME : should use lucene + + List list = dbms.select("SELECT id FROM Metadata WHERE id="+ id).getChildren(); + return list.size() != 0; + } + + /** Returns true if the metadata uuid exists in the database + */ + + public boolean existsMetadataUuid(Dbms dbms, String uuid) throws Exception + { + //FIXME : should use lucene + + List list = dbms.select("SELECT uuid FROM Metadata WHERE uuid='" + uuid + "'").getChildren(); + return list.size() != 0; + } + + //-------------------------------------------------------------------------- + /** Returns all the keywords in the system + */ + + public Element getKeywords() throws Exception + { + Vector keywords = searchMan.getTerms("keyword"); + + Element el = new Element("keywords"); + + for (Object keyword : keywords) { + el.addContent(new Element("keyword").setText((String) keyword)); + } + + return el; + } + + //-------------------------------------------------------------------------- + //--- + //--- Embedded Metadata Update API for AJAX Editor support + //--- + //-------------------------------------------------------------------------- + + private Element getMetadataFromSession(UserSession session, String id) + { + Log.debug(Geonet.DATA_MANAGER, "Retrieving metadata from session "+session.getUserId()); + Element md = (Element) session.getProperty(Geonet.Session.METADATA_EDITING + id); + md.detach(); + return md; + } + + private void setMetadataIntoSession(UserSession session, Element md, String id) + { + Log.debug(Geonet.DATA_MANAGER, "Storing metadata in session "+session.getUserId()); + session.setProperty(Geonet.Session.METADATA_EDITING + id, md); + } + + //-------------------------------------------------------------------------- + /** For Ajax Editing : removes metadata from session + */ + public void removeMetadataEmbedded(UserSession session, String id) + { + Log.debug(Geonet.DATA_MANAGER, "Removing metadata from session "+session.getUserId()); + session.removeProperty(Geonet.Session.METADATA_EDITING + id); + session.removeProperty(Geonet.Session.VALIDATION_REPORT + id); + } + + //-------------------------------------------------------------------------- + /** For Ajax Editing : gets Metadata from database and places it in session + */ + public Element getMetadataEmbedded(ServiceContext srvContext, String id, boolean forEditing, boolean withValidationErrors) throws Exception + { + Element md = getMetadata(srvContext, id, forEditing, withValidationErrors); + + UserSession session = srvContext.getUserSession(); + setMetadataIntoSession(session, md, id); + return md; + } + + //-------------------------------------------------------------------------- + /** For Ajax Editing : adds an element or an attribute to a metadata element ([add] link) + */ + public synchronized Element addElementEmbedded(Dbms dbms, UserSession session, String id, String ref, String name, String childName) throws Exception + { + + String schema = getMetadataSchema(dbms, id); + + //--- get metadata from session + Element md = getMetadataFromSession(session, id); + + //--- ref is parent element so find it + Element el = editLib.findElement(md, ref); + if (el == null) + throw new IllegalStateException("Element not found at ref = " + ref); + + //--- locate the geonet:element and geonet:info elements and clone for + //--- later re-use + Element refEl = (Element)(el.getChild(Edit.RootChild.ELEMENT, Edit.NAMESPACE)).clone(); + Element info = (Element)(md.getChild(Edit.RootChild.INFO,Edit.NAMESPACE)).clone(); + md.removeChild(Edit.RootChild.INFO,Edit.NAMESPACE); + + Element child = null; + MetadataSchema mds = getSchema(schema); + if (childName != null) { + if (childName.equals("geonet:attribute")) { + String defaultValue = ""; + List attributeDefs = el.getChildren(Edit.RootChild.ATTRIBUTE, Edit.NAMESPACE); + for (Object a : attributeDefs) { + Element attributeDef = (Element) a; + if (attributeDef != null && attributeDef.getAttributeValue(Edit.Attribute.Attr.NAME).equals(name)) { + Element defaultChild = attributeDef.getChild(Edit.Attribute.Child.DEFAULT, Edit.NAMESPACE); + if (defaultChild != null) { + defaultValue = defaultChild.getAttributeValue(Edit.Attribute.Attr.VALUE); + } + } + } + //--- Add new attribute with default value + el.setAttribute(new Attribute(name, defaultValue)); + // TODO : add attribute should be false and del true after adding an attribute + child = el; + } else { + //--- normal element + child = editLib.addElement(schema, el, name); + if (!childName.equals("")) + { + //--- or element + String uChildName = editLib.getUnqualifiedName(childName); + String prefix = editLib.getPrefix(childName); + String ns = editLib.getNamespace(childName,md,mds); + if (prefix.equals("")) { + prefix = editLib.getPrefix(el.getName()); + ns = editLib.getNamespace(el.getName(),md,mds); + } + Element orChild = new Element(uChildName,prefix,ns); + child.addContent(orChild); + + //--- add mandatory sub-tags + editLib.fillElement(schema, child, orChild); + } + } + } else { + child = editLib.addElement(schema, el, name); + } + //--- now enumerate the new child (if not a simple attribute) + if (childName == null || !childName.equals("geonet:attribute")) { + //--- now add the geonet:element back again to keep ref number + el.addContent(refEl); + + int iRef = editLib.findMaximumRef(md); + editLib.expandElements(schema, child); + editLib.enumerateTreeStartingAt(child, iRef+1, Integer.parseInt(ref)); + + //--- add editing info to everything from the parent down + editLib.expandTree(mds,el); + + } + //--- attach the info element to the child + child.addContent(info); + + //--- attach the info element to the metadata root) + md.addContent((Element)info.clone()); + + //--- store the metadata in the session again + setMetadataIntoSession(session,(Element)md.clone(), id); + + // Return element added + return child; + + } + + //-------------------------------------------------------------------------- + /** For Ajax Editing : removes an element from a metadata ([del] link) + */ + + public synchronized Element deleteElementEmbedded(Dbms dbms, UserSession session, String id, String ref, String parentRef) throws Exception + { + + String schema = getMetadataSchema(dbms, id); + + //--- get metadata from session + Element md = getMetadataFromSession(session, id); + + //--- locate the geonet:info element and clone for later re-use + Element info = (Element)(md.getChild(Edit.RootChild.INFO,Edit.NAMESPACE)).clone(); + md.removeChild(Edit.RootChild.INFO,Edit.NAMESPACE); + + //--- get element to remove + Element el = editLib.findElement(md, ref); + + if (el == null) + throw new IllegalStateException("Element not found at ref = " + ref); + + + String uName = el.getName(); + Namespace ns = el.getNamespace(); + Element parent = el.getParentElement(); + Element result = null; + if (parent != null) { + int me = parent.indexOf(el); + + //--- check and see whether the element to be deleted is the last one of its kind + Filter elFilter = new ElementFilter(uName,ns); + if (parent.getContent(elFilter).size() == 1) { + + //--- get geonet child element with attribute name = unqualified name + Filter chFilter = new ElementFilter(Edit.RootChild.CHILD, Edit.NAMESPACE); + List children = parent.getContent(chFilter); + + for (int i = 0; i < children.size(); i++) { + Element ch = (Element) children.get(i); + String name = ch.getAttributeValue("name"); + if (name != null && name.equals(uName)) { + result = (Element) ch.clone(); + break; + } + } + + // -- now delete the element as requested + parent.removeContent(me); + + //--- existing geonet child element not present so create it and insert it + //--- where the last element was deleted + if (result == null) { + result = editLib.createElement(schema,el,parent); + parent.addContent(me,result); + } + result.setAttribute(Edit.ChildElem.Attr.PARENT,parentRef); + result.addContent(info); + } + //--- if not the last one then just delete it + else { + parent.removeContent(me); + } + } else { + throw new IllegalStateException("Element at ref = " + ref + " doesn't have a parent"); + } + + // if we don't need a child then create a geonet:null element + if (result == null) { + result = new Element(Edit.RootChild.NULL, Edit.NAMESPACE); + result.addContent(info); + } + + //--- reattach the info element to the metadata + md.addContent((Element)info.clone()); + + //--- store the metadata in the session again + setMetadataIntoSession(session,(Element)md.clone(), id); + + return result; + } + + /** + * Remove attribute in embedded mode + * + * @param dbms + * @param session + * @param id + * @param ref Attribute identifier (eg. _169_uom). + * @return + * @throws Exception + */ + public synchronized Element deleteAttributeEmbedded(Dbms dbms, UserSession session, String id, String ref) throws Exception { + String[] token = ref.split("_"); + String elementId = token[1]; + String attributeName = token[2]; + Element result = new Element(Edit.RootChild.NULL, Edit.NAMESPACE); + + //--- get metadata from session + Element md = getMetadataFromSession(session, id); + + //--- get element to remove + Element el = editLib.findElement(md, elementId); + + if (el != null) { + el.removeAttribute(attributeName); + } + + //--- store the metadata in the session again + setMetadataIntoSession(session,(Element)md.clone(), id); + + return result; + } + + //-------------------------------------------------------------------------- + /** For Ajax Editing : swap element with sibling ([up] and [down] links) + */ + + public synchronized void swapElementEmbedded(Dbms dbms, UserSession session, String id, String ref, boolean down) throws Exception + { + getMetadataSchema(dbms, id); + + //--- get metadata from session + Element md = getMetadataFromSession(session, id); + + //--- get element to swap + Element elSwap = editLib... [truncated message content] |