io.coala.enterprise.persist.FactDao.java Source code

Java tutorial

Introduction

Here is the source code for io.coala.enterprise.persist.FactDao.java

Source

/* $Id: 8b3418a1e5dc159860b843b149186573f6174ded $
 * 
 * Part of ZonMW project no. 50-53000-98-156
 * 
 * @license
 * 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.
 * 
 * Copyright (c) 2016 RIVM National Institute for Health and Environment 
 */
package io.coala.enterprise.persist;

import java.util.Date;
import java.util.Map;
import java.util.Objects;

import javax.measure.unit.Unit;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NoResultException;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import com.eaio.uuid.UUID;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.TreeNode;

import io.coala.bind.BindableDao;
import io.coala.bind.LocalBinder;
import io.coala.bind.persist.LocalIdDao;
import io.coala.enterprise.Actor;
import io.coala.enterprise.Fact;
import io.coala.enterprise.Fact.ID;
import io.coala.enterprise.FactKind;
import io.coala.enterprise.Transaction;
import io.coala.json.JsonUtil;
import io.coala.persist.JsonToStringConverter;
import io.coala.persist.UUIDToByteConverter;
import io.coala.time.Instant;
import io.coala.time.persist.InstantDao;

/**
 * {@link FactDao}
 * 
 * @version $Id: 8b3418a1e5dc159860b843b149186573f6174ded $
 * @author Rick van Krevelen
 */
@Entity(name = FactDao.ENTITY_NAME)
public class FactDao implements BindableDao<Fact, FactDao> {
    public static final String ENTITY_NAME = "FACTS";

    public static final String TYPE_COL_NAME = "TYPE";

    public static final String KIND_COL_NAME = "KIND";

    public static boolean exists(final EntityManager em, final ID id) {
        final UUID uuid = Objects.requireNonNull(id.unwrap());
        try {
            //         final Integer pk = 
            em.createQuery("SELECT d.pk FROM " + ENTITY_NAME + " d WHERE d.id=?1", Integer.class)
                    .setParameter(1, uuid).getSingleResult();
            return true;
        } catch (final NoResultException ignore) {
            return false;
        }
    }

    public static FactDao find(final EntityManager em, final ID id) {
        final UUID uuid = Objects.requireNonNull(id.unwrap());
        try {
            return em.createQuery("SELECT d FROM " + ENTITY_NAME + " d WHERE d.id=?1", FactDao.class)
                    .setParameter(1, uuid).getSingleResult();
        } catch (final NoResultException ignore) {
            return null;
        }
    }

    public static FactDao create(final EntityManager em, final Fact fact) {
        final Transaction<?> tx = Objects.requireNonNull(fact.transaction());
        final Date offset = Date.from(tx.offset());
        final Unit<?> unit = tx.timeUnit();
        final Instant occur = Objects.requireNonNull(fact.occur());
        final Instant expire = fact.expire();
        final ID causeRef = fact.causeRef();

        final FactDao dao = new FactDao();
        dao.id = Objects.requireNonNull(fact.id().unwrap());
        dao.tid = Objects.requireNonNull(tx.id().unwrap());
        dao.type = Objects.requireNonNull(tx.kind());
        dao.kind = Objects.requireNonNull(fact.kind());
        dao.initiatorRef = Objects.requireNonNull(tx.initiatorRef()).persist(em);
        dao.executorRef = Objects.requireNonNull(tx.executorRef()).persist(em);
        dao.creatorRef = Objects.requireNonNull(fact.creatorRef()).persist(em);
        dao.cause = causeRef == null ? null : find(em, causeRef);
        dao.causeRef = causeRef == null ? null : Objects.requireNonNull(causeRef.unwrap());
        dao.causeTranRef = causeRef == null ? null : Objects.requireNonNull(causeRef.parentRef()).unwrap();
        dao.occur = InstantDao.of(occur, offset, unit);
        dao.expire = InstantDao.of(expire, offset, unit);
        dao.properties = JsonUtil.toTree(fact.properties());
        //         em.persist( result );
        return dao;
    }

