samedi 19 décembre 2020

Java Class to Encapsulate Large Number of Classes

I am fairly new to Java, though I've learned a lot thanks to OJT. I have a vexing problem in dealing with a legacy application's files. The application has over 600 record structures that must be handled in new Java programs being developed.

Systems vendor tools were used to generate Java classes for those 600+ structures, and those classes may get periodically re-generated due to unrelated changes. Those classes have getters/setters for the fields specific to that record, as well as marshall/unmarshall methods (for preparing a buffer for writing or processing a buffer after reading).

I've been asked to develop a "reader" class and a "writer" class to encapsulate the common functionality in those 600+ lower-level classes, and add additional processing, without writing 600+ individual "reader" and "writer" classes and replicating that additional code hundreds of times (and then having to maintain it).

I figured Java generics could help, and reflection could be used to invoke the marshall/unmarshal (and other common methods) in the specific, generated classes, but from within the generic class (if I said that right).

I've added all 600+ of those classes, and my attempts at a Reader class, in a library (jar) (throws & try/catch blocks removed for brevity):

public class RecordXyz {
    /* member data */

    /* misc other code */

    public byte[] marshal() { /*marhalling code*/ }
    public void unmarshal() { /*unmarhalling code*/ }
}

public class Reader<T> {
    private T       myT;
    private Method  getLength;
    private Method  unMarshall;

    Reader( T t, String fname ) {
        this.myT         = t;
        this.aClass      = (Class<T>)myT.getClass();
        this.marshall    = this.aClass.getMethod( "marshall", new Class[] { byte[].class, int.class } );
        this.unMarshall  = this.aClass.getMethod( "unmarshall", null );
    }
    /* Other member functions in Reader class */
}

Code trying to use the Reader class:

import io.RecordXyz;
import rw.Reader;

public class Test {
    public static void main( String[] args )
    {
        RecordXyz rec = new RecordXyz();

        */* compile error here */*
        testReader = new Reader<RecordXyz>( rec, "/usr/data/somefile.txt" );
    }
}

Unfortunately, I get a compile error on the instantiation of testReader: "The constructor Reader(T, String) is not visible"

Which makes no sense to me. But countless examples on this site and elsewhere say this is the way to do it. So, now I'm stumped and seek your help.

How do I to "pass" a RecordXyz object to the Reader class so it can use reflection to invoke the methods of a RecordXyz object at run-time? Is this even possible with Java?

I'm betting there's a simpler, more cogent solution. Please bear in mind that I'm limited to straight Java 1.8, though if there's an open source solution I may be able to convince management to approve its use.

Apologies for the verbosity but this is a stinker of a problem (for me anyway).

Thanks!





Aucun commentaire:

Enregistrer un commentaire