Java tutorial
package net.agkn.field_stripe; /* * Copyright 2012 Aggregate Knowledge, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import net.agkn.field_stripe.encode.FieldStripeEncoderFactory; import net.agkn.field_stripe.encode.RootFieldStripeEncoder; import net.agkn.field_stripe.exception.NoSuchObjectException; import net.agkn.field_stripe.exception.OperationFailedException; import net.agkn.field_stripe.record.ICompositeType; import net.agkn.field_stripe.record.IFieldType; import net.agkn.field_stripe.record.protobuf.ProtobufFieldTypeFactory; import net.agkn.field_stripe.record.reader.IRecordReader; import net.agkn.field_stripe.record.reader.SmartJsonArrayRecordReader; import net.agkn.field_stripe.stripe.BinaryVLenFieldStripeWriter; import net.agkn.field_stripe.stripe.IFieldStripeWriter; import net.agkn.field_stripe.stripe.IFieldStripeWriterFactory; import org.apache.commons.io.FileUtils; import com.dyuproject.protostuff.parser.Proto; import com.dyuproject.protostuff.parser.ProtoUtil; /** * An command-line entry point into a file-based record encoder that uses * Protobuf-based IDL to define the schema. The following information is passed:<p/> * <ul> * <li>The base path to the schema IDL (*.proto). This directory must exist * (and be a directory);</li> * <li>The fully qualified name of the message definition (within the Protobuf * IDL) for the encoded data;</li> * <li>The path and filename to the JSON record data to be encoded;</li> * <li>The base path to the output encoded field stripes. This directory must * exist (and be a directory);</li> * </ul> * * @author rgrzywinski * @see FileRecordDecoder */ public class FileRecordEncoder { /** * @param args refer to the {@link FileRecordEncoder class JavaDoc} for the * required parameters. This can never be <code>null</code>. */ public static void main(final String[] args) { if (args.length != 4) { showUsage(); System.exit(1/*EXIT_FAILURE*/); return; } /* else -- there are the expected number of arguments */ // validate all input parameters final File idlBasePath = new File(args[0]); if (!idlBasePath.exists()) { System.err.println("The IDL base path does not exist: " + args[0]); System.exit(1/*EXIT_FAILURE*/); } if (!idlBasePath.isDirectory()) { System.err.println("The IDL base path is not a directory: " + args[0]); System.exit(1/*EXIT_FAILURE*/); } final String fqMessageName = args[1]; final File jsonInputRecord = new File(args[2]); if (!jsonInputRecord.exists()) { System.err.println("The input JSON record file does not exist: " + args[2]); System.exit(1/*EXIT_FAILURE*/); } if (jsonInputRecord.isDirectory()) { System.err.println("The input JSON record is not a file: " + args[2]); System.exit(1/*EXIT_FAILURE*/); } final File outputPath = new File(args[3]); if (!outputPath.exists()) { System.err.println("The output base path does not exist: " + args[3]); System.exit(1/*EXIT_FAILURE*/); } if (!outputPath.isDirectory()) { System.err.println("The output base path is not a directory: " + args[3]); System.exit(1/*EXIT_FAILURE*/); } IFieldStripeWriterFactory fieldStripeWriterFactory = null/*none to start*/; try { final ICompositeType schema = createSchema(idlBasePath, fqMessageName); final IRecordReader recordReader = createRecordReader(jsonInputRecord); fieldStripeWriterFactory = createFieldStripeWriterFactory(outputPath); final RootFieldStripeEncoder rootEncoder = createEncoderTree(schema, fieldStripeWriterFactory); // encode each record while (rootEncoder.encode(recordReader)) ; } catch (final OperationFailedException ofe) { System.err.println( "An error occurred while encoding records into field-stripes: " + ofe.getLocalizedMessage()); System.exit(1/*EXIT_FAILURE*/); } finally { try { if (fieldStripeWriterFactory != null) fieldStripeWriterFactory.closeAllWriters(); } catch (final OperationFailedException ofe) { System.err.println( "An error occurred while closing field-stripe writers: " + ofe.getLocalizedMessage()); System.exit(1/*EXIT_FAILURE*/); } } System.exit(0/*EXIT_SUCCESS*/); } // ------------------------------------------------------------------------ /** * Parses the IDL at the specified path and finds the message definition * with the specified fully-qualified name. This is converted into a * {@link ICompositeType schema} and returned. */ public static ICompositeType createSchema(final File protobufPath, final String fqMessageName) { final List<Proto> protobufDefinitions = parseProtobufDefinitions(protobufPath); final ProtobufFieldTypeFactory fieldTypeFactory = new ProtobufFieldTypeFactory(); try { final IFieldType fieldType = fieldTypeFactory.createFieldType(protobufDefinitions, fqMessageName); if (!(fieldType instanceof ICompositeType)) { System.err.println("The message definition was not a top-level message: " + fqMessageName); System.exit(1/*EXIT_FAILURE*/); return null/*never occurs*/; } /* else -- the message was of the expected type */ return (ICompositeType) fieldType; } catch (final NoSuchObjectException nsoe) { System.err.println("The message definition could not be found: " + fqMessageName); System.exit(1/*EXIT_FAILURE*/); return null/*never occurs*/; } catch (final OperationFailedException ofe) { System.err.println("An error occurred converting the message definition into an encoding schema: " + fqMessageName); System.exit(1/*EXIT_FAILURE*/); return null/*never occurs*/; } } /** * Parse all Protobuf (*.proto) files in the specified path. */ public static List<Proto> parseProtobufDefinitions(final File protobufPath) { final List<Proto> protobufDefinitions = new ArrayList<Proto>(); final Iterator<File> protobufFiles = FileUtils.iterateFiles(protobufPath, new String[] { "proto" }, true/*recursively*/); while (protobufFiles.hasNext()) { final File protobufFile = protobufFiles.next(); if (protobufFile.isDirectory()) continue/*ignore directories*/; // CHECK: should this continue if there's an error parsing? try { protobufDefinitions.add(ProtoUtil.parseProto(protobufFile)); } catch (final RuntimeException re) { System.err.println("An error occurred while parsing: " + protobufFile.getAbsolutePath()); System.err.println(re.getLocalizedMessage()); } } return protobufDefinitions; } // ------------------------------------------------------------------------ /** * Creates and returns a {@link IRecordReader} from the specified JSON-array-based * file. */ private static IRecordReader createRecordReader(final File jsonInputRecord) { try { return new SmartJsonArrayRecordReader(new FileReader(jsonInputRecord)); } catch (final FileNotFoundException fnfe) { // NOTE: the only way that this could occur is if the file was // moved / deleted between the earlier check and this call System.err.println("JSON record file moved / deleted: " + jsonInputRecord.getAbsolutePath()); System.exit(1/*EXIT_FAILURE*/); return null/*never occurs*/; } } // ------------------------------------------------------------------------ /** * Creates the {@link IFieldStripeWriterFactory} for the specified output * path. */ private static IFieldStripeWriterFactory createFieldStripeWriterFactory(final File outputPath) { try { return BinaryVLenFieldStripeWriter.createFactory(outputPath); } catch (final OperationFailedException ofe) { // NOTE: the only way that this could occur is if the file was // moved / deleted between the earlier check and this call System.err.println("Output path moved / deleted: " + outputPath.getAbsolutePath()); System.exit(1/*EXIT_FAILURE*/); return null/*never occurs*/; } } /** * Creates the tree of {@link IFieldStripeWriter field-stripe writers} using * the specified {@link IFieldStripeWriterFactory} based on the specified * {@link ICompositeType schema} and returns the {@link RootFieldStripeEncoder}. */ private static RootFieldStripeEncoder createEncoderTree(final ICompositeType schema, final IFieldStripeWriterFactory fieldStripeWriterFactory) { try { final FieldStripeEncoderFactory encoderFactory = new FieldStripeEncoderFactory( fieldStripeWriterFactory); return encoderFactory.createEncoderTree(schema); } catch (final OperationFailedException ofe) { System.err.println( "An error occurred creating the output field stripe writers: " + ofe.getLocalizedMessage()); System.exit(1/*EXIT_FAILURE*/); return null/*never occurs*/; } } // ======================================================================== /** * Writes the CLI usage to standard out. */ public static void showUsage() { System.out.println("Usage:"); System.out.println( "\tFileRecordEncoder <IDL base path> <fully-qualified message definition> <JSON input filename> <output field-stripe path>"); } }