    /** time stamp of insert, as per http://stackoverflow.com/a/3107628 */
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATED_TS", insertable = false, updatable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
    @JsonIgnore
    protected Date created;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "PK", nullable = false, updatable = false)
    protected Integer pk;

    @Column(name = "ID", nullable = false, updatable = false, length = 16, columnDefinition = "BINARY(16)", unique = true)
    @Convert(converter = UUIDToByteConverter.class)
    protected UUID id;

    @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {})
    @JoinColumn(name = "CREATOR_ID", updatable = false)
    protected LocalIdDao creatorRef;

    @Column(name = "TID", nullable = false, updatable = false, length = 16, columnDefinition = "BINARY(16)")
    @Convert(converter = UUIDToByteConverter.class)
    protected UUID tid;

    @Column(name = "TYPE", nullable = false, updatable = false)
    protected Class<? extends Fact> type;

    @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {})
    @JoinColumn(name = "INITIATOR_ID", updatable = false)
    protected LocalIdDao initiatorRef;

    @ManyToOne(optional = false, fetch = FetchType.LAZY, cascade = {})
    @JoinColumn(name = "EXECUTOR_ID", updatable = false)
    protected LocalIdDao executorRef;

    @Column(name = KIND_COL_NAME, nullable = false, updatable = false)
    protected FactKind kind;

    @AttributeOverrides({
            @AttributeOverride(name = InstantDao.POSIX_ATTR_NAME, column = @Column(name = "OCCUR_POSIX", nullable = false, updatable = false)),
            @AttributeOverride(name = InstantDao.NUM_ATTR_NAME, column = @Column(name = "OCCUR", nullable = false, updatable = false)),
            @AttributeOverride(name = InstantDao.STR_ATTR_NAME, column = @Column(name = "OCCUR_STR", nullable = false, updatable = false)), })
    @Embedded
    protected InstantDao occur;

    @AttributeOverrides({
            @AttributeOverride(name = InstantDao.POSIX_ATTR_NAME, column = @Column(name = "EXPIRE_POSIX", updatable = false)),
            @AttributeOverride(name = InstantDao.NUM_ATTR_NAME, column = @Column(name = "EXPIRE", updatable = false)),
            @AttributeOverride(name = InstantDao.STR_ATTR_NAME, column = @Column(name = "EXPIRE_STR", updatable = false)), })
    @Embedded
    protected InstantDao expire;

    /** links to complete cause (only if persisted locally) */
    @ManyToOne(optional = true, fetch = FetchType.LAZY, cascade = {})
    @JoinColumn(name = "CAUSE_ID", updatable = false)
    protected FactDao cause;

    /** to construct cause reference, e.g. if cause is persisted remotely */
    @Column(name = "CAUSE_REF", nullable = true, updatable = false, length = 16, columnDefinition = "BINARY(16)")
    @Convert(converter = UUIDToByteConverter.class)
    protected UUID causeRef;

    /** to construct cause reference, e.g. if cause is persisted remotely */
    @Column(name = "CAUSE_TID", nullable = true, updatable = false, length = 16, columnDefinition = "BINARY(16)")
    @Convert(converter = UUIDToByteConverter.class)
    protected UUID causeTranRef;

    @Column(name = "PROPERTIES", nullable = true, updatable = false)
    @Convert(converter = JsonToStringConverter.class)
    protected TreeNode properties;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public Fact restore(final LocalBinder binder) {
        Objects.requireNonNull(this.creatorRef);
        if (this.causeRef != null)
            Objects.requireNonNull(this.causeTranRef);

        final ID id = ID.of(Objects.requireNonNull(this.id), Transaction.ID.of(this.tid, binder.id()));
        final Transaction tx = binder.inject(Transaction.Factory.class).create(
                Transaction.ID.of(this.tid, binder.id()), this.type, Actor.ID.of(this.initiatorRef.restore(binder)),
                Actor.ID.of(this.executorRef.restore(binder)));
        final ID cause = this.causeRef == null ? null
                : ID.of(this.causeRef, Transaction.ID.of(this.causeTranRef, binder.id()));
        final Instant occur = Objects.requireNonNull(this.occur).restore(binder);
        final Instant expire = this.expire == null ? null : this.expire.restore(binder);

        final Map<String, Object> properties = JsonUtil.valueOf(this.properties, Map.class);
        return binder.inject(Fact.Factory.class).create(tx.kind(), id, tx, this.kind, occur, expire, cause,
                Fact.fromJSON(JsonUtil.getJOM(), this.properties, tx.kind(), properties));
    }
}