Added:
trunk/opt/minigl/
trunk/opt/minigl/build.xml
trunk/opt/minigl/cfg/
trunk/opt/minigl/cfg/_hibernate.cfg.mappings
trunk/opt/minigl/cfg/ehcache.xml
trunk/opt/minigl/cfg/minigl.dtd
trunk/opt/minigl/src/
trunk/opt/minigl/src/org/
trunk/opt/minigl/src/org/jpos/
trunk/opt/minigl/src/org/jpos/gl/
trunk/opt/minigl/src/org/jpos/gl/Account.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/Account.java
trunk/opt/minigl/src/org/jpos/gl/AccountDetail.java
trunk/opt/minigl/src/org/jpos/gl/AccountLock.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/AccountLock.java
trunk/opt/minigl/src/org/jpos/gl/Checkpoint.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/Checkpoint.java
trunk/opt/minigl/src/org/jpos/gl/CompositeAccount.java
trunk/opt/minigl/src/org/jpos/gl/Currency.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/Currency.java
trunk/opt/minigl/src/org/jpos/gl/FinalAccount.java
trunk/opt/minigl/src/org/jpos/gl/GLCredit.java
trunk/opt/minigl/src/org/jpos/gl/GLDebit.java
trunk/opt/minigl/src/org/jpos/gl/GLEntry.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/GLEntry.java
trunk/opt/minigl/src/org/jpos/gl/GLException.java
trunk/opt/minigl/src/org/jpos/gl/GLPermission.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/GLPermission.java
trunk/opt/minigl/src/org/jpos/gl/GLSession.java
trunk/opt/minigl/src/org/jpos/gl/GLTransaction.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/GLTransaction.java
trunk/opt/minigl/src/org/jpos/gl/GLUser.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/GLUser.java
trunk/opt/minigl/src/org/jpos/gl/Journal.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/Journal.java
trunk/opt/minigl/src/org/jpos/gl/JournalRule.java
trunk/opt/minigl/src/org/jpos/gl/Layer.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/Layer.java
trunk/opt/minigl/src/org/jpos/gl/RuleEntry.java
trunk/opt/minigl/src/org/jpos/gl/RuleInfo.hbm.xml
trunk/opt/minigl/src/org/jpos/gl/RuleInfo.java
trunk/opt/minigl/src/org/jpos/gl/Util.java
trunk/opt/minigl/src/org/jpos/gl/overview.html
trunk/opt/minigl/src/org/jpos/gl/package.html
trunk/opt/minigl/src/org/jpos/gl/rule/
trunk/opt/minigl/src/org/jpos/gl/rule/CanPost.java
trunk/opt/minigl/src/org/jpos/gl/rule/CompositeBalance.java
trunk/opt/minigl/src/org/jpos/gl/rule/CompositeMaxBalance.java
trunk/opt/minigl/src/org/jpos/gl/rule/CompositeMinBalance.java
trunk/opt/minigl/src/org/jpos/gl/rule/DoubleEntry.java
trunk/opt/minigl/src/org/jpos/gl/rule/FinalBalance.java
trunk/opt/minigl/src/org/jpos/gl/rule/FinalMaxBalance.java
trunk/opt/minigl/src/org/jpos/gl/rule/FinalMinBalance.java
trunk/opt/minigl/src/org/jpos/gl/rule/package.html
trunk/opt/minigl/src/org/jpos/gl/tools/
trunk/opt/minigl/src/org/jpos/gl/tools/Export.java
trunk/opt/minigl/src/org/jpos/gl/tools/Import.java
trunk/opt/minigl/src/org/jpos/gl/tools/package.html
Log:
Added: trunk/opt/minigl/build.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/build.xml Thu May 1 11:55:29 2008
@@ -0,0 +1,31 @@
+<project name="minigl" basedir="../..">
+ <property file="build.properties"/>
+ <property name="module.name" value="minigl" />
+ <property name="dist.dir" value="dist"/>
+ <property name="build.dir" value="build"/>
+ <property name="modules.dir" value="modules"/>
+ <property name="build.src" value="${build.dir}/src"/>
+ <property name="build.lib" value="${build.dir}/lib"/>
+ <property name="build.cfg" value="${build.dir}/cfg"/>
+ <property name="classes.dir" value="${build.dir}/classes"/>
+ <property name="module.lib.dir" value="${modules.dir}/${module.name}/lib"/>
+ <property name="module.cfg.dir" value="${modules.dir}/${module.name}/cfg"/>
+ <property name="jpos.home" value="http://jpos.org/ee" />
+
+
+ <target name="prepare">
+ <copy
+ file="${module.cfg.dir}/ehcache.xml"
+ tofile="${build.dir}/classes/ehcache.xml" overwrite="true" />
+ </target>
+
+ <target name="setup" />
+
+ <target name="dist">
+ <zip zipfile="${dist.dir}/${module.name}.zip" basedir="${modules.dir}"
+ includes="${module.name}/**">
+ <exclude name="**/doc/**" />
+ </zip>
+ </target>
+</project>
+
Added: trunk/opt/minigl/cfg/_hibernate.cfg.mappings
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/cfg/_hibernate.cfg.mappings Thu May 1 11:55:29 2008
@@ -0,0 +1,13 @@
+
+ <mapping resource="org/jpos/gl/GLUser.hbm.xml"/>
+ <mapping resource="org/jpos/gl/GLPermission.hbm.xml"/>
+ <mapping resource="org/jpos/gl/Currency.hbm.xml"/>
+ <mapping resource="org/jpos/gl/Journal.hbm.xml"/>
+ <mapping resource="org/jpos/gl/Account.hbm.xml"/>
+ <mapping resource="org/jpos/gl/GLTransaction.hbm.xml"/>
+ <mapping resource="org/jpos/gl/GLEntry.hbm.xml"/>
+ <mapping resource="org/jpos/gl/RuleInfo.hbm.xml"/>
+ <mapping resource="org/jpos/gl/Checkpoint.hbm.xml"/>
+ <mapping resource="org/jpos/gl/AccountLock.hbm.xml"/>
+ <mapping resource="org/jpos/gl/Layer.hbm.xml"/>
+
Added: trunk/opt/minigl/cfg/ehcache.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/cfg/ehcache.xml Thu May 1 11:55:29 2008
@@ -0,0 +1,46 @@
+<ehcache>
+ <diskStore path="java.io.tmpdir"/>
+ <defaultCache
+ maxElementsInMemory="10000"
+ eternal="false"
+ timeToIdleSeconds="120"
+ timeToLiveSeconds="120"
+ overflowToDisk="false"
+ />
+ <cache name="org.jpos.gl.User"
+ maxElementsInMemory="100"
+ eternal="false"
+ timeToIdleSeconds="300"
+ timeToLiveSeconds="600"
+ overflowToDisk="false"
+ />
+ <cache name="org.jpos.gl.Account"
+ maxElementsInMemory="10000"
+ eternal="false"
+ timeToIdleSeconds="300"
+ timeToLiveSeconds="600"
+ overflowToDisk="false"
+ />
+ <cache name="org.jpos.gl.Journal"
+ maxElementsInMemory="100"
+ eternal="false"
+ timeToIdleSeconds="300"
+ timeToLiveSeconds="600"
+ overflowToDisk="false"
+ />
+ <cache name="org.jpos.gl.Currency"
+ maxElementsInMemory="100"
+ eternal="false"
+ timeToIdleSeconds="300"
+ timeToLiveSeconds="600"
+ overflowToDisk="false"
+ />
+ <cache name="org.jpos.gl.RuleInfo"
+ maxElementsInMemory="100"
+ eternal="false"
+ timeToIdleSeconds="300"
+ timeToLiveSeconds="600"
+ overflowToDisk="false"
+ />
+</ehcache>
+
Added: trunk/opt/minigl/cfg/minigl.dtd
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/cfg/minigl.dtd Thu May 1 11:55:29 2008
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!ELEMENT minigl (
+ create-schema?,user*,currency*,chart-of-accounts*,journal*,transaction*
+)*>
+
+<!ELEMENT create-schema EMPTY>
+<!ELEMENT user (nick+, name?,grant*) >
+<!ELEMENT nick (#PCDATA) >
+<!ELEMENT name (#PCDATA) >
+
+<!ELEMENT grant (#PCDATA) >
+<!ATTLIST grant user CDATA #IMPLIED>
+
+<!ELEMENT currency (symbol+,name*) >
+<!ATTLIST currency id CDATA #REQUIRED>
+<!ELEMENT symbol (#PCDATA) >
+
+<!ELEMENT layer (#PCDATA) >
+<!ATTLIST layer id CDATA #REQUIRED>
+
+<!ELEMENT chart-of-accounts (description?,composite-account*,account*) >
+<!ATTLIST chart-of-accounts code CDATA #REQUIRED>
+<!ATTLIST chart-of-accounts created CDATA #IMPLIED>
+<!ATTLIST chart-of-accounts currency CDATA #REQUIRED>
+<!ELEMENT description (#PCDATA) >
+
+<!ELEMENT composite-account (description?,(account|
composite-account)*) >
+<!ATTLIST composite-account code CDATA #REQUIRED>
+<!ATTLIST composite-account type (debit|credit) #REQUIRED>
+
+<!ELEMENT account (description?) >
+<!ATTLIST account code CDATA #REQUIRED>
+<!ATTLIST account type (debit|credit) #REQUIRED>
+<!ATTLIST account currency CDATA #IMPLIED>
+
+<!ELEMENT journal
(name+,start?,end?,status+,chart+,layer*,grant*,rule*) >
+<!ELEMENT start (#PCDATA) >
+<!ELEMENT end (#PCDATA) >
+<!ELEMENT status (#PCDATA) >
+<!ELEMENT chart (#PCDATA) >
+<!ELEMENT rule (#PCDATA|layers|param)* >
+<!ATTLIST rule clazz CDATA #REQUIRED>
+<!ATTLIST rule account CDATA #IMPLIED>
+<!ELEMENT param (#PCDATA) >
+<!ELEMENT layers (#PCDATA) >
+
+<!ELEMENT transaction (detail?,entry+) >
+<!ATTLIST transaction date CDATA #REQUIRED>
+<!ATTLIST transaction post-date CDATA #REQUIRED>
+<!ATTLIST transaction journal CDATA #REQUIRED>
+<!ELEMENT detail (#PCDATA) >
+
+<!ELEMENT entry (detail?,amount?) >
+<!ATTLIST entry account CDATA #REQUIRED>
+<!ATTLIST entry type (debit|credit) #REQUIRED>
+<!ATTLIST entry layer CDATA #IMPLIED>
+<!ELEMENT amount (#PCDATA) >
+
+
Added: trunk/opt/minigl/src/org/jpos/gl/Account.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Account.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.Account" table="acct" discriminator-value=" ">
+ <id name="id" column="id" type="long">
+ <generator class="native" />
+ </id>
+
+ <discriminator column="subclass" type="string" length="1" />
+
+ <property name="code">
+ <column name="code" sql-type="varchar(32)"
+ not-null="true" index="acctCode" />
+ </property>
+ <property name="description" />
+ <property name="created" type="date" />
+ <property name="expiration" type="date" />
+ <property name="type">
+ <column name="type" sql-type="smallint" />
+ </property>
+ <property name="currencyCode">
+ <column name="currency" sql-type="char(3)" />
+ </property>
+ <many-to-one name="root" not-null="false"/>
+
+ <subclass name="org.jpos.gl.CompositeAccount" discriminator-value="C">
+ <set name="children" cascade="all-delete-orphan" sort="natural"
lazy="true" inverse="true">
+ <key column="parent" />
+ <!-- index column="posn" / -->
+ <one-to-many class="org.jpos.gl.Account" />
+ </set>
+ <many-to-one name="parent" not-null="false"/>
+ </subclass>
+
+ <subclass name="org.jpos.gl.FinalAccount" discriminator-value="F">
+ <many-to-one name="parent" not-null="false"/>
+ </subclass>
+
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/Account.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Account.java Thu May 1 11:55:29 2008
@@ -0,0 +1,376 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Date;
+import java.util.Set;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.io.Serializable;
+import java.text.ParseException;
+import org.jdom.Element;
+import org.jdom.Comment;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+/**
+ * Base class for Composite and Final accounts.
+ *
+ * @see GLEntry
+ * @see CompositeAccount
+ * @see FinalAccount
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public abstract class Account implements Serializable, Comparable {
+ private long id;
+ private int version;
+ /**
+ * 0 - type is undefined (used in top level [chart-of=]account)
+ */
+ public static final int CHART = 0;
+ /**
+ * 1 - this is a debit type account
+ */
+ public static final int DEBIT = 1;
+ /**
+ * 2 - this is a credit type account
+ */
+ public static final int CREDIT = 2;
+
+ String code;
+ String description;
+
+ Date created;
+ Date expiration;
+ String currencyCode;
+ int type;
+
+ Account parent, root;
+
+ /**
+ * Default constructor.
+ */
+ public Account () {
+ super ();
+ }
+ /**
+ * Internal id.
+ * @return internal id
+ */
+ public long getId() {
+ return id;
+ }
+ /**
+ * Internal id.
+ * @param id internal Id
+ */
+ public void setId (long id) {
+ this.id = id;
+ }
+ /**
+ * Account creation date.
+ * @param created creation date
+ */
+ public void setCreated (Date created) {
+ this.created = created;
+ }
+ /**
+ * Account creation date.
+ * @return creation date
+ */
+ public Date getCreated () {
+ return created;
+ }
+ /**
+ * Expiration date.
+ * @param expiration expiration date.
+ */
+ public void setExpiration (Date expiration) {
+ this.expiration = expiration;
+ }
+ /**
+ * Expiration date.
+ * @return expiration date.
+ */
+ public Date getExpiration () {
+ return expiration;
+ }
+ /**
+ * Account code.
+ *
+ * We use an account id with no business meaning, so we need
+ * an account <code>code</code>
+ *
+ * @param code the code.
+ */
+ public void setCode (String code) {
+ this.code = code;
+ }
+
+ /**
+ * Account code.
+ * @return account code.
+ */
+ public String getCode() {
+ return code;
+ }
+ /**
+ * Description.
+ * @param description account description.
+ */
+ public void setDescription (String description) {
+ this.description = description;
+ }
+ /**
+ * Description.
+ * @return account description.
+ */
+ public String getDescription () {
+ return description;
+ }
+ /**
+ * Parent Account.
+ *
+ * @return parent account (null if this account is the toplevel root)
+ */
+ public Account getParent () {
+ return parent;
+ }
+ /**
+ * Parent Account.
+ * @param parent parent account (null if this account is the
toplevel root)
+ */
+ public void setParent (Account parent) {
+ this.parent = parent;
+ }
+ /**
+ * Root account.
+ * The root account is a top level {@link CompositeAccount}
+ * representing a Chart of Accounts.
+ * @return root account.
+ */
+ public Account getRoot () {
+ return root;
+ }
+ /**
+ * Root account.
+ *
+ * @param root root account.
+ */
+ public void setRoot (Account root) {
+ this.root = root;
+ }
+
+ /**
+ * Account's children.
+ * {@link CompositeAccount} uses this property to store its children.
+ * Calling this method on a {@link FinalAccount} raises
+ * an IllegalArgumentException.
+ * @param children a list of childrens
+ */
+ public abstract void setChildren (Set children);
+
+ /**
+ * Account's children.
+ * {@link CompositeAccount} uses this property to store its children.
+ * Calling this method on a {@link FinalAccount} would return null
+ * an IllegalArgumentException.
+ * @return children or null.
+ */
+ public abstract Set getChildren ();
+
+ /**
+ * Creates a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public abstract Element toXML ();
+
+ /**
+ * Currency Code.
+ * @return currency code.
+ */
+ public String getCurrencyCode () {
+ return currencyCode;
+ }
+ /**
+ * Currency Code.
+ * @param currencyCode a currency code.
+ * @see Currency
+ */
+ public void setCurrencyCode (String currencyCode)
+ throws IllegalArgumentException
+ {
+ if (currencyCode != null) {
+ // go up until first level, don't process the chart itself
+ // (chart's getParent() == null)
+ for (Account p = getParent();
+ p != null && p.getParent() != null;
+ p = p.getParent())
+ {
+ String pcc = p.getCurrencyCode();
+ if (pcc != null && !pcc.equals (currencyCode))
+ throw new IllegalArgumentException (
+ "Illegal currency "+currencyCode);
+ }
+ }
+ this.currencyCode = currencyCode;
+ }
+ /**
+ * Type.
+ * @param type (either DEBIT, CREDIT or CHART)
+ */
+ public void setType (int type) {
+ this.type = type;
+ }
+ /**
+ * Type.
+ * @return type (either DEBIT, CREDIT or CHART)
+ */
+ public int getType () {
+ return type;
+ }
+ /**
+ * @return true if account's type is a debit.
+ */
+ public boolean isDebit () {
+ return (type & DEBIT) == DEBIT;
+ }
+ /**
+ * @return true if account's type is a credit.
+ */
+ public boolean isCredit () {
+ return (type & CREDIT) == CREDIT;
+ }
+ /**
+ * @return true if account's type is chart (neither DEBIT nor CREDIT)
+ */
+ public boolean isChart () {
+ return (type & (DEBIT|CREDIT)) == CHART;
+ }
+ /**
+ * Account's type
+ * @return "debit", "credit" or null.
+ */
+ public String getTypeAsString() {
+ if (isDebit())
+ return "debit";
+ else if (isCredit())
+ return "credit";
+ else
+ return null;
+ }
+ /**
+ * Helper method used to create a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ protected Element toXML (Element elem) {
+ elem.setAttribute ("code", getCode ());
+ elem.addContent (new Element("description").setText (getDescription()));
+
+ if (currencyCode != null)
+ elem.setAttribute ("currency", currencyCode);
+
+ if (isDebit ())
+ elem.setAttribute ("type", "debit");
+ else if (isCredit())
+ elem.setAttribute ("type", "credit");
+
+ Util.setDateAttribute (elem, "created", getCreated());
+ return elem;
+ }
+ /**
+ * Parses a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public void fromXML (Element elem) throws ParseException {
+ setCode (elem.getAttributeValue ("code"));
+ setDescription (elem.getChildTextTrim ("description"));
+ setCreated (Util.parseDate (elem.getAttributeValue ("created")));
+ if (getCreated() == null)
+ setCreated (new Date());
+
+ setExpiration (
+ Util.parseDate (elem.getAttributeValue ("expiration"))
+ );
+ String cc = elem.getAttributeValue ("currency");
+ if (cc != null)
+ setCurrencyCode (cc);
+
+ String at = elem.getAttributeValue ("type");
+ if (at != null) {
+ if ("debit".equals (at))
+ setType (DEBIT);
+ else if ("credit".equals (at))
+ setType (CREDIT);
+ else
+ throw new IllegalArgumentException ("Invalid type "+at);
+ } else {
+ setType (0);
+ }
+ Account p = getParent();
+ if (p != null) {
+ int parentType = p.getType();
+ if (parentType > 0 && parentType != getType()) {
+ throw new IllegalArgumentException (
+ "type '" + getTypeAsString()
+ + "' doesn't match parent's type '"
+ + p.getTypeAsString() + "'"
+ );
+ }
+ }
+ }
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", getId())
+ .append("code",getCode())
+ .toString();
+ }
+ public boolean equals(Object other) {
+ if ( !(other instanceof Account) ) return false;
+ Account castOther = (Account) other;
+ return new EqualsBuilder()
+ .append(this.getId(), castOther.getId())
+ .isEquals();
+ }
+ /**
+ * @param other account
+ * @return true if other has same type as this account
+ */
+ public boolean equalsType (Account other) {
+ return (
+ getType() & (CREDIT | DEBIT))
+ == (other.getType() & (CREDIT | DEBIT));
+ }
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getId())
+ .toHashCode();
+ }
+ public int compareTo (Object o) {
+ if (o instanceof Account) {
+ return getCode().compareTo (((Account)o).getCode());
+ }
+ return 1;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/AccountDetail.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/AccountDetail.java Thu May 1
11:55:29 2008
@@ -0,0 +1,98 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Date;
+import java.util.List;
+import java.math.BigDecimal;
+
+/**
+ * Account Detail bulk response object.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see GLSession#getAccountDetail
+ */
+public class AccountDetail {
+ Journal journal;
+ Account account;
+ Date end;
+ Date start;
+ BigDecimal initialBalance;
+ BigDecimal finalBalance;
+ List entries;
+ short[] layers;
+
+ /**
+ * Constructs an AccountDetail bulk accessor.
+ * @param journal the Journal.
+ * @param account the account.
+ * @param initialBalance initial balance (reporting currency).
+ * @param finalBalance final balance (reporting currency).
+ * @param start start date (inclusive).
+ * @param end end date (inclusive).
+ * @param entries list of GLEntries.
+ */
+ public AccountDetail(
+ Journal journal, Account account,
+ BigDecimal initialBalance, BigDecimal finalBalance,
+ Date start, Date end, List entries, short[] layers)
+ {
+ super();
+ this.journal = journal;
+ this.account = account;
+ this.initialBalance = initialBalance;
+ this.finalBalance = finalBalance;
+ this.start = start;
+ this.end = end;
+ this.entries = entries;
+ this.layers = layers;
+ }
+ public Journal getJournal() {
+ return journal;
+ }
+ public Account getAccount() {
+ return account;
+ }
+ public BigDecimal getInitialBalance() {
+ return initialBalance;
+ }
+ public BigDecimal getFinalBalance() {
+ return finalBalance;
+ }
+ public Date getStart() {
+ return start;
+ }
+ public Date getEnd() {
+ return end;
+ }
+ public List getEntries() {
+ return entries;
+ }
+ public short[] getLayers() {
+ return layers;
+ }
+ /**
+ * @return number of entries.
+ */
+ public int size() {
+ return entries.size();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/AccountLock.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/AccountLock.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.AccountLock" table="acctlock">
+ <meta attribute="class-description">
+ Journal level lock.
+ </meta>
+ <composite-id unsaved-value="any">
+ <key-many-to-one name="journal" class="org.jpos.gl.Journal" />
+ <key-many-to-one name="account" class="org.jpos.gl.Account" />
+ </composite-id>
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/AccountLock.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/AccountLock.java Thu May 1
11:55:29 2008
@@ -0,0 +1,89 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.io.Serializable;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+/**
+ * Journal level lock.
+ *
+*/
+public class AccountLock implements Serializable {
+
+ /** identifier field */
+ private org.jpos.gl.Journal journal;
+
+ /** identifier field */
+ private org.jpos.gl.Account account;
+
+ /** full constructor */
+ public AccountLock(org.jpos.gl.Journal journal,
org.jpos.gl.Account account) {
+ this.journal = journal;
+ this.account = account;
+ }
+
+ /** default constructor */
+ public AccountLock() {
+ }
+
+ public org.jpos.gl.Journal getJournal() {
+ return this.journal;
+ }
+
+ public void setJournal(org.jpos.gl.Journal journal) {
+ this.journal = journal;
+ }
+
+ public org.jpos.gl.Account getAccount() {
+ return this.account;
+ }
+
+ public void setAccount(org.jpos.gl.Account account) {
+ this.account = account;
+ }
+
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("journal", getJournal())
+ .append("account", getAccount())
+ .toString();
+ }
+
+ public boolean equals(Object other) {
+ if ( (this == other ) ) return true;
+ if ( !(other instanceof AccountLock) ) return false;
+ AccountLock castOther = (AccountLock) other;
+ return new EqualsBuilder()
+ .append(this.getJournal(), castOther.getJournal())
+ .append(this.getAccount(), castOther.getAccount())
+ .isEquals();
+ }
+
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getJournal())
+ .append(getAccount())
+ .toHashCode();
+ }
+
+}
Added: trunk/opt/minigl/src/org/jpos/gl/Checkpoint.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Checkpoint.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.Checkpoint" table="checkpoint">
+ <meta attribute="class-description">
+ Journal level account Checkpoint.
+ </meta>
+ <composite-id>
+ <key-property name="date" type="date" />
+ <key-property name="layers" type="string" length="32" />
+ <key-many-to-one name="journal" class="org.jpos.gl.Journal" />
+ <key-many-to-one name="account" class="org.jpos.gl.Account" />
+ </composite-id>
+
+ <property name="balance" type="big_decimal">
+ <column name="balance" sql-type="numeric(14,2)" not-null="true" />
+ </property>
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/Checkpoint.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Checkpoint.java Thu May 1
11:55:29 2008
@@ -0,0 +1,114 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+
+/**
+ * Journal level account Checkpoint.
+ *
+*/
+public class Checkpoint implements Serializable {
+ private Date date;
+ private BigDecimal balance;
+ private org.jpos.gl.Journal journal;
+ private org.jpos.gl.Account account;
+ private String layers;
+
+ public Checkpoint() {
+ super();
+ }
+
+ public Date getDate() {
+ return this.date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public BigDecimal getBalance() {
+ return this.balance;
+ }
+
+ public void setBalance(BigDecimal balance) {
+ this.balance = balance;
+ }
+
+ public org.jpos.gl.Journal getJournal() {
+ return this.journal;
+ }
+
+ public void setJournal(org.jpos.gl.Journal journal) {
+ this.journal = journal;
+ }
+
+ public org.jpos.gl.Account getAccount() {
+ return this.account;
+ }
+
+ public void setAccount(org.jpos.gl.Account account) {
+ this.account = account;
+ }
+
+ public void setLayers (String layers) {
+ this.layers = layers;
+ }
+ public String getLayers () {
+ return layers;
+ }
+
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("date", getDate())
+ .append("laters", getLayers())
+ .append("journal", getJournal())
+ .append("account", getAccount())
+ .toString();
+ }
+
+ public boolean equals(Object other) {
+ if ( (this == other ) ) return true;
+ if ( !(other instanceof Checkpoint) ) return false;
+ Checkpoint castOther = (Checkpoint) other;
+ return new EqualsBuilder()
+ .append(this.getDate(), castOther.getDate())
+ .append(this.getLayers(), castOther.getLayers())
+ .append(this.getJournal(), castOther.getJournal())
+ .append(this.getAccount(), castOther.getAccount())
+ .isEquals();
+ }
+
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getDate())
+ .append(getLayers())
+ .append(getJournal())
+ .append(getAccount())
+ .toHashCode();
+ }
+
+}
Added: trunk/opt/minigl/src/org/jpos/gl/CompositeAccount.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/CompositeAccount.java Thu May 1
11:55:29 2008
@@ -0,0 +1,74 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.text.ParseException;
+import org.jdom.Element;
+
+/**
+ * Composite Account
+ *
+ * @see GLEntry
+ * @see Account
+ * @see FinalAccount
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class CompositeAccount extends Account {
+ Set children;
+ public CompositeAccount () {
+ super ();
+ }
+ public CompositeAccount (Element elem)
+ throws ParseException
+ {
+ super ();
+ setParent (parent);
+ fromXML (elem);
+ }
+ public CompositeAccount (Element elem, Account parent)
+ throws ParseException
+ {
+ super ();
+ setParent (parent);
+ fromXML (elem);
+ }
+ public void setChildren (Set children) {
+ this.children = children;
+ }
+ public Set getChildren () {
+ if (children == null)
+ children = new TreeSet();
+ return children;
+ }
+ public Element toXML () {
+ Element elem = super.toXML (new Element ("composite-account"));
+ Iterator iter = getChildren().iterator();
+ while (iter.hasNext()) {
+ Account acct = (Account) iter.next();
+ elem.addContent (acct.toXML ());
+ }
+ return elem;
+ }
+}
Added: trunk/opt/minigl/src/org/jpos/gl/Currency.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Currency.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.Currency" table="currency">
+ <id name="id" column="id" type="string" length="3">
+ <generator class="assigned" />
+ </id>
+ <property name="name" />
+ <property name="symbol">
+ <column name="symbol" sql-type="varchar(16)" not-null="true" />
+ </property>
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/Currency.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Currency.java Thu May 1 11:55:29 2008
@@ -0,0 +1,116 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.text.ParseException;
+import org.jdom.Element;
+import org.jdom.Comment;
+
+/**
+ * Represents a currency.
+ * <p>See: <a href="http://www.evertype.com/standards/iso4217/iso4217-en.html">ISO-4217</a></p>
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class Currency {
+ private String id;
+ private String name;
+ private String symbol;
+
+ public Currency () {
+ super();
+ }
+
+ /**
+ * Constructs a Currency out of a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ * @param elem
+ */
+ public Currency (Element elem) throws ParseException {
+ super();
+ fromXML (elem);
+ }
+ /**
+ * Currency id.
+ * It can be an ISO-4217 currency or any other internal use id.
+ *
+ * @return currency id
+ */
+ public String getId() {
+ return id;
+ }
+ /**
+ * Currency id.
+ * @param id currency id
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+ /**
+ * Currency name.
+ * @return currency name
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * Currency name.
+ * @param name currency name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+ /**
+ * Currency symbol.
+ * i.e. USD, EUR, UYU, etc.
+ * @return currency symbol
+ */
+ public String getSymbol () {
+ return symbol;
+ }
+ /**
+ * Currency symbol.
+ * (usually 3 chars, could be up to 16 chars)
+ * @param symbol currency symbol
+ */
+ public void setSymbol (String symbol) {
+ this.symbol = symbol;
+ }
+ /**
+ * Parses a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public void fromXML (Element elem) throws ParseException {
+ setId (elem.getAttributeValue ("id"));
+ setSymbol (elem.getChildTextTrim ("symbol"));
+ setName (elem.getChildTextTrim ("name"));
+ }
+ /**
+ * Creates a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public Element toXML () {
+ Element e = new Element ("currency") .
+ addContent (new Element ("symbol").setText (getSymbol())) .
+ addContent (new Element ("name").setText (getName()));
+ e.setAttribute ("id", getId());
+ return e;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/FinalAccount.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/FinalAccount.java Thu May 1
11:55:29 2008
@@ -0,0 +1,60 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Set;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import org.jdom.Element;
+
+/**
+ * Final (leaf) Account.
+ *
+ * @see GLEntry
+ * @see Account
+ * @see CompositeAccount
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class FinalAccount extends Account {
+ public FinalAccount () {
+ super ();
+ }
+ public FinalAccount (Element elem, Account parent) throws
ParseException {
+ super ();
+ setParent (parent);
+ fromXML (elem);
+ }
+ public void setChildren (Set children)
+ throws IllegalArgumentException
+ {
+ throw new IllegalArgumentException (
+ "Can't setChildren on FinalAccount"
+ );
+ }
+ public Set getChildren () {
+ return null;
+ }
+ public Element toXML () {
+ Element elem = super.toXML (new Element ("account"));
+ return elem;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLCredit.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLCredit.java Thu May 1 11:55:29 2008
@@ -0,0 +1,27 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+public class GLCredit extends GLEntry {
+ public GLCredit() {
+ super();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLDebit.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLDebit.java Thu May 1 11:55:29 2008
@@ -0,0 +1,27 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+public class GLDebit extends GLEntry {
+ public GLDebit() {
+ super();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLEntry.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLEntry.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.GLEntry" table="transentry" discriminator-value=" ">
+ <id name="id" column="id" type="long">
+ <generator class="native" />
+ </id>
+ <discriminator column="subclass" type="string" length="1" />
+
+ <property name="detail" type="string" />
+ <property name="credit" type="yes_no" />
+ <property name="layer" type="short">
+ <column name="layer" sql-type="int(5)" not-null="true" />
+ </property>
+ <many-to-one name="account" not-null="true" />
+ <many-to-one name="transaction" not-null="false" />
+
+ <property name="amount" type="big_decimal">
+ <column name="amount" sql-type="numeric(14,2)" not-null="true" />
+ </property>
+ <subclass name="org.jpos.gl.GLCredit" discriminator-value="C" />
+ <subclass name="org.jpos.gl.GLDebit" discriminator-value="D" />
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLEntry.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLEntry.java Thu May 1 11:55:29 2008
@@ -0,0 +1,258 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Iterator;
+import java.util.Date;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import org.jdom.Element;
+import org.jdom.Comment;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+
+/**
+ * GLEntry.
+ *
+ * Represents a MiniGL Transaction Entry.
+ *
+ * @see GLTransaction
+ * @see Account
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class GLEntry {
+ private long id;
+ private String detail;
+ private boolean credit;
+ private short layer;
+ private BigDecimal amount;
+ private FinalAccount account;
+ private GLTransaction transaction;
+
+ public GLEntry () {
+ super();
+ }
+
+ /**
+ * Constructs a GLEntry out of a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ * @param elem
+ */
+ public GLEntry (Element elem) throws ParseException {
+ super();
+ fromXML (elem);
+ }
+ /**
+ * GLEntry id.
+ *
+ * @return internal id
+ */
+ public long getId() {
+ return id;
+ }
+ /**
+ * GLEntry id.
+ *
+ * @param id internal id.
+ */
+ public void setId(long id) {
+ this.id = id;
+ }
+ /**
+ * Account.
+ * @param account a final account
+ */
+ public void setAccount (FinalAccount account) {
+ this.account = account;
+ }
+ /**
+ * Account.
+ * @return final account associated with GLEntry
+ */
+ public FinalAccount getAccount () {
+ return account;
+ }
+ /**
+ * Transaction.
+ * @param transaction transaction associated with this GLEntry.
+ */
+ public void setTransaction (GLTransaction transaction) {
+ this.transaction = transaction;
+ }
+ /**
+ * Transaction.
+ * @return transaction associated with this GLEntry.
+ */
+ public GLTransaction getTransaction () {
+ return transaction;
+ }
+ /**
+ * Optional GLEntry Detail.
+ *
+ * Although GLTransaction has a detail, MiniGL support additional
+ * detail information at GLEntry level.
+ *
+ * @param detail optional entry level detail
+ */
+ public void setDetail (String detail) {
+ this.detail = detail;
+ }
+ /**
+ * Optional GLEntry Detail.
+ *
+ * Although GLTransaction has a detail, MiniGL support additional
+ * detail information at GLEntry level.
+ *
+ * @return entry level detail (may be null)
+ */
+ public String getDetail () {
+ return detail;
+ }
+ /**
+ * Credit.
+ * calling setCredit(true) automatically sets <code>debit</code>
to false.
+ * @param credit true if this GLEntry is a credit.
+ */
+ public void setCredit (boolean credit) {
+ this.credit = credit;
+ }
+ /**
+ * Debit.
+ * calling setDebit(true) automatically sets <code>credit</code>
to false.
+ * @param debit true if this GLEntry is a credit.
+ */
+ public void setDebit (boolean debit) {
+ this.credit = !debit;
+ }
+ /**
+ * @return true if this entry is a credit.
+ */
+ public boolean isCredit () {
+ return credit;
+ }
+ /**
+ * @return true if this entry is a debit.
+ */
+ public boolean isDebit () {
+ return !credit;
+ }
+ /**
+ * Increase value.
+ *
+ * @return true if this entry increases the balance of its account.
+ */
+ public boolean isIncrease() {
+ return
+ (isDebit() && account.isDebit()) ||
+ (isCredit() && account.isCredit());
+ }
+ /**
+ * Decrease value.
+ *
+ * @return true if this entry decreases the balance of its account.
+ */
+ public boolean isDecrease () {
+ return !isIncrease();
+ }
+ /**
+ * Amount.
+ * @param amount the amount.
+ */
+ public void setAmount (BigDecimal amount) {
+ this.amount = amount;
+ }
+ /**
+ * Amount.
+ * @return entry's amount.
+ */
+ public BigDecimal getAmount () {
+ return amount;
+ }
+ /**
+ * Impact on balance.
+ *
+ * @return either +amount or -amount based on isIncrease/isDecrease.
+ */
+ public BigDecimal getImpact () {
+ return isIncrease() ? amount : amount.negate();
+ }
+ public void setLayer (short layer) {
+ this.layer = layer;
+ }
+ public short getLayer() {
+ return layer;
+ }
+ /**
+ * Parses a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public void fromXML (Element elem) throws ParseException {
+ setDetail (elem.getChild ("detail").getText());
+
+ setCredit ("credit".equals (elem.getAttributeValue ("type")));
+ setLayer (elem.getAttributeValue ("layer"));
+ setAmount (new BigDecimal (elem.getChild ("amount").getText()));
+ }
+ /**
+ * Creates a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public Element toXML (boolean deep) {
+ Element elem = new Element ("entry");
+ if (getDetail() != null) {
+ Element detail = new Element ("detail").setText (getDetail());
+ elem.addContent (detail);
+ }
+ elem.setAttribute ("account", getAccount().getCode());
+ elem.setAttribute ("type", isCredit() ? "credit" : "debit");
+ if (layer != 0)
+ elem.setAttribute ("layer", Integer.toString(layer));
+ Element amount = new Element ("amount");
+ amount.setText (getAmount().toString());
+ elem.addContent (amount);
+ return elem;
+ }
+ public boolean equals(Object other) {
+ if ( !(other instanceof GLEntry) ) return false;
+ GLEntry castOther = (GLEntry) other;
+ return new EqualsBuilder()
+ .append(this.getId(), castOther.getId())
+ .isEquals();
+ }
+
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getId())
+ .toHashCode();
+ }
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", getId())
+ .toString();
+ }
+ private void setLayer (String s) {
+ if (s != null)
+ setLayer (Short.parseShort (s));
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLException.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLException.java Thu May 1
11:55:29 2008
@@ -0,0 +1,94 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.io.PrintStream;
+
+/**
+ * Base class for MiniGL especific exceptions
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class GLException extends Exception {
+ /**
+ * Constructs a new GLException
+ */
+ public GLException() {
+ super();
+ }
+ /**
+ * Constructs a new exception with the specified detail message.
+ * @param s the detail message.
+ */
+ public GLException(String s) {
+ super(s);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause.
+ * @param cause the cause
+ */
+ public GLException (Exception cause) {
+ super(cause);
+ }
+ /**
+ * Constructs a new exception with the specified detail and cause.
+ * @param s the detail message.
+ * @param cause the cause
+ */
+ public GLException (String s, Exception cause) {
+ super(s, cause);
+ }
+ /**
+ * Dump this exception.
+ * @param p a print stream.
+ * @param indent how much space to indent
+ */
+ public void dump (PrintStream p, String indent) {
+ String inner = indent + " ";
+ p.println (indent + "<gl-exception>");
+ p.println (inner + getMessage());
+ Throwable cause = getCause();
+ if (cause != null) {
+ if (cause instanceof GLException)
+ ((GLException)cause).dump (p, inner);
+ else {
+ p.println (inner + "<cause>");
+ p.print (inner);
+ cause.printStackTrace (p);
+ p.println (inner + "</cause>");
+ }
+ }
+ p.print (inner);
+ printStackTrace (p);
+ p.println (indent + "</gl-exception>");
+ }
+ /**
+ * @return exceptions' detail and optional cause' detail.
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer (super.toString());
+ Throwable cause = getCause();
+ if (cause != null)
+ buf.append (" [" + cause.toString() +"]");
+ return buf.toString();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLPermission.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLPermission.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.GLPermission" table="glperm">
+ <id name="id" column="id" type="long">
+ <generator class="native" />
+ </id>
+ <property name="name">
+ <column name="name" sql-type="varchar(64)" not-null="true"
+ index="perm_name"/>
+ </property>
+ <many-to-one name="user"
+ class="org.jpos.gl.GLUser" column="gluser" />
+ <many-to-one name="journal"
+ class="org.jpos.gl.Journal" column="journal" />
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLPermission.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLPermission.java Thu May 1
11:55:29 2008
@@ -0,0 +1,125 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+/**
+ * Permissions are associated with Users and optionally with Journals.
+ *
+ * A {@link User} can have some system wide permissions and some
+ * others specific to a given {@link Journal}.
+ *
+ * @see User
+ * @see Journal
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class GLPermission {
+ public static final String READ = "read";
+ public static final String WRITE = "write";
+ public static final String POST = "post";
+ public static final String CHECKPOINT = "checkpoint";
+ public static final String SUMMARIZE = "summarize";
+ public static final String GRANT = "grant";
+
+ long id;
+ String name;
+ GLUser user;
+ Journal journal;
+
+ /**
+ * Constructs a Permission object with a "" name.
+ *
+ * The name can be modified later by calling {@link #setName}.
+ */
+ public GLPermission () {
+ super ();
+ setName ("");
+ }
+ /**
+ * Constructs a Permission with a given name.
+ * @param name the Name.
+ */
+ public GLPermission (String name) {
+ super ();
+ setName (name);
+ }
+ /**
+ * internal id
+ */
+ public void setId (long id) {
+ this.id = id;
+ }
+ /**
+ * @return internal Id
+ */
+ public long getId() {
+ return id;
+ }
+ /**
+ * @param name permission's name.
+ */
+ public void setName (String name) {
+ this.name = name;
+ }
+ /**
+ * @return permission's name.
+ */
+ public String getName () {
+ return name;
+ }
+ /**
+ * Permission belongs to user.
+ * @param user
+ */
+ public void setUser (GLUser user) {
+ this.user = user;
+ }
+ /**
+ * @return the user.
+ */
+ public GLUser getUser () {
+ return user;
+ }
+ /**
+ * Permission is associated with journal.
+ * @param journal the journal.
+ */
+ public void setJournal (Journal journal) {
+ this.journal = journal;
+ }
+ /**
+ * @return associated journal
+ */
+ public Journal getJournal () {
+ return journal;
+ }
+ public boolean equals (Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof GLPermission) {
+ return getId() == ((GLPermission)obj).getId();
+ }
+ return false;
+ }
+ public String toString () {
+ return getName ();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLSession.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLSession.java Thu May 1 11:55:29 2008
@@ -0,0 +1,1333 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.Date;
+import java.util.Calendar;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.StringTokenizer;
+import java.math.BigDecimal;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Criteria;
+import org.hibernate.LockMode;
+import org.hibernate.ScrollMode;
+import org.hibernate.Transaction;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.ScrollableResults;
+import org.hibernate.HibernateException;
+import org.hibernate.ObjectNotFoundException;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Expression;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+import org.hibernate.type.LongType;
+import org.hibernate.Hibernate;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jpos.ee.DB;
+
+/**
+ * MiniGL facility entry point.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class GLSession {
+ private static Configuration cfg;
+ private static SessionFactory sf;
+ private static Map ruleCache;
+ private GLUser user;
+ private Session session;
+ private static final Log log = LogFactory.getLog (GLSession.class);
+ private long checkpoint;
+ private DB db;
+ public static final short[] LAYER_ZERO = new short[] { 0 };
+ /**
+ * "0.00"
+ */
+ public static final BigDecimal ZERO = new BigDecimal ("0.00");
+ /**
+ * "0" (no decimals)
+ */
+ public static final BigDecimal Z = new BigDecimal ("0");
+
+ static {
+ try {
+ // init ();
+ ruleCache = new HashMap();
+ } catch (Exception e) {
+ log.fatal (e);
+ }
+ }
+ /**
+ * Construct a GLSession for a given user.
+ *
+ * User has to exist in MiniGL gluser table.
+ * @see GLUser
+ *
+ * @param username the user name.
+ */
+ public GLSession (String username)
+ throws HibernateException, GLException
+ {
+ super();
+ this.db = new DB();
+ session = db.open();
+ user = getUser (username);
+ if (user == null) {
+ close();
+ throw new GLException ("Invalid user '" + username + "'");
+ }
+ }
+ /**
+ * Construct a GLSession using property <code>user.name</code>.
+ * User has to exist in MiniGL gluser table.
+ * @see User
+ */
+ public GLSession () throws HibernateException, GLException {
+ this (System.getProperty ("user.name"));
+ }
+ /**
+ * Construct a GLSession for a given user.
+ *
+ * User has to exist in MiniGL gluser table.
+ * @see GLUser
+ *
+ * @param db EE DB
+ * @param username the user name.
+ */
+ public GLSession (DB db, String username)
+ throws HibernateException, GLException
+ {
+ super();
+ this.db = db;
+ session = db.open();
+ user = getUser (username);
+ if (user == null) {
+ close();
+ throw new GLException ("Invalid user '" + username + "'");
+ }
+ }
+ /**
+ * Construct a GLSession using property <code>user.name</code>.
+ * User has to exist in MiniGL gluser table.
+ * @param db EE DB
+ * @see User
+ */
+ public GLSession (DB db) throws HibernateException, GLException {
+ this (db, System.getProperty ("user.name"));
+ }
+ /**
+ * @param action name
+ * @return true if user has permission to perform given action
+ * @see GLPermission
+ */
+ public boolean hasPermission (String action) {
+ Iterator iter = user.getPermissions().iterator();
+ while (iter.hasNext()) {
+ GLPermission p = (GLPermission) iter.next();
+ if (p.getJournal() == null && action.equals (p.getName()))
+ return true;
+ }
+ return false;
+ }
+ /**
+ * @param action name
+ * @throws GLException if user doesn't have permission.
+ * @see GLPermission
+ */
+ public void checkPermission (String action) throws GLException {
+ if (!hasPermission (action)) {
+ throw new GLException (
+ "User '" + user.getName() + "' (" + user.getId() +
+ ") does not have '" + action + "' permission."
+ );
+ }
+ }
+ /**
+ * Grant permission to user.
+ * In order to grant a permission, we need to have both the permission
+ * and GRANT.
+ *
+ * @param userName user name
+ * @param permName permission name
+ */
+ public void grant (String userName, String permName)
+ throws GLException, HibernateException
+ {
+ checkPermission (GLPermission.GRANT);
+ checkPermission (permName);
+ GLPermission perm = new GLPermission(permName);
+ session.save (perm);
+ GLUser u = getUser (userName);
+ u.grant (perm);
+ }
+ /**
+ * Revoke permission from user.
+ * In order to grant a permission, we need to have both the permission
+ * and GRANT.
+ *
+ * @param userName user name
+ * @param permName permission name
+ */
+ public void revoke (String userName, String permName)
+ throws GLException, HibernateException
+ {
+ checkPermission (GLPermission.GRANT);
+ GLUser u = getUser (userName);
+ u.revoke (permName);
+ }
+
+ /**
+ * Verifies user's permission in a given journal.
+ * @param action name
+ * @param j journal
+ * @return true if user has permission to perform given action.
+ * @see GLPermission
+ * @see Journal
+ */
+ public boolean hasPermission (String action, Journal j) {
+ Iterator iter = user.getPermissions().iterator();
+ while (iter.hasNext()) {
+ GLPermission p = (GLPermission) iter.next();
+ Journal pj = p.getJournal();
+ if (action.equals (p.getName()) &&
+ (pj == null || (pj.getId() == j.getId())))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ /**
+ * Check user's permission in a given journal.
+ * @param action name
+ * @param j journal
+ * @throws GLException if user doesn't have permission.
+ * @see GLPermission
+ * @see Journal
+ */
+ public void checkPermission (String action, Journal j) throws
GLException {
+ if (!hasPermission (action, j)) {
+ throw new GLException (
+ "User '" + user.getName() + "' (" + user.getId() +
+ ") does not have '" + action + "' permission in
journal '" +
+ j.getName() + "' (" + j.getId() + ")"
+ );
+ }
+ }
+ /**
+ * @param code chart of account's code
+ * @return top level chart with given code or null.
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ * @see GLPermission
+ */
+ public Account getChart (String code)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ);
+ Query q = session.createQuery (
+ "from acct in class org.jpos.gl.CompositeAccount where
code=:code and parent is null"
+ );
+ q.setParameter ("code", code);
+ Iterator iter = q.list().iterator();
+ return (Account) (iter.hasNext() ? iter.next() : null);
+ }
+ /**
+ * @param chart chart of accounts.
+ * @param code account's code.
+ * @return account with given code in given chart, or null.
+ *
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ * @see GLPermission
+ */
+ public Account getAccount (Account chart, String code)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ);
+ Query q = session.createQuery (
+ "from acct in class org.jpos.gl.Account where root=:chart
and code=:code"
+ );
+ q.setLong ("chart", chart.getId());
+ q.setParameter ("code", code);
+ Iterator iter = q.list().iterator();
+ return (Account) (iter.hasNext() ? iter.next() : null);
+ }
+ /**
+ * Add account to parent.
+ * Check permissions, parent's type and optional currency.
+ *
+ * @param parent parent account
+ * @param acct account to add
+ * @throws HibernateException
+ * @throws GLException if user doesn't have permissions, or type mismatch
+ */
+ public void addAccount (CompositeAccount parent, Account acct)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.WRITE);
+ if (!parent.isChart() && !parent.equalsType (acct)) {
+ StringBuffer sb = new StringBuffer ("Type mismatch ");
+ sb.append (parent.getTypeAsString());
+ sb.append ('/');
+ sb.append (acct.getTypeAsString());
+ throw new GLException (sb.toString());
+ }
+ String currencyCode = parent.getCurrencyCode();
+ if (currencyCode != null
+ && !currencyCode.equals (acct.getCurrencyCode()))
+ {
+ StringBuffer sb = new StringBuffer ("Currency mismatch ");
+ sb.append (currencyCode);
+ sb.append ('/');
+ sb.append (acct.getCurrencyCode());
+ throw new GLException (sb.toString());
+ }
+ acct.setRoot (parent.getRoot());
+ session.save (acct);
+ // acct.setParent (parent);
+ parent.getChildren().add (acct);
+ }
+ /**
+ * @param chart chart of accounts.
+ * @param code account's code.
+ * @return final account with given code in given chart, or null.
+ *
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ * @see GLPermission
+ */
+ public FinalAccount getFinalAccount (Account chart, String code)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ);
+ Query q = session.createQuery (
+ "from acct in class org.jpos.gl.FinalAccount where
root=:chart and code=:code"
+ );
+ q.setLong ("chart", chart.getId());
+ q.setParameter ("code", code);
+ Iterator iter = q.list().iterator();
+ return (FinalAccount) (iter.hasNext() ? iter.next() : null);
+ }
+ /**
+ * @param chart chart of accounts.
+ * @param code account's code.
+ * @return composite account with given code in given chart, or null.
+ *
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ * @see GLPermission
+ */
+ public CompositeAccount getCompositeAccount (Account chart, String code)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ);
+ Query q = session.createQuery (
+ "from acct in class org.jpos.gl.CompositeAccount where
root=:chart and code=:code"
+ );
+ q.setLong ("chart", chart.getId());
+ q.setParameter ("code", code);
+ Iterator iter = q.list().iterator();
+ return (CompositeAccount) (iter.hasNext() ? iter.next() : null);
+ }
+ /**
+ * @param chartName chart of account's code.
+ * @param code account's code.
+ * @return account with given code in given chart, or null.
+ *
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ * @see GLPermission
+ */
+ public Account getAccount (String chartName, String code)
+ throws HibernateException, GLException
+ {
+ Account chart = getChart(chartName);
+ if (chart == null)
+ throw new GLException ("Chart '" + chartName + "' does not exist");
+ return getAccount(chart, code);
+ }
+ /**
+ * @param chartName chart of account's code.
+ * @param code account's code.
+ * @return final account with given code in given chart, or null.
+ *
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ * @see GLPermission
+ */
+ public FinalAccount getFinalAccount (String chartName, String code)
+ throws HibernateException, GLException
+ {
+ Account chart = getChart(chartName);
+ if (chart == null)
+ throw new GLException ("Chart '" + chartName + "' does not exist");
+ return getFinalAccount (chart, code);
+ }
+ /**
+ * @param chartName chart of account's code.
+ * @param code account's code.
+ * @return composite account with given code in given chart, or null.
+ *
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ * @see GLPermission
+ */
+ public CompositeAccount getCompositeAccount (String chartName,
String code)
+ throws HibernateException, GLException
+ {
+ Account chart = getChart(chartName);
+ if (chart == null)
+ throw new GLException ("Chart '" + chartName + "' does not exist");
+ return getCompositeAccount (chart, code);
+ }
+
+ /**
+ * @param name journal's name.
+ * @return journal or null.
+ * @throws GLException if users doesn't have global READ permission.
+ * @throws HibernateException on database errors.
+ * @see GLPermission
+ */
+ public Journal getJournal (String name)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ);
+ Query q = session.createQuery (
+ "from journal in class org.jpos.gl.Journal where name=:name"
+ );
+ q.setParameter ("name", name);
+ Iterator iter = q.list().iterator();
+ return (Journal) (iter.hasNext() ? iter.next() : null);
+ }
+
+ /**
+ * Post transaction in a given journal.
+ *
+ * @param journal the journal.
+ * @param txn the transaction.
+ * @throws GLException if user doesn't have POST permission or any
rule associated with this journal and/or account raises a GLException.
+ * @throws HibernateException on database errors.
+ * @see GLPermission
+ * @see JournalRule
+ */
+ public void post (Journal journal, GLTransaction txn)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.POST, journal);
+ txn.setJournal (journal);
+ txn.setTimestamp (new Date());
+ if (txn.getPostDate() == null)
+ txn.setPostDate (txn.getTimestamp());
+ invalidateCheckpoints (txn);
+ Collection rules = getRules (txn);
+ // dumpRules (rules);
+ applyRules (txn, rules);
+ session.save (txn);
+ }
+ /**
+ * Moves a transaction to a new journal
+ * @param txn the Transaction
+ * @param journal the New Journal
+ * @throws GLException if user doesn't have POST permission on the
old and new journals.
+ * @throws HibernateException on database errors.
+ */
+ public void move (GLTransaction txn, Journal journal)
+ throws GLException, HibernateException
+ {
+ checkPermission (GLPermission.POST, journal);
+ checkPermission (GLPermission.POST, txn.getJournal());
+ invalidateCheckpoints (txn); // invalidate in old journal
+ txn.setJournal (journal);
+ invalidateCheckpoints (txn); // invalidate in new journal
+ applyRules (txn, getRules (txn));
+ session.update (txn);
+ }
+
+ /**
+ * Summarize transactions in a journal.
+ *
+ * @param journal the journal.
+ * @param start date (inclusive).
+ * @param end date (inclusive).
+ * @param description summary transaction's description
+ * @return GLTransaction a summary transaction
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ * @throws HibernateException on database/mapping errors
+ */
+ public GLTransaction summarize
+ (Journal journal, Date start, Date end, String description,
short[] layers)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.SUMMARIZE, journal);
+ start = Util.floor (start);
+ end = Util.ceil (end);
+
+ if (end.compareTo (start) < 0) {
+ throw new GLException ("Invalid date range "
+ + Util.dateToString(start) + ":" + Util.dateToString (end));
+ }
+ Date lockDate = journal.getLockDate();
+ if (lockDate != null && start.compareTo (lockDate) <= 0) {
+ throw new GLException
+ ("Journal is locked at " + Util.dateToString (lockDate));
+ }
+ setLockDate (journal, end);
+
+ GLTransaction txn = new GLTransaction (description);
+ for (int i=0; i<layers.length; i++) {
+ Iterator debits = findSummarizedGLEntries (journal,
start, end, false, layers[i]);
+ Iterator credits = findSummarizedGLEntries (journal,
start, end, true, layers[i]);
+ while (debits.hasNext()) {
+ Object[] obj = (Object[]) debits.next();
+ txn.createDebit (
+ (FinalAccount) obj[0],
+ (BigDecimal) obj[1],
+ null, layers[i]
+ );
+ }
+ while (credits.hasNext()) {
+ Object[] obj = (Object[]) credits.next();
+ txn.createCredit (
+ (FinalAccount) obj[0],
+ (BigDecimal) obj[1],
+ null, layers[i]
+ );
+ }
+ }
+ txn.setJournal (journal);
+ txn.setTimestamp (new Date());
+ txn.setPostDate (end);
+ deleteGLTransactions (journal, start, end);
+ session.save (txn); // force post - no rule validations
+ journal.setLockDate (null);
+ return txn;
+ }
+
+ /**
+ * @param journal the journal.
+ * @param id txn id
+ * @return GLTransaction or null
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public GLTransaction getTransaction (Journal journal, long id)
+ throws HibernateException, GLException
+ {
+ GLTransaction txn = null;
+ checkPermission (GLPermission.READ, journal);
+ try {
+ txn = (GLTransaction)
+ session.load (GLTransaction.class, new Long(id));
+ if (txn.getJournal() != journal)
+ throw new GLException (
+ "The transaction does not belong to the specified journal"
+ );
+ } catch (ObjectNotFoundException e) {
+ // okay to happen
+ }
+ return txn;
+ }
+
+ /**
+ * @param journal the journal.
+ * @param start date (inclusive).
+ * @param end date (inclusive).
+ * @param destinationJournal where to move former transactions. A
null value
+would delete former transactions.
+ * @param searchString optional search string
+ * @param findByPostDate true to find by postDate, false to find
by timestamp
+ * @param pageNumber the page number
+ * @param pageSize the page size
+ * @return list of transactions
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public List findTransactions
+ (Journal journal, Date start, Date end, String searchString,
+ boolean findByPostDate, int pageNumber, int pageSize)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ, journal);
+ String dateField = findByPostDate ? "postDate" : "timestamp";
+ if (findByPostDate) {
+ if (start != null)
+ start = Util.floor (start);
+ if (end != null)
+ end = Util.ceil (end);
+ }
+ Criteria crit = session.createCriteria (GLTransaction.class)
+ .add (Expression.eq ("journal", journal));
+
+ if (start != null && start.equals (end))
+ crit.add (Expression.eq (dateField, start));
+ else {
+ if (start != null)
+ crit.add (Expression.ge (dateField, start));
+ if (end != null)
+ crit.add (Expression.le (dateField, end));
+ }
+ if (searchString != null)
+ crit.add (Expression.like ("detail", "%" + searchString + "%"));
+
+ if (pageSize > 0 && pageNumber > 0) {
+ crit.setMaxResults (pageSize);
+ crit.setFirstResult (pageSize * (pageNumber - 1));
+ }
+ return crit.list();
+ }
+
+ /**
+ * @param journal the journal.
+ * @param start date (inclusive).
+ * @param end date (inclusive).
+ * @param destinationJournal where to move former transactions. A
null value
+would delete former transactions.
+ * @param searchString optional search string
+ * @param findByPostDate true to find by postDate, false to find
by timestamp
+ * @return list of transactions
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public List findTransactions
+ (Journal journal, Date start, Date end, String searchString,
boolean findByPostDate)
+ throws HibernateException, GLException
+ {
+ return findTransactions (journal, start, end, searchString,
findByPostDate, 0, 0);
+ }
+
+ /**
+ * @return user object associated with this session.
+ */
+ public GLUser getUser() {
+ return user;
+ }
+ /**
+ * Current Balance for account in a given journal.
+ * @param journal the journal.
+ * @param acct the account.
+ * @return current balance.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal getBalance (Journal journal, Account acct)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, null, true) [0];
+ }
+ /**
+ * Current Balance for account in a given journal.
+ * @param journal the journal.
+ * @param acct the account.
+ * @param layers the layers.
+ * @return current balance.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal getBalance (Journal journal, Account acct, short layer)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, null, true, new short[] {
layer }) [0];
+ }
+ /**
+ * Current Balance for account in a given journal.
+ * @param journal the journal.
+ * @param acct the account.
+ * @param layers the layers.
+ * @return current balance.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal getBalance (Journal journal, Account acct,
short[] layers)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, null, true, layers) [0];
+ }
+ /**
+ * Current Balance for account in a given journal.
+ * @param journal the journal.
+ * @param acct the account.
+ * @param layers comma separated list of layers
+ * @return current balance.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal getBalance (Journal journal, Account acct,
String layers)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, null, true,
toLayers(layers)) [0];
+ }
+ /**
+ * Balance for account in a given journal in a given date.
+ * @param journal the journal.
+ * @param acct the account.
+ * @param date date (inclusive).
+ * @return balance at given date.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal getBalance (Journal journal, Account acct, Date date)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, date, true) [0];
+ }
+ /**
+ * Balance for account in a given journal in a given date.
+ * @param journal the journal.
+ * @param acct the account.
+ * @param date date (inclusive).
+ * @param layers layers
+ * @return balance at given date.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal getBalance (Journal journal, Account acct, Date
date, short layer)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, date, true, new short[] {
layer }) [0];
+ }
+ /**
+ * Balance for account in a given journal in a given date.
+ * @param journal the journal.
+ * @param acct the account.
+ * @param date date (inclusive).
+ * @param layers layers
+ * @return balance at given date.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal getBalance (Journal journal, Account acct, Date
date, short[] layers)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, date, true, layers) [0];
+ }
+ /**
+ * Get Both Balances at given date
+ * @param journal the journal.
+ * @param acct the account.
+ * @param date date (inclusive).
+ * @param inclusive either true or false
+ * @return array of 2 BigDecimals with balance and entry count.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal[] getBalances
+ (Journal journal, Account acct, Date date, boolean inclusive)
+ throws HibernateException, GLException
+ {
+ return getBalances (journal, acct, date, inclusive, LAYER_ZERO);
+ }
+
+ /**
+ * Get Both Balances at given date
+ * @param journal the journal.
+ * @param acct the account.
+ * @param date date (inclusive).
+ * @param inclusive either true or false
+ * @param layers the layers
+ * @return array of 2 BigDecimals with balance and entry count.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public BigDecimal[] getBalances
+ (Journal journal, Account acct, Date date, boolean inclusive,
short[] layers)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ, journal);
+ BigDecimal balance[] = { ZERO, Z };
+ if (acct.getChildren() != null) {
+ if (acct.isChart()) {
+ return getChartBalances
+ (journal, (CompositeAccount) acct, date,
inclusive, layers);
+ }
+ Iterator iter = acct.getChildren().iterator();
+ while (iter.hasNext()) {
+ Account a = (Account) iter.next();
+ BigDecimal[] b = getBalances (journal, a, date,
inclusive, layers);
+ balance[0] = balance[0].add (b[0]);
+ session.evict (a);
+ }
+ }
+ else if (acct instanceof FinalAccount) {
+ Criteria crit = session.createCriteria (GLEntry.class)
+ .add (Expression.eq ("account", acct))
+ .add (Expression.in ("layer", toShortArray (layers)));
+ crit = crit.createCriteria ("transaction")
+ .add (Expression.eq ("journal", journal));
+ if (date != null) {
+ if (inclusive) {
+ crit.add (Expression.lt ("postDate", Util.tomorrow (date)));
+ }
+ else {
+ date = Util.floor (date);
+ crit.add (Expression.lt ("postDate", date));
+ }
+ }
+ Checkpoint chkp =
+ getRecentCheckpoint (journal, acct, date, inclusive, layers);
+ if (chkp != null) {
+ balance[0] = chkp.getBalance();
+ crit.add (Expression.gt ("postDate", chkp.getDate()));
+ }
+ List l = crit.list();
+ balance[0] = applyEntries (balance[0], l);
+ balance[1] = new BigDecimal (l.size()); // hint for checkpoint
+ }
+ return balance;
+ }
+
+ /**
+ * AccountDetail for date range
+ * @param journal the journal.
+ * @param acct the account.
+ * @param start date (inclusive).
+ * @param end date (inclusive).
+ * @return Account detail for given period.
+ * @throws GLException if user doesn't have READ permission on
this jounral.
+ */
+ public AccountDetail getAccountDetail
+ (Journal journal, Account acct, Date start, Date end, short[] layers)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.READ);
+ start = Util.floor (start);
+ end = Util.ceil (end);
+ Criteria crit = session.createCriteria (GLEntry.class)
+ .add (Expression.eq ("account", acct))
+ .add (Expression.in ("layer", toShortArray (layers)));
+ crit = crit.createCriteria ("transaction")
+ .add (Expression.eq ("journal", journal))
+ .add (Expression.ge ("postDate", start))
+ .add (Expression.le ("postDate", end));
+
+ BigDecimal initialBalance[] = getBalances (journal, acct,
start, false, layers);
+ List entries = crit.list();
+ BigDecimal finalBalance = applyEntries (initialBalance[0], entries);
+
+ return new AccountDetail (
+ journal, acct,
+ initialBalance[0], finalBalance,
+ start, end, entries, layers );
+ }
+ /**
+ * @param journal the journal.
+ * @param acct the account.
+ * @param date date (null for last checkpoint)
+ * @param inclusive either true or false
+ * @return Most recent check point for given date.
+ * @throws GLException if user doesn't have CHECKPOINT permission
on this jounral.
+ */
+ public Checkpoint getRecentCheckpoint
+ (Journal journal, Account acct, Date date, boolean inclusive,
short[] layers)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.CHECKPOINT, journal);
+
+ Criteria crit = session.createCriteria (Checkpoint.class)
+ .add (Expression.eq ("journal", journal))
+ .add (Expression.eq ("account", acct));
+
+ if (layers != null)
+ crit.add (Expression.eq ("layers", layersToString(layers)));
+
+ if (date != null) {
+ if (inclusive)
+ crit.add (Expression.le ("date", date));
+ else
+ crit.add (Expression.lt ("date", date));
+ }
+ crit.addOrder (Order.desc ("date"));
+ crit.setMaxResults (1);
+ return (Checkpoint) crit.uniqueResult();
+ }
+
+ /**
+ * @param journal the Journal
+ * @param acct the account
+ * @param date checkpoint date (inclusive)
+ * @param threshold minimum number of GLEntries required to
create a checkpoint
+ * @throws GLException if user doesn't have CHECKPOINT permission
on this jounral.
+ */
+ public void createCheckpoint
+ (Journal journal, Account acct, Date date, int threshold)
+ throws HibernateException, GLException
+ {
+ createCheckpoint (journal, acct, date, threshold, LAYER_ZERO);
+ }
+ /**
+ * @param journal the Journal
+ * @param acct the account
+ * @param date checkpoint date (inclusive)
+ * @param layers taken into account in this checkpoint
+ * @param threshold minimum number of GLEntries required to
create a checkpoint
+ * @throws GLException if user doesn't have CHECKPOINT permission
on this jounral.
+ */
+ public void createCheckpoint
+ (Journal journal, Account acct, Date date, int threshold,
short[] layers)
+ throws HibernateException, GLException
+ {
+ if (date == null)
+ throw new GLException ("Invalid checkpoint date");
+ checkPermission (GLPermission.CHECKPOINT, journal);
+ // Transaction tx = session.beginTransaction();
+ session.lock (journal, LockMode.UPGRADE);
+ createCheckpoint0 (journal, acct, date, threshold, layers);
+ // tx.commit();
+ }
+ /**
+ * Lock a journal.
+ * @param journal the journal.
+ * @throws HibernateException on database errors.
+ * @throws GLException if user doesn't have POST permission on
this jounral.
+ */
+ public void lock (Journal journal)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.POST, journal);
+ session.lock (journal, LockMode.UPGRADE);
+ }
+ /**
+ * Lock an account in a given journal.
+ * @param journal the journal.
+ * @param acct the account.
+ * @throws GLException if user doesn't have POST permission on
this jounral.
+ * @throws HibernateException on database errors.
+ */
+ public void lock (Journal journal, Account acct)
+ throws HibernateException, GLException
+ {
+ checkPermission (GLPermission.POST, journal);
+ AccountLock lck = getLock (journal, acct, false);
+ if (lck == null) {
+ // Transaction tx = session.beginTransaction();
+ session.lock (journal, LockMode.UPGRADE);
+ lck = getLock (journal, acct, true);
+ // tx.commit();
+ lck = getLock (journal, acct, false); // re-get it
+ }
+ }
+
+ /**
+ * Open underlying Hibernate session.
+ * @throws HibernateException
+ */
+ public synchronized Session open () throws HibernateException {
+ return db.open();
+ }
+ /**
+ * Close underlying Hibernate session.
+ * @throws HibernateException
+ */
+ public synchronized void close () throws HibernateException {
+ db.close();
+ }
+ /**
+ * @return underlying Hibernate Session.
+ */
+ public Session session () {
+ return db.session();
+ }
+ /**
+ * @return Hibernate's session factory
+ */
+ public SessionFactory getSessionFactory () {
+ return sf;
+ }
+ /**
+ * Begin hibernate transaction.
+ * @return new Transaction
+ */
+ public Transaction beginTransaction() throws HibernateException {
+ return session.beginTransaction();
+ }
+ /**
+ * Begin hibernate transaction.
+ * @param timeout timeout in seconds
+ * @return new Transaction
+ */
+ public Transaction beginTransaction(int timeout) throws
HibernateException {
+ Transaction tx = session.beginTransaction();
+ if (timeout > 0)
+ tx.setTimeout (timeout);
+ return tx;
+ }
+ public GLUser getUser (String nick) throws HibernateException
+ {
+ return (GLUser) session.createCriteria (GLUser.class)
+ .add (Expression.eq ("nick", nick))
+ .uniqueResult();
+ }
+ /**
+ * set a journal's lockDate
+ * @param journal the Journal
+ * @param lockDate the lock date.
+ * @throws HibernateException on database errors.
+ * @throws GLException if users doesn't have global READ permission.
+ */
+ public void setLockDate (Journal journal, Date lockDate)
+ throws GLException, HibernateException
+ {
+ checkPermission (GLPermission.WRITE, journal);
+ // Transaction tx = session.beginTransaction();
+ session.lock (journal, LockMode.UPGRADE);
+ journal.setLockDate (lockDate);
+ // tx.commit();
+ }
+
+ // -----------------------------------------------------------------------
+ // PUBLIC HELPERS
+ // -----------------------------------------------------------------------
+ public short[] toLayers (String layers) {
+ StringTokenizer st = new StringTokenizer (layers, ", ");
+ short[] sa = new short[st.countTokens()];
+ for (int i=0; st.hasMoreTokens(); i++)
+ sa[i] = Short.parseShort (st.nextToken());
+ return sa;
+ }
+
+ // -----------------------------------------------------------------------
+ // PRIVATE METHODS
+ // -----------------------------------------------------------------------
+ private AccountLock getLock (Journal journal, Account acct,
boolean create)
+ throws HibernateException
+ {
+ AccountLock lck = new AccountLock (journal, acct);
+ try {
+ lck = (AccountLock)
+ session.load (AccountLock.class, lck, LockMode.UPGRADE);
+ } catch (ObjectNotFoundException e) {
+ if (create)
+ session.save (lck);
+ else
+ lck = null;
+ }
+ return lck;
+ }
+ private void createCheckpoint0
+ (Journal journal, Account acct, Date date, int threshold,
short[] layers)
+ throws HibernateException, GLException
+ {
+ if (acct instanceof CompositeAccount) {
+ Iterator iter = ((CompositeAccount) acct).getChildren().iterator();
+ while (iter.hasNext()) {
+ Account a = (Account) iter.next();
+ createCheckpoint0 (journal, a, date, threshold, layers);
+ }
+ }
+ else if (acct instanceof FinalAccount) {
+ Date sod = Util.floor (date); // sod = start of day
+ invalidateCheckpoints (journal, new Account[] { acct },
sod, sod, layers);
+ BigDecimal b[] = getBalances (journal, acct, date, true, layers);
+ if (b[1].intValue() >= threshold) {
+ Checkpoint c = new Checkpoint ();
+ c.setDate (date);
+ c.setBalance (b[0]);
+ c.setJournal (journal);
+ c.setAccount (acct);
+ c.setLayers (layersToString(layers));
+ session.save (c);
+ }
+ }
+ }
+ private Account[] getAccounts (GLTransaction txn) {
+ List list = txn.getEntries();
+ Account[] accounts = new Account[list.size()];
+ Iterator iter = list.iterator();
+ for (int i=0; iter.hasNext(); i++) {
+ GLEntry entry = (GLEntry) iter.next();
+ accounts[i] = entry.getAccount();
+ }
+ return accounts;
+ }
+ private List getAccountHierarchyIds (Account acct)
+ throws GLException
+ {
+ if (acct == null)
+ throw new GLException ("Invalid entry - account is null");
+ Account p = acct;
+ List l = new ArrayList();
+ for (int i=0; p != null; i++) {
+ l.add (new Long (p.getId()));
+ p = p.getParent();
+ }
+ return l;
+ }
+ private void invalidateCheckpoints (GLTransaction txn)
+ throws HibernateException
+ {
+ Account[] accounts = getAccounts (txn);
+ invalidateCheckpoints (
+ txn.getJournal(), accounts, txn.getPostDate(), null, null
+ );
+ }
+ private void invalidateCheckpoints
+ (Journal journal, Account[] accounts, Date start, Date end,
short[] layers)
+ throws HibernateException
+ {
+ Criteria crit = session.createCriteria (Checkpoint.class)
+ .add (Expression.eq ("journal", journal))
+ .add (Expression.in ("account", accounts));
+
+ if (layers != null)
+ crit.add (Expression.eq ("layers", layersToString(layers)));
+ if (start.equals (end))
+ crit.add (Expression.eq ("date", start));
+ else {
+ crit.add (Expression.ge ("date", start));
+ if (end != null) {
+ crit.add (Expression.le ("date", end));
+ }
+ }
+ Iterator iter = crit.list().iterator();
+ while (iter.hasNext()) {
+ Checkpoint cp = (Checkpoint) iter.next();
+ session.delete (cp);
+ }
+ session.flush();
+ }
+ private BigDecimal applyEntries (BigDecimal balance, List entries)
+ throws GLException
+ {
+ Iterator iter = entries.iterator();
+ while (iter.hasNext()) {
+ GLEntry entry = (GLEntry) iter.next();
+ if (entry.isIncrease ()) {
+ balance = balance.add (entry.getAmount());
+ }
+ else if (entry.isDecrease()) {
+ balance = balance.subtract (entry.getAmount());
+ }
+ else {
+ throw new GLException (
+ entry.toString() + " has invalid account type"
+ );
+ }
+ }
+ return balance;
+ }
+ private static void init () throws Exception {
+ synchronized (GLSession.class) {
+ if (cfg != null)
+ return;
+
+ cfg = new Configuration();
+ cfg.configure ();
+ sf = cfg.buildSessionFactory();
+ }
+ }
+ private Object getRuleImpl (String clazz) throws GLException
+ {
+ Object impl = ruleCache.get (clazz);
+ if (impl == null) {
+ synchronized (ruleCache) {
+ impl = ruleCache.get (clazz);
+ if (impl == null) {
+ try {
+ Class cls = Class.forName (clazz);
+ impl = cls.newInstance();
+ ruleCache.put (clazz, impl);
+ } catch (Exception e) {
+ throw new GLException ("Invalid rule " +
clazz, e);
+ }
+ }
+ }
+ }
+ return impl;
+ }
+ private void dumpRules (Collection rules) {
+ log.warn ("--- rules ---");
+ Iterator iter = rules.iterator();
+ while (iter.hasNext()) {
+ log.warn (iter.next());
+ }
+ }
+ private void addRules
+ (Map ruleMap, Journal journal, List acctHierarchy, int offset)
+ throws HibernateException, GLException
+ {
+ Query q = session.createQuery (
+ "from org.jpos.gl.RuleInfo where journal=:journal and
account in (:accts) order by id"
+ );
+ q.setParameter ("journal", journal);
+ q.setParameterList ("accts", acctHierarchy, new LongType());
+ q.setCacheable (true);
+ q.setCacheRegion ("rules");
+ Iterator iter = q.iterate();
+
+ while (iter.hasNext()) {
+ RuleInfo ri = (RuleInfo) iter.next();
+ RuleEntry k = new RuleEntry (ri, ri.getAccount());
+ RuleEntry re = (RuleEntry) ruleMap.get (k.getKey());
+ if (re == null)
+ ruleMap.put (k.getKey(), re = k);
+
+ re.addOffset (offset);
+ }
+ }
+ private void applyRules (GLTransaction txn, Collection rules)
+ throws HibernateException, GLException
+ {
+ Iterator iter = rules.iterator();
+ while (iter.hasNext()) {
+ RuleEntry re = (RuleEntry) iter.next();
+ RuleInfo ri = re.getRuleInfo();
+ JournalRule rule = (JournalRule) getRuleImpl (ri.getClazz());
+ rule.check (
+ this, txn, ri.getParam(), re.getAccount(),
+ re.getOffsets(), ri.getLayerArray()
+ );
+ }
+ }
+ private Collection getRules (GLTransaction txn)
+ throws HibernateException, GLException
+ {
+ Map map = new LinkedHashMap ();
+ Journal journal = txn.getJournal();
+
+ Query q = session.createQuery (
+ "from org.jpos.gl.RuleInfo where journal=:journal and
account is null order by id"
+ );
+ q.setParameter ("journal", journal);
+ Iterator iter = q.list().iterator();
+ while (iter.hasNext()) {
+ RuleInfo ri = (RuleInfo) iter.next();
+ RuleEntry re = new RuleEntry (ri);
+ map.put (re.getKey(), re);
+ }
+ iter = txn.getEntries().iterator();
+ for (int i=0; iter.hasNext(); i++) {
+ GLEntry entry = (GLEntry) iter.next();
+ addRules (map, journal,
+ getAccountHierarchyIds (entry.getAccount()), i);
+ }
+ return map.values();
+ }
+ private BigDecimal[] getChartBalances
+ (Journal journal, CompositeAccount acct, Date date, boolean
inclusive, short[] layers)
+ throws HibernateException, GLException
+ {
+ BigDecimal balance[] = { ZERO, ZERO };
+ Iterator iter = ((CompositeAccount) acct).getChildren().iterator();
+ while (iter.hasNext()) {
+ Account a = (Account) iter.next();
+ BigDecimal[] b = getBalances (journal, a, date, inclusive, layers);
+ if (a.isDebit()) {
+ balance[0] = balance[0].add (b[0]);
+ balance[1] = balance[1].add (b[1]);
+ } else if (a.isCredit()) {
+ balance[0] = balance[0].subtract (b[0]);
+ balance[1] = balance[1].subtract (b[1]);
+ } else {
+ throw new GLException ("Account " + a + " has wrong type");
+ }
+ session.evict (a);
+ }
+ return balance;
+ }
+ private Iterator findSummarizedGLEntries
+ (Journal journal, Date start, Date end, boolean credit, short layer)
+ throws HibernateException, GLException
+ {
+ StringBuffer qs = new StringBuffer (
+ "select entry.account, sum(entry.amount)" +
+ " from org.jpos.gl.GLEntry entry," +
+ " org.jpos.gl.GLTransaction txn" +
+ " where txn.id = entry.transaction" +
+ " and credit = :credit" +
+ " and txn.journal = :journal" +
+ " and entry.layer = :layer"
+ );
+ boolean equalDate = start.equals (end);
+ if (equalDate) {
+ qs.append (" and txn.postDate = :date");
+ } else {
+ qs.append (" and txn.postDate >= :start");
+ qs.append (" and txn.postDate <= :end");
+ }
+ qs.append (" group by entry.account");
+ Query q = session.createQuery (qs.toString());
+ q.setLong ("journal", journal.getId());
+ q.setParameter ("credit", credit ? "Y" : "N");
+ q.setShort ("layer", layer);
+ if (equalDate)
+ q.setParameter ("date", start);
+ else {
+ q.setParameter ("start", start);
+ q.setParameter ("end", end);
+ }
+ return q.iterate();
+ }
+ private void deleteGLTransactions (Journal journal, Date start,
Date end)
+ throws HibernateException, GLException
+ {
+ boolean equalDate = start.equals (end);
+
+ StringBuffer qs = new StringBuffer (
+ "from org.jpos.gl.GLTransaction where journal = :journal"
+ );
+ if (equalDate) {
+ qs.append (" and postDate = :date");
+ } else {
+ qs.append (" and postDate >= :start");
+ qs.append (" and postDate <= :endDate");
+ }
+ Query q = session.createQuery (qs.toString());
+ q.setLong ("journal", journal.getId());
+ if (equalDate)
+ q.setParameter ("date", start);
+ else {
+ q.setParameter ("start", start);
+ q.setParameter ("endDate", end);
+ }
+ ScrollableResults sr = q.scroll(ScrollMode.FORWARD_ONLY);
+ while (sr.next()) {
+ session.delete (sr.get(0));
+ }
+ }
+ private void reset() {
+ checkpoint = System.currentTimeMillis();
+ }
+ private long checkPoint() {
+ long now = System.currentTimeMillis();
+ long diff = now - checkpoint;
+ checkpoint = now;
+ return diff;
+ }
+ private void checkPoint (String s) {
+ System.out.println (s + " [" + checkPoint() + "ms]");
+ }
+ private static Short[] toShortArray (short[] i) {
+ if (i == null)
+ return new Short[0];
+ Short[] sa = new Short[i.length];
+ for (int j=0; j<i.length; j++)
+ sa[j] = new Short(i[j]);
+ return sa;
+ }
+ private String layersToString (short[] layers) {
+ StringBuffer sb = new StringBuffer();
+ Arrays.sort (layers);
+ for (int i=0; i<layers.length; i++) {
+ if (i>0)
+ sb.append ('.');
+ sb.append (Short.toString(layers[i]));
+ }
+ return sb.toString();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLTransaction.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLTransaction.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.GLTransaction" table="transacc">
+ <id name="id" column="id" type="long">
+ <generator class="native" />
+ </id>
+
+ <property name="detail" type="string" />
+ <property name="timestamp" type="timestamp">
+ <column name="timestamp" sql-type="timestamp" not-null="true"
+ index="timestamp"/>
+ </property>
+ <property name="postDate" type="date">
+ <column name="postDate" sql-type="date" not-null="false"
+ index="postDate"/>
+ </property>
+
+ <many-to-one name="journal" column="journal" not-null="true" />
+
+ <list name="entries" cascade="all-delete-orphan" lazy="true">
+ <key column="transaction" />
+ <index column="posn" />
+ <one-to-many class="org.jpos.gl.GLEntry" />
+ </list>
+ </class>
+</hibernate-mapping>
+
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLTransaction.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLTransaction.java Thu May 1
11:55:29 2008
@@ -0,0 +1,344 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import org.jdom.Element;
+import org.jdom.Comment;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+/**
+ * GLTransaction.
+ *
+ * Represents a MiniGL Transaction.
+ *
+ * @see GLEntry
+ * @see Journal
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class GLTransaction {
+ private long id;
+ private Date timestamp;
+ private Date postDate;
+ private String detail;
+ private List children;
+ private Journal journal;
+ List entries;
+
+ public GLTransaction () {
+ super();
+ }
+ public GLTransaction (String detail) {
+ super ();
+ setDetail (detail);
+ }
+ /**
+ * Constructs a GLTransaction out of a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ * @param elem
+ */
+ public GLTransaction (Element elem) throws ParseException {
+ super();
+ fromXML (elem);
+ }
+ /**
+ * GLTransaction id.
+ *
+ * @return internal id
+ */
+ public long getId() {
+ return id;
+ }
+ /**
+ * GLTransaction id.
+ *
+ * @param id internal id.
+ */
+ public void setId(long id) {
+ this.id = id;
+ }
+ /**
+ * Timestamp.
+ * @param d transaction timestamp
+ */
+ public void setTimestamp (Date d) {
+ this.timestamp = d;
+ }
+ /**
+ * Timestamp.
+ * @return transaction timestamp
+ */
+ public Date getTimestamp () {
+ return timestamp;
+ }
+ /**
+ * Posting date
+ * @param d transaction postdate
+ */
+ public void setPostDate (Date d) {
+ this.postDate = d;
+ }
+ /**
+ * @return transaction postdate
+ */
+ public Date getPostDate () {
+ return postDate;
+ }
+ /**
+ * Detail.
+ * @param detail transaction detail
+ */
+ public void setDetail (String detail) {
+ this.detail = detail;
+ }
+ /**
+ * Detail.
+ * @return transaction detail
+ */
+ public String getDetail () {
+ return detail;
+ }
+ /**
+ * Entries.
+ * @param entries transaction entries
+ */
+ public void setEntries (List entries) {
+ this.entries = entries;
+ }
+ /**
+ * Entries.
+ * @return transaction entries
+ */
+ public List getEntries () {
+ if (entries == null)
+ entries = new ArrayList ();
+ return entries;
+ }
+ /**
+ * Journal.
+ *
+ * @return journal where this transaction has been posted.
+ */
+ public Journal getJournal () {
+ return journal;
+ }
+ /**
+ * Journal.
+ *
+ * @param journal journal where this transaction has been posted.
+ */
+ public void setJournal (Journal journal) {
+ this.journal = journal;
+ }
+
+ /**
+ * Create GLEntry associated with this GLTransaction.
+ *
+ * Factory helper method.
+ *
+ * @param acct the account
+ * @param amount amount
+ * @param detail detail
+ * @param isCredit true if credit, false if debit
+ * @param layer the layer
+ */
+ public GLEntry createGLEntry (FinalAccount acct, BigDecimal
amount, String detail, boolean isCredit, short layer)
+ {
+ GLEntry entry = isCredit ? (GLEntry) new GLCredit() :
(GLEntry) new GLDebit();
+ entry.setAccount (acct);
+ entry.setAmount (amount);
+ entry.setDetail (detail);
+ entry.setCredit (isCredit);
+ entry.setTransaction (this);
+ entry.setLayer (layer);
+ getEntries().add (entry);
+ return entry;
+ }
+ /**
+ * Create a debit GLEntry associated with this GLTransaction.
+ *
+ * Factory helper method.
+ *
+ * @param acct the account
+ * @param amount amount
+ */
+ public GLEntry createDebit (FinalAccount acct, BigDecimal amount)
+ {
+ return createGLEntry (acct, amount, null, false, (short) 0);
+ }
+ /**
+ * Create a debit GLEntry associated with this GLTransaction.
+ *
+ * Factory helper method.
+ *
+ * @param acct the account
+ * @param amount amount
+ * @param detail detail
+ */
+ public GLEntry createDebit
+ (FinalAccount acct, BigDecimal amount, String detail)
+ {
+ return createGLEntry (acct, amount, detail, false, (short) 0);
+ }
+ /**
+ * Create a debit GLEntry associated with this GLTransaction.
+ *
+ * Factory helper method.
+ *
+ * @param acct the account
+ * @param amount amount
+ * @param detail detail
+ * @param layer layer
+ */
+ public GLEntry createDebit
+ (FinalAccount acct, BigDecimal amount, String detail, short layer)
+ {
+ return createGLEntry (acct, amount, detail, false, layer);
+ }
+
+ /**
+ * Create a credit GLEntry associated with this GLTransaction.
+ *
+ * Factory helper method.
+ *
+ * @param acct the account
+ * @param amount amount
+ */
+ public GLEntry createCredit (FinalAccount acct, BigDecimal amount) {
+ return createGLEntry (acct, amount, null, true, (short) 0);
+ }
+ /**
+ * Create a credit GLEntry associated with this GLTransaction.
+ *
+ * Factory helper method.
+ *
+ * @param acct the account
+ * @param amount amount
+ * @param detail detail
+ */
+ public GLEntry createCredit
+ (FinalAccount acct, BigDecimal amount, String detail)
+ {
+ return createGLEntry (acct, amount, detail, true, (short) 0);
+ }
+ /**
+ * Create a credit GLEntry associated with this GLTransaction.
+ *
+ * Factory helper method.
+ *
+ * @param acct the account
+ * @param amount amount
+ * @param layer the layer
+ * @param detail detail
+ */
+ public GLEntry createCredit
+ (FinalAccount acct, BigDecimal amount, String detail, short layer)
+ {
+ return createGLEntry (acct, amount, detail, true, layer);
+ }
+ /**
+ *
+ * Create a reverse transaction based on this one
+ *
+ * @return a reversal transaction
+ */
+ public GLTransaction createReverse() {
+ GLTransaction glt = new GLTransaction ("(" + getDetail() + ")");
+ glt.setJournal (getJournal());
+ Iterator iter = getEntries().iterator();
+ while (iter.hasNext()) {
+ GLEntry e = (GLEntry) iter.next();
+ glt.createGLEntry (
+ e.getAccount(),
+ negate (e.getAmount()),
+ e.getDetail(),
+ e.isCredit(),
+ e.getLayer()
+ );
+ }
+ return glt;
+ }
+ /**
+ * Parses a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public void fromXML (Element elem) throws ParseException {
+ setDetail (elem.getChildTextTrim ("detail"));
+ setPostDate (
+ Util.parseDate (elem.getAttributeValue ("post-date"))
+ );
+ setTimestamp (
+ Util.parseDateTime (elem.getAttributeValue ("date"))
+ );
+ }
+ /**
+ * Creates a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public Element toXML (boolean deep) {
+ Element elem = new Element ("transaction");
+ elem.setAttribute ("id", Long.toString(getId()));
+ Util.setDateTimeAttribute (elem, "date", getTimestamp());
+ Util.setDateAttribute (elem, "post-date", getPostDate());
+
+ if (getDetail() != null) {
+ Element detail = new Element ("detail").setText (getDetail());
+ elem.addContent (detail);
+ }
+ elem.setAttribute ("journal", getJournal().getName());
+
+ Iterator iter = getEntries().iterator();
+ while (iter.hasNext()) {
+ GLEntry entry = (GLEntry) iter.next();
+ elem.addContent (entry.toXML (deep));
+ }
+ return elem;
+ }
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", getId())
+ .toString();
+ }
+ public boolean equals(Object other) {
+ if ( !(other instanceof GLTransaction) ) return false;
+ GLTransaction castOther = (GLTransaction) other;
+ return new EqualsBuilder()
+ .append(this.getId(), castOther.getId())
+ .isEquals();
+ }
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getId())
+ .toHashCode();
+ }
+ private BigDecimal negate (BigDecimal bd) {
+ return bd != null ? bd.negate() : null;
+ }
+
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLUser.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLUser.hbm.xml Thu May 1 11:55:29 2008
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.GLUser" table="gluser">
+ <id name="id" column="id" type="long">
+ <generator class="native" />
+ </id>
+ <property name="nick">
+ <column name="nick" sql-type="varchar(32)" unique="true"
+ not-null="true" />
+ </property>
+ <property name="name" length="128" not-null="true" />
+
+ <set name="permissions" lazy="true" cascade="all-delete-orphan">
+ <key column="gluser" />
+ <one-to-many class="org.jpos.gl.GLPermission" />
+ </set>
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/GLUser.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/GLUser.java Thu May 1 11:55:29 2008
@@ -0,0 +1,200 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Set;
+import java.util.LinkedHashSet;
+import java.util.Iterator;
+import org.jdom.Element;
+import org.jdom.Comment;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+/**
+ * MiniGL user
+ *
+ * A User object is required in order to create a GLSesssion.
+ *
+ * MiniGL does not take care of user authentication, that's something
+ * that has to be handled by the caller (i.e. by using JAAS).
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see GLSession
+ */
+public class GLUser {
+ private String nick;
+ private String name;
+ private Set perms;
+ private long id; // the Hibernate identifier
+
+ public GLUser() {
+ super();
+ perms = new LinkedHashSet ();
+ }
+ /**
+ * Constructs an User object out of a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ * @param elem
+ */
+ public GLUser (Element elem) {
+ this();
+ fromXML (elem);
+ }
+ /**
+ * @return user's full name (informational only)
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name users's full name
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return user's nick name
+ */
+ public String getNick() {
+ return nick;
+ }
+ /**
+ * @param nick users's nick name
+ */
+ public void setNick(String nick) {
+ this.nick = nick;
+ }
+ /**
+ * @return internal id
+ */
+ public long getId() {
+ return id;
+ }
+ /**
+ * @param id internal id
+ */
+ public void setId(long id) {
+ this.id = id;
+ }
+ /**
+ * @param perms Set of permissions
+ */
+ public void setermissions (Set perms) {
+ this.perms = perms;
+ }
+ /**
+ * @return Set of permissions
+ */
+ public Set getPermissions () {
+ return perms;
+ }
+ /**
+ * @return true if user has a given permission
+ */
+ public boolean hasPermission (GLPermission perm) {
+ return perms.contains (perm);
+ }
+ /**
+ * @param perms Set of permissions
+ */
+ public void setPermissions (Set perms) {
+ this.perms = perms;
+ }
+ /**
+ * Grant user a given permission
+ * @param perm the permission
+ */
+ public void grant (GLPermission perm) {
+ if (!perms.contains (perm))
+ perms.add (perm);
+ }
+ /**
+ * Grant user a given permission
+ * @param permName the permission
+ */
+ public void grant (String permName) {
+ grant (new GLPermission (permName));
+ }
+ /**
+ * Revoke permission from user
+ * @param perm the permission
+ */
+ public void revoke (String permName) {
+ Iterator iter = perms.iterator();
+ while (iter.hasNext()) {
+ GLPermission p = (GLPermission) iter.next();
+ if (permName.equals (p.getName())) {
+ perms.remove (p);
+ }
+ }
+ }
+ /**
+ * Revoke all permissions
+ */
+ public void revokeAll () {
+ perms.clear ();
+ }
+ /**
+ * Parses a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public void fromXML (Element elem) {
+ setNick (elem.getChildTextTrim ("nick"));
+ setName (elem.getChildTextTrim ("name"));
+ }
+ /**
+ * Creates a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public Element toXML () {
+ Element e = new Element ("user");
+ e.addContent (new Comment ("id " +Long.toString (getId())));
+ e.addContent (new Element ("nick").setText (getNick()));
+ e.addContent (new Element ("name").setText (getName()));
+ Iterator iter = getPermissions().iterator();
+ while (iter.hasNext()) {
+ GLPermission p = (GLPermission) iter.next();
+ if (p.getJournal() == null)
+ e.addContent (new Element ("grant").setText (p.getName()));
+ }
+ return e;
+ }
+ public boolean equals(Object other) {
+ if ( !(other instanceof GLUser) ) return false;
+ GLUser castOther = (GLUser) other;
+ return new EqualsBuilder()
+ .append(this.getId(), castOther.getId())
+ .isEquals();
+ }
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getId())
+ .toHashCode();
+ }
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", getId())
+ .append("name", getName())
+ .toString();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/Journal.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Journal.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.Journal" table="journal">
+ <id name="id" column="id" type="long">
+ <generator class="native" />
+ </id>
+ <property name="name">
+ <column name="name" sql-type="varchar(32)" not-null="true"
unique="true" />
+ </property>
+ <property name="start" type="date" />
+ <property name="end" type="date" column="end_" />
+ <property name="closed" type="boolean" />
+ <property name="lockDate" type="date" />
+ <many-to-one name="chart" not-null="true" />
+
+ <set name="layers" lazy="true">
+ <key column="journal" />
+ <one-to-many class="org.jpos.gl.Layer" />
+ </set>
+ <set name="permissions" lazy="true">
+ <key column="journal" />
+ <one-to-many class="org.jpos.gl.GLPermission" />
+ </set>
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/Journal.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Journal.java Thu May 1 11:55:29 2008
@@ -0,0 +1,261 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Set;
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import org.jdom.Element;
+import org.jdom.Comment;
+import java.text.ParseException;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+/**
+ * Journal is the place to post GLTransactions.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see GLTransaction
+ */
+public class Journal {
+ private long id;
+ private Date start, end, lockDate;
+ private String name;
+ private boolean closed;
+ private Account chart;
+ private Set permissions;
+ private Set layers;
+
+ /**
+ * Constructs a journal.
+ */
+ public Journal () {
+ super();
+ }
+ /**
+ * Constructs a Journal out of a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>.
+ * @param elem
+ */
+ public Journal (Element elem) throws ParseException {
+ super();
+ fromXML (elem);
+ }
+ /**
+ * @return internal ID
+ */
+ public long getId() {
+ return id;
+ }
+ /**
+ * @param id intenal ID
+ */
+ public void setId(long id) {
+ this.id = id;
+ }
+ /**
+ * @return journal name.
+ */
+ public String getName () {
+ return name;
+ }
+ /**
+ * @param name the name.
+ */
+ public void setName (String name) {
+ this.name = name;
+ }
+ /**
+ * A closed journal should not accept transactions
+ * @param closed true if this journal is closed.
+ * @see org.jpos.gl.rule.CanPost
+ */
+ public void setClosed (boolean closed) {
+ this.closed = closed;
+ }
+ /**
+ * @return true if this journal has a <code>closed</code> indicator
+ * @see org.jpos.gl.rule.CanPost
+ */
+ public boolean isClosed () {
+ return closed;
+ }
+ /**
+ * Set the initial date for this journal.
+ *
+ * Transactions with a postDate less than this start date are
+ * rejected by {@link org.jpos.gl.rule.CanPost}.
+ *
+ * @param start journal's start date
+ */
+ public void setStart (Date start) {
+ this.start = start;
+ }
+ /**
+ * @return the start date.
+ */
+ public Date getStart () {
+ return start;
+ }
+ /**
+ * Set the end date for this journal.
+ *
+ * Transactions with a postDate greater than this end date are
+ * rejected by {@link org.jpos.gl.rule.CanPost}.
+ *
+ * @param end journal's end date
+ */
+ public void setEnd (Date end) {
+ this.end = end;
+ }
+ /**
+ * @return the end date.
+ */
+ public Date getEnd () {
+ return end;
+ }
+ /**
+ * Transactions should not be posted to this journal using
+ * a postDate <= the lockDate.
+ *
+ * @lockDate lockDate the lock date.
+ */
+ public void setLockDate (Date lockDate) {
+ this.lockDate = lockDate;
+ }
+ /**
+ * @return journal lock date (or null if there's no lock date)
+ */
+ public Date getLockDate() {
+ return lockDate;
+ }
+ /**
+ * Journals have a default Chart of Accounts.
+ *
+ * @param chart a toplevel {@link CompositeAccount}
+ */
+ public void setChart (Account chart) {
+ this.chart = chart;
+ }
+ /**
+ * return the default chart.
+ */
+ public Account getChart () {
+ return chart;
+ }
+ /**
+ * @param layers associated with this Journal.
+ */
+ public void setLayers (Set layers) {
+ this.layers = layers;
+ }
+ /**
+ * @return permissions associated with this Journal.
+ */
+ public Set getLayers () {
+ return layers;
+ }
+ /**
+ * @param permissions associated with this Journal.
+ */
+ public void setPermissions (Set permissions) {
+ this.permissions = permissions;
+ }
+ /**
+ * @return permissions associated with this Journal.
+ */
+ public Set getPermissions () {
+ return permissions;
+ }
+ /**
+ * populates this Journal out of a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>.
+ * @param elem
+ */
+ public void fromXML (Element elem) throws ParseException {
+ setStart (
+ Util.parseDate (elem.getChildTextTrim ("start"))
+ );
+ setEnd (
+ Util.parseDate (elem.getChildTextTrim ("end"))
+ );
+ setName (elem.getChildTextTrim ("name"));
+ setClosed (
+ "closed".equalsIgnoreCase (elem.getChildTextTrim ("status"))
+ );
+ }
+ /**
+ * Creates a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public Element toXML () {
+ Element elem = new Element ("journal");
+ elem.addContent (new Comment("id " + getId()) );
+ elem.addContent (new Element("name").setText (getName ()));
+ elem.addContent (
+ new Element("start").setText (Util.dateToString (getStart()))
+ );
+
+ Date d = getEnd ();
+ if (d != null)
+ elem.addContent (new Element("end").setText
(Util.dateToString (d)));
+
+ if (isClosed())
+ elem.addContent (new Element ("status").setText ("closed"));
+
+ elem.addContent (new Element ("chart").setText (getChart().getCode()));
+
+ Iterator iter = getLayers().iterator();
+ while (iter.hasNext()) {
+ Layer l = (Layer) iter.next();
+ elem.addContent (l.toXML());
+ }
+
+ iter = getPermissions().iterator();
+ while (iter.hasNext()) {
+ GLPermission p = (GLPermission) iter.next();
+ Element e = new Element ("grant").setText (p.getName());
+ e.setAttribute ("user", p.getUser().getNick());
+ elem.addContent (e);
+ }
+ return elem;
+ }
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", getId())
+ .toString();
+ }
+ public boolean equals(Object other) {
+ if ( !(other instanceof Journal) ) return false;
+ Journal castOther = (Journal) other;
+ return new EqualsBuilder()
+ .append(this.getId(), castOther.getId())
+ .isEquals();
+ }
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getId())
+ .toHashCode();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/JournalRule.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/JournalRule.java Thu May 1
11:55:29 2008
@@ -0,0 +1,38 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import org.hibernate.Session;
+import org.hibernate.HibernateException;
+
+public interface JournalRule {
+ /**
+ * @param session current GLSession
+ * @param txn GLTransaction
+ * @param param rule handback parameter
+ * @param account account that triggers this rule (may be an ancestor)
+ * @param entryOffsets entries that matches this rule
+ * @throws GLException if rule denies transaction
+ */
+ public void check (GLSession session, GLTransaction txn,
+ String param, Account account, int[] entryOffsets, short[] layers)
+ throws GLException, HibernateException;
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/Layer.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Layer.hbm.xml Thu May 1 11:55:29 2008
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.Layer" table="layer">
+ <meta attribute="class-description">
+ Journal level layer information.
+ </meta>
+ <composite-id>
+ <key-property name="id" type="short" />
+ <key-many-to-one name="journal" class="org.jpos.gl.Journal" />
+ </composite-id>
+ <property name="name" type="string" length="80" />
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/Layer.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Layer.java Thu May 1 11:55:29 2008
@@ -0,0 +1,87 @@
+package org.jpos.gl;
+
+import java.io.Serializable;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+import java.text.ParseException;
+import org.jdom.Element;
+import org.jdom.Comment;
+
+/**
+ * Journal level layer information.
+*/
+public class Layer implements Serializable {
+ private short id;
+ private String name;
+ private org.jpos.gl.Journal journal;
+
+ public Layer(short id, String name, org.jpos.gl.Journal journal) {
+ this.id = id;
+ this.name = name;
+ this.journal = journal;
+ }
+ public Layer() {
+ super();
+ }
+ /** minimal constructor */
+ public Layer(short id, org.jpos.gl.Journal journal) {
+ super();
+ this.id = id;
+ this.journal = journal;
+ }
+ public Layer (Element elem) throws ParseException {
+ super();
+ fromXML (elem);
+ }
+ public short getId() {
+ return this.id;
+ }
+ public void setId(short id) {
+ this.id = id;
+ }
+ public String getName() {
+ return this.name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public org.jpos.gl.Journal getJournal() {
+ return this.journal;
+ }
+ public void setJournal(org.jpos.gl.Journal journal) {
+ this.journal = journal;
+ }
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", getId())
+ .append("journal", getJournal())
+ .toString();
+ }
+ public boolean equals(Object other) {
+ if ( (this == other ) ) return true;
+ if ( !(other instanceof Layer) ) return false;
+ Layer castOther = (Layer) other;
+ return new EqualsBuilder()
+ .append(this.getId(), castOther.getId())
+ .append(this.getJournal(), castOther.getJournal())
+ .isEquals();
+ }
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getId())
+ .append(getJournal())
+ .toHashCode();
+ }
+ public void fromXML (Element elem) throws ParseException {
+ setId (Short.parseShort(elem.getAttributeValue ("id")));
+ setName (elem.getText().trim());
+ }
+ public Element toXML () {
+ Element e = new Element ("layer").setText(getName());
+ e.setAttribute ("id", Short.toString(getId()));
+ return e;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/RuleEntry.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/RuleEntry.java Thu May 1 11:55:29 2008
@@ -0,0 +1,89 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+class RuleEntry {
+ RuleInfo ri;
+ String param;
+ Account account;
+ int[] offsets;
+
+ public RuleEntry (RuleInfo ri) {
+ super();
+ this.ri = ri;
+ }
+ public RuleEntry (RuleInfo ri, Account acct) {
+ super();
+ this.ri = ri;
+ this.account = acct;
+ }
+ public String getKey() {
+ StringBuffer sb = new StringBuffer (Long.toString (ri.getId()));
+ if (account != null) {
+ sb.append ('.');
+ sb.append (Long.toString (account.getId()));
+ }
+ return sb.toString();
+ }
+ public RuleInfo getRuleInfo() {
+ return ri;
+ }
+ public Account getAccount() {
+ return account;
+ }
+ public void addOffset (int i) {
+ if (offsets == null) {
+ offsets = new int[1];
+ } else {
+ int[] o = new int[offsets.length + 1];
+ System.arraycopy (offsets, 0, o, 0, offsets.length);
+ offsets = o;
+ }
+ offsets[offsets.length-1] = i;
+ }
+ public int[] getOffsets () {
+ return offsets;
+ }
+ public String toString() {
+ StringBuffer sb = new StringBuffer ();
+ sb.append (ri.getClazz());
+ if (ri.getParam() != null) {
+ sb.append ('[');
+ sb.append (ri.getParam());
+ sb.append (']');
+ }
+ if (account != null) {
+ sb.append ('[');
+ sb.append (account.toString());
+ sb.append (']');
+ }
+ if (offsets != null) {
+ sb.append ('[');
+ for (int i=0; i<offsets.length; i++) {
+ if (i > 0)
+ sb.append (',');
+ sb.append (offsets[i]);
+ }
+ sb.append (']');
+ }
+ return sb.toString();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/RuleInfo.hbm.xml
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/RuleInfo.hbm.xml Thu May 1
11:55:29 2008
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping>
+ <class name="org.jpos.gl.RuleInfo" table="ruleinfo">
+ <id name="id" column="id" type="long">
+ <generator class="native" />
+ </id>
+ <property name="description" type="string" />
+ <property name="clazz" type="string" />
+ <property name="layers" type="string" />
+ <property name="param" type="string" />
+ <many-to-one name="journal" not-null="false" />
+ <many-to-one name="account" not-null="false" />
+ </class>
+</hibernate-mapping>
+
Added: trunk/opt/minigl/src/org/jpos/gl/RuleInfo.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/RuleInfo.java Thu May 1 11:55:29 2008
@@ -0,0 +1,200 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.io.Serializable;
+import java.text.ParseException;
+import java.util.StringTokenizer;
+import org.jdom.Element;
+import org.jdom.Comment;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.commons.lang.builder.ToStringBuilder;
+
+/**
+ * Store information about a {@link JournalRule} implementation.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see JournalRule
+ */
+public class RuleInfo implements java.io.Serializable {
+ private long id;
+ private String description;
+ private String clazz;
+ private String param;
+ private Journal journal;
+ private Account account;
+ private String layers;
+
+ public RuleInfo() {
+ super();
+ }
+ /**
+ * Constructs a RuleInfo object out of a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ * @param elem
+ */
+ public RuleInfo (Element elem) throws ParseException {
+ fromXML (elem);
+ }
+ /**
+ * @return internal ID
+ */
+ public long getId() {
+ return this.id;
+ }
+ public void setId(long id) {
+ this.id = id;
+ }
+ /**
+ * @return description
+ */
+ public String getDescription() {
+ return this.description;
+ }
+ /**
+ * @param description rule description
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * @return implementation class name
+ */
+ public String getClazz() {
+ return this.clazz;
+ }
+ /**
+ * @param clazz implemenation class name
+ */
+ public void setClazz(String clazz) {
+ this.clazz = clazz;
+ }
+
+ /**
+ * Handback parameter.
+ * @return handback parameter
+ */
+ public String getParam () {
+ return param;
+ }
+ /**
+ * Handback parameter.
+ * @param param handback parameter
+ */
+ public void setParam (String param) {
+ this.param = param;
+ }
+ public void setLayers (String layers) {
+ this.layers = layers;
+ }
+ public String getLayers () {
+ return layers;
+ }
+ public String toString() {
+ return new ToStringBuilder(this)
+ .append("id", getId())
+ .append("layers", getLayers())
+ .append("param", getParam())
+ .toString();
+ }
+ /**
+ * @return Journal associated with this rule
+ */
+ public Journal getJournal() {
+ return journal;
+ }
+ /**
+ * @param journal associate this rule with a Journal
+ */
+ public void setJournal (Journal journal) {
+ this.journal = journal;
+ }
+ /**
+ * @return Account associated with this rule
+ */
+ public Account getAccount() {
+ return account;
+ }
+ /**
+ * @param account associate this rule with an Account
+ */
+ public void setAccount (Account account) {
+ this.account = account;
+ }
+ public boolean equals(Object other) {
+ if ( !(other instanceof RuleInfo) ) return false;
+ RuleInfo castOther = (RuleInfo) other;
+ return new EqualsBuilder()
+ .append(this.getId(), castOther.getId())
+ .isEquals();
+ }
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(getId())
+ .toHashCode();
+ }
+ public short[] getLayerArray() {
+ if (layers == null)
+ return new short[] { 0 };
+ StringTokenizer st = new StringTokenizer (layers, ", ");
+ short[] sa = new short[st.countTokens()];
+ for (int i=0; st.hasMoreTokens(); i++) {
+ sa[i] = Short.parseShort (st.nextToken());
+ }
+ return sa;
+ }
+
+ /**
+ * Parses a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public void fromXML (Element elem) throws ParseException {
+ setClazz (elem.getAttributeValue ("clazz"));
+ setDescription (elem.getText().trim());
+ setLayers (elem.getChildTextTrim ("layers"));
+ setParam (elem.getChildTextTrim ("param"));
+ }
+ /**
+ * Creates a JDOM Element as defined in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ */
+ public Element toXML () {
+ Element e = new Element ("rule");
+ e.setAttribute ("clazz", getClazz());
+ e.setText (getDescription());
+ if (layers != null) {
+ Element p = new Element ("layers");
+ p.setText (layers);
+ e.addContent (p);
+ }
+ if (param != null) {
+ Element p = new Element ("param");
+ p.setText (param);
+ e.addContent (p);
+ }
+ if (account != null) {
+ e.setAttribute ("account", account.getCode());
+ }
+ return e;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/Util.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/Util.java Thu May 1 11:55:29 2008
@@ -0,0 +1,173 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import org.jdom.Element;
+
+/**
+ * Assorted helper methods
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class Util {
+ static SimpleDateFormat df_yyyyMMdd;
+ static SimpleDateFormat df_yyyyMMddhhmmss;
+ static {
+ df_yyyyMMdd = (SimpleDateFormat) DateFormat.getDateTimeInstance();
+ df_yyyyMMdd.applyPattern("yyyyMMdd");
+ df_yyyyMMddhhmmss = (SimpleDateFormat)
+ DateFormat.getDateTimeInstance();
+ df_yyyyMMddhhmmss.applyPattern("yyyyMMddHHmmss");
+ }
+ static SimpleDateFormat dfDate = (SimpleDateFormat)
+ DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
+ static SimpleDateFormat dfDateTime = (SimpleDateFormat)
+ DateFormat.getDateTimeInstance(
+ DateFormat.SHORT, DateFormat.MEDIUM, Locale.UK);
+
+ /**
+ * @param s date string in YYYYMMdd format
+ * @return a Date object
+ */
+ public static Date parseDate (String s) throws ParseException {
+ if (s == null)
+ return null;
+ return df_yyyyMMdd.parse (s);
+ }
+ /**
+ * @param s date string in YYYYMMddhhmmss format
+ * @return a Date object
+ */
+ public static Date parseDateTime (String s) throws ParseException {
+ if (s == null)
+ return null;
+ return df_yyyyMMddhhmmss.parse (s);
+ }
+ /**
+ * @param d a date object
+ * @return date string in YYYYMMDD format
+ */
+ public static String dateToString (Date d) {
+ if (d == null)
+ return null;
+ return df_yyyyMMdd.format (d);
+ }
+ /**
+ * @param d a date object
+ * @return date string in YYYYMMDDHHMMSS format
+ */
+ public static String dateTimeToString (Date d) {
+ if (d == null)
+ return null;
+ return df_yyyyMMddhhmmss.format (d);
+ }
+ /**
+ * Sets date="YYYYMMDD" attribute to an XML Element
+ * @param elem JDOM Element
+ * @param attributeName attribute name
+ * @param d date object
+ */
+ public static void setDateAttribute
+ (Element elem, String attributeName, Date d)
+ {
+ if (d != null) {
+ elem.setAttribute (attributeName, dateToString (d));
+ }
+ }
+ /**
+ * Sets date="YYYYMMDDHHMMSS" attribute to an XML Element
+ * @param elem JDOM Element
+ * @param attributeName attribute name
+ * @param d date object
+ */
+ public static void setDateTimeAttribute
+ (Element elem, String attributeName, Date d)
+ {
+ if (d != null) {
+ elem.setAttribute (attributeName, dateTimeToString (d));
+ }
+ }
+ /**
+ * Force the 'time' portion of a date up to 23:59:59.999
+ * @param d date
+ * @return converted date
+ */
+ public static Date ceil (Date d) {
+ Calendar cal = Calendar.getInstance();
+ if (d != null)
+ cal.setTime (d);
+ else {
+ cal.set (Calendar.DAY_OF_MONTH, 31);
+ cal.set (Calendar.MONTH, 12);
+ cal.set (Calendar.YEAR, 2099);
+ }
+ cal.set (Calendar.AM_PM, Calendar.PM);
+ cal.set (Calendar.HOUR, 11);
+ cal.set (Calendar.MINUTE, 59);
+ cal.set (Calendar.SECOND, 59);
+ cal.set (Calendar.MILLISECOND, 999);
+ return cal.getTime();
+ }
+ /**
+ * Force the 'time' portion of a date down to 00:00:00.000
+ * @param d date (if null, we default to 01/01/1970)
+ * @return converted date
+ */
+ public static Date floor (Date d) {
+ Calendar cal = Calendar.getInstance();
+ if (d != null)
+ cal.setTime (d);
+ else {
+ cal.set (Calendar.DAY_OF_MONTH, 1);
+ cal.set (Calendar.MONTH, 1);
+ cal.set (Calendar.YEAR, 1970);
+ }
+ cal.set (Calendar.AM_PM, Calendar.AM);
+ cal.set (Calendar.HOUR, 0);
+ cal.set (Calendar.MINUTE, 0);
+ cal.set (Calendar.SECOND, 0);
+ cal.set (Calendar.MILLISECOND, 0);
+ return cal.getTime();
+ }
+ /**
+ * Force date to tomorrow at 00:00:00.000
+ * @param d date
+ * @return converted date
+ */
+ public static Date tomorrow (Date d) {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime (d);
+ cal.add (Calendar.DATE, 1);
+ cal.set (Calendar.AM_PM, Calendar.AM);
+ cal.set (Calendar.HOUR, 0);
+ cal.set (Calendar.MINUTE, 0);
+ cal.set (Calendar.SECOND, 0);
+ cal.set (Calendar.MILLISECOND, 0);
+ return cal.getTime();
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/overview.html
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/overview.html Thu May 1 11:55:29 2008
@@ -0,0 +1,8 @@
+<body>
+ <p><b>MiniGL</b> is a general purpose, multi-book, multi-currency,
+ embedable general ledger engine with support for user-specified
+ multi-level account hierarchies, massive number of transactions,
+ fine-grained rule sub-system that can be used to enforce double-entry
+ as well as sophisticated custom rules.</p>
+</body>
+
Added: trunk/opt/minigl/src/org/jpos/gl/package.html
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/package.html Thu May 1 11:55:29 2008
@@ -0,0 +1,3 @@
+<body>
+ Core package
+</body>
Added: trunk/opt/minigl/src/org/jpos/gl/rule/CanPost.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/CanPost.java Thu May 1
11:55:29 2008
@@ -0,0 +1,119 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+import java.math.BigDecimal;
+import org.hibernate.Session;
+import org.jpos.gl.JournalRule;
+import org.jpos.gl.GLSession;
+import org.jpos.gl.GLException;
+import org.jpos.gl.Account;
+import org.jpos.gl.GLEntry;
+import org.jpos.gl.GLTransaction;
+import org.jpos.gl.GLPermission;
+import org.jpos.gl.Journal;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Verify that user can post to a given journal.
+ *
+ * This rule check the following conditions:
+ * <ul>
+ * <li>GLUser has GLPermission.POST in this journal.</li>
+ * <li>Journal is not closed.</li>
+ * <li>Transaction posting date is not null.</li>
+ * <li>If Journal has a start date, check it against txn.postDate</li>
+ * <li>If Journal has an end date, check it against txn.postDate</li>
+ * <li>Check entries' accounts for expired accounts</li>
+ * </ul>
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see org.jpos.gl.JournalRule
+ * @see org.jpos.gl.RuleInfo
+ */
+public class CanPost implements JournalRule {
+ private static final BigDecimal ZERO = new BigDecimal ("0.00");
+ private static final Log log =
+ LogFactory.getLog (CanPost.class);
+
+ public void check (GLSession session, GLTransaction txn,
+ String param, Account account, int[] entryOffsets, short[] layers)
+ throws GLException
+ {
+ Journal journal = txn.getJournal();
+ Date postDate = txn.getPostDate();
+ Date end = journal.getEnd();
+ Date start = journal.getStart();
+ Date lockDate = journal.getLockDate();
+
+ session.checkPermission (GLPermission.POST, journal);
+
+ if (journal.isClosed()) {
+ throw new GLException (
+ "Journal '" + journal.getName() + "' is closed");
+ }
+ if (postDate == null)
+ throw new GLException ("Invalid transaction. Posting date
is null");
+
+ if (start != null && postDate.compareTo (start) < 0) {
+ throw new GLException (
+ "Journal '" + journal.getName() +
+ "' cannot accept transactions with a posting date less
than " +
+ start.toString()
+ );
+ }
+ if (end != null && postDate.compareTo (end) > 0) {
+ throw new GLException (
+ "Journal '" + journal.getName() +
+ "' cannot accept transactions with a post date greater
than " +
+ end.toString()
+ );
+ }
+ if (lockDate != null && postDate.compareTo (lockDate) <= 0) {
+ throw new GLException (
+ "Journal '" + journal.getName() +
+ "' has a temporary lockDate at " + lockDate.toString()
+ );
+ }
+ checkEntries (txn, postDate);
+ }
+ private void checkEntries (GLTransaction txn, Date postDate)
+ throws GLException
+ {
+ List list = txn.getEntries();
+ Iterator iter = list.iterator();
+ while (iter.hasNext()) {
+ GLEntry entry = (GLEntry) iter.next();
+ Account acct = entry.getAccount();
+ Date end = acct.getExpiration();
+ if (end != null && postDate.compareTo (end) > 0) {
+ throw new GLException (
+ "Account '" + acct.toString() +
+ "' cannot accept transactions with a post date greater
than " +
+ end.toString()
+ );
+ }
+ }
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/CompositeBalance.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/CompositeBalance.java Thu May
1 11:55:29 2008
@@ -0,0 +1,84 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+import java.math.BigDecimal;
+import org.jpos.gl.Account;
+import org.jpos.gl.JournalRule;
+import org.jpos.gl.GLSession;
+import org.jpos.gl.GLException;
+import org.jpos.gl.GLEntry;
+import org.jpos.gl.GLTransaction;
+import org.jpos.gl.Journal;
+import org.hibernate.Session;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+
+abstract class CompositeBalance implements JournalRule {
+ private static final BigDecimal ZERO = new BigDecimal ("0.00");
+ private static final Log log =
+ LogFactory.getLog (CompositeMinBalance.class);
+
+ protected abstract String getRuleName();
+ protected abstract boolean isError
+ (BigDecimal balance, BigDecimal paramBalance);
+
+ public void check (GLSession session, GLTransaction txn,
+ String param, Account account, int[] offsets, short[] layers)
+
+ throws GLException, HibernateException
+ {
+ Journal journal = txn.getJournal();
+ session.lock (journal, account);
+ BigDecimal balance = session.getBalance (journal, account);
+ BigDecimal paramBalance =
+ (param != null) ? new BigDecimal (param) : ZERO;
+ BigDecimal impact = getImpact (txn, offsets);
+
+ if (isError (balance.add(impact), paramBalance)) {
+ StringBuffer sb = new StringBuffer (getRuleName());
+ sb.append (" rule for account ");
+ sb.append (account.getCode());
+ sb.append (" failed. balance=");
+ sb.append (balance);
+ sb.append (", impact=");
+ sb.append (impact);
+ sb.append (", minimum=");
+ sb.append (param);
+ throw new GLException (sb.toString());
+ }
+ }
+ private BigDecimal getImpact (GLTransaction txn, int[] offsets) {
+ BigDecimal impact = ZERO;
+ List entries = txn.getEntries();
+
+ for (int i=0; i<offsets.length; i++) {
+ impact = impact.add (
+ ((GLEntry) entries.get (offsets[i])).getImpact ()
+ );
+ }
+ return impact;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/CompositeMaxBalance.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/CompositeMaxBalance.java Thu
May 1 11:55:29 2008
@@ -0,0 +1,41 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.math.BigDecimal;
+
+/**
+ * Check that composite account's balance (in reporting currency) is
not greater than the ruleinfo param.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see org.jpos.gl.JournalRule
+ * @see org.jpos.gl.RuleInfo
+ */
+public class CompositeMaxBalance extends CompositeBalance {
+ protected String getRuleName() {
+ return "CompositeMaxBalance";
+ }
+ protected boolean isError
+ (BigDecimal balance, BigDecimal maxBalance)
+ {
+ return balance.compareTo (maxBalance) > 0;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/CompositeMinBalance.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/CompositeMinBalance.java Thu
May 1 11:55:29 2008
@@ -0,0 +1,41 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.math.BigDecimal;
+
+/**
+ * Check that composite account's balance (in reporting currency) is
not less than the ruleinfo param.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see org.jpos.gl.JournalRule
+ * @see org.jpos.gl.RuleInfo
+ */
+public class CompositeMinBalance extends CompositeBalance {
+ protected String getRuleName() {
+ return "CompositeMinBalance";
+ }
+ protected boolean isError
+ (BigDecimal balance, BigDecimal minBalance)
+ {
+ return balance.compareTo (minBalance) < 0;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/DoubleEntry.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/DoubleEntry.java Thu May 1
11:55:29 2008
@@ -0,0 +1,90 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+import java.math.BigDecimal;
+import org.hibernate.Session;
+import org.jpos.gl.JournalRule;
+import org.jpos.gl.Account;
+import org.jpos.gl.GLSession;
+import org.jpos.gl.GLException;
+import org.jpos.gl.GLEntry;
+import org.jpos.gl.GLTransaction;
+import org.jpos.gl.GLPermission;
+import org.jpos.gl.Journal;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Verify that debits equals credits.
+ *
+ * This rule check the following conditions:
+ * <ul>
+ * <li>This {@link GLTransaction} has two or more {@link GLEntry}s.</li>
+ * <li>Debits equals Credits (in the reporting currency).</li>
+ * </ul>
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see org.jpos.gl.JournalRule
+ * @see org.jpos.gl.RuleInfo
+ */
+public class DoubleEntry implements JournalRule {
+ private static final BigDecimal ZERO = new BigDecimal ("0.00");
+ private static final Log log =
+ LogFactory.getLog (DoubleEntry.class);
+
+ public void check (GLSession session, GLTransaction txn,
+ String param, Account account, int[] entryOffsets, short[] layers)
+ throws GLException
+ {
+ for (int i=0; i<layers.length; i++)
+ checkEntries (txn, layers[i]);
+ }
+
+ private void checkEntries (GLTransaction txn, short layer)
+ throws GLException
+ {
+ List list = txn.getEntries();
+ // if (list.size() < 2)
+ // throw new GLException ("too few entries (" +
list.size() + ")");
+ BigDecimal debits = ZERO;
+ BigDecimal credits = ZERO;
+ Iterator iter = list.iterator();
+
+ while (iter.hasNext()) {
+ GLEntry entry = (GLEntry) iter.next();
+ if (entry.getLayer() == layer) {
+ if (entry.isDebit ())
+ debits = debits.add (entry.getAmount());
+ else
+ credits = credits.add (entry.getAmount());
+ }
+ }
+ if (!debits.equals (credits)) {
+ throw new GLException (
+ "Transaction does not balance.
debits="+debits.toString() +
+ ", credits=" + credits.toString()
+ );
+ }
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/FinalBalance.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/FinalBalance.java Thu May 1
11:55:29 2008
@@ -0,0 +1,107 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+import java.math.BigDecimal;
+import org.jpos.gl.Account;
+import org.jpos.gl.JournalRule;
+import org.jpos.gl.GLSession;
+import org.jpos.gl.GLException;
+import org.jpos.gl.GLEntry;
+import org.jpos.gl.GLTransaction;
+import org.jpos.gl.Journal;
+import org.hibernate.Session;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.HibernateException;
+
+public abstract class FinalBalance implements JournalRule {
+ private static final BigDecimal ZERO = new BigDecimal ("0.00");
+ private static final Log log =
+ LogFactory.getLog (FinalMinBalance.class);
+
+ protected abstract String getRuleName();
+ protected abstract boolean isError
+ (BigDecimal balance, BigDecimal paramBalance);
+
+ public void check (GLSession session, GLTransaction txn,
+ String param, Account account, int[] offsets, short[] layers)
+ throws GLException, HibernateException
+ {
+ List entries = txn.getEntries();
+ if (entries.size() == 0 || offsets.length ==0)
+ return;
+ for (int i=0; i<offsets.length; i++) {
+ GLEntry entry = ((GLEntry) entries.get (offsets[i]));
+ if (match (entry.getLayer(), layers))
+ checkBalance (session, txn, entry, param, offsets, layers);
+ }
+ }
+ private void checkBalance
+ (GLSession session, GLTransaction txn, GLEntry entry,
+ String param, int[] offsets, short[] layers)
+ throws GLException, HibernateException
+ {
+ Journal journal = txn.getJournal();
+ Account account = entry.getAccount();
+ session.lock (journal, account);
+
+ BigDecimal balance = session.getBalance (journal, account, layers);
+ BigDecimal minBalance =
+ (param != null) ? new BigDecimal (param) : ZERO;
+ BigDecimal impact = getImpact (txn, account, offsets, layers);
+
+ if (isError (balance.add (impact), minBalance)) {
+ StringBuffer sb = new StringBuffer (getRuleName());
+ sb.append (" rule for account ");
+ sb.append (account.getCode());
+ sb.append (" failed. balance=");
+ sb.append (balance);
+ sb.append (", impact=");
+ sb.append (impact);
+ sb.append (", minimum=");
+ sb.append (param);
+ throw new GLException (sb.toString());
+ }
+ }
+ private BigDecimal getImpact
+ (GLTransaction txn, Account account, int[] offsets, short[] layers)
+ {
+ BigDecimal impact = ZERO;
+ List entries = txn.getEntries();
+
+ for (int i=0; i<offsets.length; i++) {
+ GLEntry entry = ((GLEntry) entries.get (offsets[i]));
+ if (account.equals (entry.getAccount()) && match
(entry.getLayer(), layers))
+ impact = impact.add (entry.getImpact());
+ }
+ return impact;
+ }
+ private boolean match (short layer, short[] layers) {
+ for (int i=0; i<layers.length; i++)
+ if (layers[i] == layer)
+ return true;
+ return false;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/FinalMaxBalance.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/FinalMaxBalance.java Thu May
1 11:55:29 2008
@@ -0,0 +1,41 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.math.BigDecimal;
+
+/**
+ * Check that final account's balance (in reporting currency) is not
greater than the ruleinfo param.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see org.jpos.gl.JournalRule
+ * @see org.jpos.gl.RuleInfo
+ */
+public class FinalMaxBalance extends FinalBalance {
+ protected String getRuleName() {
+ return "FinalMaxBalance";
+ }
+ protected boolean isError
+ (BigDecimal balance, BigDecimal maxBalance)
+ {
+ return balance.compareTo (maxBalance) > 0;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/FinalMinBalance.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/FinalMinBalance.java Thu May
1 11:55:29 2008
@@ -0,0 +1,41 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.rule;
+
+import java.math.BigDecimal;
+
+/**
+ * Check that final account's balance (in reporting currency) is not
less than the ruleinfo param.
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ * @see org.jpos.gl.JournalRule
+ * @see org.jpos.gl.RuleInfo
+ */
+public class FinalMinBalance extends FinalBalance {
+ protected String getRuleName() {
+ return "FinalMinBalance";
+ }
+ protected boolean isError
+ (BigDecimal balance, BigDecimal minBalance)
+ {
+ return balance.compareTo (minBalance) < 0;
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/rule/package.html
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/rule/package.html Thu May 1
11:55:29 2008
@@ -0,0 +1,3 @@
+<body>
+ Rule implementations
+</body>
Added: trunk/opt/minigl/src/org/jpos/gl/tools/Export.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/tools/Export.java Thu May 1
11:55:29 2008
@@ -0,0 +1,200 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.DocType;
+import org.jdom.Comment;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
+
+import java.sql.SQLException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Hibernate;
+import org.hibernate.Transaction;
+import org.hibernate.SessionFactory;
+import org.hibernate.HibernateException;
+
+import org.jpos.gl.GLUser;
+import org.jpos.gl.Journal;
+import org.jpos.gl.RuleInfo;
+import org.jpos.gl.GLPermission;
+import org.jpos.gl.CompositeAccount;
+import org.jpos.gl.FinalAccount;
+import org.jpos.gl.Account;
+import org.jpos.gl.GLEntry;
+import org.jpos.gl.GLException;
+import org.jpos.gl.GLSession;
+import org.jpos.gl.GLTransaction;
+import org.jpos.gl.Currency;
+
+/**
+ * Export to an XML document as described in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class Export {
+ GLSession gls;
+
+ public Export () throws HibernateException, GLException {
+ super();
+ gls = new GLSession (System.getProperty ("user.name"));
+ }
+
+ public Document getDocument ()
+ throws SQLException, HibernateException
+ {
+ Document doc = new Document ();
+ doc.setDocType (new DocType ("minigl", "http://jpos.org/minigl.dtd"));
+ Element root = new Element ("minigl");
+ root.addContent (
+ new Comment (
+ "jPOS MiniGL export $"
+ )
+ );
+ root.addContent (new Element ("create-schema"));
+ addUsers (root);
+ addCurrencies (root);
+ addCharts (root);
+ addJournals (root);
+ addTransactions (root);
+ doc.setRootElement (root);
+ return doc;
+ }
+
+ public void export (OutputStream os)
+ throws IOException, SQLException, HibernateException
+ {
+ XMLOutputter out = new XMLOutputter (Format.getPrettyFormat ());
+ out.output (getDocument(), os);
+ }
+
+ public void export (PrintWriter writer)
+ throws IOException, SQLException, HibernateException
+ {
+ XMLOutputter out = new XMLOutputter (Format.getPrettyFormat ());
+ out.output (getDocument(), writer);
+ }
+
+ private void addCharts (Element parentElement)
+ throws SQLException, HibernateException
+ {
+ Session sess = gls.open();
+ Query q = sess.createQuery (
+ "from acct in class org.jpos.gl.CompositeAccount where
parent is null order by code");
+ Iterator iter = q.list().iterator();
+ while (iter.hasNext()) {
+ Account acct = (Account) iter.next ();
+ parentElement.addContent (acct.toXML ());
+ }
+ gls.close ();
+ }
+
+ private void addTransactions (Element parentElement)
+ throws SQLException, HibernateException
+ {
+ Session sess = gls.open();
+ Iterator iter = sess.createQuery (
+ "from transacc in class org.jpos.gl.GLTransaction order by id"
+ ).list().iterator();
+ while (iter.hasNext()) {
+ GLTransaction glt = (GLTransaction) iter.next ();
+ parentElement.addContent (glt.toXML (true));
+ }
+ gls.close ();
+ }
+
+ private void addUsers (Element parentElement)
+ throws SQLException, HibernateException
+ {
+ Session sess = gls.open();
+ Iterator iter = sess.createQuery (
+ "from gluser in class org.jpos.gl.GLUser order by id"
+ ).list().iterator();
+ while (iter.hasNext()) {
+ GLUser user = (GLUser) iter.next ();
+ parentElement.addContent (user.toXML ());
+ }
+ gls.close ();
+ }
+
+ private void addCurrencies (Element parentElement)
+ throws SQLException, HibernateException
+ {
+ Session sess = gls.open();
+ Iterator iter = sess.createQuery (
+ "from currency in class org.jpos.gl.Currency order by id"
+ ).list().iterator();
+ while (iter.hasNext()) {
+ Currency currency = (Currency) iter.next ();
+ parentElement.addContent (currency.toXML ());
+ }
+ gls.close ();
+ }
+ private void addJournalRules
+ (Session sess, Journal journal, Element parentElement)
+ throws SQLException, HibernateException
+ {
+ Query q = sess.createQuery ("from ruleinfo in class
org.jpos.gl.RuleInfo where journal=:journal order by id");
+ q.setParameter ("journal", journal);
+ Iterator iter = q.list().iterator();
+ while (iter.hasNext()) {
+ RuleInfo rule = (RuleInfo) iter.next ();
+ parentElement.addContent (rule.toXML ());
+ }
+ }
+ private void addJournals (Element root)
+ throws SQLException, HibernateException
+ {
+ Session sess = gls.open();
+ Iterator iter = sess.createQuery (
+ "from journal in class org.jpos.gl.Journal order by id"
+ ).list().iterator();
+
+ while (iter.hasNext()) {
+ Journal journal = (Journal) iter.next ();
+ Element journalElement = journal.toXML ();
+ addJournalRules (sess, journal, journalElement);
+ root.addContent (journalElement);
+ }
+ gls.close ();
+ }
+
+ public static void main (String[] args) {
+ try {
+ new Export ().export (System.out);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
Added: trunk/opt/minigl/src/org/jpos/gl/tools/Import.java
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/tools/Import.java Thu May 1
11:55:29 2008
@@ -0,0 +1,401 @@
+/*
+ * MiniGL
+ * Copyright (C) 2005 Alejandro Revilla
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
+ */
+
+package org.jpos.gl.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.io.InputStream;
+import java.util.Date;
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.HashSet;
+import java.text.ParseException;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.XMLOutputter;
+import org.xml.sax.InputSource;
+import org.xml.sax.EntityResolver;
+
+import java.sql.SQLException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.Hibernate;
+import org.hibernate.Transaction;
+import org.hibernate.SessionFactory;
+import org.hibernate.HibernateException;
+import org.hibernate.type.Type;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.jpos.gl.GLUser;
+import org.jpos.gl.Journal;
+import org.jpos.gl.RuleInfo;
+import org.jpos.gl.GLPermission;
+import org.jpos.gl.CompositeAccount;
+import org.jpos.gl.FinalAccount;
+import org.jpos.gl.Account;
+import org.jpos.gl.GLEntry;
+import org.jpos.gl.GLDebit;
+import org.jpos.gl.GLCredit;
+import org.jpos.gl.GLSession;
+import org.jpos.gl.GLException;
+import org.jpos.gl.GLTransaction;
+import org.jpos.gl.Currency;
+import org.jpos.gl.Layer;
+
+/**
+ * Import an XML document as described in
+ * <a href="http://jpos.org/minigl.dtd">minigl.dtd</a>
+ *
+ * @author <a href="mailto:a...@jpos.org">Alejandro Revilla</a>
+ */
+public class Import implements EntityResolver {
+ SessionFactory sf;
+ Configuration cfg;
+ Log log = LogFactory.getLog (Import.class);
+ private static final String URL = "http://jpos.org/";
+ public Import () throws HibernateException, GLException {
+ super();
+ cfg = new Configuration();
+ cfg.configure ();
+ sf = cfg.buildSessionFactory();
+ }
+
+ public static void usage () {
+ System.out.println ("Usage: org.jpos.gl.Import filename");
+ System.exit (0);
+ }
+
+ private void createSchema () throws HibernateException {
+ SchemaExport export = new SchemaExport (cfg);
+ // export.setOutputFile ("/tmp/schema.sql");
+ // export.setDelimiter (";");
+ export.create (true, true); // don't create tables
+ }
+
+ private void createCharts (Session sess, Iterator iter)
+ throws SQLException, HibernateException, ParseException
+ {
+ Transaction txn = sess.beginTransaction();
+ while (iter.hasNext()) {
+ Element elem = (Element) iter.next ();
+ CompositeAccount acct = new CompositeAccount (elem);
+ sess.save (acct);
+ acct.setRoot (acct);
+ processChartChildren (
+ sess, acct, elem.getChildren().iterator()
+ );
+ sess.flush ();
+ }
+ txn.commit();
+ sess.flush ();
+ }
+ private void createCurrencies (Session sess, Iterator iter)
+ throws SQLException, HibernateException, ParseException
+ {
+ Transaction txn = sess.beginTransaction();
+ while (iter.hasNext()) {
+ Element elem = (Element) iter.next ();
+ Currency currency = new Currency (elem);
+ sess.save (currency);
+ }
+ txn.commit();
+ sess.flush ();
+ }
+ private void createUsers (Session sess, Iterator iter)
+ throws SQLException, HibernateException, ParseException
+ {
+ Transaction txn = sess.beginTransaction();
+ while (iter.hasNext()) {
+ Element elem = (Element) iter.next ();
+ GLUser user = new GLUser (elem);
+
+ Iterator permIter = elem.getChildren ("grant").iterator();
+ while (permIter.hasNext()) {
+ Element perm = (Element) permIter.next();
+ GLPermission p = new GLPermission (perm.getTextTrim());
+ sess.save (p);
+ user.grant (p);
+ }
+ sess.save (user);
+ }
+ txn.commit();
+ sess.flush ();
+ }
+ private void createJournals (Session sess, Iterator iter)
+ throws SQLException, HibernateException, ParseException
+ {
+ Transaction txn = sess.beginTransaction();
+ while (iter.hasNext()) {
+ Element elem = (Element) iter.next ();
+ Journal journal = new Journal (elem);
+ journal.setChart (
+ getChart (sess, elem.getChildTextTrim ("chart"))
+ );
+ journal.setPermissions (
+ createPermissions (
+ sess, elem.getChildren ("grant").iterator()
+ )
+ );
+ sess.save (journal);
+ createJournalLayers (
+ sess, journal, elem.getChildren ("layer").iterator()
+ );
+ createJournalRules (
+ sess, journal, elem.getChildren ("rule").iterator()
+ );
+ }
+ txn.commit();
+ sess.flush ();
+ }
+ private void processChartChildren
+ (Session sess, Account parent, Iterator iter)
+ throws SQLException, HibernateException, ParseException
+ {
+ while (iter.hasNext ()) {
+ Element e = (Element) iter.next ();
+ String name = e.getName();
+ if ("composite-account".equals (name))
+ createComposite (sess, parent, e);
+ else if ("account".equals (name))
+ createFinal (sess, parent, e);
+ }
+ }
+
+ private void createComposite (Session sess, Account parent,
Element elem)
+ throws SQLException, HibernateException, ParseException
+ {
+ CompositeAccount acct = new CompositeAccount (elem, parent);
+ acct.setRoot (parent.getRoot ());
+ sess.save (acct);
+ acct.setParent (parent);
+ parent.getChildren().add (acct);
+ sess.flush ();
+ processChartChildren (sess, acct, elem.getChildren().iterator());
+ }
+
+ private void createFinal (Session sess, Account parent, Element elem)
+ throws SQLException, HibernateException, ParseException
+ {
+ FinalAccount acct = new FinalAccount (elem, parent);
+ acct.setRoot (parent.getRoot ());
+ sess.save (acct);
+ acct.setParent (parent);
+ parent.getChildren().add (acct);
+ }
+
+ private void createTransactions (Session sess, Iterator iter)
+ throws SQLException, HibernateException, ParseException
+ {
+ while (iter.hasNext()) {
+ Transaction txn = sess.beginTransaction();
+ Element elem = (Element) iter.next ();
+ GLTransaction glt = new GLTransaction (elem);
+ Journal journal = getJournal (
+ sess, elem.getAttributeValue ("journal")
+ );
+ glt.setJournal (journal);
+ sess.save (glt);
+ createEntries (
+ sess, glt,
+ elem.getChildren("entry").iterator()
+ );
+ txn.commit ();
+ }
+ sess.flush ();
+ }
+ private void createEntries (
+ Session sess, GLTransaction glt, Iterator iter)
+ throws SQLException, HibernateException, ParseException
+ {
+ Account chart = glt.getJournal().getChart ();
+ while (iter.hasNext()) {
+ Element elem = (Element) iter.next ();
+ GLEntry entry =
+ "credit".equals (elem.getAttributeValue ("type")) ?
+ ((GLEntry) new GLCredit ()) :
+ ((GLEntry) new GLDebit ());
+ entry.fromXML (elem);
+ entry.setAccount (getFinalAccount (sess, chart, elem));
+ entry.setTransaction (glt);
+ sess.save (entry);
+ glt.getEntries().add (entry);
+ }
+ }
+ private Account getAccount (Session sess, Account chart, Element elem)
+ throws SQLException, HibernateException
+ {
+ Query q = sess.createQuery (
+ "from acct in class org.jpos.gl.Account where code = :code
and acct.root = :chart");
+
+ q.setParameter ("code", elem.getAttributeValue ("account"));
+ q.setLong ("chart", chart.getId());
+ List l = q.list();
+ return l.size() == 1 ? ((Account) l.get (0)) : null;
+ }
+ private FinalAccount getFinalAccount
+ (Session sess, Account chart, Element elem)
+ throws SQLException, HibernateException
+ {
+ Query q = sess.createQuery (
+ "from acct in class org.jpos.gl.FinalAccount where code
= :code and acct.root = :root"
+ );
+ q.setParameter ("code", elem.getAttributeValue ("account"));
+ q.setLong ("root", chart.getId());
+ List l = q.list();
+ return l.size() == 1 ? ((FinalAccount) l.get (0)) : null;
+ }
+ private CompositeAccount getChart (Session sess, String chartCode)
+ throws SQLException, HibernateException
+ {
+ Query q = sess.createQuery (
+ "from acct in class org.jpos.gl.CompositeAccount where
code = :code and parent is null"
+ );
+ q.setParameter ("code", chartCode);
+ List l = q.list();
+ return (CompositeAccount) ((l.size() > 0) ? l.get (0) : null);
+ }
+ private void createJournalRules
+ (Session session, Journal journal, Iterator iter)
+ throws HibernateException, ParseException, SQLException
+ {
+ while (iter.hasNext()) {
+ Element e = (Element) iter.next();
+ RuleInfo ri = new RuleInfo (e);
+ ri.setJournal (journal);
+ ri.setAccount (getAccount (session, journal.getChart(), e));
+ session.save (ri);
+ }
+ }
+ private void createJournalLayers
+ (Session session, Journal journal, Iterator iter)
+ throws HibernateException, ParseException, SQLException
+ {
+ while (iter.hasNext()) {
+ Element e = (Element) iter.next();
+ Layer layer = new Layer (e);
+ layer.setJournal (journal);
+ session.save (layer);
+ }
+ }
+ private GLUser getUser (Session session, String nick)
+ throws HibernateException
+ {
+ Query q = session.createQuery ("from GLUser u where u.nick=:nick");
+ q.setParameter ("nick", nick);
+ List l = q.list();
+ if (l.size() == 0) {
+ throw new IllegalArgumentException (
+ "Invalid nick '" + nick + "'"
+ );
+ }
+ return (GLUser) l.get(0);
+ }
+ private Set createPermissions (Session session, Iterator iter)
+ throws HibernateException
+ {
+ Set permissions = new HashSet ();
+ while (iter.hasNext()) {
+ Element e = (Element) iter.next();
+ GLUser user = getUser (session, e.getAttributeValue ("user"));
+ GLPermission p = new GLPermission (e.getTextTrim());
+ p.setUser (user);
+ session.save (p);
+ permissions.add (p);
+ }
+ return permissions;
+ }
+ private Journal getJournal (Session sess, String name)
+ throws SQLException, HibernateException
+ {
+ Query q = sess.createQuery (
+ "from journal in class org.jpos.gl.Journal where name = :name"
+ );
+ q.setParameter ("name", name);
+ List l = q.list();
+ return (Journal) ((l.size() > 0) ? l.get (0) : null);
+ }
+ public InputSource resolveEntity (String publicId, String
systemId) {
+ if (systemId != null && systemId.startsWith (URL)) {
+ log.debug ("trying to locate " + systemId + " in classpath");
+ ClassLoader classLoader = this.getClass().getClassLoader();
+ InputStream dtd = classLoader.getResourceAsStream (
+ systemId.substring (URL.length())
+ );
+ if (dtd == null) {
+ log.debug (systemId + "not found in classpath");
+ return null;
+ }
+ else {
+ log.debug ("found " + systemId + " in classpath");
+ return new InputSource (dtd);
+ }
+ }
+ else
+ return null;
+ }
+ public void parse (String file)
+ throws JDOMException, SQLException, HibernateException,
+ ParseException, IOException, GLException
+ {
+ SAXBuilder builder = new SAXBuilder (true);
+ builder.setEntityResolver (this);
+
+ Document doc = builder.build (file);
+ Element root = doc.getRootElement ();
+
+ if (!"minigl".equals (root.getName ())) {
+ throw new IllegalStateException (
+ "Invalid root element "+root.getName ()
+ );
+ }
+
+ if (root.getChild ("create-schema") != null)
+ createSchema ();
+
+ Session sess = sf.openSession();
+ createUsers (sess, root.getChildren ("user").iterator());
+ createCurrencies (sess, root.getChildren ("currency").iterator());
+ createCharts (sess, root.getChildren ("chart-of-accounts").iterator());
+ createJournals (sess, root.getChildren ("journal").iterator());
+ createTransactions (sess, root.getChildren ("transaction").iterator());
+ sess.close ();
+ }
+
+ public static void main (String[] args) {
+ if (args.length == 0)
+ usage ();
+
+ try {
+ new Import().parse (args[0]);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
Added: trunk/opt/minigl/src/org/jpos/gl/tools/package.html
==============================================================================
--- (empty file)
+++ trunk/opt/minigl/src/org/jpos/gl/tools/package.html Thu May 1
11:55:29 2008
@@ -0,0 +1,3 @@
+<body>
+ Tools
+</body>