/*
 * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.yangtools.yang.data.impl.schema.transform.base;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UsesNode;

import com.google.common.base.Optional;
import com.google.common.collect.Maps;

/**
 * Proxy for AugmentationSchema. Child node schemas are replaced with actual schemas from parent.
 */
public final class AugmentationSchemaProxy implements AugmentationSchema {
    private final AugmentationSchema delegate;
    private final Set<DataSchemaNode> realChildSchemas;
    private final Map<QName, DataSchemaNode> mappedChildSchemas;

    public AugmentationSchemaProxy(final AugmentationSchema augmentSchema, final Set<DataSchemaNode> realChildSchemas) {
        this.delegate = augmentSchema;
        this.realChildSchemas = realChildSchemas;

        this.mappedChildSchemas = Maps.newHashMap();
        for (DataSchemaNode realChildSchema : realChildSchemas) {
            mappedChildSchemas.put(realChildSchema.getQName(), realChildSchema);
        }
    }

    @Override
    public RevisionAwareXPath getWhenCondition() {
        return delegate.getWhenCondition();
    }

    @Override
    public String getDescription() {
        return delegate.getDescription();
    }

    @Override
    public String getReference() {
        return delegate.getReference();
    }

    @Override
    public Status getStatus() {
        return delegate.getStatus();
    }

    @Override
    public SchemaPath getTargetPath() {
        return delegate.getTargetPath();
    }

    @Override
    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
        return delegate.getUnknownSchemaNodes();
    }

    @Override
    public Set<TypeDefinition<?>> getTypeDefinitions() {
        return delegate.getTypeDefinitions();
    }

    @Override
    public Set<DataSchemaNode> getChildNodes() {
        return realChildSchemas;
    }

    @Override
    public Set<GroupingDefinition> getGroupings() {
        return delegate.getGroupings();
    }

    @Override
    public DataSchemaNode getDataChildByName(final QName name) {
        if(mappedChildSchemas.containsKey(name)) {
            return mappedChildSchemas.get(name);
        }

        throw new IllegalArgumentException("Unknown child: " + name + " in: " + delegate);
    }

    @Override
    public DataSchemaNode getDataChildByName(final String name) {
        // Unused
        throw new UnsupportedOperationException("Unable to retrieve child node by name");
    }

    @Override
    public Set<UsesNode> getUses() {
        return delegate.getUses();
    }

    @Override
    public Optional<AugmentationSchema> getOriginalDefinition() {
        return delegate.getOriginalDefinition();
    }
}

@@ -371,24 +371,183 @@
 form.base;%0A%0A
+import com.google.common.base.Optional;%0Aimport com.google.common.base.Preconditions;%0Aimport com.google.common.collect.ImmutableMap;%0A%0Aimport java.util.HashMap;%0A
 import java.
@@ -1242,88 +1242,8 @@
 e;%0A%0A
-import com.google.common.base.Optional;%0Aimport com.google.common.collect.Maps;%0A%0A
 /**%0A
@@ -1811,50 +1811,82 @@
     
-this.mappedChildSchemas = Maps.
+final Map%3CQName, DataSchemaNode%3E m = 
 new
+ 
 HashMap
-(
+%3C%3E(realChildSchemas.size()
 );%0A 
@@ -1963,33 +1963,16 @@
        m
-appedChildSchemas
 .put(rea
@@ -2023,16 +2023,75 @@
        %7D
+%0A%0A        this.mappedChildSchemas = ImmutableMap.copyOf(m);
 %0A    %7D%0A%0A
@@ -3156,69 +3156,34 @@
     
-if(mappedChildSchemas.containsKey(name)) %7B%0A           
+final DataSchemaNode
  ret
-urn
+ =
  map
@@ -3221,100 +3221,112 @@
     
-%7D%0A%0A        throw new IllegalArgumentException(%22Unknown child: %22 + name + %22 in: %22 + delegate)
+Preconditions.checkArgument(ret != null, %22Unknown child: %25s in: %25s%22, name, delegate);%0A        return ret
 ;%0A  

optimize AugmentationSchemaProxy for lookup speed