/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* CVS $Id: MetaSystemCollection.java,v 1.13 2004/03/15 13:46:30 vgritsenko Exp $
*/
package org.apache.xindice.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xindice.core.meta.MetaData;
import org.apache.xindice.util.Configuration;
import org.apache.xindice.xml.dom.DOMParser;
import org.w3c.dom.Document;
import java.util.StringTokenizer;
/**
* MetaSystemCollection represents the Meta System Collection. Beyond
* standard Collection operations, this class will provide facilities
* for Meta data management.
*
* @version CVS $Revision: 1.13 $, $Date: 2004/03/15 13:46:30 $
*/
public final class MetaSystemCollection extends Collection {
private static final Log log = LogFactory.getLog(MetaSystemCollection.class);
public static final String METACOL = "meta";
public static final String METAS = "Metas";
public static final String COLLECTION_META_DATA = "_META_DATA_";
private static String METACOL_DEFINITION
// Meta System Collection
= "<collection name=\"" + METACOL + "\">"
+ " <collections>"
// Meta Collections
+ " <collection name=\"" + METAS + "\" compressed=\"true\">"
+ " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
+ " <collections>"
// Add Meta collections for System collections to avoid eternal loop during initialization
+ " <collection name=\"" + SystemCollection.SYSCOL + "\">"
+ " <collections>"
// Meta for Symbol Tables Collection
+ " <collection name=\"" + SystemCollection.SYMBOLS + "\" compressed=\"true\">"
+ " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
+ " <symbols>"
+ " <symbol name=\"meta\" nsuri=\"http://apache.org/xindice/metadata\" id=\"0\" />"
+ " <symbol name=\"xmlns\" nsuri=\"http://www.w3.org/2000/xmlns/\" id=\"1\" />"
+ " <symbol name=\"system\" nsuri=\"http://apache.org/xindice/metadata\" id=\"2\" />"
+ " <symbol name=\"type\" id=\"3\" />"
+ " <symbol name=\"attr\" nsuri=\"http://apache.org/xindice/metadata\" id=\"4\" />"
+ " <symbol name=\"name\" id=\"5\" />"
+ " <symbol name=\"value\" id=\"6\" />"
+ " </symbols>"
+ " </collection>"
// System Configuration Collection
+ " <collection name=\"" + SystemCollection.CONFIGS + "\" compressed=\"false\">"
+ " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
+ " </collection>"
+ " </collections>"
+ " </collection>"
+ " </collections>"
+ " </collection>"
+ " </collections>"
+ "</collection>";
private String dbCanonicalName;
// private String sysCanonicalName;
public MetaSystemCollection(Database db) {
super(db);
// Set the canonical names
dbCanonicalName = db.getCanonicalName();
// sysCanonicalName = db.getSystemCollection().getCanonicalName();
}
public void init() throws DBException {
// Bootstrap the Meta Collection
try {
Document metaDoc = DOMParser.toDocument(METACOL_DEFINITION);
Configuration metaCfg = new Configuration(metaDoc, false);
setConfig(metaCfg);
} catch (Exception e) {
if (log.isFatalEnabled()) {
log.fatal("FATAL ERROR: Generating System Collection '" + METACOL + "'", e);
}
System.exit(1);
}
}
/**
* Returns the corresponding Meta Collection for the given
* collection, optionally creating the hierarchy
*
* @param collection the collection whose meta you want
* @param create whether or not to create the meta if its missing
* @return collection the meta collection for the requested collection
*/
public Collection getMetaCollection(Collection collection, boolean create) throws DBException {
String path = collection.getCanonicalName();
// different database
if (!path.startsWith(dbCanonicalName)) {
return null;
}
// this is the meta collection
if (path.startsWith(getCanonicalName())) {
return null;
}
// this is the system collection
// if (path.startsWith(sysCanonicalName)) {
// return null;
// }
Collection current = getCollection(METAS);
StringTokenizer st = new StringTokenizer(path.substring(dbCanonicalName.length()), "/");
while (current != null && st.hasMoreTokens()) {
String segment = st.nextToken().trim();
if (segment.length() == 0) {
continue;
}
Collection childcol = current.getCollection(segment);
if (null == childcol) {
if (!create) {
return null;
}
String cfgText
= "<collection name=\"" + segment + "\" compressed=\"true\">"
+ " <filer class=\"org.apache.xindice.core.filer.BTreeFiler\" />"
+ "</collection>";
try {
Document cfgDoc = DOMParser.toDocument(cfgText);
Configuration cfg = new Configuration(cfgDoc, false);
childcol = current.createCollection(segment, cfg);
} catch (DBException de) {
throw de;
} catch (Exception e) {
throw new DBException(FaultCodes.getFaultCode(e));
}
}
current = childcol;
}
return current;
}
/**
* dropCollectionMeta removes the MetaData for the specified
* Collection.
*
* @param collection The Collection whose meta is required
*/
public void dropCollectionMeta(Collection collection) throws DBException {
Collection mcol = getMetaCollection(collection, false);
if (null != mcol) {
try {
dropCollection(mcol);
} catch (DBException e) {
if (log.isWarnEnabled()) {
log.warn("ignored exception", e);
}
}
}
}
/**
* getCollectionMeta retrieves the MetaData for the specified
* Collection. Assumption is that the corresponding collection
* must already exist.
*
* @param collection The Collection whose meta is required
* @return The requested MetaData
*/
public MetaData getCollectionMeta(Collection collection) throws DBException {
Collection mcol = getMetaCollection(collection, true);
if (null != mcol) {
MetaData meta = (MetaData) mcol.getObject(COLLECTION_META_DATA);
if (meta == null) {
meta = new MetaData();
}
if (meta.getType() == MetaData.UNKNOWN) {
meta.setType(MetaData.COLLECTION);
}
meta.setOwner(collection.getCanonicalName());
meta.setDirty(false);
return meta;
}
return null;
}
/**
* setCollectionMeta save the Meta for the specified Collection.
*
* @param collection The Collection that owns the MetaData
* @param meta The MetaData
*/
public void setCollectionMeta(Collection collection, MetaData meta) throws DBException {
if (null == meta) {
return;
}
Collection mcol = getMetaCollection(collection, true);
if (null != mcol) {
mcol.setObject(COLLECTION_META_DATA, meta);
meta.setDirty(false);
}
}
/**
* dropDocumentMeta removes the MetaData for the specified
* Document.
*
* @param collection The Collection whose meta is required
* @param id the Document id
*/
public void dropDocumentMeta(Collection collection, String id) throws DBException {
Collection mcol = getMetaCollection(collection, false);
if (null != mcol) {
try {
mcol.remove(id);
} catch (DBException e) {
if (log.isWarnEnabled()) {
log.warn("ignored exception", e);
}
}
}
}
/**
* getDocumentMeta retrieves the MetaData for the specified
* document.
*
* @param collection The Collection whose meta is required
* @param id the ID
* @return The requested MetaData
*/
public MetaData getDocumentMeta(Collection collection, String id) throws DBException {
Collection mcol = getMetaCollection(collection, true);
if (null != mcol) {
MetaData meta = (MetaData) mcol.getObject(id);
if (meta == null) {
meta = new MetaData();
}
if (meta.getType() == MetaData.UNKNOWN) {
meta.setType(MetaData.DOCUMENT);
}
meta.setOwner(collection.getCanonicalName() + "/" + id);
meta.setDirty(false);
return meta;
}
return null;
}
/**
* setDocumentMeta save the Meta for the specified Collection.
*
* @param collection The Collection that owns the MetaData
* @param id
* @param meta The MetaData
*/
public void setDocumentMeta(Collection collection, String id, MetaData meta) throws DBException {
if (null == meta) {
return;
}
Collection mcol = getMetaCollection(collection, true);
if (null != mcol) {
mcol.setObject(id, meta);
meta.setDirty(false);
}
}
}