gt:             joinColumns = @JoinColumn(name = "transaction_fee_id"),
context: /*
      This file is part of Cyclos (www.cyclos.org).
      A project of the Social Trade Organisation (www.socialtrade.org).
  
      Cyclos 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.
  
      Cyclos 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 Cyclos; if not, write to the Free Software
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  
   */
  package nl.strohalm.cyclos.entities.accounts.fees.transaction;
  
  import nl.strohalm.cyclos.entities.Entity;
  import nl.strohalm.cyclos.entities.Relationship;
  import nl.strohalm.cyclos.entities.accounts.transactions.Transfer;
  import nl.strohalm.cyclos.entities.accounts.transactions.TransferType;
  import nl.strohalm.cyclos.entities.groups.MemberGroup;
  import nl.strohalm.cyclos.entities.members.Member;
  import nl.strohalm.cyclos.entities.utils.Amount;
  import nl.strohalm.cyclos.utils.StringValuedEnum;
  
  import javax.persistence.Cacheable;
  import javax.persistence.Column;
  import javax.persistence.Convert;
  import javax.persistence.DiscriminatorColumn;
  import javax.persistence.Inheritance;
  import javax.persistence.JoinColumn;
  import javax.persistence.JoinTable;
  import javax.persistence.ManyToMany;
  import javax.persistence.ManyToOne;
  import javax.persistence.OneToMany;
  import javax.persistence.Table;
  import java.math.BigDecimal;
  import java.util.Collection;
  
  /**
   * A fee is applied on transfers
   * 
   * @author luis
   */
  @Cacheable
  @Inheritance
  @DiscriminatorColumn(name = "subclass", length = 1)
  @Table(name = "transaction_fees")
  @javax.persistence.Entity
  public abstract class TransactionFee extends Entity {
  
      public static enum ChargeType implements StringValuedEnum {
          FIXED("F"), PERCENTAGE("P"), A_RATE("A"), D_RATE("D"), MIXED_A_D_RATES("M");
  
          public static ChargeType from(final Amount.Type type) {
              if (type == null) {
                  return null;
              }
              switch (type) {
                  case FIXED:
                      return FIXED;
                  case PERCENTAGE:
                      return PERCENTAGE;
              }
              return null;
          }
  
          private final String value;
  
          private ChargeType(final String value) {
              this.value = value;
          }
  
          @Override
          public String getValue() {
              return value;
          }
  
          public Amount.Type toAmountType() {
              switch (this) {
                  case FIXED:
                      return Amount.Type.FIXED;
                  case PERCENTAGE:
                  case A_RATE:
                  case D_RATE:
                  case MIXED_A_D_RATES:
                      return Amount.Type.PERCENTAGE;
                  default:
                      return null;
              }
          }
      }
  
      public static enum Nature implements StringValuedEnum {
          SIMPLE("S"), BROKER("B");
  
          private final String value;
  
          private Nature(final String value) {
              this.value = value;
          }
  
          public Class<? extends TransactionFee> getFeeClass() {
              if (this == SIMPLE) {
                  return SimpleTransactionFee.class;
              } else {
                  return BrokerCommission.class;
              }
          }
  
          @Override
          public String getValue() {
              return value;
          }
      }
  
      public static enum Relationships implements Relationship {
          GENERATED_TRANSFER_TYPE("generatedTransferType"), ORIGINAL_TRANSFER_TYPE("originalTransferType"), TRANSFERS("transfers"), FROM_GROUPS("fromGroups"), TO_GROUPS("toGroups"), FROM_FIXED_MEMBER("fromFixedMember");
          private final String name;
  
          private Relationships(final String name) {
              this.name = name;
          }
  
          @Override
          public String getName() {
              return name;
          }
      }
  
      public static enum Subject implements StringValuedEnum {
          SYSTEM("sys"), SOURCE("src"), SOURCE_BROKER("sbr"), DESTINATION("dst"), DESTINATION_BROKER("dbr"), FIXED_MEMBER("mem");
          private final String value;
  
          private Subject(final String value) {
              this.value = value;
          }
  
          @Override
          public String getValue() {
              return value;
          }
      }
  
      private static final long       serialVersionUID = -3840663900697716307L;
  
      @Column(name = "name", nullable = false, length = 100)
      private String                  name;
  
      @Column(name = "description", columnDefinition = "text")
      private String                  description;
  
      @Convert(converter = SubjectAttributeConverter.class)
      @Column(name = "payer", nullable = false, length = 3)
  	private Subject                 payer;
  
      @Column(name = "enabled", nullable = false)
      private boolean                 enabled;
  
      @ManyToOne
      @JoinColumn(name = "original_type_id", nullable = false)
  	private TransferType            originalTransferType;
  
      @ManyToOne
      @JoinColumn(name = "generated_type_id", nullable = false)
  	private TransferType            generatedTransferType;
  
      @Convert(converter = ChargeTypeAttributeConverter.class)
      @Column(name = "amount_type", nullable = false, length = 1)
  	private ChargeType              chargeType;
  
      @Column(name = "amount", precision = 15, scale = 6)
      private BigDecimal              value;
  
      @Column(name = "max_fixed_value", precision = 15, scale = 6)
      private BigDecimal              maxFixedValue;
  
      @Column(name = "max_percentage_value", precision = 15, scale = 6)
      private BigDecimal              maxPercentageValue;
  
      @Column(name = "initial_amount", precision = 15, scale = 6)
      private BigDecimal              initialAmount;
  
      @Column(name = "final_amount", precision = 15, scale = 6)
      private BigDecimal              finalAmount;
  
      @Column(name = "deduct_amount", nullable = false)
      private boolean                 deductAmount;
  
      @OneToMany(mappedBy = "transactionFee")
  	private Collection<Transfer>    transfers;
  
      @Column(name = "from_all_groups", nullable = false)
      private boolean                 fromAllGroups    = true;
  
      @ManyToMany(targetEntity = MemberGroup.class)
      @JoinTable(name = "groups_from_transaction_fees",
              joinColumns = @JoinColumn(name = "transaction_fee_id"),
              inverseJoinColumns = @JoinColumn(name = "group_id"))
  	private Collection<MemberGroup> fromGroups;
  
      @Column(name = "to_all_groups", nullable = false)
      private boolean                 toAllGroups      = true;
  
      @ManyToMany
      @JoinTable(name = "groups_to_transaction_fees",
  