/******************************************************************************* * Copyright (c) 2011 Arapiki Solutions Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * "Peter Smith <psmith@arapiki.com>" - initial API and * implementation and/or initial documentation *******************************************************************************/ package com.buildml.model.impl; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.buildml.model.FatalBuildStoreError; import com.buildml.model.IFileIncludeMgr; /** * A manager class (that supports the BuildStore class) that manages all BuildStore * information on the relationship between paths. That is, if one file in the build * system "includes" another file, the relationship is recorded by this class. * <p> * There should be exactly one FileIncludeMgr object per BuildStore object. Use the * BuildStore's getFileIncludeMgr() method to obtain that one instance. * * @author "Peter Smith <psmith@arapiki.com>" */ /* package private */ class FileIncludeMgr implements IFileIncludeMgr { /*=====================================================================================* * TYPES/FIELDS *=====================================================================================*/ /** * Our database manager object, used to access the database content. This is provided * to us when the FileIncludeMgr object is first instantiated. */ private BuildStoreDB db = null; /** * Various prepared statements for database access. */ private PreparedStatement insertFileIncludesPrepStmt = null, updateFileIncludesPrepStmt = null, deleteFileIncludesPrepStmt = null, deleteFilesIncludedByPrepStmt = null, selectUsageFromFileIncludesPrepStmt = null, selectTotalUsageFromFileIncludesPrepStmt = null, selectFile1FromFileIncludesPrepStmt = null, selectFile2FromFileIncludesPrepStmt = null; /*=====================================================================================* * CONSTRUCTORS *=====================================================================================*/ /** * Create a new FileIncludeMgr manager object. * * @param buildStore The BuildStore object that owns this FileIncludeMgr object. */ public FileIncludeMgr(BuildStore buildStore) { this.db = buildStore.getBuildStoreDB(); /* create prepared database statements */ insertFileIncludesPrepStmt = db.prepareStatement("insert into fileIncludes values (?, ?, 1)"); updateFileIncludesPrepStmt = db.prepareStatement("update fileIncludes set usage = usage + 1 " + "where fileId1 = ? and fileId2 = ?"); deleteFileIncludesPrepStmt = db.prepareStatement( "delete from fileIncludes where fileId1 = ? and fileId2 = ?"); deleteFilesIncludedByPrepStmt = db.prepareStatement("delete from fileIncludes where fileId1 = ?"); selectUsageFromFileIncludesPrepStmt = db.prepareStatement( "select usage from fileIncludes where fileId1 = ? and fileId2 = ?"); selectTotalUsageFromFileIncludesPrepStmt = db.prepareStatement( "select sum(usage) from fileIncludes where fileId2 = ?"); selectFile1FromFileIncludesPrepStmt = db.prepareStatement( "select fileId1 from fileIncludes where fileId2 = ?"); selectFile2FromFileIncludesPrepStmt = db.prepareStatement( "select fileId2 from fileIncludes where fileId1 = ?"); } /*=====================================================================================* * PUBLIC METHODS *=====================================================================================*/ /* (non-Javadoc) * @see com.buildml.model.impl.IFileIncludeMgr#addFileIncludes(int, int) */ @Override public void addFileIncludes(int file1, int file2) { try { updateFileIncludesPrepStmt.setInt(1, file1); updateFileIncludesPrepStmt.setInt(2, file2); int rowCount = db.executePrepUpdate(updateFileIncludesPrepStmt); if (rowCount == 0) { insertFileIncludesPrepStmt.setInt(1, file1); insertFileIncludesPrepStmt.setInt(2, file2); db.executePrepUpdate(insertFileIncludesPrepStmt); } } catch (SQLException e) { throw new FatalBuildStoreError("Unable to execute SQL statement", e); } } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see com.buildml.model.impl.IFileIncludeMgr#getFileIncludesCount(int, int) */ @Override public int getFileIncludesCount(int file1, int file2) { Integer results[]; try { selectUsageFromFileIncludesPrepStmt.setInt(1, file1); selectUsageFromFileIncludesPrepStmt.setInt(2, file2); results = db.executePrepSelectIntegerColumn(selectUsageFromFileIncludesPrepStmt); } catch (SQLException e) { throw new FatalBuildStoreError("Unable to execute SQL statement", e); } /* if there's no entry at all, return a 0 usage count */ if (results.length == 0) { return 0; } /* if there's one entry, that's good - just return that number. */ if (results.length == 1) { return results[0]; } /* else, problem - too many records */ throw new FatalBuildStoreError("Too many records in includes table for " + file1 + "/" + file2); } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see com.buildml.model.impl.IFileIncludeMgr#getTotalFileIncludedCount(int) */ @Override public int getTotalFileIncludedCount(int file) { ResultSet rs; int usageCount = 0; try { selectTotalUsageFromFileIncludesPrepStmt.setInt(1, file); rs = db.executePrepSelectResultSet(selectTotalUsageFromFileIncludesPrepStmt); /* if there's no entry at all, return a 0 usage count */ if (rs.next()) { usageCount = rs.getInt(1); } rs.close(); } catch (SQLException e) { throw new FatalBuildStoreError("Unable to execute SQL statement", e); } return usageCount; } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see com.buildml.model.impl.IFileIncludeMgr#getFilesThatInclude(int) */ @Override public Integer[] getFilesThatInclude(int fileId) { Integer results[]; try { selectFile1FromFileIncludesPrepStmt.setInt(1, fileId); results = db.executePrepSelectIntegerColumn(selectFile1FromFileIncludesPrepStmt); } catch (SQLException e) { throw new FatalBuildStoreError("Unable to execute SQL statement", e); } return results; } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see com.buildml.model.impl.IFileIncludeMgr#getFilesIncludedBy(int) */ @Override public Integer[] getFilesIncludedBy(int fileId) { Integer results[]; try { selectFile2FromFileIncludesPrepStmt.setInt(1, fileId); results = db.executePrepSelectIntegerColumn(selectFile2FromFileIncludesPrepStmt); } catch (SQLException e) { throw new FatalBuildStoreError("Unable to execute SQL statement", e); } return results; } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see com.buildml.model.IFileIncludeMgr#deleteFileIncludes(int, int) */ @Override public void removeFileIncludes(int pathId1, int pathId2) { try { deleteFileIncludesPrepStmt.setInt(1, pathId1); deleteFileIncludesPrepStmt.setInt(2, pathId2); db.executePrepUpdate(deleteFileIncludesPrepStmt); } catch (SQLException e) { throw new FatalBuildStoreError("Unable to execute SQL statement", e); } } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see com.buildml.model.impl.IFileIncludeMgr#deleteFilesIncludedBy(int) */ @Override public void removeFilesIncludedBy(int pathId) { try { deleteFilesIncludedByPrepStmt.setInt(1, pathId); db.executePrepUpdate(deleteFilesIncludedByPrepStmt); } catch (SQLException e) { throw new FatalBuildStoreError("Unable to execute SQL statement", e); } } /*=====================================================================================*/ }