no.abmu.questionnaire.domain.metadata.FieldImpl.java Source code

Java tutorial

Introduction

Here is the source code for no.abmu.questionnaire.domain.metadata.FieldImpl.java

Source

/*$Id: FieldImpl.java 15337 2010-03-09 09:24:54Z jens $*/
/*
 ****************************************************************************
 *                                                                          *
 *                   (c) Copyright 2009 ABM-utvikling                       *
 *                                                                          *
 * 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. http://www.gnu.org/licenses/gpl.html    *
 *                                                                          *
 ****************************************************************************
 */

package no.abmu.questionnaire.domain.metadata;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import no.abmu.questionnaire.domain.constants.DbSchemaNameConst;
import no.abmu.questionnaire.domain.data.DomainObject;
import no.abmu.questionnaire.domain.data.FieldData;
import no.abmu.questionnaire.domain.types.SchoolHas;
import no.abmu.questionnaire.domain.validators.FieldValidator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Index;
import org.hibernate.annotations.Type;

/**
 * Implements interface Field. 
 *
 * @author Aase Mestad
 * @author $Author: jens $
 * @version $Rev: 15337 $
 * @date $Date: 2010-03-09 10:24:54 +0100 (Tue, 09 Mar 2010) $
 * @copyright ABM-Utvikling
 */
