package x.y.z;

import java.util.List;

import javax.jdo.annotations.Index;
import javax.jdo.annotations.Unique;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Persistence;
import javax.persistence.SequenceGenerator;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import com.objectdb.Enhancer;


public class DBTestLike {
	
	public static void main(String[] args) throws Exception{

		enhanceClasses();
		
		EntityManagerFactory emf = Persistence
		.createEntityManagerFactory("test2-company.odb");
		String companyId = "test"+System.currentTimeMillis();
		Company company = new Company();
		company.setCompanyId(companyId);
		company.setName("Test Company"+companyId);
		
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();		
		em.persist(company);		
		System.out.println("Saved company with id: " + company.getId());
		em.getTransaction().commit();
		
		em.getTransaction().begin();
		// Fetch
		System.out.println("Loading company with companyId: " + companyId);
		TypedQuery<Company> createQuery = 
			em.createQuery("select c from Company c where c.companyId=:companyId",
				Company.class);
		createQuery.setParameter("companyId", companyId);
		Company loadedCompany = createQuery.getSingleResult();
		System.out.println("Loaded company with companyId: " + companyId +" and id: " + loadedCompany.getId());
		// Update the loaded company
		String newName = loadedCompany.getName()+" " + System.currentTimeMillis();
		System.out.println("Updating company.name to: " + newName);
		loadedCompany.setName(newName);
		em.getTransaction().commit();
//		emf.close();
		
		
		// select out
		em.getTransaction().begin();
		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<Company> c = builder.createQuery(Company.class);
		Root<Company> root = c.from(Company.class);
		ParameterExpression<String> nameParam = builder.parameter(String.class);
		Path<String> namePath = root.get("companyId");
		
		Path<Boolean> conditionOnePath = root.get("conditionOne");
		
		Path<Boolean> conditionTwoParam = root.get("conditionTwo");
		
		Path<Boolean> conditionThreeParam = root.get("conditionThree");
		
		c.select(root);
		c.where(
				builder.and(builder.like(namePath, nameParam),
							builder.equal(conditionOnePath, true)),
				
				builder.and(			
						builder.or(
								builder.equal(conditionTwoParam, false),
								builder.equal(conditionThreeParam, false)
					
				)));
		System.out.println("Query: " + c);
		TypedQuery<Company> q = em.createQuery(c);
		q.setParameter(nameParam, companyId);
		List<Company> companiesFound = q.getResultList();
		System.out.println("Found : " + companiesFound.size());
	}

	/**
	 * 
	 */
	private static void enhanceClasses() {
		Enhancer.enhance(Company.class.getName()+"," +Company.class.getName());
	}
	
	@Entity
	@SequenceGenerator(name="company_seq", initialValue=1,allocationSize=5)
	public static class Company {
		
	    @Id 
	    @GeneratedValue(strategy=GenerationType.IDENTITY, generator="company_seq")
	    private Long id;		

	    /**
		 * 
		 */
		private static final long serialVersionUID = -299617781352746768L;

		/**
	     * Name
	     */
	    @Column(nullable = false, length = 128)
	    @Unique(name="uq_company_name")
	    private String name;
	    
	    /**
	     * Short name to identify company
	     */
	    @Column(name="company_id")
	    @NotNull
	    @Size(min=3)
	    @Index(name="idx_company_id")
	    @Unique(name="uq_company_id")
	    private String companyId;
	    
	    private boolean conditionOne = false;
	    
	    private boolean conditionTwo = false;
	    
	    private boolean conditionThree = false;

	    @Column(name = "detailed_desc")
	    @Lob
	    private String detailedDescription;

	    public String getName() {
	        return name;
	    }

	    public void setName(String name) {
	        this.name = name;
	    }

	    public String getDetailedDescription() {
	        return detailedDescription;
	    }

	    public void setDetailedDescription(String detailedDescription) {
	        this.detailedDescription = detailedDescription;
	    }

		/**
		 * @return the id
		 */
		public Long getId() {
			return id;
		}

		/**
		 * @return the companyId
		 */
		public String getCompanyId() {
			return companyId;
		}

		/**
		 * @param companyId the companyId to set
		 */
		public void setCompanyId(String companyId) {
			this.companyId = companyId;
		}

		/**
		 * @return the conditionOne
		 */
		public boolean isConditionOne() {
			return conditionOne;
		}

		/**
		 * @param conditionOne the conditionOne to set
		 */
		public void setConditionOne(boolean conditionOne) {
			this.conditionOne = conditionOne;
		}

		/**
		 * @return the conditionTwo
		 */
		public boolean isConditionTwo() {
			return conditionTwo;
		}

		/**
		 * @param conditionTwo the conditionTwo to set
		 */
		public void setConditionTwo(boolean conditionTwo) {
			this.conditionTwo = conditionTwo;
		}

		/**
		 * @return the conditionThree
		 */
		public boolean isConditionThree() {
			return conditionThree;
		}

		/**
		 * @param conditionThree the conditionThree to set
		 */
		public void setConditionThree(boolean conditionThree) {
			this.conditionThree = conditionThree;
		}
	}
}