All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.gkutiel.store.Store Maven / Gradle / Ivy

There is a newer version: 7-RELEASE
Show newest version
package com.github.gkutiel.store;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import org.h2.Driver;

import com.github.gkutiel.store.ConnectionPool.Connection;
import com.google.gson.Gson;

public class Store {

	@Target(ElementType.FIELD)
	@Retention(RetentionPolicy.RUNTIME)
	public static @interface Index {
	}

	@Target(ElementType.TYPE)
	@Retention(RetentionPolicy.RUNTIME)
	public static @interface Key {
		String[] value();
	}

	private static final Gson GSON = new Gson();
	private static final Logger LOGGER = Logger.getLogger(Store.class.getCanonicalName());

	public static  Store create(final Class c) {
		return new Store<>(c);
	}

	private static  List getIndexableFields(final Class c) {
		final List indexedFields = new ArrayList<>();

		final Field[] declaredFields = c.getDeclaredFields();
		AccessibleObject.setAccessible(declaredFields, true);

		for (final Field field : declaredFields)
			if (field.isAnnotationPresent(Index.class)) indexedFields.add(field);

		return indexedFields;
	}

	private final ConnectionPool pool;

	private final Class clazz;
	private final List indexableFields;

	private final String tableName;
	private final String insert;
	private final String delete;

	private Store(final Class c) {
		this.clazz = c;
		new Driver();

		indexableFields = getIndexableFields(c);

		tableName = clazz.getSimpleName();
		insert = Temp.insert(clazz.isAnnotationPresent(Key.class), tableName, indexableFields.size());
		delete = "DELETE FROM " + tableName + " WHERE ";

		pool = new ConnectionPool("jdbc:h2:db/store");

		createTable();
		createIndexes();
	}

	public void add(final T t) {
		try (Connection con = pool.get()) {
			getInsertStmt(con, t).executeUpdate();
		} catch (final Exception e) {
			throw new RuntimeException(e);
		}
	}

	private void createIndex(final Connection con, final Field field) {
		try {
			con.prepareStatement(getCreateIndex(field)).execute();
		} catch (final SQLException e) {
			throw new RuntimeException();
		}
	}

	private void createIndexes() {
		try (Connection con = pool.get()) {
			for (final Field field : indexableFields)
				createIndex(con, field);
		}
	}

	private void createTable() {
		try (Connection con = pool.get()) {
			final String table = Temp.table(tableName, indexableFields, getPrimaryKey(clazz));
			LOGGER.info(table);

			con.createStatement().execute(table);

		} catch (final SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public void delIf(final String cond, final Object... args) {
		try (Connection con = pool.get()) {
			getDelete(con, cond, args).executeUpdate();
		} catch (final SQLException e) {
			throw new RuntimeException(e);
		}
	}

	public List getAll() {
		return getWhere("true");
	}

	private String getCreateIndex(final Field field) {
		final String createIndex = "CREATE INDEX  IF NOT EXISTS " + field.getName() + " ON " + tableName + "(" + field.getName() + ")";
		LOGGER.info(createIndex);
		return createIndex;
	}

	private PreparedStatement getDelete(final Connection con, final String cond, final Object... args) {
		final PreparedStatement ps = con.prepareStatement(delete + cond);

		int i = 1;
		for (final Object v : args)
			Utils.set(ps, i++, v);

		LOGGER.info(ps.toString());
		return ps;
	}

	private PreparedStatement getInsertStmt(final Connection con, final T t) throws IllegalAccessException, SQLException {
		final PreparedStatement ps = con.prepareStatement(insert);

		int i = 1;
		ps.setString(i, GSON.toJson(t));
		for (final Field field : indexableFields)
			Utils.set(ps, ++i, field.get(t));

		LOGGER.info(ps.toString());
		return ps;
	}

	private String[] getPrimaryKey(final Class c) {
		if (c.isAnnotationPresent(Key.class)) return c.getAnnotation(Key.class).value();
		return null;
	}

	private PreparedStatement getSelect(final Connection con, final String cond, final Object... args) {
		final PreparedStatement ps = con.prepareStatement("SELECT _obj FROM " + clazz.getSimpleName() + " WHERE " + cond);
		int i = 1;
		for (final Object v : args)
			Utils.set(ps, i++, v);
		return ps;
	}

	public List getWhere(final String cond, final Object... args) {
		try (Connection con = pool.get()) {
			final List ts = new ArrayList<>();

			final ResultSet rs = getSelect(con, cond, args).executeQuery();
			while (rs.next())
				ts.add(GSON.fromJson(rs.getString(1), clazz));

			return ts;
		} catch (final SQLException e) {
			throw new RuntimeException(e);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy