src/main/java/gov/nysenate/openleg/dao/base/SqlBaseDao.java
return schema() + "." + tableName;
    /**
     * Outputs the ORDER BY clause for multiple column name and sort order pairs.
     * @param columnNames List<String>
     * @param sortOrders List<SortOrder>>
     * @return String
     */
    protected String orderBy(List<String> columnNames, List<SortOrder> sortOrders) {
        if (columnNames.size() != sortOrders.size()) {
            throw new IllegalArgumentException("For order by clause, number of column names must match sort orders!");
String schema()
Bill bill  SOBIFragment sobiFragment
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
// Update the bill record
        MapSqlParameterSource billParams = getBillParams(bill, sobiFragment);
        if (jdbcNamed.update(SqlBillQuery.UPDATE_BILL_SQL.getSql(schema()), billParams) == 0) {
            jdbcNamed.update(SqlBillQuery.INSERT_BILL_SQL.getSql(schema()), billParams);
void updateBill(Bill bill, SOBIFragment sobiFragment)
BillAction action : existingBillActions
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
MapSqlParameterSource actionParams = getBillActionParams(action, sobiFragment);
            jdbcNamed.update(SqlBillQuery.DELETE_BILL_ACTION_SQL.getSql(schema()), actionParams);
list
        for (BillAction action : existingBillActions)
BillAction action : newBillActions
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
MapSqlParameterSource actionParams = getBillActionParams(action, sobiFragment);
            jdbcNamed.update(SqlBillQuery.INSERT_BILL_ACTION_SQL.getSql(schema()), actionParams);
actions
        for (BillAction action : newBillActions)
Bill bill
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
void deleteBill(Bill bill)
Bill bill
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
void publishBill(Bill bill)
Bill bill
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
void unPublishBill(Bill bill)
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
void deleteAllBills()
Bill bill  SOBIFragment fragment
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("printNo", bill.getPrintNo());
        params.addValue("sessionYear", bill.getSession());
        params.addValue("title", bill.getTitle());
        params.addValue("lawSection", bill.getLawSection());
        params.addValue("lawCode", bill.getLaw());
        params.addValue("summary", bill.getSummary());
        params.addValue("activeVersion", bill.getActiveVersion());
        params.addValue("sponsorId", null /**TODO */);
        params.addValue("activeYear", bill.getYear());
        params.addValue("modifiedDateTime", toTimestamp(bill.getModifiedDate()));
        params.addValue("publishedDateTime", toTimestamp(bill.getPublishDate()));
        addSOBIFragmentParams(fragment, params);
        return params;
MapSqlParameterSource getBillParams(Bill bill, SOBIFragment fragment)
BillAmendment amendment  SOBIFragment fragment
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("printNo", amendment.getBaseBillPrintNo());
        params.addValue("sessionYear", amendment.getSession());
        params.addValue("version", amendment.getVersion());
        params.addValue("sponsorMemo", amendment.getMemo());
        params.addValue("actClause", amendment.getActClause());
        params.addValue("fullText", amendment.getFulltext());
        params.addValue("stricken", amendment.isStricken());
        params.addValue("currentCommitteeId", null);
        params.addValue("uniBill", amendment.isUniBill());
        params.addValue("modifiedDateTime", toTimestamp(amendment.getModifiedDate()));
        params.addValue("publishedDateTime", toTimestamp(amendment.getPublishDate()));
        addSOBIFragmentParams(fragment, params);
        return params;
MapSqlParameterSource getBillAmendmentParams(BillAmendment amendment, SOBIFragment fragment)
BillAction billAction  SOBIFragment fragment
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("printNo", billAction.getBaseBillPrintNo());
        params.addValue("sessionYear", billAction.getSession());
        params.addValue("version", billAction.getAmendmentVersion());
        params.addValue("effectDate", billAction.getDate());
        params.addValue("text", billAction.getText());
        params.addValue("modifiedDateTime", toTimestamp(billAction.getModifiedDate()));
        params.addValue("publishedDateTime", toTimestamp(billAction.getPublishDate()));
        addSOBIFragmentParams(fragment, params);
        return params;
MapSqlParameterSource getBillActionParams(BillAction billAction, SOBIFragment fragment)
BillAmendment billAmendment  BillId sameAs  SOBIFragment fragment
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("printNo", billAmendment.getBaseBillPrintNo());
        params.addValue("sessionYear", billAmendment.getSession());
        params.addValue("version", billAmendment.getVersion());
        params.addValue("sameAsPrintNo", sameAs.getBasePrintNo());
        params.addValue("sameAsSessionYear", sameAs.getSession());
        params.addValue("sameAsVersion", sameAs.getVersion());
        addSOBIFragmentParams(fragment, params);
        return params;
MapSqlParameterSource getBillSameAsParams(BillAmendment billAmendment, BillId sameAs, SOBIFragment fragment)
SOBIFragment fragment  MapSqlParameterSource params
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
params.addValue("lastFragmentFileName", fragment.getFileName());
        params.addValue("lastFragmentType", fragment.getType().name());
void addSOBIFragmentParams(SOBIFragment fragment, MapSqlParameterSource params)
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFileDao.java
public SOBIFileRowMapper()
String pfx
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFileDao.java
this.pfx = pfx;
        @Override
        public SOBIFile mapRow(ResultSet rs, int rowNum) throws SQLException {
            String fileName = rs.getString(pfx + "file_name");
            Date publishedDateTime = rs.getDate(pfx + "published_date_time");
            boolean pendingProcessing = rs.getBoolean(pfx + "pending_processing");
            File file = getSOBIFileFromFileSystem(fileName, publishedDateTime, pendingProcessing);
            try {
                SOBIFile sobiFile = new SOBIFile(file);
                sobiFile.setPendingProcessing(pendingProcessing);
                sobiFile.setProcessedDateTime(rs.getDate(pfx + "processed_date_time"));
                sobiFile.setProcessedCount(rs.getInt(pfx + "processed_count"));
                return sobiFile;
            catch (FileNotFoundException ex) {
                logger.error("SOBI file " + rs.getString("file_name") + " was not found in the expected location! \n" +
                        "This could be a result of modifications to the sobi file directory that were not synced with " +
                        "the database. ", ex);
public SOBIFileRowMapper(String pfx)
String fileName  Date publishedDateTime  boolean pendingProcessing
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFileDao.java
return (pendingProcessing) ? getFileInWorkingDirectory(fileName) : getFileInArchiveDirectory(fileName, publishedDateTime);
     * Moves the file into the working SOBI file directory.
     * @param file File
    private void moveFileToWorking(File file) throws IOException {
        File workingFile = getFileInWorkingDirectory(file.getName());
        if (workingFile.exists()) {
            FileUtils.deleteQuietly(workingFile);
        FileUtils.moveFile(file, workingFile);
File getSOBIFileFromFileSystem(String fileName, Date publishedDateTime, boolean pendingProcessing)
String fileName  Date publishedDateTime
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFileDao.java
FileUtils.deleteQuietly(getFileInWorkingDirectory(fileName));
        FileUtils.deleteQuietly(getFileInArchiveDirectory(fileName, publishedDateTime));
     * @param publishedDateTime Date
    private File getFileInArchiveDirectory(String fileName, Date publishedDateTime) {
        String year = Integer.toString(new LocalDate(publishedDateTime).getYear());
     * Returns a MapSqlParameterSource with columns mapped to SOBIFile values for use in update/insert queries.
        params.addValue("stagedDateTime", toTimestamp(sobiFile.getStagedDateTime()));
void deleteSOBIFileFromFileSystem(String fileName, Date publishedDateTime)
SOBIFragmentType fragmentType  String fragmentFileName
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFragmentDao.java
MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("sobiFragmentType", fragmentType.name());
        params.addValue("fileName", fragmentFileName);
        return jdbcNamed.queryForObject(GET_SOBI_FRAGMENT_BY_FILE_NAME_SQL, params, new SOBIFragmentRowMapper());
    /** {@inheritDoc
SOBIFragment getSOBIFragment(SOBIFragmentType fragmentType, String fragmentFileName)
List<SOBIFragment> fragments
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFragmentDao.java
for (SOBIFragment fragment : fragments) {
            // Set a unique file name for this fragment
            fragment.setFileName(createFileNameForFragment(fragment));
            // Persist the meta data of the fragment in the database
            MapSqlParameterSource params = new MapSqlParameterSource();
            params.addValue("sobiFileName", fragment.getParentSOBIFile().getFileName());
            params.addValue("fragmentFileName", fragment.getFileName());
            params.addValue("publishedDateTime", toTimestamp(fragment.getPublishedDateTime()));
            params.addValue("sobiFragmentType", fragment.getType().name());
            params.addValue("fileCounter", fragment.getCounter());
            params.addValue("text", fragment.getText().replace('\0', ' '));
            if (jdbcNamed.update(UPDATE_SOBI_FRAGMENT_SQL, params) == 0) {
                jdbcNamed.update(INSERT_SOBI_FRAGMENT_SQL, params);
void saveSOBIFragments(List<SOBIFragment> fragments)
SOBIFile sobiFile
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFragmentDao.java
MapSqlParameterSource params = new MapSqlParameterSource("sobiFileName", sobiFile.getFileName());
        jdbcNamed.update(DELETE_SOBI_FRAGMENTS_SQL, params);
void deleteSOBIFragments(SOBIFile sobiFile)
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFragmentDao.java
this("", Collections.<SOBIFile>emptyList());
public SOBIFragmentRowMapper()
SOBIFile sobiFile
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFragmentDao.java
this("", Arrays.asList(sobiFile));
public SOBIFragmentRowMapper(SOBIFile sobiFile)
String pfx  List<SOBIFile> sobiFiles
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFragmentDao.java
this.pfx = pfx;
            for (SOBIFile sobiFile : sobiFiles) {
                this.sobiFileMap.put(sobiFile.getFileName(), sobiFile);
public SOBIFragmentRowMapper(String pfx, List<SOBIFile> sobiFiles)
String source
src/main/java/gov/nysenate/openleg/model/BaseObject.java
dataSources.add(source);
void addDataSource(String source)
String printNo  int sessionYear
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.printNo = printNo;
        this.session = sessionYear;
        this.year = sessionYear;
    /** --- Functional Getters/Setter --- */

     * Indicates if this bill is currently set to the base version.
    public static boolean isBaseVersion(String version) {
     * Creates a unique id for the bill by using printNo and session year, e.g S1234-2013
    public String getBillId() {
        return this.printNo + "-" + this.session;
     * Indicate if this bill is a resolution by checking that it's not a senate/assembly bill.
     * @return - True if this bill is a resolution of some sort.
    public boolean isResolution() {
        return this.printNo.charAt(0) != 'A' && this.printNo.charAt(0) != 'S';
     * Creates a unique id for the bill with padding to resemble LBDC's representation.
    public String getPaddedBillId() {
        return this.getPaddedPrintNumber() + "-" + this.getSession();
     * Returns the print number padded with 5 zeros, e.g S01234. This is how LBDC represents
     * print numbers in their SOBI files.
    public String getPaddedPrintNumber() {
        Matcher billIdMatcher = printNumberPattern.matcher(this.getPrintNo());
            return String.format("%s%05d%s", billIdMatcher.group(1), Integer.parseInt(billIdMatcher.group(2)),
                                             billIdMatcher.group(3));
        return "";
     * Retrieves an amendment stored in this bill using the version as the key.
     * @return BillAmendment if found, null otherwise
    public BillAmendment getAmendment(String version) {
     * Retrieves a list of all amendments stored in this bill.
     * @return - List<BillAmendment>
    public List<BillAmendment> getAmendmentList() {
     * @param billAmendment - Amendment to add to this bill.
    public void addAmendment(BillAmendment billAmendment) {
    /**
     * Associate a list of amendments with this bill.
     * @param billAmendments - List<Amendment> - Amendments to add to this bill
     */
    public void addAmendments(List<BillAmendment> billAmendments) {
        for (BillAmendment billAmendment : billAmendments) {
            this.addAmendment(billAmendment);
public Bill(String printNo, int sessionYear)
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
this.setBaseBillPrintNo(bill.getPrintNo());
        this.setAmendmentVersion(billAmendment);
    /** --- Functional Getters/Setters --- */
    public int getYear() {
        return new LocalDate(date).getYear();
    /** --- Overrides --- */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BillAction that = (BillAction) o;
        if (baseBillPrintNo != null ? !baseBillPrintNo.equals(that.baseBillPrintNo) : that.baseBillPrintNo != null)
            return false;
        if (amendmentVersion != null ? !amendmentVersion.equals(that.amendmentVersion) : that.amendmentVersion != null) return false;
        if (date != null ? !date.equals(that.date) : that.date != null) return false;
        if (text != null ? !text.equals(that.text) : that.text != null) return false;
        return true;
    @Override
    public int hashCode() {
        int result = baseBillPrintNo != null ? baseBillPrintNo.hashCode() : 0;
        result = 31 * result + (amendmentVersion != null ? amendmentVersion.hashCode() : 0);
        result = 31 * result + (date != null ? date.hashCode() : 0);
        result = 31 * result + (text != null ? text.hashCode() : 0);
        return result;
    public String toString() {
        return date.toString() + " " + text;
    /** --- Helper classes --- */
    /** --- Basic Getters/Setters --- */

    public String getBaseBillPrintNo() {
        return baseBillPrintNo;
public BillAction()
String baseBillPrintNo
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
this.baseBillPrintNo = baseBillPrintNo;
void setBaseBillPrintNo(String baseBillPrintNo)
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
return date;
Date getDate()
Date date
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
this.date = date;
void setDate(Date date)
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
return text;
String getText()
Bill baseBill  String version
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
this.baseBillPrintNo = baseBill.getPrintNo();
    /** --- Functional Getters/Setters --- */

    public String getBillId() {
        return this.baseBillPrintNo + this.version + "-" + this.session;
    public void setVersion(String version) {
        this.version = version.trim().toUpperCase();
    public void updateVote(Vote vote) {
        this.getVotes().remove(vote);
        this.getVotes().add(vote);
public BillAmendment(Bill baseBill, String version)
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
public Set<BillId> getSameAs() {
    public void setSameAs(Set<BillId> sameAs) {
    public String getMemo() {
    public void setMemo(String memo) {
    public String getActClause() {
    public void setActClause(String actClause) {
    public String getFulltext() {
    public void setFulltext(String fulltext) {
    public String getCurrentCommittee() {
    public void setCurrentCommittee(String currentCommittee) {
    public List<Person> getCoSponsors() {
    public void setCoSponsors(List<Person> coSponsors) {
    public List<Person> getMultiSponsors() {
    public void setMultiSponsors(List<Person> multiSponsors) {
    public Boolean isStricken() {
    public void setStricken(Boolean stricken) {
    public Boolean isUniBill() {
    public void setUniBill(Boolean uniBill) {
String getVersion()
String fragmentFileName  SOBIFragmentType type  int startLineNo  String line
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.fragmentFileName = fragmentFileName;
        this.fragmentType = type;
        return (this.fragmentFileName + ":" + this.getStartLineNo() + "-" + this.getEndLineNo());
     * Returns the session year of the bill.
     */
    public int getYear() {
        return (this.billId != null) ? this.billId.getSession() : -1;
public SOBIBlock(String fragmentFileName, SOBIFragmentType type, int startLineNo, String line)
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
return (this.billId != null) ? this.billId.getBasePrintNo() : null;
String getBasePrintNo()
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
return (this.billId != null) ? this.billId.getVersion() : null;
String getAmendment()
String printNo  String version  int session
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.billId = new BillId(printNo.substring(0,1) + Integer.parseInt(printNo.substring(1)),
                                 session, version.trim());
    public String getFragmentFileName() {
        return fragmentFileName;
void setBillId(String printNo, String version, int session)
String fragmentFileName
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.fragmentFileName = fragmentFileName;
void setFragmentFileName(String fragmentFileName)
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
return fragmentType;
SOBIFragmentType getFragmentType()
SOBIFragmentType fragmentType
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.fragmentType = fragmentType;
void setFragmentType(SOBIFragmentType fragmentType)
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFile.java
this.processedCount++;
    public Date getStagedDateTime() {
        return stagedDateTime;
void incrementProcessedCount()
Date stagedDateTime
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFile.java
this.stagedDateTime = stagedDateTime;
void setStagedDateTime(Date stagedDateTime)
SOBIFile parentSOBIFile  SOBIFragmentType type  String text  int counter
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragment.java
this.type = type;
        this.text = text;
        this.counter = counter;
        return type.equals(SOBIFragmentType.BILL);
    public List<SOBIBlock> getSOBIBlocks() {
            List<String> lines = new ArrayList<>(Arrays.asList(this.text.split("\\r?\\n")));
                        block = new SOBIBlock(fileName, type, lineNo, line);
                        SOBIBlock newBlock = new SOBIBlock(fileName, type, lineNo, line);
                                blocks.add(new SOBIBlock(fileName, type, lineNo,
                                           block.getBillHeader() + SOBILineType.LAW.getTypeCode()));
    @Override
    public String toString() {
        return "SOBIFragment{" + "fragmentType=" + type + ", fileName='" + fileName + '\'' +
                ", parentSOBIFile=" + parentSOBIFile + '
public SOBIFragment(SOBIFile parentSOBIFile, SOBIFragmentType type, String text, int counter)
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragment.java
return parentSOBIFile.getPublishedDateTime();
Date getPublishedDateTime()
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragment.java
return parentSOBIFile.getProcessedDateTime();
Date getProcessedDateTime()
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragmentType.java
return isXml;
boolean isXml()
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragmentType.java
return startPattern;
String getStartPattern()
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragmentType.java
return endPattern;
String getEndPattern()
Environment environment
src/main/java/gov/nysenate/openleg/processors/DataProcessor.java
this.environment = environment;

        SqlSOBIFragmentDao fragmentDao = new SqlSOBIFragmentDao(environment);
        this.sobiFileDao = fragmentDao;
        this.sobiFragmentDao = fragmentDao;

        this.processorMap = new HashMap<>();
        this.processorMap.put(SOBIFragmentType.BILL, new BillProcessor(environment));
        this.processorMap.put(SOBIFragmentType.AGENDA, new AgendaProcessor());
        this.processorMap.put(SOBIFragmentType.AGENDA_VOTE, new AgendaVoteProcessor());
        this.processorMap.put(SOBIFragmentType.CALENDAR, new CalendarProcessor());
        this.processorMap.put(SOBIFragmentType.CALENDAR_ACTIVE, new CalendarActiveListProcessor());
        this.processorMap.put(SOBIFragmentType.COMMITTEE, new CommitteeProcessor());
    /** --- Processing methods --- */

     * @throws ParseException
    public void stage(File sourceDir, File workDir) throws IOException, ParseException {
        // Prepares incoming SOBI files for processing
        sobiFileDao.stageSOBIFiles(true);
        // TODO: Stage all hearings to the work directory.
        // TODO: Stage all transcripts
     *
     * @throws IOException, ParseException
    public void collate(File workDir) throws IOException, ParseException {
        for (SOBIFile sobiFile : sobiFileDao.getPendingSOBIFiles(SortOrder.ASC)) {
            StringBuilder billBuffer = new StringBuilder();
            int fragmentCounter = 1;
            List<SOBIFragment> sobiFragments = new ArrayList<>();
            List<String> lines = Arrays.asList(sobiFile.getText().split("\\r?\\n"));
            Iterator<String> lineIterator = lines.iterator();
            // Construct fragments from SOBI text
            while (lineIterator.hasNext()) {
                String line = lineIterator.next();
                SOBIFragmentType fragmentType = getFragmentTypeFromLine(line);
                if (fragmentType != null) {
                    // Bill portions are appended into a single buffer
                    if (fragmentType.equals(SOBIFragmentType.BILL)) {
                        if (line.charAt(11) == 'M') {
                            // Memos are latin1 encoding
                            line = new String(line.getBytes(encoding), "latin1");
public DataProcessor(Environment environment)
Storage storage  List<Entry<String  Change>> changes  List<ServiceBase> services
src/main/java/gov/nysenate/openleg/processors/DataProcessor.java
public void archive(File workingDir, File archiveDir) throws IOException {
    /** --- Internal Methods --- */

    /**
     * Check the given SOBI line to determine if it matches the start of a SOBI Fragment type.
     * @param line String
     * @return SOBIFragmentType or null if no match
     */
    protected SOBIFragmentType getFragmentTypeFromLine(String line) {
        for (SOBIFragmentType fragmentType : SOBIFragmentType.values()) {
            if (line.matches(fragmentType.getStartPattern())) {
                return fragmentType;
void push(Storage storage, List<Entry<String, Change>> changes, List<ServiceBase> services)
cls == Calendar.class
src/main/java/gov/nysenate/openleg/util/Storage.java
//                        value = this.converter.readCalendar(storageFile);
//
else if (cls == Calendar.class)
cls == Transcript.class
src/main/java/gov/nysenate/openleg/util/Storage.java
//                        value = this.converter.readTranscript(storageFile);
//
else if (cls == Transcript.class)
value instanceof Calendar
src/main/java/gov/nysenate/openleg/util/Storage.java
//                    this.converter.write((Calendar)value, storageFile);
//
else if (value instanceof Calendar)
value instanceof Transcript
src/main/java/gov/nysenate/openleg/util/Storage.java
//                    this.converter.write((Transcript)value, storageFile);
//
else if (value instanceof Transcript)
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
super(null);
public SqlBillDao()
Bill bill  SOBIFragment sobiFragment
src/main/java/gov/nysenate/openleg/dao/bill/SqlBillDao.java
if (bill != null) {
            /* try {
                runner.update(UPDATE_BILL_SQL, bill.getTitle(), bill.getLawSection(), bill.getSummary(), bill.getActiveVersion(),
                        bill.getSponsor().getId(), bill.getYear(), new Timestamp(bill.getModifiedDate().getTime()),
                        new Timestamp(bill.getPublishDate().getTime()), bill.getPrintNumber(), bill.getSession());
                runner.update(INSERT_BILL_SQL,
                        bill.getPrintNumber(), bill.getSession(), bill.getTitle(), bill.getLawSection(),
                        bill.getSummary(), bill.getActiveVersion(), bill.getSponsor().getId(), bill.getYear(),
                        new Timestamp(bill.getModifiedDate().getTime()), new Timestamp(bill.getPublishDate().getTime()), bill.getPrintNumber(), bill.getSession());
void saveBill(Bill bill, SOBIFragment sobiFragment)
SOBIFile sobiFile
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFileDao.java
sobiFile.setProcessedDateTime(this.processedDateTime);
            sobiFile.setPendingProcessing(this.pendingProcessing);
            sobiFile.setProcessedCount(this.processedCount);
        /** Row Mapper implementation */
        static class Mapper implements RowMapper<SOBIMetadata> {
            @Override
            public SOBIMetadata mapRow(ResultSet rs, int rowNum) throws SQLException {
                SOBIMetadata metadata = new SOBIMetadata();
                metadata.fileName = rs.getString("file_name");
                metadata.publishedDateTime = rs.getDate("published_date_time");
                metadata.processedDateTime = rs.getDate("processed_date_time");
                metadata.pendingProcessing = rs.getBoolean("pending_processing");
                metadata.processedCount = rs.getInt("processed_count");
                return metadata;
        if (sobiFile != null) {
            jdbcNamed.update(INSERT_SOBI_FILE, getSOBIInsertUpdateParams(sobiFile));
void applyToSOBIFile(SOBIFile sobiFile)
String fileName  Date publishedDate  boolean pendingProcessing
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFileDao.java
return (pendingProcessing) ? getFileInWorkingDirectory(fileName) : getFileInArchiveDirectory(fileName, publishedDate);
File getSOBIFileFromFileSystem(String fileName, Date publishedDate, boolean pendingProcessing)
SOBIMetadata metaData
src/main/java/gov/nysenate/openleg/dao/sobi/SqlSOBIFileDao.java
return getSOBIFileFromFileSystem(metaData.fileName, metaData.publishedDateTime, metaData.pendingProcessing);
     * Deletes the actual SOBI file from the file system and writes the contents of SOBIFile to the appropriate directory.
     * @param sobiFile SOBIFile
     * @return File - Newly written file.
     * @throws IOException
    private File updateSOBIFileInFileSystem(SOBIFile sobiFile) throws IOException {
        File workFile = getFileInWorkingDirectory(sobiFile.getFileName());
        File archiveFile = getFileInArchiveDirectory(sobiFile.getFileName(), sobiFile.getPublishedDateTime());

        // Delete the file from any possible directory so we don't have to keep track of where it is.
        FileUtils.deleteQuietly(workFile);
        FileUtils.deleteQuietly(archiveFile);

        if (sobiFile.isPendingProcessing()) {
            // Write to the working directory.
            FileUtils.write(workFile, sobiFile.getText());
            return workFile;
        else {
            // Create any sub directories just to be safe and write to archive directory.
            archiveFile.getParentFile().mkdirs();
            FileUtils.write(archiveFile, sobiFile.getText());
            return archiveFile;
     * @param publishedDate Date
    private File getFileInArchiveDirectory(String fileName, Date publishedDate) {
        LocalDate localDate = new LocalDate(publishedDate);
        String year = Integer.toString(localDate.getYear());
     * Convenience method to convert a list of SOBIMetaData objects into SOBIFile objects.
     * @param metaDataList List<SOBIMetaData>
     * @return List<SOBIFile>
     */
    private List<SOBIFile> getSobiFileListFromMetaDataList(List<SOBIMetadata> metaDataList) {
        List<SOBIFile> sobiFiles = new ArrayList<>();
        try {
            for (SOBIMetadata metaData : metaDataList) {
                SOBIFile sobiFile = new SOBIFile(getSOBIFileFromFileSystem(metaData));
                metaData.applyToSOBIFile(sobiFile);
                sobiFiles.add(sobiFile);
File getSOBIFileFromFileSystem(SOBIMetadata metaData)
src/main/java/gov/nysenate/openleg/model/BaseObject.java
/**
     * Set the last publish date.
     *
     * @param publishDate - The new publish date.
     */
    public void setPublishDate(Date publishDate)
    {
    /**
     * @return - true if the object has been published
     */
    public boolean isPublished()
    {
    /**
     * Gets the last modified time in milliseconds since epoch.
     */
    /**
     * Sets the last modified timestamp in milliseconds since epoch.
     */
    /**
     * @return - The session this object was created in.
     */
    /**
     * @param session - The new session this object was created in.
     */
    /**
     * @return - The calendar year this object was active in.
     */
    /**
     * @param year - The new calendar year for this object.
     */
    /**
     * Get the set of SOBI files that contain modifications for this object.
     */
    /**
     * @param dataSources - The new set of data sources that contain modifications for this object.
     */

    /**
     * Add a new source to the set of data sources. This is preferred to
     * getting a reference to the list and directly adding filenames
     *
     * @param source - The new source to add to the data sources.
     */
    public void addDataSource(String source)
    {
        dataSources.add(source);
Date getPublishDate()
src/main/java/gov/nysenate/openleg/model/agenda/AgendaInfoAddendum.java
return this.getOtype()+"-"+this.getYear()+"-"+this.getAgendaNumber()+this.getId();
String getOid()
src/main/java/gov/nysenate/openleg/model/agenda/AgendaInfoAddendum.java
return "agenda-info";
String getOtype()
src/main/java/gov/nysenate/openleg/model/agenda/AgendaVoteAddendum.java
// TODO Auto-generated method stub
        return null;
String getOid()
src/main/java/gov/nysenate/openleg/model/agenda/AgendaVoteAddendum.java
return "agendavote";
String getOtype()
String billId  int session
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this();
        this.setBillId(billId);
        this.setSession(session);
        this.setYear(session);
    @JsonIgnore
    public static boolean isBaseVersion(String version)
    {
     * @return - True if this bill is a resolution of some sort.
     */
    @JsonIgnore
    public boolean isResolution()
    {
        return billId.charAt(0)!='A' && billId.charAt(0)!='S';
public Bill(String billId, int session)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (this.getSession()==2009) {
            String disqusId = this.getBillId().split("-")[0];
            return "http://open.nysenate.gov/legislation/api/html/bill/" + disqusId;
String getDisqusUrl()
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return billId;
     * @param billId - The new bill id.
     */
    public void setBillId(String billId)
    {
        this.billId = billId;
String getBillId()
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return "bill";
String getOtype()
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return this.getBillId();
    @JsonIgnore
    public String getPaddedBillId()
    {
        return this.getPaddedPrintNumber()+"-"+this.getSession();
    @JsonIgnore
    public String getPaddedPrintNumber()
    {
        Matcher billIdMatcher = billIdPattern.matcher(this.getBillId());
        if (billIdMatcher.find()) {
            return String.format("%s%05d%s", billIdMatcher.group(2), Integer.parseInt(billIdMatcher.group(3)), billIdMatcher.group(4));
String getOid()
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
Matcher billIdMatcher = billIdPattern.matcher(this.getBillId());
            return billIdMatcher.group(1);
String getPrintNumber()
String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
* @return - A list of all Amendments associated with this Bill.
    @JsonIgnore
    public List<BillAmendment> getAmendmentList()
    {
     * @param billAmendment - Amendment to associate.
    public void addAmendment(BillAmendment billAmendment)
    {
     * @return Mapping of Amendment versions to Amendment objects for keyed retrieval.
    public Map<String, BillAmendment> getAmendmentMap()
    {
        return amendmentMap;
BillAmendment getAmendment(String version)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
/**
     * @return The active amendment version.
     */
    public String getActiveVersion()
    {
        return activeVersion;
BillAmendment getActiveAmendment()
String activeVersion
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.activeVersion = activeVersion;
void setActiveVersion(String activeVersion)
LinkedList<String> activeHistory
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.activeHistory = activeHistory;
void setActiveHistory(LinkedList<String> activeHistory)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return title;
String getTitle()
String title
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.title = title;
void setTitle(String title)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return lawSection;
String getLawSection()
String lawSection
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.lawSection = lawSection;
void setLawSection(String lawSection)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return this.getActiveAmendment().getSameAs();
String getSameAs()
String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            return getAmendment(version).getSameAs();
String getSameAs(String version)
String sameAs  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setSameAs(sameAs);
void setSameAs(String sameAs, String version)
List<String> previousVersions
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.previousVersions = previousVersions;
void setPreviousVersions(List<String> previousVersions)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return sponsor;
Person getSponsor()
Person sponsor
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.sponsor = sponsor;
void setSponsor(Person sponsor)
List<Person> otherSponsors
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.otherSponsors = otherSponsors;
void setOtherSponsors(List<Person> otherSponsors)
List<Person> coSponsors  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setCoSponsors(coSponsors);
void setCoSponsors(List<Person> coSponsors, String version)
List<Person> multiSponsors  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setMultiSponsors(multiSponsors);
void setMultiSponsors(List<Person> multiSponsors, String version)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return summary;
String getSummary()
String summary
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.summary = summary;
void setSummary(String summary)
List<BillAction> actions
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.actions = actions;
void setActions(List<BillAction> actions)
BillAction action
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
actions.add(action);
void addAction(BillAction action)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
public String getFulltext(String version)
    {
        if (hasAmendment(version)) {
            return getAmendment(version).getFulltext();
String getFulltext()
String fulltext  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setFulltext(fulltext);
void setFulltext(String fulltext, String version)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return this.getActiveAmendment().getMemo();
    public String getMemo(String version)
    {
        if (hasAmendment(version)) {
            getAmendment(version).getMemo();
String getMemo()
String memo  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setMemo(memo);
void setMemo(String memo, String version)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return this.getActiveAmendment().getLaw();
    public String getLaw(String version)
    {
        if (hasAmendment(version)) {
            return getAmendment(version).getLaw();
String getLaw()
String law  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setLaw(law);
void setLaw(String law, String version)
String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            return getAmendment(version).getActClause();
String getActClause(String version)
String actClause  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setActClause(actClause);
void setActClause(String actClause, String version)
String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            return getAmendment(version).isStricken();
Boolean isStricken(String version)
Boolean stricken  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setStricken(stricken);
void setStricken(Boolean stricken, String version)
String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            return this.getAmendment(version).isUniBill();
boolean isUniBill(String version)
boolean uniBill  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            this.getAmendment(version).setUniBill(uniBill);
void setUniBill(boolean uniBill, String version)
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
return this.getActiveAmendment().getCurrentCommittee();
    public String getCurrentCommittee(String version)
    {
        if (hasAmendment(version)) {
            return getAmendment(version).getCurrentCommittee();
String getCurrentCommittee()
String currentCommittee  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setCurrentCommittee(currentCommittee);
void setCurrentCommittee(String currentCommittee, String version)
List<String> pastCommittees
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
this.pastCommittees = new ArrayList<String>(pastCommittees);
    public void addPastCommittee(String committee)
    {
        if(!pastCommittees.contains(committee)) {
            pastCommittees.add(committee);
void setPastCommittees(List<String> pastCommittees)
List<Vote> votes  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).setVotes(votes);
void setVotes(List<Vote> votes, String version)
Vote vote  String version
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
if (hasAmendment(version)) {
            getAmendment(version).getVotes().remove(vote);
            getAmendment(version).getVotes().add(vote);
void updateVote(Vote vote, String version)
Date publishDate
src/main/java/gov/nysenate/openleg/model/bill/Bill.java
public Date getModifiedDate()
    {
    /**
     * @param vote - The vote to remove from the list of votes on this bill.
     */
    public void removeVote(Vote vote, String version)
    {
        if (hasAmendment(version)) {
            getAmendment(version).getVotes().remove(vote);
void setPublishDate(Date publishDate)
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
this.bill = bill;
        this.setBillAmendment(billAmendment);
        this.oid = this.bill.getBillId() + "-" + this.date.getTime() + "-" + this.text;
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.setTime(date);
        this.setYear(calendar.get(java.util.Calendar.YEAR));
    /**
     * @return - The object's otype
     */
    public String getOtype()
    {
        return "action";
public BillAction()
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
return this.oid;
String getOid()
String oid
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
this.oid = oid;
    /**
     * @return - The date of the action.
     */
    public Date getDate() {
        return date;
void setOid(String oid)
Date date
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
this.date = date;
void setDate(Date date)
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
return text;
String getText()
String text
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
this.text = text;
void setText(String text)
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
return bill;
    /**
     * @param bill - The new bill to this action targets.
     */
    public void setBill(Bill bill) {
        this.bill = bill;
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof BillAction) {
            BillAction other = (BillAction)obj;
            return this.getOid().equals(other.getOid());
Bill getBill()
src/main/java/gov/nysenate/openleg/model/bill/BillAction.java
java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(date);
        return cal.get(java.util.Calendar.YEAR);
int getYear()
Bill baseBill  String version
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
this.baseBillPrintNo = baseBill.getPrintNumber();
        this.baseBillId = baseBill.getBillId();
    public String getBaseBillId()
    {
        return baseBillId;
    public void setBaseBillId(String baseBillId)
    {
        this.baseBillId = baseBillId;
    public String getBillId()
    {
        return this.baseBillPrintNo + this.version + "-" + this.session;
public BillAmendment(Bill baseBill, String version)
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
public void setVersion(String version)
    {
        this.version = version.trim().toUpperCase();
String getVersion()
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
public void setSameAs(String sameAs)
    {
    public String getMemo()
    {
    public void setMemo(String memo)
    {
    public String getLaw()
    {
        return law;
String getSameAs()
String law
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
this.law = law;
void setLaw(String law)
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
public void setActClause(String actClause)
    {
    public String getFulltext()
    {
    public void setFulltext(String fulltext)
    {
    public String getCurrentCommittee()
    {
    public void setCurrentCommittee(String currentCommittee)
    {
    public List<Person> getCoSponsors()
    {
    public void setCoSponsors(List<Person> coSponsors)
    {
    public List<Person> getMultiSponsors()
    {
    public void setMultiSponsors(List<Person> multiSponsors)
    {
    public Boolean isStricken()
    {
    public void setStricken(Boolean stricken)
    {
    @Override
    public String getOid()
    {
        return this.getBillId();
String getActClause()
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
return "billamendment";
String getOtype()
src/main/java/gov/nysenate/openleg/model/bill/BillAmendment.java
public void setUniBill(Boolean uniBill)
    {
Boolean isUniBill()
src/main/java/gov/nysenate/openleg/model/calendar/Calendar.java
return "calendar-"+this.getYear()+"-"+this.getNumber();
String getOid()
src/main/java/gov/nysenate/openleg/model/calendar/Calendar.java
return "calendar";
String getOtype()
src/main/java/gov/nysenate/openleg/model/calendar/CalendarActiveList.java
return this.getOtype()+"-"+DateHelper.LRS_DATE_ONLY_FORMAT.format(this.getCalDate())+"-"+this.getId();
String getOid()
src/main/java/gov/nysenate/openleg/model/calendar/CalendarActiveList.java
return "calendar-active";
String getOtype()
src/main/java/gov/nysenate/openleg/model/calendar/CalendarSupplemental.java
return this.getOtype()+"-"+DateHelper.LRS_DATE_ONLY_FORMAT.format(this.getCalDate())+"-"+this.getId();
String getOid()
src/main/java/gov/nysenate/openleg/model/calendar/CalendarSupplemental.java
return "calendar-supplemental";
String getOtype()
File file  int startLineNo  String line
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.setFile(file);
        return (this.getFile() == null ? "null" : this.getFile().getName())+":"+this.getStartLineNo();
     * Strips all leading zeros from the numerical part of the print number:
     * <p>
     * A00370 -> A370
     *
     * @param printNo
    public void setPrintNo(String printNo) {
        this.printNo = printNo.substring(0,1)+Integer.parseInt(printNo.substring(1));
    public File getFile() {
        return file;
public SOBIBlock(File file, int startLineNo, String line)
File file
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.file = file;
void setFile(File file)
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
return year;
int getYear()
int year
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.year = year;
void setYear(int year)
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
return printNo;
String getPrintNo()
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
return amendment;
String getAmendment()
String amendment
src/main/java/gov/nysenate/openleg/model/sobi/SOBIBlock.java
this.amendment = amendment;
void setAmendment(String amendment)
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragment.java
return fragmentType;
    public String getText() {
        return text;
SOBIFragmentType getFragmentType()
String text
src/main/java/gov/nysenate/openleg/model/sobi/SOBIFragment.java
this.text = text;
void setText(String text)
Storage storage  List<Entry<String  Change>> changes  List<ServiceBase> services
src/main/java/gov/nysenate/openleg/processors/DataProcessor.java
public void archive(File workingDir, File archiveDir) throws IOException
    {
    public void moveFileToDirectory(File file, File directory, boolean createDirectory) throws IOException
    {
        File newFile = new File(directory, file.getName());
        if (newFile.exists()) {
            newFile.delete();
        FileUtils.moveFileToDirectory(file, directory, true);
    protected void archiveFiles(File sourceDir, File destDir, String subFolder) throws IOException
    {
     * Returns a collection of files sorted by file name (not file path!)
     *
     * @param directory - The directory to get files from.
     * @param recursive - true to retrieve files from sub-directories.
     * @return
     * @throws IOException
     */
    protected Collection<File> getSortedFiles(File directory, boolean recursive, String[] excludeDirs) throws IOException {
        Collection<File> files = safeListFiles(directory, recursive, excludeDirs);
        Collections.sort((List<File>)files, new Comparator<File>(){
            public int compare(File a, File b) {
                return a.getName().compareTo(b.getName());
void push(Storage storage, List<Entry<String, Change>> changes, List<ServiceBase> services)
src/main/java/gov/nysenate/openleg/util/Application.java
return appInstance.lucene;
Lucene getLucene()
String[] args
src/main/java/gov/nysenate/openleg/util/Storage.java
List<String> test = new ArrayList<String>();
        System.out.println(test.getClass().cast(test));
void main(String[] args)
cls == Calendar.class
src/main/java/gov/nysenate/openleg/util/Storage.java
value = this.converter.readCalendar(storageFile);
else if (cls == Calendar.class)
cls == Transcript.class
src/main/java/gov/nysenate/openleg/util/Storage.java
value = this.converter.readTranscript(storageFile);
else if (cls == Transcript.class)
value instanceof Calendar
src/main/java/gov/nysenate/openleg/util/Storage.java
this.converter.write((Calendar)value, storageFile);
else if (value instanceof Calendar)
value instanceof Transcript
src/main/java/gov/nysenate/openleg/util/Storage.java
this.converter.write((Transcript)value, storageFile);
else if (value instanceof Transcript)