| /* |
| * 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.filemgr.catalog; |
| |
| //OODT imports |
| import org.apache.oodt.cas.filemgr.structs.BooleanQueryCriteria; |
| import org.apache.oodt.cas.filemgr.structs.Element; |
| import org.apache.oodt.cas.filemgr.structs.Product; |
| import org.apache.oodt.cas.filemgr.structs.ProductPage; |
| import org.apache.oodt.cas.filemgr.structs.ProductType; |
| import org.apache.oodt.cas.filemgr.structs.Query; |
| import org.apache.oodt.cas.filemgr.structs.QueryCriteria; |
| import org.apache.oodt.cas.filemgr.structs.RangeQueryCriteria; |
| import org.apache.oodt.cas.filemgr.structs.Reference; |
| import org.apache.oodt.cas.filemgr.structs.TermQueryCriteria; |
| import org.apache.oodt.cas.filemgr.structs.exceptions.CatalogException; |
| import org.apache.oodt.cas.filemgr.structs.exceptions.ValidationLayerException; |
| import org.apache.oodt.cas.filemgr.util.DbStructFactory; |
| import org.apache.oodt.cas.filemgr.validation.ValidationLayer; |
| import org.apache.oodt.cas.metadata.Metadata; |
| import org.apache.oodt.commons.pagination.PaginationUtils; |
| import org.apache.oodt.commons.util.DateConvert; |
| |
| //SPRING imports |
| import org.springframework.util.StringUtils; |
| |
| |
| |
| //JDK imports |
| import java.sql.Connection; |
| import java.sql.ResultSet; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| import java.util.Date; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.TreeMap; |
| import java.util.UUID; |
| import java.util.Vector; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| import javax.sql.DataSource; |
| |
| /** |
| * @author mattmann |
| * @author bfoster |
| * @author luca |
| * @version $Revision$ |
| * |
| * <p> |
| * Implementation of a {@link Catalog} that is backed by a {@link DataSource} |
| * front-end to a SQL DBMS. |
| * </p> |
| * |
| */ |
| public class DataSourceCatalog implements Catalog { |
| |
| /* our sql data source */ |
| protected DataSource dataSource = null; |
| |
| /* our log stream */ |
| private static final Logger LOG = Logger.getLogger(DataSourceCatalog.class.getName()); |
| |
| /* our validation layer */ |
| private ValidationLayer validationLayer = null; |
| |
| /* boolean flag on whether or not product type id and element id are strings */ |
| protected boolean fieldIdStringFlag = false; |
| |
| /* size of pages of products within the catalog */ |
| protected int pageSize = -1; |
| |
| /* flag to indicate whether the "product_id" key type should be treated as a string */ |
| boolean productIdString = false; |
| |
| protected boolean orderedValues = false; |
| |
| /* |
| * cache of products per product type: [productTypeId]=>([ISO8601 time of |
| * last update]=>[List of products]) |
| */ |
| private static TreeMap<String, TreeMap<String, Object>> PRODUCT_CACHE = new TreeMap<String, TreeMap<String, Object>>(); |
| |
| /* |
| * the amount of minutes inbetween the time in which we should update the |
| * PRODUCT_CACHE |
| */ |
| private long cacheUpdateMinutes = 0L; |
| |
| /** |
| * <p> |
| * Default Constructor |
| * </p>. |
| * @throws |
| */ |
| public DataSourceCatalog(DataSource ds, ValidationLayer valLayer, |
| boolean fieldId, int pageSize, long cacheUpdateMin, boolean productIdString, boolean orderedValues) { |
| this.dataSource = ds; |
| this.validationLayer = valLayer; |
| fieldIdStringFlag = fieldId; |
| this.pageSize = pageSize; |
| cacheUpdateMinutes = cacheUpdateMin; |
| this.productIdString = productIdString; |
| this.orderedValues = orderedValues; |
| } |
| |
| /** |
| * Constructor that assumes productIdString=false |
| * to support current subclasses. |
| * @param ds |
| * @param valLayer |
| * @param fieldId |
| * @param pageSize |
| * @param cacheUpdateMin |
| */ |
| public DataSourceCatalog(DataSource ds, ValidationLayer valLayer, |
| boolean fieldId, int pageSize, long cacheUpdateMin) { |
| this(ds, valLayer, fieldId, pageSize, cacheUpdateMin, false, false); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addMetadata(org.apache.oodt.cas.metadata.Metadata, |
| * org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public synchronized void addMetadata(Metadata m, Product product) |
| throws CatalogException { |
| List<Element> metadataTypes = null; |
| |
| try { |
| metadataTypes = validationLayer.getElements(product |
| .getProductType()); |
| } catch (ValidationLayerException e) { |
| e.printStackTrace(); |
| throw new CatalogException( |
| "ValidationLayerException when trying to obtain element list for product type: " |
| + product.getProductType().getName() |
| + ": Message: " + e.getMessage()); |
| } |
| |
| for (Iterator<Element> i = metadataTypes.iterator(); i.hasNext();) { |
| Element element = i.next(); |
| List<String> values = m.getAllMetadata(element.getElementName()); |
| |
| if (values == null) { |
| LOG.log(Level.WARNING, "No Metadata specified for product [" |
| + product.getProductName() + "] for required field [" |
| + element.getElementName() |
| + "]: Attempting to continue processing metadata"); |
| continue; |
| } |
| |
| for (Iterator<String> j = values.iterator(); j.hasNext();) { |
| String value = j.next(); |
| |
| try { |
| addMetadataValue(element, product, value); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG |
| .log( |
| Level.WARNING, |
| "Exception ingesting metadata. Error inserting field: [" |
| + element.getElementId() |
| + "=>" |
| + value |
| + "]: for product: [" |
| + product.getProductName() |
| + "]: Message: " |
| + e.getMessage() |
| + ": Attempting to continue processing metadata"); |
| } |
| } |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addMetadata(org.apache.oodt.cas.metadata.Metadata, |
| * org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public synchronized void removeMetadata(Metadata m, Product product) |
| throws CatalogException { |
| List<Element> metadataTypes = null; |
| |
| try { |
| metadataTypes = validationLayer.getElements(product |
| .getProductType()); |
| } catch (ValidationLayerException e) { |
| e.printStackTrace(); |
| throw new CatalogException( |
| "ValidationLayerException when trying to obtain element list for product type: " |
| + product.getProductType().getName() |
| + ": Message: " + e.getMessage()); |
| } |
| |
| for (Iterator<Element> i = metadataTypes.iterator(); i.hasNext();) { |
| Element element = i.next(); |
| List<String> values = m.getAllMetadata(element.getElementName()); |
| |
| if (values != null) { |
| for (Iterator<String> j = values.iterator(); j.hasNext();) { |
| String value = j.next(); |
| |
| try { |
| removeMetadataValue(element, product, value); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG |
| .log( |
| Level.WARNING, |
| "Exception removing metadata. Error deleting field: [" |
| + element.getElementId() |
| + "=>" |
| + value |
| + "]: for product: [" |
| + product.getProductName() |
| + "]: Message: " |
| + e.getMessage() |
| + ": Attempting to continue processing metadata"); |
| } |
| } |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addProduct(org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public synchronized void addProduct(Product product) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| String addProductSql = null; |
| String productTypeIdStr = null; |
| |
| if (fieldIdStringFlag) { |
| productTypeIdStr = "'" |
| + product.getProductType().getProductTypeId() + "'"; |
| } else { |
| productTypeIdStr = product.getProductType().getProductTypeId(); |
| } |
| |
| if (productIdString==false) { |
| |
| addProductSql = "INSERT INTO products (product_name, product_structure, product_transfer_status, product_type_id) " |
| + "VALUES ('" |
| + product.getProductName() |
| + "', '" |
| + product.getProductStructure() |
| + "', '" |
| + product.getTransferStatus() |
| + "', " |
| + productTypeIdStr |
| + ")"; |
| |
| LOG.log(Level.FINE, "addProduct: Executing: " + addProductSql); |
| statement.execute(addProductSql); |
| |
| // read "product_id" value that was automatically assigned by the database |
| String productId = new String(); |
| |
| String getProductIdSql = "SELECT MAX(product_id) AS max_id FROM products"; |
| |
| rs = statement.executeQuery(getProductIdSql); |
| |
| while (rs.next()) { |
| productId = String.valueOf(rs.getInt("max_id")); |
| } |
| |
| product.setProductId(productId); |
| conn.commit(); |
| |
| } else { |
| |
| // reuse the existing product id if possible, or generate a new UUID string |
| String productId = product.getProductId(); |
| if (!StringUtils.hasText(productId)) productId = UUID.randomUUID().toString(); |
| // insert product in database |
| addProductSql = "INSERT INTO products (product_id, product_name, product_structure, product_transfer_status, product_type_id, product_datetime) " |
| + "VALUES ('" |
| + productId |
| + "', '" |
| + product.getProductName() |
| + "', '" |
| + product.getProductStructure() |
| + "', '" |
| + product.getTransferStatus() |
| + "', " |
| + productTypeIdStr |
| +", now()" |
| + ")"; |
| |
| LOG.log(Level.FINE, "addProduct: Executing: " + addProductSql); |
| statement.execute(addProductSql); |
| |
| product.setProductId(productId); |
| conn.commit(); |
| |
| } |
| |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception adding product. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback addProduct transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#modifyProduct(org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public synchronized void modifyProduct(Product product) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| String modifyProductSql = "UPDATE products SET product_name='" |
| + product.getProductName() + "', product_structure='" |
| + product.getProductStructure() |
| + "', product_transfer_status='" |
| + product.getTransferStatus() + "' " |
| + "WHERE product_id = " + quoteIt(product.getProductId()); |
| |
| LOG |
| .log(Level.FINE, "modifyProduct: Executing: " |
| + modifyProductSql); |
| statement.execute(modifyProductSql); |
| conn.commit(); |
| |
| // now update the refs |
| updateReferences(product); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception modifying product. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback modifyProduct transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#removeProduct(org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public synchronized void removeProduct(Product product) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| String deleteProductSql = "DELETE FROM products WHERE product_id = " |
| + quoteIt(product.getProductId()); |
| |
| LOG |
| .log(Level.FINE, "removeProduct: Executing: " |
| + deleteProductSql); |
| statement.execute(deleteProductSql); |
| deleteProductSql = "DELETE FROM " |
| + product.getProductType().getName() + "_metadata " |
| + " WHERE product_id = " + quoteIt(product.getProductId()); |
| LOG |
| .log(Level.FINE, "removeProduct: Executing: " |
| + deleteProductSql); |
| statement.execute(deleteProductSql); |
| deleteProductSql = "DELETE FROM " |
| + product.getProductType().getName() + "_reference " |
| + " WHERE product_id = " + quoteIt(product.getProductId()); |
| LOG |
| .log(Level.FINE, "removeProduct: Executing: " |
| + deleteProductSql); |
| statement.execute(deleteProductSql); |
| conn.commit(); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception removing product. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback removeProduct transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#setProductTransferStatus(org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public synchronized void setProductTransferStatus(Product product) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| String modifyProductSql = "UPDATE products SET product_transfer_status='" |
| + product.getTransferStatus() |
| + "' " |
| + "WHERE product_id = " + quoteIt(product.getProductId()); |
| |
| LOG.log(Level.FINE, "setProductTransferStatus: Executing: " |
| + modifyProductSql); |
| statement.execute(modifyProductSql); |
| conn.commit(); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, |
| "Exception setting transfer status for product. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback setProductTransferStatus transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#addProductReferences(org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public synchronized void addProductReferences(Product product) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| String productRefTable = product.getProductType().getName() |
| + "_reference"; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| for (Iterator<Reference> i = product.getProductReferences().iterator(); i |
| .hasNext();) { |
| Reference r = i.next(); |
| |
| String addRefSql = "INSERT INTO " |
| + productRefTable |
| + " " |
| + "(product_id, product_orig_reference, product_datastore_reference, product_reference_filesize, product_reference_mimetype) " |
| + "VALUES (" |
| + quoteIt(product.getProductId()) |
| + ", '" |
| + r.getOrigReference() |
| + "', '" |
| + r.getDataStoreReference() |
| + "', " |
| + r.getFileSize() |
| + ",'" |
| + ((r.getMimeType() == null) ? "" : r.getMimeType() |
| .getName()) + "')"; |
| |
| LOG.log(Level.FINE, "addProductReferences: Executing: " |
| + addRefSql); |
| statement.execute(addRefSql); |
| } |
| |
| conn.commit(); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, |
| "Exception adding product references. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback addProductReferences transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductById(java.lang.String) |
| */ |
| public Product getProductById(String productId) throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| Product product = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String getProductSql = "SELECT * " + "FROM products " |
| + "WHERE product_id = " + quoteIt(productId); |
| |
| LOG.log(Level.FINE, "getProductById: Executing: " + getProductSql); |
| rs = statement.executeQuery(getProductSql); |
| |
| while (rs.next()) { |
| product = DbStructFactory.getProduct(rs, false, productIdString); |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting product. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback getProductById transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return product; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductByName(java.lang.String) |
| */ |
| public Product getProductByName(String productName) throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| Product product = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String getProductSql = "SELECT products.* " + "FROM products " |
| + "WHERE product_name = '" + productName + "'"; |
| |
| LOG |
| .log(Level.FINE, "getProductByName: Executing: " |
| + getProductSql); |
| rs = statement.executeQuery(getProductSql); |
| |
| while (rs.next()) { |
| product = DbStructFactory.getProduct(rs, false, productIdString); |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting product. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback getProductByName transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return product; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductReferences(org.apache.oodt.cas.filemgr.structs.Product) |
| */ |
| public List<Reference> getProductReferences(Product product) throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| List<Reference> references = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String getProductRefSql = "SELECT * FROM " |
| + product.getProductType().getName() + "_reference" |
| + " WHERE product_id = " + quoteIt(product.getProductId()); |
| |
| if(this.orderedValues) getProductRefSql += " ORDER BY pkey"; |
| |
| LOG.log(Level.FINE, "getProductReferences: Executing: " |
| + getProductRefSql); |
| rs = statement.executeQuery(getProductRefSql); |
| |
| references = new Vector<Reference>(); |
| while (rs.next()) { |
| Reference r = DbStructFactory.getReference(rs); |
| references.add(r); |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting product type. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback getProductTypeById transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return references; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProducts() |
| */ |
| public List<Product> getProducts() throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| List<Product> products = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String getProductSql = "SELECT products.* " + "FROM products " |
| + "ORDER BY products.product_id DESC"; |
| |
| LOG.log(Level.FINE, "getProducts: Executing: " + getProductSql); |
| rs = statement.executeQuery(getProductSql); |
| products = new Vector<Product>(); |
| |
| while (rs.next()) { |
| Product product = DbStructFactory.getProduct(rs, false, productIdString); |
| products.add(product); |
| } |
| |
| if (products.size() == 0) { |
| products = null; |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting products. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback getProductstransaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return products; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getProductsByProductType(org.apache.oodt.cas.filemgr.structs.ProductType) |
| */ |
| public List<Product> getProductsByProductType(ProductType type) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| List<Product> products = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String getProductSql = null; |
| String productTypeIdStr = null; |
| |
| if (fieldIdStringFlag) { |
| productTypeIdStr = "'" + type.getProductTypeId() + "'"; |
| } else { |
| productTypeIdStr = type.getProductTypeId(); |
| } |
| |
| getProductSql = "SELECT products.* " + "FROM products " |
| + "WHERE products.product_type_id = " + productTypeIdStr; |
| |
| LOG.log(Level.FINE, "getProductsByProductType: Executing: " |
| + getProductSql); |
| rs = statement.executeQuery(getProductSql); |
| products = new Vector<Product>(); |
| |
| while (rs.next()) { |
| Product product = DbStructFactory.getProduct(rs, false, productIdString); |
| products.add(product); |
| } |
| |
| if (products.size() == 0) { |
| products = null; |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting products. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback getProductsByProductType transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return products; |
| } |
| |
| public Metadata getMetadata(Product product) throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| Metadata m = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String metadataSql = "SELECT * FROM " |
| + product.getProductType().getName() + "_metadata" |
| + " WHERE product_id = " + quoteIt(product.getProductId()); |
| |
| if(this.orderedValues) metadataSql += " ORDER BY pkey"; |
| |
| LOG.log(Level.FINE, "getMetadata: Executing: " + metadataSql); |
| rs = statement.executeQuery(metadataSql); |
| |
| m = new Metadata(); |
| List<Element> elements = null; |
| |
| try { |
| elements = validationLayer.getElements(product.getProductType()); |
| } catch (ValidationLayerException e) { |
| e.printStackTrace(); |
| throw new CatalogException( |
| "ValidationLayerException when trying to obtain element list for product type: " |
| + product.getProductType().getName() |
| + ": Message: " + e.getMessage()); |
| } |
| |
| while (rs.next()) { |
| for (Iterator<Element> i = elements.iterator(); i.hasNext();) { |
| Element e = i.next(); |
| |
| // right now, we just support STRING |
| String elemValue = rs.getString("metadata_value"); |
| String elemId = rs.getString("element_id"); |
| |
| if (elemId.equals(e.getElementId())) { |
| elemValue = (elemValue != null ? elemValue : ""); |
| m.addMetadata(e.getElementName(), elemValue); |
| } |
| } |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting metadata. Message: " |
| + e.getMessage()); |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return m; |
| } |
| |
| public Metadata getReducedMetadata(Product product, List<String> elems) throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| Metadata m = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String elementIds = ""; |
| if (elems.size() > 0) { |
| elementIds += " AND (element_id = '" + this.validationLayer.getElementByName(elems.get(0)).getElementId() + "'"; |
| for (int i = 1; i < elems.size(); i++) |
| elementIds += " OR element_id = '" + this.validationLayer.getElementByName(elems.get(i)).getElementId() + "'"; |
| elementIds += ")"; |
| } |
| String metadataSql = "SELECT element_id,metadata_value FROM " |
| + product.getProductType().getName() + "_metadata" |
| + " WHERE product_id = " + quoteIt(product.getProductId()) + elementIds; |
| if(this.orderedValues) metadataSql += " ORDER BY pkey"; |
| |
| LOG.log(Level.FINE, "getMetadata: Executing: " + metadataSql); |
| rs = statement.executeQuery(metadataSql); |
| |
| m = new Metadata(); |
| List<Element> elements = null; |
| |
| try { |
| elements = validationLayer.getElements(product.getProductType()); |
| } catch (ValidationLayerException e) { |
| e.printStackTrace(); |
| throw new CatalogException( |
| "ValidationLayerException when trying to obtain element list for product type: " |
| + product.getProductType().getName() |
| + ": Message: " + e.getMessage()); |
| } |
| |
| while (rs.next()) { |
| for (Iterator<Element> i = elements.iterator(); i.hasNext();) { |
| Element e = i.next(); |
| |
| // right now, we just support STRING |
| String elemValue = rs.getString("metadata_value"); |
| String elemId = rs.getString("element_id"); |
| |
| if (elemId.equals(e.getElementId())) { |
| elemValue = (elemValue != null ? elemValue : ""); |
| m.addMetadata(e.getElementName(), elemValue); |
| } |
| } |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting metadata. Message: " |
| + e.getMessage()); |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return m; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#query(org.apache.oodt.cas.filemgr.structs.Query |
| * org.apache.oodt.cas.filemgr.structs.ProductType) |
| */ |
| public List<String> query(Query query, ProductType type) throws CatalogException { |
| return paginateQuery(query, type, -1); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getTopNProducts(int) |
| */ |
| public List<Product> getTopNProducts(int n) throws CatalogException { |
| return getTopNProducts(n, null); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getTopNProducts(int, |
| * org.apache.oodt.cas.filemgr.structs.ProductType) |
| */ |
| public List<Product> getTopNProducts(int n, ProductType type) |
| throws CatalogException { |
| List<Product> products = null; |
| |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| statement.setMaxRows(n); |
| |
| String getProductSql = "SELECT products.* " + "FROM products "; |
| |
| if (type != null && type.getProductTypeId() != null) { |
| if (fieldIdStringFlag) { |
| getProductSql += "WHERE products.product_type_id = '" |
| + type.getProductTypeId() + "' "; |
| } else { |
| getProductSql += "WHERE products.product_type_id = " |
| + type.getProductTypeId() + " "; |
| } |
| |
| } |
| |
| getProductSql += "ORDER BY products.product_id DESC"; |
| |
| LOG.log(Level.FINE, "getTopNProducts: executing: " + getProductSql); |
| |
| rs = statement.executeQuery(getProductSql); |
| products = new Vector<Product>(); |
| |
| while (rs.next()) { |
| Product product = DbStructFactory.getProduct(rs, false, productIdString); |
| products.add(product); |
| } |
| |
| if (products.size() == 0) { |
| products = null; |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, |
| "Exception getting top N products. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback get top N products. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return products; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getValidationLayer() |
| */ |
| public ValidationLayer getValidationLayer() throws CatalogException { |
| // note that validationLayer may be null to allow for leniency in subclasses |
| return validationLayer; |
| } |
| |
| private synchronized void addMetadataValue(Element element, |
| Product product, String value) throws CatalogException { |
| |
| Connection conn = null; |
| Statement statement = null; |
| |
| String metadataTable = product.getProductType().getName() + "_metadata"; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| // build up the sql statement |
| StringBuffer insertClauseSql = new StringBuffer(); |
| StringBuffer valueClauseSql = new StringBuffer(); |
| |
| insertClauseSql.append("INSERT INTO " + metadataTable |
| + " (product_id, element_id, metadata_value) "); |
| valueClauseSql.append("VALUES "); |
| |
| // now do the value clause |
| if (fieldIdStringFlag) { |
| valueClauseSql.append("(" + product.getProductId() + ", '" |
| + element.getElementId() + "', '" + value + "')"); |
| } else { |
| valueClauseSql.append("(" + product.getProductId() + ", " |
| + element.getElementId() + ", '" + value + "')"); |
| } |
| |
| String metaIngestSql = insertClauseSql.toString() |
| + valueClauseSql.toString(); |
| LOG |
| .log(Level.FINE, "addMetadataValue: Executing: " |
| + metaIngestSql); |
| statement.execute(metaIngestSql); |
| conn.commit(); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception adding metadata value. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback add metadata value. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| } |
| |
| private synchronized void removeMetadataValue(Element element, |
| Product product, String value) throws CatalogException { |
| |
| Connection conn = null; |
| Statement statement = null; |
| |
| String metadataTable = product.getProductType().getName() + "_metadata"; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| // build up the sql statement |
| String metRemoveSql = "DELETE FROM " + metadataTable + " WHERE "; |
| if (fieldIdStringFlag) { |
| metRemoveSql += "PRODUCT_ID = '" + product.getProductId() |
| + "' AND "; |
| metRemoveSql += "ELEMENT_ID = '" + element.getElementId() |
| + "' AND "; |
| metRemoveSql += "METADATA_VALUE = '" + value + "'"; |
| } else { |
| metRemoveSql += "PRODUCT_ID = " + product.getProductId() |
| + " AND "; |
| metRemoveSql += "ELEMENT_ID = " + element.getElementId() |
| + " AND "; |
| metRemoveSql += "METADATA_VALUE = " + value; |
| } |
| |
| LOG.log(Level.FINE, "removeMetadataValue: Executing: " |
| + metRemoveSql); |
| statement.execute(metRemoveSql); |
| conn.commit(); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, |
| "Exception removing metadata value. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback remove metadata value. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#getNumProducts(org.apache.oodt.cas.filemgr.structs.ProductType) |
| */ |
| public int getNumProducts(ProductType type) throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| int numProducts = -1; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| String getProductSql = "SELECT COUNT(products.product_id) AS numProducts " |
| + "FROM products "; |
| |
| if (fieldIdStringFlag) { |
| getProductSql += "WHERE products.product_type_id = '" |
| + type.getProductTypeId() + "' "; |
| } else { |
| getProductSql += "WHERE products.product_type_id = " |
| + type.getProductTypeId() + " "; |
| } |
| |
| LOG.log(Level.FINE, "getNumProducts: executing: " + getProductSql); |
| |
| rs = statement.executeQuery(getProductSql); |
| |
| while (rs.next()) { |
| numProducts = rs.getInt("numProducts"); |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception getting num products. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback get num products. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return numProducts; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.util.Pagination#getFirstPage(org.apache.oodt.cas.filemgr.structs.ProductType) |
| */ |
| public ProductPage getFirstPage(ProductType type) { |
| Query query = new Query(); |
| ProductPage firstPage = null; |
| |
| try { |
| firstPage = pagedQuery(query, type, 1); |
| } catch (CatalogException e) { |
| LOG.log(Level.WARNING, "Exception getting first page: Message: " |
| + e.getMessage()); |
| } |
| return firstPage; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.util.Pagination#getLastProductPage(org.apache.oodt.cas.filemgr.structs.ProductType) |
| */ |
| public ProductPage getLastProductPage(ProductType type) { |
| ProductPage lastPage = null; |
| ProductPage firstPage = getFirstPage(type); |
| Query query = new Query(); |
| try { |
| lastPage = pagedQuery(query, type, firstPage.getTotalPages()); |
| } catch (CatalogException e) { |
| LOG.log(Level.WARNING, "Exception getting last page: Message: " |
| + e.getMessage()); |
| } |
| |
| return lastPage; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.util.Pagination#getNextPage(org.apache.oodt.cas.filemgr.structs.ProductType, |
| * org.apache.oodt.cas.filemgr.structs.ProductPage) |
| */ |
| public ProductPage getNextPage(ProductType type, ProductPage currentPage) { |
| if (currentPage == null) { |
| return getFirstPage(type); |
| } |
| |
| if (currentPage.isLastPage()) { |
| return currentPage; |
| } |
| |
| ProductPage nextPage = null; |
| Query query = new Query(); |
| |
| try { |
| nextPage = pagedQuery(query, type, currentPage.getPageNum() + 1); |
| } catch (CatalogException e) { |
| LOG.log(Level.WARNING, "Exception getting next page: Message: " |
| + e.getMessage()); |
| } |
| |
| return nextPage; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.util.Pagination#getPrevPage(org.apache.oodt.cas.filemgr.structs.ProductType, |
| * org.apache.oodt.cas.filemgr.structs.ProductPage) |
| */ |
| public ProductPage getPrevPage(ProductType type, ProductPage currentPage) { |
| if (currentPage == null) { |
| return getFirstPage(type); |
| } |
| |
| if (currentPage.isFirstPage()) { |
| return currentPage; |
| } |
| ProductPage prevPage = null; |
| Query query = new Query(); |
| |
| try { |
| prevPage = pagedQuery(query, type, currentPage.getPageNum() - 1); |
| } catch (CatalogException e) { |
| LOG.log(Level.WARNING, "Exception getting prev page: Message: " |
| + e.getMessage()); |
| } |
| |
| return prevPage; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.oodt.cas.filemgr.catalog.Catalog#pagedQuery(org.apache.oodt.cas.filemgr.structs.Query, |
| * org.apache.oodt.cas.filemgr.structs.ProductType, int) |
| */ |
| public ProductPage pagedQuery(Query query, ProductType type, int pageNum) |
| throws CatalogException { |
| int totalPages = PaginationUtils.getTotalPage(getResultListSize(query, |
| type), this.pageSize); |
| |
| /* |
| * if there are 0 total pages in the result list size then don't bother |
| * returning a valid product page instead, return blank ProductPage |
| */ |
| if (totalPages == 0) { |
| return ProductPage.blankPage(); |
| } |
| |
| ProductPage retPage = new ProductPage(); |
| retPage.setPageNum(pageNum); |
| retPage.setPageSize(this.pageSize); |
| retPage.setTotalPages(totalPages); |
| |
| List<String> productIds = paginateQuery(query, type, pageNum); |
| |
| if (productIds != null && productIds.size() > 0) { |
| List<Product> products = new Vector<Product>(productIds.size()); |
| |
| for (Iterator<String> i = productIds.iterator(); i.hasNext();) { |
| String productId = i.next(); |
| Product p = getProductById(productId); |
| products.add(p); |
| } |
| |
| retPage.setPageProducts(products); |
| } |
| |
| return retPage; |
| } |
| |
| protected int getResultListSize(Query query, ProductType type) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| int resultCount = 0; |
| |
| try { |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(); |
| |
| String getProductSql = ""; |
| String tableName = type.getName() + "_metadata"; |
| String subSelectQueryBase = "SELECT product_id FROM " + tableName |
| + " "; |
| StringBuffer selectClause = new StringBuffer( |
| "SELECT COUNT(DISTINCT p.product_id) AS numResults "); |
| StringBuffer fromClause = new StringBuffer("FROM " + tableName |
| + " p "); |
| StringBuffer whereClause = new StringBuffer("WHERE "); |
| |
| boolean gotFirstClause = false; |
| int clauseNum = 0; |
| |
| if (query.getCriteria() != null && query.getCriteria().size() > 0) { |
| for (Iterator<QueryCriteria> i = query.getCriteria().iterator(); i.hasNext();) { |
| QueryCriteria criteria = i.next(); |
| clauseNum++; |
| |
| String elementIdStr = null; |
| |
| if (fieldIdStringFlag) { |
| elementIdStr = "'" + this.validationLayer.getElementByName(criteria.getElementName()).getElementId() + "'"; |
| } else { |
| elementIdStr = this.validationLayer.getElementByName(criteria.getElementName()).getElementId(); |
| } |
| |
| String clause = null; |
| |
| if (!gotFirstClause) { |
| clause = "(p.element_id = " + elementIdStr + " AND "; |
| if (criteria instanceof TermQueryCriteria) { |
| clause += " metadata_value LIKE '%" |
| + ((TermQueryCriteria) criteria).getValue() |
| + "%') "; |
| } else if (criteria instanceof RangeQueryCriteria) { |
| String startVal = ((RangeQueryCriteria) criteria) |
| .getStartValue(); |
| String endVal = ((RangeQueryCriteria) criteria) |
| .getEndValue(); |
| boolean inclusive = ((RangeQueryCriteria) criteria) |
| .getInclusive(); |
| |
| if ((startVal != null && !startVal.equals("")) |
| || (endVal != null && !endVal.equals(""))) { |
| clause += " metadata_value "; |
| |
| boolean gotStart = false; |
| |
| if (startVal != null && !startVal.equals("")) { |
| if (inclusive) |
| clause += ">= '" + startVal + "'"; |
| else |
| clause += "> '" + startVal + "'"; |
| gotStart = true; |
| } |
| |
| if (endVal != null && !endVal.equals("")) { |
| if (gotStart) { |
| if (inclusive) |
| clause += " AND metadata_value <= '" |
| + endVal + "'"; |
| else |
| clause += " AND metadata_value < '" |
| + endVal + "'"; |
| } else if (inclusive) |
| clause += "<= '" + endVal + "'"; |
| else |
| clause += "< '" + endVal + "'"; |
| } |
| |
| clause += ") "; |
| } |
| } |
| whereClause.append(clause); |
| gotFirstClause = true; |
| } else { |
| String subSelectTblName = "p" + clauseNum; |
| String subSelectQuery = subSelectQueryBase |
| + "WHERE (element_id = " + elementIdStr |
| + " AND "; |
| if (criteria instanceof TermQueryCriteria) { |
| subSelectQuery += " metadata_value LIKE '%" |
| + ((TermQueryCriteria) criteria).getValue() |
| + "%')"; |
| } else if (criteria instanceof RangeQueryCriteria) { |
| String startVal = ((RangeQueryCriteria) criteria) |
| .getStartValue(); |
| String endVal = ((RangeQueryCriteria) criteria) |
| .getEndValue(); |
| |
| if (startVal != null || endVal != null) { |
| subSelectQuery += " metadata_value "; |
| |
| boolean gotStart = false; |
| |
| if (startVal != null && !startVal.equals("")) { |
| subSelectQuery += ">= '" + startVal + "'"; |
| gotStart = true; |
| } |
| |
| if (endVal != null && !endVal.equals("")) { |
| if (gotStart) { |
| subSelectQuery += " AND metadata_value <= '" |
| + endVal + "'"; |
| } else |
| subSelectQuery += "<= '" + endVal + "'"; |
| } |
| |
| subSelectQuery += ") "; |
| |
| } |
| } |
| |
| fromClause.append("INNER JOIN (" + subSelectQuery |
| + ") " + subSelectTblName + " ON " |
| + subSelectTblName |
| + ".product_id = p.product_id "); |
| |
| } |
| } |
| } |
| |
| getProductSql = selectClause.toString() + fromClause.toString(); |
| if (gotFirstClause) { |
| getProductSql += whereClause.toString(); |
| } |
| |
| |
| LOG.log(Level.FINE, "catalog get num results: executing: " |
| + getProductSql); |
| |
| rs = statement.executeQuery(getProductSql); |
| |
| while (rs.next()) { |
| resultCount = rs.getInt("numResults"); |
| } |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, |
| "Exception performing get num results. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback get num results transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| return resultCount; |
| } |
| |
| private boolean stillFresh(String productTypeId) { |
| Date currentTime = new Date(); |
| |
| if (PRODUCT_CACHE.get(productTypeId) == null) { |
| return false; |
| } else { |
| TreeMap<String, Object> productListAndUpdateTime = PRODUCT_CACHE |
| .get(productTypeId); |
| String lastUpdateTime = (String) productListAndUpdateTime |
| .get("lastUpdateTime"); |
| Date lastUpdateTimeDate = null; |
| |
| try { |
| lastUpdateTimeDate = DateConvert.isoParse(lastUpdateTime); |
| |
| long timeDifferenceMilis = currentTime.getTime() |
| - lastUpdateTimeDate.getTime(); |
| long timeDifferenceSeconds = timeDifferenceMilis * 1000; |
| long timeDifferenceMinutes = timeDifferenceSeconds / 60; |
| |
| if (timeDifferenceMinutes >= cacheUpdateMinutes) { |
| return false; |
| } else { |
| return true; |
| } |
| } catch (Exception e) { |
| LOG.log(Level.WARNING, |
| "Unable to parse last update time for product type: [" |
| + productTypeId + "]: Message: " |
| + e.getMessage()); |
| return false; |
| } |
| } |
| |
| } |
| |
| @SuppressWarnings("unchecked") |
| private List<Product> getProductsFromCache(String productTypeId) { |
| List<Product> products = null; |
| |
| if (PRODUCT_CACHE.get(productTypeId) == null) { |
| return null; |
| } else { |
| TreeMap<String, Object> productListAndUpdateTime = PRODUCT_CACHE |
| .get(productTypeId); |
| products = (List<Product>) productListAndUpdateTime.get("productList"); |
| } |
| |
| return products; |
| } |
| |
| private void flagCacheUpdate(String productTypeId, List<Product> products) { |
| Date currentDateTime = new Date(); |
| String isoDateStr = DateConvert.isoFormat(currentDateTime); |
| TreeMap<String, Object> productListAndUpdateTime = new TreeMap<String, Object>(); |
| productListAndUpdateTime.put("productList", products); |
| productListAndUpdateTime.put("lastUpdateTime", isoDateStr); |
| PRODUCT_CACHE.put(productTypeId, productListAndUpdateTime); |
| } |
| |
| @SuppressWarnings("unused") |
| private List<Product> getProductsByProductTypeCached(ProductType type) { |
| List<Product> products = null; |
| // check the product cache first |
| if (stillFresh(type.getProductTypeId())) { |
| products = getProductsFromCache(type.getProductTypeId()); |
| } else { |
| // go get a fresh set |
| try { |
| products = getProductsByProductType(type); |
| flagCacheUpdate(type.getProductTypeId(), products); |
| } catch (CatalogException e) { |
| LOG.log(Level.WARNING, |
| "CatalogException getting cached products for type: [" |
| + type.getProductTypeId() + "]: Message: " |
| + e.getMessage()); |
| return products; |
| } |
| } |
| |
| return products; |
| } |
| |
| private List<String> paginateQuery(Query query, ProductType type, int pageNum) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| boolean doSkip = true; |
| int numResults = -1; |
| |
| if (pageNum == -1) { |
| doSkip = false; |
| } else { |
| numResults = getResultListSize(query, type); |
| } |
| |
| try { |
| |
| conn = dataSource.getConnection(); |
| statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, |
| ResultSet.CONCUR_READ_ONLY); |
| |
| String getProductSql = null; |
| |
| if (!productIdString) { |
| |
| if (query.getCriteria().size() == 0) { |
| getProductSql = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata"; |
| }else if (query.getCriteria().size() == 1) { |
| getProductSql = this.getSqlQuery(query.getCriteria().get(0), type); |
| }else { |
| getProductSql = this.getSqlQuery(new BooleanQueryCriteria(query.getCriteria(), BooleanQueryCriteria.AND), type); |
| } |
| getProductSql += " ORDER BY product_id DESC "; |
| |
| } else { |
| |
| if (query.getCriteria().size() == 0) { |
| getProductSql = "SELECT DISTINCT products.product_id FROM products, " + type.getName() + "_metadata" |
| + " WHERE products.product_id="+type.getName() + "_metadata.product_id"; |
| } else if (query.getCriteria().size() == 1) { |
| getProductSql = this.getSqlQuery(query.getCriteria().get(0), type); |
| } else { |
| getProductSql = this.getSqlQuery(new BooleanQueryCriteria(query.getCriteria(), BooleanQueryCriteria.AND), type); |
| } |
| getProductSql += " ORDER BY products.product_datetime DESC "; |
| |
| } |
| |
| LOG.log(Level.FINE, "catalog query: executing: " + getProductSql); |
| |
| rs = statement.executeQuery(getProductSql); |
| |
| List<String> productIds = new Vector<String>(); |
| if (doSkip) { |
| int startNum = (pageNum - 1) * pageSize; |
| |
| if (startNum > numResults) { |
| startNum = 0; |
| } |
| |
| // must call next first, or else no relative cursor |
| if (rs.next()) { |
| // grab the first one |
| int numGrabbed = -1; |
| |
| if (pageNum == 1) { |
| numGrabbed = 1; |
| productIds.add(rs.getString("product_id")); |
| } else { |
| numGrabbed = 0; |
| } |
| |
| // now move the cursor to the correct position |
| if (pageNum != 1) { |
| rs.relative(startNum - 1); |
| } |
| |
| // grab the rest |
| while (rs.next() && numGrabbed < pageSize) { |
| String productId = rs.getString("product_id"); |
| productIds.add(productId); |
| numGrabbed++; |
| } |
| } |
| |
| } else { |
| while (rs.next()) { |
| String productId = rs.getString("product_id"); |
| productIds.add(productId); |
| } |
| } |
| |
| return productIds; |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, "Exception performing query. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback query transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| } |
| |
| protected String getSqlQuery(QueryCriteria queryCriteria, ProductType type) throws ValidationLayerException, CatalogException { |
| String sqlQuery = null; |
| if (queryCriteria instanceof BooleanQueryCriteria) { |
| BooleanQueryCriteria bqc = (BooleanQueryCriteria) queryCriteria; |
| if (bqc.getOperator() == BooleanQueryCriteria.NOT) { |
| if (!this.productIdString) { |
| sqlQuery = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata WHERE product_id NOT IN (" + this.getSqlQuery(bqc.getTerms().get(0), type) + ")"; |
| } else { |
| sqlQuery = "SELECT DISTINCT products.product_id FROM products," + type.getName() + "_metadata" |
| + " WHERE products.product_id="+type.getName() + "_metadata.product_id" |
| + " AND products.product_id NOT IN (" + this.getSqlQuery(bqc.getTerms().get(0), type) + ")"; |
| } |
| }else { |
| sqlQuery = "(" + this.getSqlQuery(bqc.getTerms().get(0), type); |
| String op = bqc.getOperator() == BooleanQueryCriteria.AND ? "INTERSECT" : "UNION"; |
| for (int i = 1; i < bqc.getTerms().size(); i++) |
| sqlQuery += ") " + op + " (" + this.getSqlQuery(bqc.getTerms().get(i), type); |
| sqlQuery += ")"; |
| } |
| }else { |
| String elementIdStr = this.validationLayer.getElementByName(queryCriteria.getElementName()).getElementId(); |
| if (fieldIdStringFlag) |
| elementIdStr = "'" + elementIdStr + "'"; |
| if (!this.productIdString) { |
| sqlQuery = "SELECT DISTINCT product_id FROM " + type.getName() + "_metadata WHERE element_id = " + elementIdStr + " AND "; |
| } else { |
| sqlQuery = "SELECT DISTINCT products.product_id FROM products," + type.getName() + "_metadata" |
| + " WHERE products.product_id="+type.getName() + "_metadata.product_id" |
| + " AND element_id = " + elementIdStr + " AND "; |
| } |
| if (queryCriteria instanceof TermQueryCriteria) { |
| sqlQuery += "metadata_value = '" + ((TermQueryCriteria) queryCriteria).getValue() + "'"; |
| } else if (queryCriteria instanceof RangeQueryCriteria) { |
| RangeQueryCriteria rqc = (RangeQueryCriteria) queryCriteria; |
| String rangeSubQuery = null; |
| if (rqc.getStartValue() != null) |
| rangeSubQuery = "metadata_value" + (rqc.getInclusive() ? " >= " : " > ") + "'" + rqc.getStartValue() + "'"; |
| if (rqc.getEndValue() != null) { |
| if (rangeSubQuery == null) |
| rangeSubQuery = "metadata_value" + (rqc.getInclusive() ? " <= " : " < ") + "'" + rqc.getEndValue() + "'"; |
| else |
| rangeSubQuery = "(" + rangeSubQuery + " AND metadata_value" + (rqc.getInclusive() ? " <= " : " < ") + "'" + rqc.getEndValue() + "')"; |
| } |
| sqlQuery += rangeSubQuery; |
| } else { |
| throw new CatalogException("Invalid QueryCriteria [" + queryCriteria.getClass().getCanonicalName() + "]"); |
| } |
| } |
| |
| return sqlQuery; |
| } |
| |
| private synchronized void updateReferences(Product product) |
| throws CatalogException { |
| Connection conn = null; |
| Statement statement = null; |
| ResultSet rs = null; |
| |
| String productRefTable = product.getProductType().getName() |
| + "_reference"; |
| |
| try { |
| conn = dataSource.getConnection(); |
| conn.setAutoCommit(false); |
| statement = conn.createStatement(); |
| |
| // first remove the refs |
| String deleteProductSql = "DELETE FROM " |
| + product.getProductType().getName() + "_reference " |
| + " WHERE product_id = " + quoteIt(product.getProductId()); |
| LOG.log(Level.FINE, "updateProductReferences: Executing: " |
| + deleteProductSql); |
| statement.execute(deleteProductSql); |
| |
| // now add the new ones back in |
| for (Iterator<Reference> i = product.getProductReferences().iterator(); i |
| .hasNext();) { |
| Reference r = i.next(); |
| |
| String addRefSql = "INSERT INTO " |
| + productRefTable |
| + " " |
| + "(product_id, product_orig_reference, product_datastore_reference, product_reference_filesize," |
| + "product_reference_mimetype) " + "VALUES (" |
| + product.getProductId() + ", '" + r.getOrigReference() |
| + "', '" + r.getDataStoreReference() + "', " |
| + r.getFileSize() + ",'" + r.getMimeType().getName() |
| + "')"; |
| |
| LOG.log(Level.FINE, "updateProductReferences: Executing: " |
| + addRefSql); |
| statement.execute(addRefSql); |
| } |
| |
| conn.commit(); |
| |
| } catch (Exception e) { |
| e.printStackTrace(); |
| LOG.log(Level.WARNING, |
| "Exception updating product references. Message: " |
| + e.getMessage()); |
| try { |
| conn.rollback(); |
| } catch (SQLException e2) { |
| LOG.log(Level.SEVERE, |
| "Unable to rollback updateProductReferences transaction. Message: " |
| + e2.getMessage()); |
| } |
| throw new CatalogException(e.getMessage()); |
| } finally { |
| |
| if (rs != null) { |
| try { |
| rs.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| rs = null; |
| } |
| |
| if (statement != null) { |
| try { |
| statement.close(); |
| } catch (SQLException ignore) { |
| } |
| |
| statement = null; |
| } |
| |
| if (conn != null) { |
| try { |
| conn.close(); |
| |
| } catch (SQLException ignore) { |
| } |
| |
| conn = null; |
| } |
| } |
| |
| } |
| |
| /** |
| * Utility method to quote the "productId" value |
| * if the column type is "string". |
| * @param productId |
| * @return |
| */ |
| protected String quoteIt(String productId) { |
| if (this.productIdString) { |
| return "'"+productId+"'"; |
| } else { |
| return productId; |
| } |
| } |
| |
| } |