/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ package org.apache.pig.data; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.pig.data.SchemaTuple.SchemaTupleQuickGenerator; import org.apache.pig.data.SchemaTupleClassGenerator.GenContext; import org.apache.pig.impl.logicalLayer.schema.Schema; /** * This is an implementation of TupleFactory that will instantiate * SchemaTuple's. This class has nothing to do with the actual generation * of code, and instead simply encapsulates the classes which allow * for efficiently creating SchemaTuples. */ public class SchemaTupleFactory implements TupleMaker<SchemaTuple<?>> { static final Log LOG = LogFactory.getLog(SchemaTupleFactory.class); private SchemaTupleQuickGenerator<? extends SchemaTuple<?>> generator; private Class<SchemaTuple<?>> clazz; private int tupleSize; protected SchemaTupleFactory(Class<SchemaTuple<?>> clazz, SchemaTupleQuickGenerator<? extends SchemaTuple<?>> generator) { this.clazz = clazz; this.generator = generator; tupleSize = generator.make().size(); } /** * This method inspects a Schema to see whether or * not a SchemaTuple implementation can be generated * for the types present. Currently, bags and maps * are not supported. * @param s as Schema * @return boolean type value, true if it is generatable */ public static boolean isGeneratable(Schema s) { if (s == null || s.size() == 0) { return false; } for (Schema.FieldSchema fs : s.getFields()) { if (fs.type == DataType.TUPLE && !isGeneratable(fs.schema)) { return false; } } return true; } @Override public SchemaTuple<?> newTuple() { return generator.make(); } @Override public SchemaTuple<?> newTuple(int size) { if (size != tupleSize) { throw new RuntimeException("Request a SchemaTuple of the wrong size! Requested [" + size + "], can only be [" + tupleSize + "]" ); } return generator.make(); } public Class<SchemaTuple<?>> tupleClass() { return clazz; } // We could make this faster by caching the result, but I doubt it will be called // in any great volume. public boolean isFixedSize() { return clazz.isAssignableFrom(AppendableSchemaTuple.class); } /** * This method is the publicly facing method which returns a SchemaTupleFactory * which will generate the SchemaTuple associated with the given identifier. This method * is primarily for internal use in cases where the problem SchemaTuple is known * based on the identifier associated with it (such as when deserializing). * @param id as int, means identifier * @return SchemaTupleFactory which will return SchemaTuple's of the given identifier */ protected static SchemaTupleFactory getInstance(int id) { return SchemaTupleBackend.newSchemaTupleFactory(id); } /** * This method is the publicly facing method which returns a SchemaTupleFactory * which will generate SchemaTuples of the given Schema. Note that this method * returns null if such a given SchemaTupleFactory does not exist, instead of * throwing an error. The GenContext is used to specify the context in which we * are requesting a SchemaTupleFactory. This is necessary so that the use * of SchemaTuple can be controlled -- it is possible that someone wants a * factory that generates code in the context of joins, but wants to disable such * use for udfs. * @param s the Schema generated * @param isAppendable whether or not the SchemaTuple should be appendable * @param context the context in which we want a SchemaTupleFactory * @return SchemaTupleFactory which will return SchemaTuple's of the desired Schema */ public static SchemaTupleFactory getInstance(Schema s, boolean isAppendable, GenContext context) { return SchemaTupleBackend.newSchemaTupleFactory(s, isAppendable, context); } public static SchemaTupleFactory getInstance(Schema s, boolean isAppendable) { return getInstance(s, isAppendable, GenContext.FORCE_LOAD); } public static SchemaTupleFactory getInstance(Schema s) { return getInstance(s, false); } }