11adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov/** 211a89b445f3bde56bf07e6a0d04f0b0256dcb215Andrey Somov * Copyright (c) 2008, http://www.snakeyaml.org 31adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * 41adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * Licensed under the Apache License, Version 2.0 (the "License"); 51adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * you may not use this file except in compliance with the License. 61adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * You may obtain a copy of the License at 71adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * 81adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * http://www.apache.org/licenses/LICENSE-2.0 91adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * 101adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * Unless required by applicable law or agreed to in writing, software 111adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * distributed under the License is distributed on an "AS IS" BASIS, 121adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * See the License for the specific language governing permissions and 141adf3a94fce500e0bda933e4b495a004d5789bd7Andrey Somov * limitations under the License. 159629be70863521bead138c295351f3dec926ab1Andrey Somov */ 169629be70863521bead138c295351f3dec926ab1Andrey Somovpackage org.yaml.snakeyaml.constructor; 179629be70863521bead138c295351f3dec926ab1Andrey Somov 189629be70863521bead138c295351f3dec926ab1Andrey Somovimport java.beans.IntrospectionException; 19583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somovimport java.math.BigDecimal; 209629be70863521bead138c295351f3dec926ab1Andrey Somovimport java.math.BigInteger; 21c084ec7a5d61af0edce644cd1ec400a8df838f4cAndrey Somovimport java.util.ArrayList; 22b4779f9a8e0eaf921e4838fc9c68b8e9c0be963cAndrey Somovimport java.util.Calendar; 2325b326160d3a4ec112768f32ae44250e4897eceaAndrey Somovimport java.util.Collection; 249629be70863521bead138c295351f3dec926ab1Andrey Somovimport java.util.Date; 259629be70863521bead138c295351f3dec926ab1Andrey Somovimport java.util.HashMap; 269629be70863521bead138c295351f3dec926ab1Andrey Somovimport java.util.List; 279629be70863521bead138c295351f3dec926ab1Andrey Somovimport java.util.Map; 28cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somovimport java.util.Properties; 29377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somovimport java.util.Set; 30cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somovimport java.util.SortedMap; 31f88e848a4d49bd347840dce4b43573aec8fe74e3Andrey Somovimport java.util.SortedSet; 32cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somovimport java.util.TreeMap; 33f88e848a4d49bd347840dce4b43573aec8fe74e3Andrey Somovimport java.util.TreeSet; 34ebe7279d7a16518cd05078e24ce240af52c8597eAndrey Somovimport java.util.UUID; 359629be70863521bead138c295351f3dec926ab1Andrey Somov 369629be70863521bead138c295351f3dec926ab1Andrey Somovimport org.yaml.snakeyaml.TypeDescription; 379629be70863521bead138c295351f3dec926ab1Andrey Somovimport org.yaml.snakeyaml.error.YAMLException; 389629be70863521bead138c295351f3dec926ab1Andrey Somovimport org.yaml.snakeyaml.introspector.Property; 399629be70863521bead138c295351f3dec926ab1Andrey Somovimport org.yaml.snakeyaml.nodes.MappingNode; 409629be70863521bead138c295351f3dec926ab1Andrey Somovimport org.yaml.snakeyaml.nodes.Node; 41ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somovimport org.yaml.snakeyaml.nodes.NodeId; 429da9b5c833e9e30ec0991f8fc4181d29384ed939Andrey Somovimport org.yaml.snakeyaml.nodes.NodeTuple; 439629be70863521bead138c295351f3dec926ab1Andrey Somovimport org.yaml.snakeyaml.nodes.ScalarNode; 449629be70863521bead138c295351f3dec926ab1Andrey Somovimport org.yaml.snakeyaml.nodes.SequenceNode; 4587ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somovimport org.yaml.snakeyaml.nodes.Tag; 469629be70863521bead138c295351f3dec926ab1Andrey Somov 479629be70863521bead138c295351f3dec926ab1Andrey Somov/** 48205e9cd24e59a3f9005213cb68899b9ba95a06d2Andrey Somov * Construct a custom Java instance. 499629be70863521bead138c295351f3dec926ab1Andrey Somov */ 509629be70863521bead138c295351f3dec926ab1Andrey Somovpublic class Constructor extends SafeConstructor { 511fa9989515d2c8fc77d5c7b363d735efd7e443cfAndrey Somov private final Map<Tag, Class<? extends Object>> typeTags; 52ddeae0b94884e98a832f12e1586c76d37e2e74f4Andrey Somov protected final Map<Class<? extends Object>, TypeDescription> typeDefinitions; 539629be70863521bead138c295351f3dec926ab1Andrey Somov 549629be70863521bead138c295351f3dec926ab1Andrey Somov public Constructor() { 559629be70863521bead138c295351f3dec926ab1Andrey Somov this(Object.class); 569629be70863521bead138c295351f3dec926ab1Andrey Somov } 579629be70863521bead138c295351f3dec926ab1Andrey Somov 58ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov /** 59ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov * Create Constructor for the specified class as the root. 60ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov * 61ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov * @param theRoot 62ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov * - the class (usually JavaBean) to be constructed 63ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov */ 649629be70863521bead138c295351f3dec926ab1Andrey Somov public Constructor(Class<? extends Object> theRoot) { 65701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov this(new TypeDescription(checkRoot(theRoot))); 66701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov } 67701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov 68701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov /** 69701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov * Ugly Java way to check the argument in the constructor 70701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov */ 71701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov private static Class<? extends Object> checkRoot(Class<? extends Object> theRoot) { 72701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov if (theRoot == null) { 73701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov throw new NullPointerException("Root class must be provided."); 74701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov } else 75701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov return theRoot; 76701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov } 77701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov 78701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov public Constructor(TypeDescription theRoot) { 799629be70863521bead138c295351f3dec926ab1Andrey Somov if (theRoot == null) { 809629be70863521bead138c295351f3dec926ab1Andrey Somov throw new NullPointerException("Root type must be provided."); 819629be70863521bead138c295351f3dec926ab1Andrey Somov } 82b2ec508da00f4ce0ca420aff9e99ab6b68d7457eAndrey Somov this.yamlConstructors.put(null, new ConstructYamlObject()); 83701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov if (!Object.class.equals(theRoot.getType())) { 84701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov rootTag = new Tag(theRoot.getType()); 85979636c0ebbe94a0d6e3a06218e2368bb44b2802Andrey Somov } 861fa9989515d2c8fc77d5c7b363d735efd7e443cfAndrey Somov typeTags = new HashMap<Tag, Class<? extends Object>>(); 879629be70863521bead138c295351f3dec926ab1Andrey Somov typeDefinitions = new HashMap<Class<? extends Object>, TypeDescription>(); 88cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov yamlClassConstructors.put(NodeId.scalar, new ConstructScalar()); 89cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov yamlClassConstructors.put(NodeId.mapping, new ConstructMapping()); 90cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov yamlClassConstructors.put(NodeId.sequence, new ConstructSequence()); 91701d55e6c01ee5f4276a0ebcc4d78904619b8595Andrey Somov addTypeDescription(theRoot); 929629be70863521bead138c295351f3dec926ab1Andrey Somov } 939629be70863521bead138c295351f3dec926ab1Andrey Somov 949629be70863521bead138c295351f3dec926ab1Andrey Somov /** 959629be70863521bead138c295351f3dec926ab1Andrey Somov * Create Constructor for a class which does not have to be in the classpath 969629be70863521bead138c295351f3dec926ab1Andrey Somov * or for a definition from a Spring ApplicationContext. 979629be70863521bead138c295351f3dec926ab1Andrey Somov * 989629be70863521bead138c295351f3dec926ab1Andrey Somov * @param theRoot 99ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov * fully qualified class name of the root class (usually 100ae99b743010c3330b8bf850cdd56fdbcd8b67a82Andrey Somov * JavaBean) 1019629be70863521bead138c295351f3dec926ab1Andrey Somov * @throws ClassNotFoundException 1029629be70863521bead138c295351f3dec926ab1Andrey Somov */ 1039629be70863521bead138c295351f3dec926ab1Andrey Somov public Constructor(String theRoot) throws ClassNotFoundException { 1049629be70863521bead138c295351f3dec926ab1Andrey Somov this(Class.forName(check(theRoot))); 1059629be70863521bead138c295351f3dec926ab1Andrey Somov } 1069629be70863521bead138c295351f3dec926ab1Andrey Somov 1079629be70863521bead138c295351f3dec926ab1Andrey Somov private static final String check(String s) { 1089629be70863521bead138c295351f3dec926ab1Andrey Somov if (s == null) { 1099629be70863521bead138c295351f3dec926ab1Andrey Somov throw new NullPointerException("Root type must be provided."); 1109629be70863521bead138c295351f3dec926ab1Andrey Somov } 1119629be70863521bead138c295351f3dec926ab1Andrey Somov if (s.trim().length() == 0) { 1129629be70863521bead138c295351f3dec926ab1Andrey Somov throw new YAMLException("Root type must be provided."); 1139629be70863521bead138c295351f3dec926ab1Andrey Somov } 1149629be70863521bead138c295351f3dec926ab1Andrey Somov return s; 1159629be70863521bead138c295351f3dec926ab1Andrey Somov } 1169629be70863521bead138c295351f3dec926ab1Andrey Somov 1179629be70863521bead138c295351f3dec926ab1Andrey Somov /** 1189629be70863521bead138c295351f3dec926ab1Andrey Somov * Make YAML aware how to parse a custom Class. If there is no root Class 1199629be70863521bead138c295351f3dec926ab1Andrey Somov * assigned in constructor then the 'root' property of this definition is 1209629be70863521bead138c295351f3dec926ab1Andrey Somov * respected. 1219629be70863521bead138c295351f3dec926ab1Andrey Somov * 1229629be70863521bead138c295351f3dec926ab1Andrey Somov * @param definition 1239629be70863521bead138c295351f3dec926ab1Andrey Somov * to be added to the Constructor 1249629be70863521bead138c295351f3dec926ab1Andrey Somov * @return the previous value associated with <tt>definition</tt>, or 1259629be70863521bead138c295351f3dec926ab1Andrey Somov * <tt>null</tt> if there was no mapping for <tt>definition</tt>. 1269629be70863521bead138c295351f3dec926ab1Andrey Somov */ 1279629be70863521bead138c295351f3dec926ab1Andrey Somov public TypeDescription addTypeDescription(TypeDescription definition) { 1289629be70863521bead138c295351f3dec926ab1Andrey Somov if (definition == null) { 1299629be70863521bead138c295351f3dec926ab1Andrey Somov throw new NullPointerException("TypeDescription is required."); 1309629be70863521bead138c295351f3dec926ab1Andrey Somov } 1311fa9989515d2c8fc77d5c7b363d735efd7e443cfAndrey Somov Tag tag = definition.getTag(); 1329629be70863521bead138c295351f3dec926ab1Andrey Somov typeTags.put(tag, definition.getType()); 1339629be70863521bead138c295351f3dec926ab1Andrey Somov return typeDefinitions.put(definition.getType(), definition); 1349629be70863521bead138c295351f3dec926ab1Andrey Somov } 1359629be70863521bead138c295351f3dec926ab1Andrey Somov 136cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov /** 137cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov * Construct mapping instance (Map, JavaBean) when the runtime class is 138903025b9188a49d214131ba4fdb2bc49a1bcc317Andrey Somov * known. 139cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov */ 140903025b9188a49d214131ba4fdb2bc49a1bcc317Andrey Somov protected class ConstructMapping implements Construct { 1419ab17c02ff6c2127ac57aab7a26505240ff41b07Andrey Somov 142ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov /** 143ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * Construct JavaBean. If type safe collections are used please look at 144ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * <code>TypeDescription</code>. 145ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * 146ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * @param node 147ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * node where the keys are property names (they can only be 148ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * <code>String</code>s) and values are objects to be created 149ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * @return constructed JavaBean 150ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov */ 1519629be70863521bead138c295351f3dec926ab1Andrey Somov public Object construct(Node node) { 152ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov MappingNode mnode = (MappingNode) node; 153cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov if (Properties.class.isAssignableFrom(node.getType())) { 154cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov Properties properties = new Properties(); 155cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov if (!node.isTwoStepsConstruction()) { 15672f4f1885f1ff089d9b593d159e6ec3651ba7182maslovalex constructMapping2ndStep(mnode, properties); 157cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov } else { 158cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov throw new YAMLException("Properties must not be recursive."); 159cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov } 160cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov return properties; 161cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov } else if (SortedMap.class.isAssignableFrom(node.getType())) { 162cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov SortedMap<Object, Object> map = new TreeMap<Object, Object>(); 163cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov if (!node.isTwoStepsConstruction()) { 164cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov constructMapping2ndStep(mnode, map); 165cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov } 166cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov return map; 167cf48aa042c0255c41b3f8fec801163af06f3061eAndrey Somov } else if (Map.class.isAssignableFrom(node.getType())) { 1689506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov if (node.isTwoStepsConstruction()) { 169ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return createDefaultMap(); 1709506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov } else { 1716a14494b7d3eb2945af24b151cbd87e6c33d1b17Andrey Somov return constructMapping(mnode); 1729506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov } 173f88e848a4d49bd347840dce4b43573aec8fe74e3Andrey Somov } else if (SortedSet.class.isAssignableFrom(node.getType())) { 174f88e848a4d49bd347840dce4b43573aec8fe74e3Andrey Somov SortedSet<Object> set = new TreeSet<Object>(); 175c7b07c668a6c86ddd0890d24a89f6531bc8d17b3Andrey Somov // XXX why this is not used ? 176c7b07c668a6c86ddd0890d24a89f6531bc8d17b3Andrey Somov // if (!node.isTwoStepsConstruction()) { 177f532df6caa89678542a21a22a0b0a9e3638a37ccAndrey Somov constructSet2ndStep(mnode, set); 178c7b07c668a6c86ddd0890d24a89f6531bc8d17b3Andrey Somov // } 179f88e848a4d49bd347840dce4b43573aec8fe74e3Andrey Somov return set; 18025b326160d3a4ec112768f32ae44250e4897eceaAndrey Somov } else if (Collection.class.isAssignableFrom(node.getType())) { 1819506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov if (node.isTwoStepsConstruction()) { 182ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return createDefaultSet(); 1839506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov } else { 1846a14494b7d3eb2945af24b151cbd87e6c33d1b17Andrey Somov return constructSet(mnode); 1859506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov } 1869629be70863521bead138c295351f3dec926ab1Andrey Somov } else { 1871db5c999dfee2026c058a4df2e85edcede7b9d86Andrey Somov if (node.isTwoStepsConstruction()) { 188ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return createEmptyJavaBean(mnode); 189377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov } else { 190ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return constructJavaBean2ndStep(mnode, createEmptyJavaBean(mnode)); 191377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov } 1929629be70863521bead138c295351f3dec926ab1Andrey Somov } 1939629be70863521bead138c295351f3dec926ab1Andrey Somov } 1949629be70863521bead138c295351f3dec926ab1Andrey Somov 195ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov @SuppressWarnings("unchecked") 196ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov public void construct2ndStep(Node node, Object object) { 197ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (Map.class.isAssignableFrom(node.getType())) { 198ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov constructMapping2ndStep((MappingNode) node, (Map<Object, Object>) object); 199ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else if (Set.class.isAssignableFrom(node.getType())) { 200ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov constructSet2ndStep((MappingNode) node, (Set<Object>) object); 201ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else { 202ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov constructJavaBean2ndStep((MappingNode) node, object); 203ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 204c6d9f4f6d5613d347e5c8f1a54ec759d50690e16Andrey Somov } 205ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov 2068f6ec8c2337c1c83e27059d34a05295d3e93de23Andrey Somov protected Object createEmptyJavaBean(MappingNode node) { 207ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov try { 208ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov /** 209ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * Using only default constructor. Everything else will be 210ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * initialized on 2nd step. If we do here some partial 211ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * initialization, how do we then track what need to be done on 212ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * 2nd step? I think it is better to get only object here (to 213ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * have it as reference for recursion) and do all other thing on 214ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * 2nd step. 215ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov */ 21687bde16e30ef24e63364ac981b1a598d5f971737maslovalex java.lang.reflect.Constructor<?> c = node.getType().getDeclaredConstructor(); 21787bde16e30ef24e63364ac981b1a598d5f971737maslovalex c.setAccessible(true); 21887bde16e30ef24e63364ac981b1a598d5f971737maslovalex return c.newInstance(); 21987bde16e30ef24e63364ac981b1a598d5f971737maslovalex } catch (Exception e) { 220ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov throw new YAMLException(e); 221ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 222ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 223ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov 2248f6ec8c2337c1c83e27059d34a05295d3e93de23Andrey Somov protected Object constructJavaBean2ndStep(MappingNode node, Object object) { 22572f4f1885f1ff089d9b593d159e6ec3651ba7182maslovalex flattenMapping(node); 226ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Class<? extends Object> beanType = node.getType(); 22772f4f1885f1ff089d9b593d159e6ec3651ba7182maslovalex List<NodeTuple> nodeValue = node.getValue(); 228ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov for (NodeTuple tuple : nodeValue) { 229ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov ScalarNode keyNode; 230ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (tuple.getKeyNode() instanceof ScalarNode) { 231ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov // key must be scalar 232ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov keyNode = (ScalarNode) tuple.getKeyNode(); 233377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov } else { 234ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov throw new YAMLException("Keys must be scalars but found: " + tuple.getKeyNode()); 235ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 236ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Node valueNode = tuple.getValueNode(); 237ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov // keys can only be Strings 238ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov keyNode.setType(String.class); 239ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov String key = (String) constructObject(keyNode); 240ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov try { 241ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Property property = getProperty(beanType, key); 242ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov valueNode.setType(property.getType()); 243ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov TypeDescription memberDescription = typeDefinitions.get(beanType); 244e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov boolean typeDetected = false; 245ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (memberDescription != null) { 246ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov switch (valueNode.getNodeId()) { 247ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov case sequence: 248ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov SequenceNode snode = (SequenceNode) valueNode; 249ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Class<? extends Object> memberType = memberDescription 250ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov .getListPropertyType(key); 251ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (memberType != null) { 252ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov snode.setListType(memberType); 253e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov typeDetected = true; 254ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else if (property.getType().isArray()) { 255ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov snode.setListType(property.getType().getComponentType()); 256e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov typeDetected = true; 257ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 258ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov break; 259ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov case mapping: 260ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov MappingNode mnode = (MappingNode) valueNode; 261ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Class<? extends Object> keyType = memberDescription.getMapKeyType(key); 262ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (keyType != null) { 2635e819b5115ddc5c432fac860440b48f34bac3200maslovalex mnode.setTypes(keyType, memberDescription.getMapValueType(key)); 264e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov typeDetected = true; 265ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 266ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov break; 26734f59d77fd0a29b085d4c642eb1db6b8925fc3c3Andrey Somov default: // scalar 268ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 269ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 270a9de7ef39a1f086be052dfcc75ad671078c5a8a4Andrey Somov if (!typeDetected && valueNode.getNodeId() != NodeId.scalar) { 271e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov // only if there is no explicit TypeDescription 272e85d52ba83eb6cb37dc1bf71e7c4f8c2a5d71670Andrey Somov Class<?>[] arguments = property.getActualTypeArguments(); 27388c1e8787f0d72fdfea3a3315c4cc95d8f1c11adAndrey Somov if (arguments != null && arguments.length > 0) { 274a9de7ef39a1f086be052dfcc75ad671078c5a8a4Andrey Somov // type safe (generic) collection may contain the 275a9de7ef39a1f086be052dfcc75ad671078c5a8a4Andrey Somov // proper class 276a9de7ef39a1f086be052dfcc75ad671078c5a8a4Andrey Somov if (valueNode.getNodeId() == NodeId.sequence) { 27701f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?> t = arguments[0]; 278e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov SequenceNode snode = (SequenceNode) valueNode; 279e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov snode.setListType(t); 28087ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov } else if (valueNode.getTag().equals(Tag.SET)) { 28101f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?> t = arguments[0]; 282e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov MappingNode mnode = (MappingNode) valueNode; 2835e819b5115ddc5c432fac860440b48f34bac3200maslovalex mnode.setOnlyKeyType(t); 284e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov mnode.setUseClassConstructor(true); 28501f469ecf699181a0799cfed097b6021db0777c4Andrey Somov } else if (property.getType().isAssignableFrom(Map.class)) { 28601f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?> ketType = arguments[0]; 28701f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?> valueType = arguments[1]; 288a9de7ef39a1f086be052dfcc75ad671078c5a8a4Andrey Somov MappingNode mnode = (MappingNode) valueNode; 2895e819b5115ddc5c432fac860440b48f34bac3200maslovalex mnode.setTypes(ketType, valueType); 290a9de7ef39a1f086be052dfcc75ad671078c5a8a4Andrey Somov mnode.setUseClassConstructor(true); 291e85d52ba83eb6cb37dc1bf71e7c4f8c2a5d71670Andrey Somov } else { 292fd906b76dd780bc2271da9f597b4cf2793d630acAndrey Somov // the type for collection entries cannot be 293fd906b76dd780bc2271da9f597b4cf2793d630acAndrey Somov // detected 294e82ce6dd9dc482001bc5bc9fb9494f53da0449e9Andrey Somov } 295f88e848a4d49bd347840dce4b43573aec8fe74e3Andrey Somov } 2968caea31160c72bce4181ed38b16f850e06d29a14Andrey Somov } 2978c0d5ed989759b2e9c903928fd09cf3964e15d6aAndrey Somov 298ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Object value = constructObject(valueNode); 299615d3719f75e5aad70d1598ef160123705008216Andrey Somov // Correct when the property expects float but double was 300615d3719f75e5aad70d1598ef160123705008216Andrey Somov // constructed 3018c0d5ed989759b2e9c903928fd09cf3964e15d6aAndrey Somov if (property.getType() == Float.TYPE || property.getType() == Float.class) { 3028c0d5ed989759b2e9c903928fd09cf3964e15d6aAndrey Somov if (value instanceof Double) { 3038c0d5ed989759b2e9c903928fd09cf3964e15d6aAndrey Somov value = ((Double) value).floatValue(); 3048c0d5ed989759b2e9c903928fd09cf3964e15d6aAndrey Somov } 3058c0d5ed989759b2e9c903928fd09cf3964e15d6aAndrey Somov } 3060fca80757efbb4219edb6a0173e4f6365c8903f9Andrey Somov // Correct when the property a String but the value is binary 3070fca80757efbb4219edb6a0173e4f6365c8903f9Andrey Somov if (property.getType() == String.class && Tag.BINARY.equals(valueNode.getTag()) && value instanceof byte[]) { 3080fca80757efbb4219edb6a0173e4f6365c8903f9Andrey Somov value = new String((byte[])value); 3090fca80757efbb4219edb6a0173e4f6365c8903f9Andrey Somov } 3109b3d9d765773e00ad481ac2d5e89eab32ae68ea1Andrey Somov 311ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov property.set(object, value); 312ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } catch (Exception e) { 31386516d77409b9a2e61c82a28d1ffaf52eaf03837Andrey Somov throw new ConstructorException("Cannot create property=" + key 31486516d77409b9a2e61c82a28d1ffaf52eaf03837Andrey Somov + " for JavaBean=" + object, node.getStartMark(), e.getMessage(), 31586516d77409b9a2e61c82a28d1ffaf52eaf03837Andrey Somov valueNode.getStartMark(), e); 316ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 317ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 318ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return object; 319ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 320ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov 3218f6ec8c2337c1c83e27059d34a05295d3e93de23Andrey Somov protected Property getProperty(Class<? extends Object> type, String name) 322ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov throws IntrospectionException { 32387bde16e30ef24e63364ac981b1a598d5f971737maslovalex return getPropertyUtils().getProperty(type, name); 324ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 325ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 326ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov 327cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov /** 328cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov * Construct an instance when the runtime class is not known but a global 329cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov * tag with a class name is defined. It delegates the construction to the 330cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov * appropriate constructor based on the node kind (scalar, sequence, 331903025b9188a49d214131ba4fdb2bc49a1bcc317Andrey Somov * mapping) 332cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov */ 333903025b9188a49d214131ba4fdb2bc49a1bcc317Andrey Somov protected class ConstructYamlObject implements Construct { 33443eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov 33543eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov private Construct getConstructor(Node node) { 33601f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?> cl = getClassForNode(node); 33743eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov node.setType(cl); 33843eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov // call the constructor as if the runtime class is defined 33943eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov Construct constructor = yamlClassConstructors.get(node.getNodeId()); 34043eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov return constructor; 34143eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov } 34243eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov 343ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov public Object construct(Node node) { 344ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Object result = null; 345ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov try { 34643eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov result = getConstructor(node).construct(node); 34786516d77409b9a2e61c82a28d1ffaf52eaf03837Andrey Somov } catch (ConstructorException e) { 34886516d77409b9a2e61c82a28d1ffaf52eaf03837Andrey Somov throw e; 349ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } catch (Exception e) { 350ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov throw new ConstructorException(null, null, "Can't construct a java object for " 351ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov + node.getTag() + "; exception=" + e.getMessage(), node.getStartMark(), e); 352ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 353ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return result; 354377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov } 35543eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov 35643eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov public void construct2ndStep(Node node, Object object) { 35743eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov try { 35843eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov getConstructor(node).construct2ndStep(node, object); 35943eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov } catch (Exception e) { 36043eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov throw new ConstructorException(null, null, 36143eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov "Can't construct a second step for a java object for " + node.getTag() 36243eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov + "; exception=" + e.getMessage(), node.getStartMark(), e); 36343eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov } 36443eb6e5f495f9fd150d86caf033deaa47549ffa6Andrey Somov } 3651db5c999dfee2026c058a4df2e85edcede7b9d86Andrey Somov } 366377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov 367ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov /** 368ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * Construct scalar instance when the runtime class is known. Recursive 369ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov * structures are not supported. 370ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov */ 371ccc3b9a3ce0c926a9b13c0e4244dcce87aeaa21bAndrey Somov protected class ConstructScalar extends AbstractConstruct { 372ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov public Object construct(Node nnode) { 373ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov ScalarNode node = (ScalarNode) nnode; 37401f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?> type = node.getType(); 375ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Object result; 376ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (type.isPrimitive() || type == String.class || Number.class.isAssignableFrom(type) 377ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov || type == Boolean.class || Date.class.isAssignableFrom(type) 378ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov || type == Character.class || type == BigInteger.class 37984e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov || type == BigDecimal.class || Enum.class.isAssignableFrom(type) 380ebe7279d7a16518cd05078e24ce240af52c8597eAndrey Somov || Tag.BINARY.equals(node.getTag()) || Calendar.class.isAssignableFrom(type) || type == UUID.class) { 381ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov // standard classes created directly 382ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov result = constructStandardJavaInstance(type, node); 383ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else { 384ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov // there must be only 1 constructor with 1 argument 385d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex java.lang.reflect.Constructor<?>[] javaConstructors = type 386d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex .getDeclaredConstructors(); 387d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov int oneArgCount = 0; 38801f469ecf699181a0799cfed097b6021db0777c4Andrey Somov java.lang.reflect.Constructor<?> javaConstructor = null; 38901f469ecf699181a0799cfed097b6021db0777c4Andrey Somov for (java.lang.reflect.Constructor<?> c : javaConstructors) { 390ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (c.getParameterTypes().length == 1) { 391d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov oneArgCount++; 392ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov javaConstructor = c; 393ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 394ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 395d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov Object argument; 396ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (javaConstructor == null) { 397ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov throw new YAMLException("No single argument constructor found for " + type); 398d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov } else if (oneArgCount == 1) { 399d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov argument = constructStandardJavaInstance( 400d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov javaConstructor.getParameterTypes()[0], node); 401ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else { 402d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov // TODO it should be possible to use implicit types instead 403d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov // of forcing String. Resolver must be available here to 404d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov // obtain the implicit tag. Then we can set the tag and call 405ab2e864982dc460583b287da179712eaadbbf409Andrey Somov // callConstructor(node) to create the argument instance. 406ab2e864982dc460583b287da179712eaadbbf409Andrey Somov // On the other hand it may be safer to require a custom 407ab2e864982dc460583b287da179712eaadbbf409Andrey Somov // constructor to avoid guessing the argument class 408d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov argument = constructScalar(node); 409ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov try { 410d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex javaConstructor = type.getDeclaredConstructor(String.class); 411ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } catch (Exception e) { 41229a5af489bbe2a14de867828fd12ba527fed342fAndrey Somov throw new YAMLException("Can't construct a java object for scalar " 41329a5af489bbe2a14de867828fd12ba527fed342fAndrey Somov + node.getTag() + "; No String constructor found. Exception=" 41429a5af489bbe2a14de867828fd12ba527fed342fAndrey Somov + e.getMessage(), e); 415ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 416ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 417d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov try { 418d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex javaConstructor.setAccessible(true); 419d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov result = javaConstructor.newInstance(argument); 420d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov } catch (Exception e) { 421d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov throw new ConstructorException(null, null, 422d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov "Can't construct a java object for scalar " + node.getTag() 423d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov + "; exception=" + e.getMessage(), node.getStartMark(), e); 424d9d317fef9a029bc281e6d39d8906d9415dd5396Andrey Somov } 425ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 426ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return result; 427ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 428ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov 429ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov @SuppressWarnings("unchecked") 430ddeae0b94884e98a832f12e1586c76d37e2e74f4Andrey Somov private Object constructStandardJavaInstance(@SuppressWarnings("rawtypes") 431ddeae0b94884e98a832f12e1586c76d37e2e74f4Andrey Somov Class type, ScalarNode node) { 432ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov Object result; 4339629be70863521bead138c295351f3dec926ab1Andrey Somov if (type == String.class) { 43487ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov Construct stringConstructor = yamlConstructors.get(Tag.STR); 43572f4f1885f1ff089d9b593d159e6ec3651ba7182maslovalex result = stringConstructor.construct(node); 4369629be70863521bead138c295351f3dec926ab1Andrey Somov } else if (type == Boolean.class || type == Boolean.TYPE) { 43787ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov Construct boolConstructor = yamlConstructors.get(Tag.BOOL); 43872f4f1885f1ff089d9b593d159e6ec3651ba7182maslovalex result = boolConstructor.construct(node); 4399629be70863521bead138c295351f3dec926ab1Andrey Somov } else if (type == Character.class || type == Character.TYPE) { 44087ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov Construct charConstructor = yamlConstructors.get(Tag.STR); 44172f4f1885f1ff089d9b593d159e6ec3651ba7182maslovalex String ch = (String) charConstructor.construct(node); 442ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (ch.length() == 0) { 443ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov result = null; 444ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else if (ch.length() != 1) { 4459629be70863521bead138c295351f3dec926ab1Andrey Somov throw new YAMLException("Invalid node Character: '" + ch + "'; length: " 4469629be70863521bead138c295351f3dec926ab1Andrey Somov + ch.length()); 447ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else { 44834f59d77fd0a29b085d4c642eb1db6b8925fc3c3Andrey Somov result = Character.valueOf(ch.charAt(0)); 4499629be70863521bead138c295351f3dec926ab1Andrey Somov } 450068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov } else if (Date.class.isAssignableFrom(type)) { 45187ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov Construct dateConstructor = yamlConstructors.get(Tag.TIMESTAMP); 45272f4f1885f1ff089d9b593d159e6ec3651ba7182maslovalex Date date = (Date) dateConstructor.construct(node); 453068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov if (type == Date.class) { 454068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov result = date; 455068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov } else { 456068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov try { 457068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov java.lang.reflect.Constructor<?> constr = type.getConstructor(long.class); 458068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov result = constr.newInstance(date.getTime()); 459d62b0618ab6e59c72fc5670e785163357f8fdda7Andrey Somov } catch (RuntimeException e) { 460d62b0618ab6e59c72fc5670e785163357f8fdda7Andrey Somov throw e; 461068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov } catch (Exception e) { 462583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somov throw new YAMLException("Cannot construct: '" + type + "'"); 463068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov } 464068685adad298fbfcbaa8f6606ec7aed7a678c79Andrey Somov } 4659629be70863521bead138c295351f3dec926ab1Andrey Somov } else if (type == Float.class || type == Double.class || type == Float.TYPE 466583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somov || type == Double.TYPE || type == BigDecimal.class) { 46784e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov if (type == BigDecimal.class) { 46884e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov result = new BigDecimal(node.getValue()); 46984e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov } else { 47087ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov Construct doubleConstructor = yamlConstructors.get(Tag.FLOAT); 47184e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov result = doubleConstructor.construct(node); 47284e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov if (type == Float.class || type == Float.TYPE) { 47384e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov result = new Float((Double) result); 47484e718ae12a709b34b5d5c2a2a9d4af2699c20cfAndrey Somov } 4759629be70863521bead138c295351f3dec926ab1Andrey Somov } 476583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somov } else if (type == Byte.class || type == Short.class || type == Integer.class 477583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somov || type == Long.class || type == BigInteger.class || type == Byte.TYPE 4789629be70863521bead138c295351f3dec926ab1Andrey Somov || type == Short.TYPE || type == Integer.TYPE || type == Long.TYPE) { 47987ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov Construct intConstructor = yamlConstructors.get(Tag.INT); 4800e5ab7057788fa02567cbdd03c33d5912cf0c389Andrey Somov result = intConstructor.construct(node); 4819629be70863521bead138c295351f3dec926ab1Andrey Somov if (type == Byte.class || type == Byte.TYPE) { 482d62b0618ab6e59c72fc5670e785163357f8fdda7Andrey Somov result = Byte.valueOf(result.toString()); 4839629be70863521bead138c295351f3dec926ab1Andrey Somov } else if (type == Short.class || type == Short.TYPE) { 484d62b0618ab6e59c72fc5670e785163357f8fdda7Andrey Somov result = Short.valueOf(result.toString()); 4859629be70863521bead138c295351f3dec926ab1Andrey Somov } else if (type == Integer.class || type == Integer.TYPE) { 48634f59d77fd0a29b085d4c642eb1db6b8925fc3c3Andrey Somov result = Integer.parseInt(result.toString()); 4879629be70863521bead138c295351f3dec926ab1Andrey Somov } else if (type == Long.class || type == Long.TYPE) { 488d62b0618ab6e59c72fc5670e785163357f8fdda7Andrey Somov result = Long.valueOf(result.toString()); 4899629be70863521bead138c295351f3dec926ab1Andrey Somov } else { 490583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somov // only BigInteger left 491583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somov result = new BigInteger(result.toString()); 4929629be70863521bead138c295351f3dec926ab1Andrey Somov } 4939629be70863521bead138c295351f3dec926ab1Andrey Somov } else if (Enum.class.isAssignableFrom(type)) { 494ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov String enumValueName = node.getValue(); 495ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov try { 496ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov result = Enum.valueOf(type, enumValueName); 497ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } catch (Exception ex) { 498ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov throw new YAMLException("Unable to find enum value '" + enumValueName 499ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov + "' for enum class: " + type.getName()); 500ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } 501b4779f9a8e0eaf921e4838fc9c68b8e9c0be963cAndrey Somov } else if (Calendar.class.isAssignableFrom(type)) { 502b4779f9a8e0eaf921e4838fc9c68b8e9c0be963cAndrey Somov ConstructYamlTimestamp contr = new ConstructYamlTimestamp(); 503b4779f9a8e0eaf921e4838fc9c68b8e9c0be963cAndrey Somov contr.construct(node); 504b4779f9a8e0eaf921e4838fc9c68b8e9c0be963cAndrey Somov result = contr.getCalendar(); 5058723ed34a3d556a43b418bb2e39bc7458386afc5Andrey Somov } else if (Number.class.isAssignableFrom(type)) { 5068723ed34a3d556a43b418bb2e39bc7458386afc5Andrey Somov ConstructYamlNumber contr = new ConstructYamlNumber(); 5078723ed34a3d556a43b418bb2e39bc7458386afc5Andrey Somov result = contr.construct(node); 508ebe7279d7a16518cd05078e24ce240af52c8597eAndrey Somov } else if (UUID.class == type) { 509ebe7279d7a16518cd05078e24ce240af52c8597eAndrey Somov result = UUID.fromString(node.getValue()); 5109629be70863521bead138c295351f3dec926ab1Andrey Somov } else { 511d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex if (yamlConstructors.containsKey(node.getTag())) { 512d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex result = yamlConstructors.get(node.getTag()).construct(node); 513d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex } else { 514d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex throw new YAMLException("Unsupported class: " + type); 515d187b365cd221bc347354518a5582f4f37b2f68cmaslovalex } 5169629be70863521bead138c295351f3dec926ab1Andrey Somov } 517ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return result; 518377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov } 519377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov } 520377e2ff253ffd47c072a2cd057d3aa0fa8f27616Andrey Somov 521cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov /** 522cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov * Construct sequence (List, Array, or immutable object) when the runtime 523903025b9188a49d214131ba4fdb2bc49a1bcc317Andrey Somov * class is known. 524cc370ac444192e2693a98749996f4eeb5a03f0ebAndrey Somov */ 525903025b9188a49d214131ba4fdb2bc49a1bcc317Andrey Somov protected class ConstructSequence implements Construct { 526ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov @SuppressWarnings("unchecked") 527ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov public Object construct(Node node) { 528ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov SequenceNode snode = (SequenceNode) node; 52942220bac2e8060b1eaac221cf931ecf52165047cAndrey Somov if (Set.class.isAssignableFrom(node.getType())) { 53042220bac2e8060b1eaac221cf931ecf52165047cAndrey Somov if (node.isTwoStepsConstruction()) { 531f532df6caa89678542a21a22a0b0a9e3638a37ccAndrey Somov throw new YAMLException("Set cannot be recursive."); 53242220bac2e8060b1eaac221cf931ecf52165047cAndrey Somov } else { 53342220bac2e8060b1eaac221cf931ecf52165047cAndrey Somov return constructSet(snode); 53442220bac2e8060b1eaac221cf931ecf52165047cAndrey Somov } 53542220bac2e8060b1eaac221cf931ecf52165047cAndrey Somov } else if (Collection.class.isAssignableFrom(node.getType())) { 536ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov if (node.isTwoStepsConstruction()) { 537ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return createDefaultList(snode.getValue().size()); 538ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else { 539ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov return constructSequence(snode); 5409629be70863521bead138c295351f3dec926ab1Andrey Somov } 5414cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex } else if (node.getType().isArray()) { 5424cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex if (node.isTwoStepsConstruction()) { 5434cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex return createArray(node.getType(), snode.getValue().size()); 5444cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex } else { 5454cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex return constructArray(snode); 5464cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex } 547ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov } else { 548ae63c4043d331c5d538d75b9c797268d5e561f97Andrey Somov // create immutable object 54901f469ecf699181a0799cfed097b6021db0777c4Andrey Somov List<java.lang.reflect.Constructor<?>> possibleConstructors = new ArrayList<java.lang.reflect.Constructor<?>>( 550c084ec7a5d61af0edce644cd1ec400a8df838f4cAndrey Somov snode.getValue().size()); 55158dcb8e34c17d0174c4ec2e5587f570d86d6ae12maslovalex for (java.lang.reflect.Constructor<?> constructor : node 55258dcb8e34c17d0174c4ec2e5587f570d86d6ae12maslovalex .getType().getDeclaredConstructors()) { 55358dcb8e34c17d0174c4ec2e5587f570d86d6ae12maslovalex if (snode.getValue() 55458dcb8e34c17d0174c4ec2e5587f570d86d6ae12maslovalex .size() == constructor.getParameterTypes().length) { 555050c422c295a0ff956f79ba91c4c5a21b255f721Andrey Somov possibleConstructors.add(constructor); 556050c422c295a0ff956f79ba91c4c5a21b255f721Andrey Somov } 557050c422c295a0ff956f79ba91c4c5a21b255f721Andrey Somov } 5586db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (!possibleConstructors.isEmpty()) { 5596db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (possibleConstructors.size() == 1) { 5606db1cdfea180251646dc68924ed2f18339f9d984maslovalex Object[] argumentList = new Object[snode.getValue().size()]; 56101f469ecf699181a0799cfed097b6021db0777c4Andrey Somov java.lang.reflect.Constructor<?> c = possibleConstructors.get(0); 5626db1cdfea180251646dc68924ed2f18339f9d984maslovalex int index = 0; 5636db1cdfea180251646dc68924ed2f18339f9d984maslovalex for (Node argumentNode : snode.getValue()) { 56401f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?> type = c.getParameterTypes()[index]; 5656db1cdfea180251646dc68924ed2f18339f9d984maslovalex // set runtime classes for arguments 5666db1cdfea180251646dc68924ed2f18339f9d984maslovalex argumentNode.setType(type); 5676db1cdfea180251646dc68924ed2f18339f9d984maslovalex argumentList[index++] = constructObject(argumentNode); 5686db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 5696db1cdfea180251646dc68924ed2f18339f9d984maslovalex 5706db1cdfea180251646dc68924ed2f18339f9d984maslovalex try { 57158dcb8e34c17d0174c4ec2e5587f570d86d6ae12maslovalex c.setAccessible(true); 5726db1cdfea180251646dc68924ed2f18339f9d984maslovalex return c.newInstance(argumentList); 5736db1cdfea180251646dc68924ed2f18339f9d984maslovalex } catch (Exception e) { 5746db1cdfea180251646dc68924ed2f18339f9d984maslovalex throw new YAMLException(e); 5756db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 5766db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 5776db1cdfea180251646dc68924ed2f18339f9d984maslovalex 5786db1cdfea180251646dc68924ed2f18339f9d984maslovalex // use BaseConstructor 5796db1cdfea180251646dc68924ed2f18339f9d984maslovalex List<Object> argumentList = (List<Object>) constructSequence(snode); 58001f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?>[] parameterTypes = new Class[argumentList.size()]; 581050c422c295a0ff956f79ba91c4c5a21b255f721Andrey Somov int index = 0; 5826db1cdfea180251646dc68924ed2f18339f9d984maslovalex for (Object parameter : argumentList) { 5836db1cdfea180251646dc68924ed2f18339f9d984maslovalex parameterTypes[index] = parameter.getClass(); 584050c422c295a0ff956f79ba91c4c5a21b255f721Andrey Somov index++; 585050c422c295a0ff956f79ba91c4c5a21b255f721Andrey Somov } 5866db1cdfea180251646dc68924ed2f18339f9d984maslovalex 58701f469ecf699181a0799cfed097b6021db0777c4Andrey Somov for (java.lang.reflect.Constructor<?> c : possibleConstructors) { 58801f469ecf699181a0799cfed097b6021db0777c4Andrey Somov Class<?>[] argTypes = c.getParameterTypes(); 5896db1cdfea180251646dc68924ed2f18339f9d984maslovalex boolean foundConstructor = true; 5906db1cdfea180251646dc68924ed2f18339f9d984maslovalex for (int i = 0; i < argTypes.length; i++) { 5916db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (!wrapIfPrimitive(argTypes[i]).isAssignableFrom(parameterTypes[i])) { 5926db1cdfea180251646dc68924ed2f18339f9d984maslovalex foundConstructor = false; 5936db1cdfea180251646dc68924ed2f18339f9d984maslovalex break; 5946db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 5956db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 5966db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (foundConstructor) { 5976db1cdfea180251646dc68924ed2f18339f9d984maslovalex try { 59858dcb8e34c17d0174c4ec2e5587f570d86d6ae12maslovalex c.setAccessible(true); 5996db1cdfea180251646dc68924ed2f18339f9d984maslovalex return c.newInstance(argumentList.toArray()); 6006db1cdfea180251646dc68924ed2f18339f9d984maslovalex } catch (Exception e) { 6016db1cdfea180251646dc68924ed2f18339f9d984maslovalex throw new YAMLException(e); 6026db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6036db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6046db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 605583bd9a0e9fedbe9dffb6bee8183b06be204b15eAndrey Somov } 6065aa0441307ecee16c9d80ce2b5b8aff4c23091b3Andrey Somov throw new YAMLException("No suitable constructor with " 6076db1cdfea180251646dc68924ed2f18339f9d984maslovalex + String.valueOf(snode.getValue().size()) + " arguments found for " 6086db1cdfea180251646dc68924ed2f18339f9d984maslovalex + node.getType()); 6096db1cdfea180251646dc68924ed2f18339f9d984maslovalex 6106db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6116db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6126db1cdfea180251646dc68924ed2f18339f9d984maslovalex 6136db1cdfea180251646dc68924ed2f18339f9d984maslovalex private final Class<? extends Object> wrapIfPrimitive(Class<?> clazz) { 6146db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (!clazz.isPrimitive()) { 6156db1cdfea180251646dc68924ed2f18339f9d984maslovalex return clazz; 6166db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6176db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (clazz == Integer.TYPE) { 6186db1cdfea180251646dc68924ed2f18339f9d984maslovalex return Integer.class; 6196db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6206db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (clazz == Float.TYPE) { 6216db1cdfea180251646dc68924ed2f18339f9d984maslovalex return Float.class; 6226db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6236db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (clazz == Double.TYPE) { 6246db1cdfea180251646dc68924ed2f18339f9d984maslovalex return Double.class; 6256db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6266db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (clazz == Boolean.TYPE) { 6276db1cdfea180251646dc68924ed2f18339f9d984maslovalex return Boolean.class; 6286db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 629eb1c68f2396b6da521f4ae5778e845aade5bff1dAndrey Somov if (clazz == Long.TYPE) { 630eb1c68f2396b6da521f4ae5778e845aade5bff1dAndrey Somov return Long.class; 631eb1c68f2396b6da521f4ae5778e845aade5bff1dAndrey Somov } 6326db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (clazz == Character.TYPE) { 6336db1cdfea180251646dc68924ed2f18339f9d984maslovalex return Character.class; 6346db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6356db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (clazz == Short.TYPE) { 6366db1cdfea180251646dc68924ed2f18339f9d984maslovalex return Short.class; 6376db1cdfea180251646dc68924ed2f18339f9d984maslovalex } 6386db1cdfea180251646dc68924ed2f18339f9d984maslovalex if (clazz == Byte.TYPE) { 6396db1cdfea180251646dc68924ed2f18339f9d984maslovalex return Byte.class; 6409629be70863521bead138c295351f3dec926ab1Andrey Somov } 641eb1c68f2396b6da521f4ae5778e845aade5bff1dAndrey Somov throw new YAMLException("Unexpected primitive " + clazz); 6429629be70863521bead138c295351f3dec926ab1Andrey Somov } 643686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov 644686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov @SuppressWarnings("unchecked") 645686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov public void construct2ndStep(Node node, Object object) { 646686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov SequenceNode snode = (SequenceNode) node; 6474cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex if (List.class.isAssignableFrom(node.getType())) { 6484cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex List<Object> list = (List<Object>) object; 649686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov constructSequenceStep2(snode, list); 6504cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex } else if (node.getType().isArray()) { 6514cdfade09a608d4e09cdae6531fefe33048b685bmaslovalex constructArrayStep2(snode, object); 652686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov } else { 653050c422c295a0ff956f79ba91c4c5a21b255f721Andrey Somov throw new YAMLException("Immutable objects cannot be recursive."); 654686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov } 655686d75fdde8a24dbe13646c3693f27776cd23831Andrey Somov } 6569629be70863521bead138c295351f3dec926ab1Andrey Somov } 6579506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov 658b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov protected Class<?> getClassForNode(Node node) { 659b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov Class<? extends Object> classForTag = typeTags.get(node.getTag()); 660b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov if (classForTag == null) { 66187ff57908e8ccf62ef984bb067a61b815a9a1074Andrey Somov String name = node.getTag().getClassName(); 662b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov Class<?> cl; 663b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov try { 664db93e7b6ba4a6f93289325e236d278a510a59e47Andrey Somov cl = getClassForName(name); 665b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov } catch (ClassNotFoundException e) { 666b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov throw new YAMLException("Class not found: " + name); 667b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov } 6681fa9989515d2c8fc77d5c7b363d735efd7e443cfAndrey Somov typeTags.put(node.getTag(), cl); 6699506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov return cl; 6709506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov } else { 671b5cbc4593dc009a3aa856bd70d5d1584609b8b8bAndrey Somov return classForTag; 6729506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov } 6739506e323ef3bd1554a138c978b8523e6831775bbAndrey Somov } 674db93e7b6ba4a6f93289325e236d278a510a59e47Andrey Somov 675db93e7b6ba4a6f93289325e236d278a510a59e47Andrey Somov protected Class<?> getClassForName(String name) throws ClassNotFoundException { 67651cc2aaca608d78bfd8c546ca3de60057e5488cfmaslovalex try { 67751cc2aaca608d78bfd8c546ca3de60057e5488cfmaslovalex return Class.forName(name, true, Thread.currentThread().getContextClassLoader()); 67851cc2aaca608d78bfd8c546ca3de60057e5488cfmaslovalex } catch (ClassNotFoundException e) { 67951cc2aaca608d78bfd8c546ca3de60057e5488cfmaslovalex return Class.forName(name); 68051cc2aaca608d78bfd8c546ca3de60057e5488cfmaslovalex } 681db93e7b6ba4a6f93289325e236d278a510a59e47Andrey Somov } 6829629be70863521bead138c295351f3dec926ab1Andrey Somov} 683