blob: 4f5fc933f2b84d29c9420df6e9c375799cbc8e7c [file] [log] [blame]
/*
* 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.
*/
package org.apache.oodt.cas.catalog.system;
//JDK imports
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
//OODT imports
import org.apache.oodt.cas.catalog.exception.CatalogDictionaryException;
import org.apache.oodt.cas.catalog.exception.CatalogException;
import org.apache.oodt.cas.catalog.exception.CatalogIndexException;
import org.apache.oodt.cas.catalog.exception.IngestServiceException;
import org.apache.oodt.cas.catalog.page.CatalogReceipt;
import org.apache.oodt.cas.catalog.page.IndexPager;
import org.apache.oodt.cas.catalog.page.IngestReceipt;
import org.apache.oodt.cas.catalog.query.QueryExpression;
import org.apache.oodt.cas.catalog.struct.Dictionary;
import org.apache.oodt.cas.catalog.struct.Index;
import org.apache.oodt.cas.catalog.struct.IngestService;
import org.apache.oodt.cas.catalog.struct.QueryService;
import org.apache.oodt.cas.catalog.struct.TransactionId;
import org.apache.oodt.cas.catalog.struct.TransactionIdFactory;
import org.apache.oodt.cas.catalog.term.Term;
import org.apache.oodt.cas.catalog.term.TermBucket;
import org.apache.oodt.cas.metadata.Metadata;
/**
* @author bfoster
* @version $Revision$
*
* <p>
* A Calatog is a communication interface between the CatalogService and an underlying
* database or index service
* <p>
*/
public class Catalog {
private static Logger LOG = Logger.getLogger(Catalog.class.getName());
protected Vector<Dictionary> dictionaries;
protected Index index;
protected String id;
protected boolean restrictQueryPermissions = true;
protected boolean restrictIngestPermissions = true;
public Catalog(String id, Index index, List<Dictionary> dictionaries, boolean restrictQueryPermissions, boolean restrictIngestPermissions) {
this.id = id;
this.index = index;
if (dictionaries != null)
this.dictionaries = new Vector<Dictionary>(dictionaries);
this.restrictQueryPermissions = restrictQueryPermissions;
this.restrictIngestPermissions = restrictIngestPermissions;
}
public String getId() {
return this.id;
}
public TransactionIdFactory getTransactionIdFactory() throws CatalogIndexException {
return this.index.getTransactionIdFactory();
}
public void setIndex(Index index) {
this.index = index;
}
public void setDictionaries(List<Dictionary> dictionaries) {
this.dictionaries = new Vector<Dictionary>(dictionaries);
}
public List<Dictionary> getDictionaries() {
return Collections.unmodifiableList(this.dictionaries);
}
public void addDictionary(Dictionary dictionary) {
if (this.dictionaries == null)
this.dictionaries = new Vector<Dictionary>();
this.dictionaries.add(dictionary);
}
public void setRestrictQueryPermissions(boolean restrictQueryPermissions) {
this.restrictQueryPermissions = restrictQueryPermissions;
}
public void setRestrictIngestPermissions(boolean restrictIngestPermissions) {
this.restrictIngestPermissions = restrictIngestPermissions;
}
public boolean isQueriable() {
return this.index instanceof QueryService && !this.restrictQueryPermissions;
}
public boolean isIngestable() {
return this.index instanceof IngestService && !this.restrictIngestPermissions;
}
public List<TransactionId<?>> getPage(IndexPager indexPage) throws CatalogIndexException {
return this.index.getPage(indexPage);
}
public TransactionId<?> getTransactionIdFromString(String catalogTransactionId) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException, CatalogIndexException {
return this.getTransactionIdFactory().createTransactionId(catalogTransactionId);
}
public boolean hasTransactionId(TransactionId<?> catalogTransactionid) throws CatalogIndexException {
return this.index.hasTransactionId(catalogTransactionid);
}
public String getProperty(String key) throws CatalogException {
try {
return this.index.getProperty(key);
}catch (Exception e) {
throw new CatalogException("Failed to get property '" + key + "' : " + e.getMessage(), e);
}
}
public Properties getProperties() throws CatalogException {
try {
return this.index.getProperties();
}catch (Exception e) {
throw new CatalogException("Failed to get properties : " + e.getMessage(), e);
}
}
/**
*
* @param transactionId
* @param metadata
* @return TransactionId param if used by underlying catalog, otherwise
* the TransactionId generated and used by underlying catalog. if no
* TermBuckets where created from the Metadata then null is returned
* @throws IngestServiceException
*/
public CatalogReceipt ingest(Metadata metadata) throws CatalogException {
try {
if (this.isIngestable()) {
List<TermBucket> termBuckets = this.getTermBuckets(metadata);
if (termBuckets.size() > 0) {
LOG.log(Level.INFO, "Catalog '" + this + "' attemping ingest metadata");
return new CatalogReceipt(((IngestService) this.index).ingest(termBuckets), this.getId());
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' dictionaries did not generate any TermBuckets from Metadata");
return null;
}
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
return null;
}
}catch (Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public CatalogReceipt update(TransactionId<?> transactionId, Metadata metadata) throws CatalogException {
try {
if (this.isIngestable()) {
List<TermBucket> termBuckets = this.getTermBuckets(metadata);
if (termBuckets.size() > 0) {
LOG.log(Level.INFO, "Catalog '" + this + "' attemping update metadata for catalog TransactionId [id = '" + transactionId + "']");
IngestReceipt ingestReceipt = ((IngestService) this.index).update(transactionId, termBuckets);
if (ingestReceipt != null)
return new CatalogReceipt(ingestReceipt, this.getId());
else
return null;
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' did not generate any TermBuckets from Metadata for catalog TransactionId [id = '" + transactionId + "']");
return null;
}
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
return null;
}
}catch (Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public boolean delete(TransactionId<?> transactionId) throws CatalogException {
try {
if (this.isIngestable()) {
LOG.log(Level.INFO, "Catalog '" + this + "' attemping to delete all TermBuckets associated with catalog TransactionId [id = '" + transactionId + "']");
return ((IngestService) this.index).delete(transactionId);
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
return false;
}
}catch (Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public boolean reduce(TransactionId<?> transactionId, Metadata metadata) throws CatalogException {
try {
if (this.isIngestable()) {
List<TermBucket> termBuckets = this.getTermBuckets(metadata);
if (termBuckets.size() > 0) {
LOG.log(Level.INFO, "Catalog '" + this + "' attemping reduce metadata for catalog TransactionId [id = '" + transactionId + "']");
return ((IngestService) this.index).reduce(transactionId, termBuckets);
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' did not generate any TermBuckets from Metadata for catalog TransactionId [id = '" + transactionId + "'] -- no metadata reduction took place");
return false;
}
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not ingestable");
return false;
}
}catch(Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public List<CatalogReceipt> query(QueryExpression queryExpression) throws CatalogException {
try {
if (this.isQueriable()) {
QueryService queryService = (QueryService) this.index;
List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
for (IngestReceipt ingestReceipt : queryService.query(queryExpression))
catalogReceipts.add(new CatalogReceipt(ingestReceipt, this.getId()));
return Collections.unmodifiableList(catalogReceipts);
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
return Collections.emptyList();
}
}catch (Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public List<CatalogReceipt> query(QueryExpression queryExpression, int startIndex, int endIndex) throws CatalogException {
try {
if (this.isQueriable()) {
QueryService queryService = (QueryService) this.index;
List<CatalogReceipt> catalogReceipts = new Vector<CatalogReceipt>();
for (IngestReceipt ingestReceipt : queryService.query(queryExpression, startIndex, endIndex))
catalogReceipts.add(new CatalogReceipt(ingestReceipt, this.getId()));
return Collections.unmodifiableList(catalogReceipts);
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
return Collections.emptyList();
}
}catch (Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public int sizeOf(QueryExpression queryExpression) throws CatalogException {
try {
if (this.isQueriable()) {
QueryService queryService = (QueryService) this.index;
return queryService.sizeOf(queryExpression);
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
return 0;
}
}catch (Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public Metadata getMetadata(TransactionId<?> transactionId) throws CatalogException {
try {
if (this.isQueriable()) {
QueryService queryService = (QueryService) this.index;
return this.getMetadataFromBuckets(queryService.getBuckets(transactionId));
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
return new Metadata();
}
}catch(Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public Map<TransactionId<?>, Metadata> getMetadata(List<TransactionId<?>> transactionIds) throws CatalogException {
try {
Map<TransactionId<?>, Metadata> metadataMap = new HashMap<TransactionId<?>, Metadata>();
if (this.isQueriable()) {
QueryService queryService = (QueryService) this.index;
Map<TransactionId<?>, List<TermBucket>> termBucketMap = queryService.getBuckets(transactionIds);
for (TransactionId<?> transactionId : termBucketMap.keySet())
metadataMap.put(transactionId, this.getMetadataFromBuckets(termBucketMap.get(transactionId)));
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' is not queriable");
}
return metadataMap;
}catch(Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
public boolean isInterested(QueryExpression queryExpression) throws CatalogException {
try {
if (this.dictionaries != null) {
for (Dictionary dictionary : this.dictionaries)
if (dictionary.understands(queryExpression))
return true;
return false;
}else {
return true;
}
}catch(Exception e) {
throw new CatalogException(e.getMessage(), e);
}
}
protected Metadata getMetadataFromBuckets(List<TermBucket> termBuckets) throws CatalogDictionaryException {
Metadata metadata = new Metadata();
for (TermBucket termBucket : termBuckets) {
if (this.dictionaries != null) {
for (Dictionary dictionary : this.dictionaries)
metadata.addMetadata(dictionary.reverseLookup(termBucket));
}else {
metadata.addMetadata(this.asMetadata(termBuckets));
}
}
return metadata;
}
protected Metadata asMetadata(List<TermBucket> termBuckets) {
Metadata m = new Metadata();
for (TermBucket bucket : termBuckets)
for (Term term : bucket.getTerms())
m.addMetadata(term.getName(), term.getValues());
return m;
}
protected List<TermBucket> getTermBuckets(Metadata metadata) throws CatalogDictionaryException {
List<TermBucket> termBuckets = new Vector<TermBucket>();
if (this.dictionaries != null) {
for (Dictionary dictionary : this.dictionaries) {
TermBucket termBucket = dictionary.lookup(metadata);
if (termBucket != null)
termBuckets.add(termBucket);
}
}else {
LOG.log(Level.WARNING, "Catalog '" + this + "' has no dictionaries defined, attempting to send all Metadata in a default TermBucket");
TermBucket bucket = new TermBucket();
for (String key : metadata.getAllKeys())
bucket.addTerm(new Term(key, metadata.getAllMetadata(key)));
termBuckets.add(bucket);
}
return termBuckets;
}
public int hashCode() {
return this.toString().hashCode();
}
public boolean equals(Object obj) {
if (obj instanceof Catalog)
return ((Catalog) obj).getId().equals(this.getId());
else if (obj instanceof String)
return this.getId().equals((String) obj);
else
return false;
}
public String toString() {
return this.getId();
}
}