You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pig.apache.org by dv...@apache.org on 2011/03/18 08:45:50 UTC
svn commit: r1082836 - in /pig/trunk: ./ contrib/piggybank/java/
contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/
contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/
src/org/apache/pig/ src/org/apache/pig/builtin/ ...
Author: dvryaboy
Date: Fri Mar 18 07:45:49 2011
New Revision: 1082836
URL: http://svn.apache.org/viewvc?rev=1082836&view=rev
Log:
PIG-1830: Type mismatch error in key from map, when doing GROUP on PigStorageSchema() variable
Modified:
pig/trunk/CHANGES.txt
pig/trunk/contrib/piggybank/java/build.xml
pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/JsonMetadata.java
pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/PigStorageSchema.java
pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/TestPigStorageSchema.java
pig/trunk/src/org/apache/pig/ResourceSchema.java
pig/trunk/src/org/apache/pig/builtin/PigStorage.java
pig/trunk/src/org/apache/pig/impl/util/CastUtils.java
pig/trunk/src/org/apache/pig/impl/util/Utils.java
Modified: pig/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/pig/trunk/CHANGES.txt?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/CHANGES.txt (original)
+++ pig/trunk/CHANGES.txt Fri Mar 18 07:45:49 2011
@@ -26,6 +26,8 @@ PIG-1680: HBaseStorage should work with
IMPROVEMENTS
+PIG-1830: Type mismatch error in key from map, when doing GROUP on PigStorageSchema() variable (dvryaboy)
+
PIG-1566: Support globbing for registering jars in pig script (nrai via daijy)
PIG-1886: Add zookeeper jar to list of jars shipped when HBaseStorage used (dvryaboy)
Modified: pig/trunk/contrib/piggybank/java/build.xml
URL: http://svn.apache.org/viewvc/pig/trunk/contrib/piggybank/java/build.xml?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/contrib/piggybank/java/build.xml (original)
+++ pig/trunk/contrib/piggybank/java/build.xml Fri Mar 18 07:45:49 2011
@@ -21,7 +21,7 @@
<property name="javac.level" value="source,lines,vars"/>
<property name="javac.optimize" value="on" />
<property name="javac.deprecation" value="off" />
- <property name="javac.version" value="1.5" />
+ <property name="javac.version" value="1.6" />
<property name="javac.args" value="" />
<!-- TODO we should use warning... <property name="javac.args.warnings" value="-Xlint:unchecked" /> -->
<property name="javac.args.warnings" value="" />
@@ -109,7 +109,8 @@
</target>
<target depends="compile" name="compile-test">
<echo> *** Compiling UDF tests ***</echo>
- <javac srcdir="${test.src.dir}" debug="true" debuglevel="${debuglevel}" destdir="${test.classes}" source="${javac.version}" target="${javac.version}">
+ <javac srcdir="${test.src.dir}" debug="${javac.debug}" debuglevel="${javac.level}" destdir="${test.classes}" source="${javac.version}" target="${javac.version}">
+ <compilerarg line="${javac.args} ${javac.args.warnings}"/>
<classpath refid="pigudf.classpath"/>
</javac>
</target>
Modified: pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/JsonMetadata.java
URL: http://svn.apache.org/viewvc/pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/JsonMetadata.java?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/JsonMetadata.java (original)
+++ pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/JsonMetadata.java Fri Mar 18 07:45:49 2011
@@ -145,7 +145,6 @@ public class JsonMetadata implements Loa
* For JsonMetadata schema is considered optional
* This method suppresses (and logs) errors if they are encountered.
*
- * TODO location and conf params are ignored in favor of initialzation data
*/
@Override
public ResourceSchema getSchema(String location, Job job) throws IOException {
@@ -166,7 +165,7 @@ public class JsonMetadata implements Loa
log.warn("Could not find schema file for "+location);
return null;
}
- log.info("Found schema file: "+schemaFile.toString());
+ log.debug("Found schema file: "+schemaFile.toString());
ResourceSchema resourceSchema = null;
try {
resourceSchema = new ObjectMapper().readValue(schemaFile.open(), ResourceSchema.class);
@@ -180,7 +179,6 @@ public class JsonMetadata implements Loa
log.warn("Unable to load Resource Schema for "+location);
e.printStackTrace();
}
-
return resourceSchema;
}
@@ -206,7 +204,7 @@ public class JsonMetadata implements Loa
log.warn("Could not find stat file for "+location);
return null;
}
- log.info("Found stat file "+statFile.toString());
+ log.debug("Found stat file "+statFile.toString());
ResourceStatistics resourceStats = null;
try {
resourceStats = new ObjectMapper().readValue(statFile.open(), ResourceStatistics.class);
Modified: pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/PigStorageSchema.java
URL: http://svn.apache.org/viewvc/pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/PigStorageSchema.java?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/PigStorageSchema.java (original)
+++ pig/trunk/contrib/piggybank/java/src/main/java/org/apache/pig/piggybank/storage/PigStorageSchema.java Fri Mar 18 07:45:49 2011
@@ -19,15 +19,23 @@
package org.apache.pig.piggybank.storage;
import java.io.IOException;
+import java.util.Properties;
-import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.Job;
import org.apache.pig.Expression;
+import org.apache.pig.LoadCaster;
import org.apache.pig.LoadMetadata;
import org.apache.pig.ResourceSchema;
+import org.apache.pig.ResourceSchema.ResourceFieldSchema;
import org.apache.pig.ResourceStatistics;
import org.apache.pig.StoreMetadata;
import org.apache.pig.builtin.PigStorage;
+import org.apache.pig.data.DataByteArray;
+import org.apache.pig.data.Tuple;
+import org.apache.pig.impl.logicalLayer.parser.ParseException;
+import org.apache.pig.impl.util.CastUtils;
+import org.apache.pig.impl.util.UDFContext;
+import org.apache.pig.impl.util.Utils;
/**
* This Load/Store Func reads/writes metafiles that allow the schema and
@@ -43,6 +51,9 @@ import org.apache.pig.builtin.PigStorage
*/
public class PigStorageSchema extends PigStorage implements LoadMetadata, StoreMetadata {
+ private ResourceSchema schema;
+ LoadCaster caster;
+
public PigStorageSchema() {
super();
}
@@ -51,13 +62,59 @@ public class PigStorageSchema extends Pi
super(delim);
}
+ @Override
+ public Tuple getNext() throws IOException {
+ Tuple tup = super.getNext();
+ if (tup == null) return null;
+
+ if ( caster == null) {
+ caster = getLoadCaster();
+ }
+ if (signature != null) {
+ Properties p = UDFContext.getUDFContext().getUDFProperties(this.getClass(),
+ new String[] {signature});
+ String serializedSchema = p.getProperty(signature+".schema");
+ if (serializedSchema == null) return tup;
+ try {
+ schema = new ResourceSchema(Utils.getSchemaFromString(serializedSchema));
+ } catch (ParseException e) {
+ mLog.error("Unable to parse serialized schema " + serializedSchema, e);
+ }
+ }
+
+ if (schema != null) {
+
+ ResourceFieldSchema[] fieldSchemas = schema.getFields();
+ int tupleIdx = 0;
+ // If some fields have been projected out, the tuple
+ // only contains required fields.
+ // We walk the requiredColumns array to find required fields,
+ // and cast those.
+ for (int i = 0; i < fieldSchemas.length; i++) {
+ if (mRequiredColumns == null || mRequiredColumns[i]) {
+ byte[] bytes = ((DataByteArray) tup.get(tupleIdx)).get();
+ tup.set(tupleIdx, CastUtils.convertToType(caster, bytes,
+ fieldSchemas[i], fieldSchemas[i].getType()));
+ tupleIdx++;
+ }
+ }
+ }
+ return tup;
+ }
+
//------------------------------------------------------------------------
// Implementation of LoadMetaData interface
@Override
public ResourceSchema getSchema(String location,
Job job) throws IOException {
- return (new JsonMetadata()).getSchema(location, job);
+ schema = (new JsonMetadata()).getSchema(location, job);
+ if (signature != null && schema != null) {
+ Properties p = UDFContext.getUDFContext().getUDFProperties(this.getClass(),
+ new String[] {signature});
+ p.setProperty(signature + ".schema", schema.toString());
+ }
+ return schema;
}
@Override
Modified: pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/TestPigStorageSchema.java
URL: http://svn.apache.org/viewvc/pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/TestPigStorageSchema.java?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/TestPigStorageSchema.java (original)
+++ pig/trunk/contrib/piggybank/java/src/test/java/org/apache/pig/piggybank/test/TestPigStorageSchema.java Fri Mar 18 07:45:49 2011
@@ -19,8 +19,7 @@
package org.apache.pig.piggybank.test;
-import static org.junit.Assert.assertEquals;
-
+import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -42,14 +41,15 @@ import org.apache.pig.test.MiniCluster;
import org.apache.pig.test.Util;
import org.apache.pig.test.utils.TypeCheckingTestUtil;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import junit.framework.TestCase;
-
-public class TestPigStorageSchema extends TestCase {
+public class TestPigStorageSchema {
protected ExecType execType = ExecType.MAPREDUCE;
+ static MiniCluster cluster = MiniCluster.buildCluster();
+ static PigServer pig;
PigContext pigContext = new PigContext(ExecType.MAPREDUCE, new Properties());
Map<LogicalOperator, LogicalPlan> aliases = new HashMap<LogicalOperator, LogicalPlan>();
@@ -57,14 +57,8 @@ public class TestPigStorageSchema extend
Map<String, LogicalOperator> aliasOp = new HashMap<String, LogicalOperator>();
Map<String, String> fileNameMap = new HashMap<String, String>();
- MiniCluster cluster = MiniCluster.buildCluster();
-
- private PigServer pig;
-
@Before
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ public void setUp() throws Exception {
pig = new PigServer(ExecType.MAPREDUCE, cluster.getProperties());
String origPath = FileLocalizer.fullPath("originput", pig.getPigContext());
if (FileLocalizer.fileExists(origPath, pig.getPigContext())) {
@@ -78,19 +72,22 @@ public class TestPigStorageSchema extend
}
@After
- @Override
- protected void tearDown() throws Exception {
- Util.deleteFile(cluster, "originput");
- String aoutPath = FileLocalizer.fullPath("aout", pig.getPigContext());
- if (FileLocalizer.fileExists(aoutPath, pig.getPigContext())) {
- FileLocalizer.delete(aoutPath, pig.getPigContext());
+ public void tearDown() throws Exception {
+ for (String f : new String[] {"originput", "aout", "originput2",
+ "bout", ".pig_schema.bout", ".pig_schema.aout", "cout", ".pig_schema.cout",
+ ".pig_schema"}) {
+ if (FileLocalizer.fileExists(f, pig.getPigContext())) {
+ FileLocalizer.delete(f, pig.getPigContext());
}
}
+ pig.shutdown();
+ }
@Test
public void testPigStorageSchema() throws Exception {
pigContext.connect();
- String query = "a = LOAD 'originput' using org.apache.pig.piggybank.storage.PigStorageSchema() as (f1:chararray, f2:int);";
+ String query = "a = LOAD 'originput' using org.apache.pig.piggybank.storage.PigStorageSchema() " +
+ "as (f1:chararray, f2:int);";
pig.registerQuery(query);
Schema origSchema = pig.dumpSchema("a");
pig.registerQuery("STORE a into 'aout' using org.apache.pig.piggybank.storage.PigStorageSchema();");
@@ -102,16 +99,19 @@ public class TestPigStorageSchema extend
pig.registerQuery("b = LOAD 'aout' using org.apache.pig.piggybank.storage.PigStorageSchema();");
Schema genSchema = pig.dumpSchema("b");
- assertTrue("generated schema equals original" , Schema.equals(genSchema, origSchema, true, false));
+ Assert.assertTrue("generated schema equals original" ,
+ Schema.equals(genSchema, origSchema, true, false));
// Verify that giving our own schema works
String [] aliases ={"foo", "bar"};
byte[] types = {DataType.INTEGER, DataType.LONG};
Schema newSchema = TypeCheckingTestUtil.genFlatSchema(
aliases,types);
- pig.registerQuery("c = LOAD 'aout' using org.apache.pig.piggybank.storage.PigStorageSchema() as (foo:int, bar:long);");
+ pig.registerQuery("c = LOAD 'aout' using org.apache.pig.piggybank.storage.PigStorageSchema() "+
+ "as (foo:int, bar:long);");
Schema newGenSchema = pig.dumpSchema("c");
- assertTrue("explicit schema overrides metadata", Schema.equals(newSchema, newGenSchema, true, false));
+ Assert.assertTrue("explicit schema overrides metadata",
+ Schema.equals(newSchema, newGenSchema, true, false));
}
@@ -123,7 +123,8 @@ public class TestPigStorageSchema extend
"5", "5", "8", "8",
"8", "9"});
- pig.registerQuery("A = LOAD 'originput2' using org.apache.pig.piggybank.storage.PigStorageSchema() as (f:int);");
+ pig.registerQuery("A = LOAD 'originput2' using org.apache.pig.piggybank.storage.PigStorageSchema() " +
+ "as (f:int);");
pig.registerQuery("B = group A by f;");
Schema origSchema = pig.dumpSchema("B");
ResourceSchema rs1 = new ResourceSchema(origSchema);
@@ -132,7 +133,7 @@ public class TestPigStorageSchema extend
pig.registerQuery("C = LOAD 'bout' using org.apache.pig.piggybank.storage.PigStorageSchema();");
Schema genSchema = pig.dumpSchema("C");
ResourceSchema rs2 = new ResourceSchema(genSchema);
- assertTrue("generated schema equals original" , ResourceSchema.equals(rs1, rs2));
+ Assert.assertTrue("generated schema equals original" , ResourceSchema.equals(rs1, rs2));
pig.registerQuery("C1 = LOAD 'bout' as (a0:int, A: {t: (f:int) } );");
pig.registerQuery("D = foreach C1 generate a0, SUM(A);");
@@ -150,16 +151,17 @@ public class TestPigStorageSchema extend
Iterator<Tuple> iter = pig.openIterator("D");
int counter = 0;
while (iter.hasNext()) {
- assertEquals(expectedResults.get(counter++).toString(), iter.next().toString());
+ Assert.assertEquals(expectedResults.get(counter++).toString(), iter.next().toString());
}
- assertEquals(expectedResults.size(), counter);
+ Assert.assertEquals(expectedResults.size(), counter);
}
@Test
public void testSchemaConversion2() throws Exception {
- pig.registerQuery("A = LOAD 'originput' using org.apache.pig.piggybank.storage.PigStorageSchema(',') as (f1:chararray, f2:int);");
+ pig.registerQuery("A = LOAD 'originput' using org.apache.pig.piggybank.storage.PigStorageSchema(',') " +
+ "as (f1:chararray, f2:int);");
pig.registerQuery("B = group A by f1;");
Schema origSchema = pig.dumpSchema("B");
ResourceSchema rs1 = new ResourceSchema(origSchema);
@@ -168,7 +170,7 @@ public class TestPigStorageSchema extend
pig.registerQuery("C = LOAD 'cout' using org.apache.pig.piggybank.storage.PigStorageSchema();");
Schema genSchema = pig.dumpSchema("C");
ResourceSchema rs2 = new ResourceSchema(genSchema);
- assertTrue("generated schema equals original" , ResourceSchema.equals(rs1, rs2));
+ Assert.assertTrue("generated schema equals original" , ResourceSchema.equals(rs1, rs2));
pig.registerQuery("C1 = LOAD 'cout' as (a0:chararray, A: {t: (f1:chararray, f2:int) } );");
pig.registerQuery("D = foreach C1 generate a0, SUM(A.f2);");
@@ -184,10 +186,37 @@ public class TestPigStorageSchema extend
Iterator<Tuple> iter = pig.openIterator("D");
int counter = 0;
while (iter.hasNext()) {
- assertEquals(expectedResults.get(counter++).toString(), iter.next().toString());
+ Assert.assertEquals(expectedResults.get(counter++).toString(), iter.next().toString());
}
- assertEquals(expectedResults.size(), counter);
+ Assert.assertEquals(expectedResults.size(), counter);
}
+ /**
+ * See PIG-1830
+ * @throws IOException
+ */
+ @Test
+ public void testByteArrayConversion() throws IOException {
+ Util.createInputFile(cluster, "originput2",
+ new String[] {"peter\t1", "samir\t2", "michael\t4",
+ "peter\t2", "peter\t4", "samir\t1"
+ });
+ Util.createInputFile(cluster, ".pig_schema",
+ new String[] {
+ "{\"fields\":[{\"name\":\"name\",\"type\":55,\"schema\":null," +
+ "\"description\":\"autogenerated from Pig Field Schema\"}," +
+ "{\"name\":\"val\",\"type\":10,\"schema\":null,\"description\":"+
+ "\"autogenerated from Pig Field Schema\"}],\"version\":0," +
+ "\"sortKeys\":[],\"sortKeyOrders\":[]}"
+ });
+ pig.registerQuery("Events = LOAD 'originput2' USING org.apache.pig.piggybank.storage.PigStorageSchema();");
+ pig.registerQuery("Sessions = GROUP Events BY name;");
+ Iterator<Tuple> sessions = pig.openIterator("Sessions");
+ while (sessions.hasNext()) {
+ System.out.println(sessions.next());
+}
+
+
+ }
}
Modified: pig/trunk/src/org/apache/pig/ResourceSchema.java
URL: http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/ResourceSchema.java?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/ResourceSchema.java (original)
+++ pig/trunk/src/org/apache/pig/ResourceSchema.java Fri Mar 18 07:45:49 2011
@@ -483,9 +483,8 @@ public class ResourceSchema implements S
private static void stringifyResourceSchema(StringBuilder sb,
ResourceSchema rs, byte type, boolean printAlias) {
- if (type == DataType.UNKNOWN) {
- sb.append("<");
- } else if (type == DataType.BAG) {
+
+ if (type == DataType.BAG) {
sb.append("{");
} else if (type == DataType.TUPLE) {
sb.append("(");
@@ -500,9 +499,7 @@ public class ResourceSchema implements S
}
}
- if (type == DataType.UNKNOWN) {
- sb.append(">");
- } else if (type == DataType.BAG) {
+ if (type == DataType.BAG) {
sb.append("}");
} else if (type == DataType.TUPLE) {
sb.append(")");
Modified: pig/trunk/src/org/apache/pig/builtin/PigStorage.java
URL: http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/builtin/PigStorage.java?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/builtin/PigStorage.java (original)
+++ pig/trunk/src/org/apache/pig/builtin/PigStorage.java Fri Mar 18 07:45:49 2011
@@ -69,7 +69,7 @@ LoadPushDown {
protected RecordReader in = null;
protected RecordWriter writer = null;
protected final Log mLog = LogFactory.getLog(getClass());
- private String signature;
+ protected String signature;
private byte fieldDel = '\t';
private ArrayList<Object> mProtoTuple = null;
@@ -79,7 +79,7 @@ LoadPushDown {
public PigStorage() {
}
- private boolean[] mRequiredColumns = null;
+ protected boolean[] mRequiredColumns = null;
private boolean mRequiredColumnsInitialized = false;
@@ -267,7 +267,7 @@ LoadPushDown {
@Override
public int hashCode() {
- return (int)fieldDel;
+ return fieldDel;
}
Modified: pig/trunk/src/org/apache/pig/impl/util/CastUtils.java
URL: http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/impl/util/CastUtils.java?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/impl/util/CastUtils.java (original)
+++ pig/trunk/src/org/apache/pig/impl/util/CastUtils.java Fri Mar 18 07:45:49 2011
@@ -18,9 +18,15 @@
package org.apache.pig.impl.util;
+import java.io.IOException;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.pig.LoadCaster;
import org.apache.pig.PigWarning;
+import org.apache.pig.ResourceSchema.ResourceFieldSchema;
+import org.apache.pig.data.DataByteArray;
+import org.apache.pig.data.DataType;
public class CastUtils {
@@ -30,6 +36,30 @@ public class CastUtils {
protected static final Log mLog = LogFactory.getLog(CastUtils.class);
+ /**
+ *
+ * @param caster LoadCaster to be used to convert the bytes into a field.
+ * @param bytes
+ * @param fieldSchema schema of Bag or Tuple; pass in null if a simple type.
+ * @param dataType type from DataType
+ * @return converted object.
+ * @throws IOException
+ */
+ public static Object convertToType(LoadCaster caster, byte[] bytes,
+ ResourceFieldSchema fieldSchema, byte dataType) throws IOException {
+ switch (dataType) {
+ case (DataType.BAG): return caster.bytesToBag(bytes, fieldSchema);
+ case (DataType.BYTEARRAY): return new DataByteArray(bytes);
+ case (DataType.CHARARRAY): return caster.bytesToCharArray(bytes);
+ case (DataType.DOUBLE): return caster.bytesToDouble(bytes);
+ case (DataType.FLOAT): return caster.bytesToFloat(bytes);
+ case (DataType.INTEGER): return caster.bytesToInteger(bytes);
+ case (DataType.LONG): return caster.bytesToLong(bytes);
+ case (DataType.MAP): return caster.bytesToMap(bytes);
+ case (DataType.TUPLE): return caster.bytesToTuple(bytes, fieldSchema);
+ default: throw new IOException("Unknown type " + dataType);
+ }
+ }
public static Double stringToDouble(String str) {
if (str == null) {
Modified: pig/trunk/src/org/apache/pig/impl/util/Utils.java
URL: http://svn.apache.org/viewvc/pig/trunk/src/org/apache/pig/impl/util/Utils.java?rev=1082836&r1=1082835&r2=1082836&view=diff
==============================================================================
--- pig/trunk/src/org/apache/pig/impl/util/Utils.java (original)
+++ pig/trunk/src/org/apache/pig/impl/util/Utils.java Fri Mar 18 07:45:49 2011
@@ -235,9 +235,9 @@ public class Utils {
Collection<O> result = null;
try {
if (a!=null)
- result = (Collection<O>)a.getClass().newInstance();
+ result = a.getClass().newInstance();
else
- result = (Collection<O>)b.getClass().newInstance();
+ result = b.getClass().newInstance();
} catch (Exception e) {
// Shall not happen
}