/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id: MetaSystemCollection.java 541508 2007-05-25 01:54:12Z vgritsenko $
*/
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 $Revision: 541508 $, $Date: 2007-05-24 21:54:12 -0400 (Thu, 24 May 2007) $
*/
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'>"
+ " </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
* @throws DBException if unable to get meta 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
* @throws DBException if unable to delete collection meta data
*/
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
* @throws DBException if unable to retrieve collection meta data
*/
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
* @throws DBException if unable to update collection meta data
*/
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 meta data for the specified
* document.
*
* @param collection Document collection
* @param id Document key
* @throws DBException if unable to delete document meta data
*/
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 meta data for the specified
* document.
*
* @param collection Document collection
* @param id Document key
* @return The requested MetaData
* @throws DBException if unable to retrieve document meta data
*/
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 sets the meta data for the specified document.
*
* @param collection Document collection
* @param id Document key
* @param meta New document meta data
* @throws DBException if unable to update document meta data
*/
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);
}
}
}