com.github.jrh3k5.membership.renewal.mailer.service.jpa.JpaMembershipService.java Source code

Java tutorial

Introduction

Here is the source code for com.github.jrh3k5.membership.renewal.mailer.service.jpa.JpaMembershipService.java

Source

package com.github.jrh3k5.membership.renewal.mailer.service.jpa;

/*
 * #%L
 * KCAC Membership Management Application
 * %%
 * Copyright (C) 2014 Kansas City Atheist Coalition
 * %%
 * Licensed 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.
 * #L%
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.jrh3k5.membership.renewal.mailer.service.MembershipService;
import com.github.jrh3k5.membership.renewal.mailer.service.jpa.data.JpaMembershipDate;
import com.github.jrh3k5.membership.renewal.mailer.service.jpa.data.JpaMembershipRecord;
import com.googlecode.jcsv.CSVStrategy;
import com.googlecode.jcsv.reader.internal.CSVReaderBuilder;
import com.googlecode.jcsv.reader.internal.DefaultCSVEntryParser;

public class JpaMembershipService extends AbstractJpaService implements MembershipService<JpaMembershipRecord> {
    private static final Logger LOGGER = LoggerFactory.getLogger(JpaMembershipService.class);
    private static final Pattern DATE_PATTERN = Pattern.compile("[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]");
    private final EntityManagerFactory entityManagerFactory;

    @Inject
    public JpaMembershipService(EntityManagerFactory entityManagerFactory) {
        super(entityManagerFactory);
        this.entityManagerFactory = entityManagerFactory;
    }

    @Override
    public void loadMemberships(InputStream csvData) throws IOException {
        final Reader membershipCsvReader = new InputStreamReader(csvData);
        try {
            final DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
            for (String[] row : new CSVReaderBuilder<String[]>(membershipCsvReader)
                    .entryParser(new DefaultCSVEntryParser()).strategy(CSVStrategy.UK_DEFAULT).build()) {
                // Index 1 - date of membership
                // Index 4 - Name, full
                // Not all rows may be actual membership data
                if (row.length < 5) {
                    continue;
                }

                if (!DATE_PATTERN.matcher(row[1]).matches()) {
                    continue;
                }

                // Skip blank names
                if (StringUtils.isBlank(row[4])) {
                    continue;
                }

                final String[] splitName = row[4].split(" ");
                final String givenName = splitName[0];
                final String familyName = splitName[splitName.length - 1];
                Date membershipDate;
                try {
                    membershipDate = dateFormat.parse(row[1]);
                } catch (ParseException e) {
                    throw new IOException(String.format("Failed to parse date %s for %s", row[1], row[4]));
                }
                addMembershipRecord(givenName, familyName, membershipDate);
            }
        } finally {
            membershipCsvReader.close();
        }
    }

    @Override
    public JpaMembershipRecord addMembershipRecord(String givenName, String familyName, Date membershipDate) {
        // Does the record already exist? If so, update it
        // Do it within an entity so that the dates collection can be modified while attached
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        try {
            final JpaMembershipRecord byName = getByName(entityManager, givenName, familyName);
            if (byName != null) {
                byName.addMembershipDate(membershipDate);
                updateMembership(entityManager, byName);
                return byName;
            }
        } finally {
            entityManager.close();
        }

        final JpaMembershipRecord newRecord = new JpaMembershipRecord();
        newRecord.setFamilyName(familyName);
        newRecord.setGivenName(givenName);
        newRecord.addMembershipDate(membershipDate);
        persistEntity(newRecord);
        return newRecord;
    }

    @Override
    public JpaMembershipRecord getByName(String givenName, String familyName) {
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        try {
            return getByName(entityManager, givenName, familyName);
        } finally {
            entityManager.close();
        }
    }

    private JpaMembershipRecord getByName(EntityManager entityManager, String givenName, String familyName) {
        final Query query = entityManager.createQuery(
                "select m from MembershipRecord m where m.givenName = :givenName and m.familyName = :familyName");
        query.setParameter("givenName", givenName);
        query.setParameter("familyName", familyName);
        @SuppressWarnings("unchecked")
        final List<JpaMembershipRecord> results = query.getResultList();
        return results.size() == 1 ? results.get(0) : null;
    }

    @SuppressWarnings("unchecked")
    @Override
    public Collection<JpaMembershipRecord> getLapsedMemberships(Date lowerExclusiveBound,
            Date upperInclusiveBound) {
        LOGGER.info("Finding members who have lapsed memberships between ({}, {}]", lowerExclusiveBound,
                upperInclusiveBound);
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        try {
            final Query query = entityManager.createQuery(
                    "select m from MembershipRecord m where m.latestMembershipDate > :lowerBound and m.latestMembershipDate <= :upperBound");
            query.setParameter("lowerBound", lowerExclusiveBound);
            query.setParameter("upperBound", upperInclusiveBound);
            return query.getResultList();
        } finally {
            entityManager.close();
        }
    }

    @Override
    public void updateMembership(JpaMembershipRecord membership) {
        final EntityManager entityManager = entityManagerFactory.createEntityManager();
        try {
            updateMembership(entityManager, membership);
        } finally {
            entityManager.close();
        }
    }

    private void updateMembership(EntityManager entityManager, JpaMembershipRecord membership) {
        final EntityTransaction transaction = entityManager.getTransaction();
        try {
            transaction.begin();
            entityManager.merge(membership);
            transaction.commit();
        } catch (RuntimeException e) {
            transaction.rollback();
            throw e;
        }
    }

    @Override
    public long getMemberCount() {
        return getEntityCount(JpaMembershipRecord.class);
    }

    @Override
    public long getRecordCount() {
        return getEntityCount(JpaMembershipDate.class);
    }

}