@SuppressWarnings("serial")
@Entity
@Table(name = "BASEFIELD", schema = DbSchemaNameConst.QUESTIONNAIRE_DB_SCHEMA_NAME)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "discriminatorValue", length = 35, discriminatorType = DiscriminatorType.STRING)
//@ForceDiscriminator
//@Inheritance(strategy=InheritanceType.JOINED)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public abstract class FieldImpl extends DomainObject implements Field {

    private static final Log logger = (Log) LogFactory.getLog(FieldImpl.class);

    private String code;
    private String fieldName;
    private String fieldDescription;
    private Date periodFrom;
    private Date periodTo;

    private Account account;
    private Set validators = new HashSet();
    private FieldPeriod period;
    private FieldType type;
    private boolean finishField = false;

    public FieldImpl() {
    }

    public FieldImpl(String code, FieldPeriod period, FieldType type) {
        this.code = code;
        this.period = period;
        this.type = type;
    }

    public String getCode() {
        return code;
    }

    public String getFieldName() {
        return fieldName;
    }

    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public String getFieldDescription() {
        return fieldDescription;
    }

    public void setFieldDescription(String fieldDescription) {
        this.fieldDescription = fieldDescription;
    }

    @Type(type = "no.abmu.util.hibernate3.DateType")
    public Date getPeriodFrom() {
        return periodFrom;
    }

    public void setPeriodFrom(Date periodFrom) {
        this.periodFrom = periodFrom;
    }

    @Type(type = "no.abmu.util.hibernate3.DateType")
    public Date getPeriodTo() {
        return periodTo;
    }

    public void setPeriodTo(Date periodTo) {
        this.periodTo = periodTo;
    }

    public boolean isFinishField() {
        return finishField;
    }

    public void setFinishField(Boolean finishField) {
        this.finishField = finishField;
    }

    /**
     * This helper method initializes the extra properties like stringLength in StringField.
     *
     * @param arguments the values for properties in fields
     */
    protected abstract void initialize(String[] arguments);

    public void setCode(String code) {
        this.code = code;
    }

    @ManyToOne(targetEntity = Account.class)
    @Index(name = "field_account_fk_idx")
    @JoinColumn(name = "FK_ACCOUNT_ID", insertable = false, updatable = false)
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }

    @ManyToOne(cascade = CascadeType.ALL)
    public FieldType getType() {
        return type;
    }

    public void setType(FieldType type) {
        this.type = type;
    }

    @ManyToOne(cascade = CascadeType.ALL)
    public FieldPeriod getPeriod() {
        return period;
    }

    public void setPeriod(FieldPeriod period) {
        this.period = period;
    }

    /*
        @OneToMany(targetEntity = FieldValidator.class, cascade = CascadeType.ALL, fetch=FetchType.EAGER)
        @JoinTable(
        name = "FIELD_FIELDVALIDATOR", 
        schema = DbSchemaNameConst.QUESTIONNAIRE_DB_SCHEMA_NAME,
        joinColumns = @JoinColumn(name = "FK_FIELD_ID"),
        inverseJoinColumns = @JoinColumn(name = "FK_FIELDVALIDATOR_ID"))
    */
    @OneToMany(cascade = CascadeType.ALL, targetEntity = FieldValidator.class, fetch = FetchType.EAGER)
    @JoinColumn(name = "FK_FIELD_ID")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    //    @Fetch(FetchMode.SUBSELECT)
    public Set getValidators() {
        return validators;
    }

    public void setValidators(Set<FieldValidator> validators) {
        this.validators = validators;
    }

    public void addValidator(FieldValidator validator) {
        validators.add(validator);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        FieldImpl field = (FieldImpl) o;

        if (account != null ? !account.equals(field.account) : field.account != null) {
            return false;
        }
        if (code != null ? !code.equals(field.code) : field.code != null) {
            return false;
        }
        if (period != null ? !period.equals(field.period) : field.period != null) {
            return false;
        }
        //        if (schem != null ? !schema.equals(field.schema) : field.schema != null) {
        //            return false;
        //        }
        if (type != null ? !type.equals(field.type) : field.type != null) {
            return false;
        }

        return true;
    }

    @Override
    public int hashCode() {
        int result = code != null ? code.hashCode() : 0;
        result = 31 * result + (account != null ? account.hashCode() : 0);
        result = 31 * result + (period != null ? period.hashCode() : 0);
        result = 31 * result + (type != null ? type.hashCode() : 0);
        //        result = 31 * result + (schema != null ? schema.hashCode() : 0);
        return result;
    }

    public abstract FieldData createFieldData();

    /**
     * FieldFactory.
     * 
     */
    public static final class FieldFactory {

        private static HashMap<String, Class> fieldClassMap;

        private static String patternStr = "(.+)\\((.+)\\)";

        private static Pattern pattern = Pattern.compile(patternStr);

        // Suppress default constructor for noninstantiability
        private FieldFactory() {
            // This constructor will never be invoked.
            // See Item 3 on page 12 in
            // Joshua Bloch: Effective Java: Programming Language Guide, 2001
            // ISBN 0-201-31005-8
        }

        private static HashMap<String, Class> initializeFieldClassMap() {
            HashMap<String, Class> map = new HashMap<String, Class>();
            map.put("string", StringField.class);
            map.put("boolean", BooleanField.class);
            map.put("yesnopartly", YesNoPartlyField.class);
            map.put("decimal", BigDecimalField.class);
            map.put("long", LongField.class);
            map.put("skolenssamlinger", SkolensSamlingerField.class);
            map.put("hovedomraade", MuseumHovedOmraadeField.class);
            map.put("organizationform", MuseumOrganizationFormField.class);
            map.put("date", DateField.class);
            map.put("fireorfirestart", FireOrFireStartField.class);
            map.put("theftortheftattempt", TheftOrTheftAttemptField.class);
            map.put("discoveryoffire", DiscoveryOfFireField.class);
            map.put("extinguishmethod", ExtinguishMethodField.class);
            map.put("reasonoffire", ReasonOfFireField.class);
            map.put("whoextinguished", WhoExtinguishedField.class);
            map.put("schoolhas", SchoolHasField.class);

            return map;
        }

        /**
         * Parses the input string to find arguments to the class in 
         * parentheses at the end of the string. String and Decimal 
         * accepts arguments.
         *
         * @param fieldClassNameAndArgs String with code to lookup 
         * the proper class and arguments to initialize the class.
         * @return an array of Strings with the parsed arguments.
         */
        private static String[] getArguments(String fieldClassNameAndArgs) {
            Matcher matcher = pattern.matcher(fieldClassNameAndArgs);
            if (!matcher.matches()) {
                return null;
            }
            String args = matcher.group(2);
            return args.split(",");
        }

        /**
         * Looks up the proper class from fieldClassMap. Some classes needs 
         * to be initialized, these parameters are in parentheses at the end 
         * of the string. String and Decimal expect one argument each, the 
         * other classes expects no arguments. If a class expects several 
         * arguments, these are separated by comma.
         *
         * @param fieldClassNameAndArgs code to look up the proper class and 
         * argument to initialize the class.
         * @param name   name of field
         * @param code   string with two or three digits that identifies the field uniquely within a schema.
         * @return instantiated field
         */
        public static FieldImpl createField(String fieldClassNameAndArgs, String name, String code, Schema schema) {
            if (fieldClassMap == null) {
                fieldClassMap = initializeFieldClassMap();
            }
            String[] arguments = getArguments(fieldClassNameAndArgs);
            String className = null;
            if (arguments == null) {
                className = fieldClassNameAndArgs;
            } else {
                className = fieldClassNameAndArgs.substring(0, fieldClassNameAndArgs.indexOf("("));
            }
            Class clazz = fieldClassMap.get(className.toLowerCase());
            if (clazz == null) {
                String message = "Can not find class name for field with argument=[" + fieldClassNameAndArgs + "].";
                logger.error(message);
                throw new RuntimeException(message);
            }
            try {
                FieldImpl field = (FieldImpl) clazz.newInstance();
                if (arguments != null) {
                    field.initialize(arguments);
                }
                //                field.setSchema(schema);
                field.setCode(code);
                return field;
            } catch (InstantiationException e) {
                String message = "Exception when creating class " + clazz.getName();
                logger.error(message, e.getCause());
                throw new RuntimeException(message, e.getCause());
            } catch (IllegalAccessException e) {
                String message = "The class " + clazz.getName() + " did not have a public empty constructor";
                logger.error(message, e.getCause());
                throw new RuntimeException(message, e.getCause());
            }
        }

    }
}