/**
 * Copyright (c) 2008-2012, http://www.snakeyaml.org
 *
 * 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.
 */
package org.yaml.snakeyaml.issues.issue150;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.Reader;
import java.io.StringReader;
import java.util.List;
import java.util.regex.Pattern;

import org.junit.Before;
import org.junit.Test;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.AbstractConstruct;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;

public class YamlLoadAsIssueTest {

    private StringBuilder doc;

    @Before
    public void setUp() {
        doc = new StringBuilder();
        line("!car");
        line("plate: 12-XP-F4");
        line("wheels:");
        line("- w#1");
        line("- w#2");
        line("- w#3");
        line("- w#4");
    }

    private StringBuilder line(String text) {
        return doc.append(text).append('\n');
    }

    @Test
    public void loadConstructsDocumentCorrectly() {
        Yaml yaml = yaml();
        Object result = yaml.load(reader());
        assertNotNull(result);
        assertEquals(Car.class, result.getClass());
        assertEquals("12-XP-F4", ((Car) result).getPlate());
        assertEquals(4, ((Car) result).getWheels().size());
    }

    private Yaml yaml() {
        Yaml yaml = new Yaml(new MyConstructor());
        yaml.addImplicitResolver(new Tag("!wheel"), Pattern.compile("w#\\d+"), "w");
        return yaml;
    }

    @Test
    public void ignoreImplicitTag() {
        Yaml yaml = yaml();
        try {
            yaml.loadAs(reader(), Car.class);
            fail();
        } catch (Exception e) {
            assertTrue(e
                    .getMessage()
                    .startsWith(
                            "null; Can't construct a java object for tag:yaml.org,2002:org.yaml.snakeyaml.issues.issue150.Car; exception=Cannot create property=wheels for JavaBean=org.yaml.snakeyaml.issues.issue150.Car"));
        }
    }

    private Reader reader() {
        return new StringReader(doc.toString());
    }

    private class MyConstructor extends Constructor {
        public MyConstructor() {
            yamlConstructors.put(new Tag("!car"), new ConstructCar());
            yamlConstructors.put(new Tag("!wheel"), new ConstructWheel());
        }

        private String toScalarString(Node node) {
            return (String) constructScalar((ScalarNode) node);
        }

        private class ConstructCar extends AbstractConstruct {

            @SuppressWarnings("unchecked")
            public Car construct(Node node) {
                Car car = new Car();
                MappingNode mapping = (MappingNode) node;
                List<NodeTuple> list = mapping.getValue();
                for (NodeTuple tuple : list) {
                    String field = toScalarString(tuple.getKeyNode());
                    if ("plate".equals(field)) {
                        car.setPlate(toScalarString(tuple.getValueNode()));
                    }
                    if ("wheels".equals(field)) {
                        SequenceNode snode = (SequenceNode) tuple.getValueNode();
                        for (Node leafNode : snode.getValue()) {
                            leafNode.setTag(new Tag("!wheel"));
                        }
                        List<Wheel> wheels = (List<Wheel>) constructSequence(snode);
                        car.setWheels(wheels);
                    }
                }
                return car;
            }
        }

        private class ConstructWheel extends AbstractConstruct {

            public Wheel construct(Node node) {
                Wheel w = null;
                String strValue = toScalarString(node);
                if (strValue != null && strValue.length() > 2) {
                    strValue = strValue.trim().substring(2);
                    w = new Wheel();
                    w.setId(Integer.valueOf(strValue));
                }
                return w;
            }
        }
    }
}

@@ -4135,166 +4135,8 @@
 );%0D%0A
-                        for (Node leafNode : snode.getValue()) %7B%0D%0A                            leafNode.setTag(new Tag(%22!wheel%22));%0D%0A                        %7D%0D%0A
     

Update the test for issue 150