org.qxsched.doc.afp.impl.AfpClasses.java Source code

Java tutorial

Introduction

Here is the source code for org.qxsched.doc.afp.impl.AfpClasses.java

Source

package org.qxsched.doc.afp.impl;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.qxsched.doc.afp.AfpException;
import org.qxsched.doc.afp.AfpFactory;
import org.qxsched.doc.afp.AfpRecord;
import org.qxsched.doc.afp.AfpStructuredFieldDefinitions;
import org.qxsched.doc.afp.AfpTriplet;

/*
 * 
 * Copyright 2009, 2010, 2011 Vincenzo Zocca
 * 
 * This file is part of Java library org.qxsched.doc.afp.
 *
 * Java library org.qxsched.doc.afp 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 3 of the
 * License, or (at your option) any later version.
 *
 * Java library org.qxsched.doc.afp 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 Java library org.qxsched.doc.afp.
 * If not, see <http://www.gnu.org/licenses/>.
 * 
 */

/**
 * Class {@link AfpClasses} contains all {@link AfpRecord} classes that
 * implement a specific AFP identifier.
 * 
 * @author Vincenzo Zocca
 * 
 */
public class AfpClasses {

    private static AfpClasses instance;

    private static Logger LOG = Logger.getLogger(AfpClasses.class);

    public synchronized static AfpClasses instance() throws AfpException {

        // Return if already instantiated
        if (instance != null) {
            return instance;
        }

        // Instantiate and return
        instance = new AfpClasses();
        return instance;
    }

    private Map<String, Class<AfpRecord>> recordAbbrev2class = new HashMap<String, Class<AfpRecord>>();
    private Map<Integer, Class<AfpRecord>> recordCode2class = new HashMap<Integer, Class<AfpRecord>>();

    private Map<Integer, Class<AfpTriplet>> tripletCode2class = new HashMap<Integer, Class<AfpTriplet>>();

    private AfpClasses() throws AfpException {
        init();
    }

    public Class<AfpRecord> getSpecificAfpRecordClass(AfpRecord record) {
        return recordCode2class.get(record.getSFIdentifier());
    }

    public Class<AfpRecord> getSpecificAfpRecordClass(Integer code) {
        return recordCode2class.get(code);
    }

    public Class<AfpTriplet> getSpecificAfpTripletClass(AfpTriplet triplet) {
        return tripletCode2class.get(triplet.getTid());
    }

    public Class<AfpTriplet> getSpecificAfpTripletClass(Integer code) {
        return tripletCode2class.get(code);
    }

    public Class<AfpRecord> getSpecificClass(String abbrev) {
        return recordAbbrev2class.get(abbrev);
    }

    private void init() throws AfpException {

        // Get definitions
        AfpStructuredFieldDefinitions defs = AfpStructuredFieldDefinitions.instance();

        // Get class loader
        ClassLoader ldr = Thread.currentThread().getContextClassLoader();

        // Get package directory
        Package pkg = AfpClasses.class.getPackage();
        String recClassBaseName = AfpRecord.class.getName().replaceFirst("^.*\\.", "");
        String recClassBase = pkg.getName() + "." + recClassBaseName;

        // Iterate through all abbreviations and try and find classes
        Set<String> abbrevs = defs.getAbbrev();
        for (String abbrev : abbrevs) {

            // Make class name
            String recordClassName = recClassBase + abbrev;
            if (LOG.isTraceEnabled()) {
                LOG.trace("AFP record class name: " + recordClassName);
            }

            // Load class
            Class<?> recordClass = null;
            try {
                recordClass = ldr.loadClass(recordClassName);
            } catch (ClassNotFoundException e) {
            }

            // Ignore null
            if (recordClass == null) {
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Ignoring unfound class: " + recordClassName);
                }
                continue;
            }

            // Ignore non AfpRecords
            if (!AfpRecord.class.isAssignableFrom(recordClass)) {
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Ignoring non AfpRecord: " + recordClassName);
                }
                continue;
            }

            // Map
            Integer code = defs.getCode(abbrev);
            recordCode2class.put(code, (Class<AfpRecord>) recordClass);
            recordAbbrev2class.put(abbrev, (Class<AfpRecord>) recordClass);
        }

        // Try finding al triplet classes this package implements
        String tripClassBaseName = AfpTriplet.class.getName().replaceFirst("^.*\\.", "");
        String tripClassBase = pkg.getName() + "." + tripClassBaseName;
        for (int i = 0; i < 0x100; i++) {

            // Make class name
            String abbrev = StringUtils.leftPad(Integer.toString(i, 16).toUpperCase(), 2, '0');
            String tripClassName = tripClassBase + abbrev;
            if (LOG.isTraceEnabled()) {
                LOG.trace("AFP triplet class name: " + tripClassName);
            }

            // Load class
            Class<?> tripClass = null;
            try {
                tripClass = ldr.loadClass(tripClassName);
            } catch (ClassNotFoundException e) {
            }

            // Ignore null
            if (tripClass == null) {
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Ignoring unfound class: " + tripClassName);
                }
                continue;
            }

            // Ignore non AfpTriplet
            if (!AfpTriplet.class.isAssignableFrom(tripClass)) {
                if (LOG.isTraceEnabled()) {
                    LOG.trace("Ignoring non AfpTriplet: " + tripClassName);
                }
                continue;
            }

            // Map
            if (LOG.isTraceEnabled()) {
                LOG.trace("Found AfpTriplet: " + tripClassName);
            }
            tripletCode2class.put(i, (Class<AfpTriplet>) tripClass);
        }
    }

    public AfpRecord instantiateSpecific(AfpRecord record, AfpFactory fact) throws AfpException {

        // Get record class
        Class<AfpRecord> cls = getSpecificAfpRecordClass(record);

        // Do nothing if no class
        if (cls == null) {
            LOG.warn("No specific class found for AFP identifier '" + record.getSFIdentifierAbbrev() + "'/"
                    + record.getSFIdentifierString());
            return record;
        }

        // Get constructor
        Constructor<AfpRecord> constr;
        try {
            Class[] prams = { AfpRecord.class, AfpFactory.class };
            constr = cls.getConstructor(prams);
        } catch (SecurityException e) {
            throw new AfpException(e.getMessage(), e);
        } catch (NoSuchMethodException e) {
            LOG.error("No constructor found accepting AfpRecord in class " + cls.getName(), e);
            return record;
        }

        // Instantiate
        try {
            Object[] prams = { record, fact };
            AfpRecord inst = constr.newInstance(prams);
            return inst;
        } catch (IllegalArgumentException e) {
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return record;
        } catch (InstantiationException e) {
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return record;
        } catch (IllegalAccessException e) {
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return record;
        } catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            if (cause instanceof AfpException) {
                throw (AfpException) cause;
            }
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return record;
        }
    }

    public AfpTriplet instantiateSpecific(AfpTriplet triplet, AfpFactory fact) throws AfpException {

        // Get triplet class
        Class<AfpTriplet> cls = getSpecificAfpTripletClass(triplet);

        // Do nothing if no class
        if (cls == null) {
            LOG.warn("No specific class found for AFP triplet 0x" + Integer.toString(triplet.getTid(), 16));
            return triplet;
        }

        // Get constructor
        Constructor<AfpTriplet> constr;
        try {
            constr = cls.getConstructor(AfpTriplet.class);
        } catch (SecurityException e) {
            throw new AfpException(e.getMessage(), e);
        } catch (NoSuchMethodException e) {
            LOG.error("No constructor found accepting AfpTriplet in class " + cls.getName());
            return triplet;
        }
        if (LOG.isTraceEnabled()) {
            LOG.trace("Constructor found accepting AfpTriplet in class " + cls.getName());
        }

        // Instantiate
        try {
            Object[] prams = { triplet };
            AfpTriplet inst = constr.newInstance(prams);
            return inst;
        } catch (IllegalArgumentException e) {
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return triplet;
        } catch (InstantiationException e) {
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return triplet;
        } catch (IllegalAccessException e) {
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return triplet;
        } catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            if (cause instanceof AfpException) {
                throw (AfpException) cause;
            }
            LOG.error("Unexpected exception: " + e.getMessage(), e);
            return triplet;
        }
    }
}