/*
 * Copyright (c) 2014 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.util;

import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import java.util.Map;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;

/**
 * Abstract utility class for representations which encode {@link YangInstanceIdentifier} as a
 * prefix:name tuple. Typical uses are RESTCONF/JSON (module:name) and XML (prefix:name).
 */
@Beta
public abstract class AbstractStringInstanceIdentifierCodec extends AbstractNamespaceCodec implements InstanceIdentifierCodec<String> {

    @Override
    public final String serialize(final YangInstanceIdentifier data) {
        StringBuilder sb = new StringBuilder();
        DataSchemaContextNode<?> current = getDataContextTree().getRoot();
        for (PathArgument arg : data.getPathArguments()) {
            current = current.getChild(arg);

            if(current.isMixin()) {
                /*
                 * XML/YANG instance identifier does not have concept
                 * of augmentation identifier, or list as whole which
                 * identifies mixin (same as paretn element),
                 * so we can safely ignore it if it is part of path
                 * (since child node) is identified in same fashion.
                 *
                 */
                continue;
            }

            sb.append('/');
            appendQName(sb, arg.getNodeType());

            if (arg instanceof NodeIdentifierWithPredicates) {
                for (Map.Entry<QName, Object> entry : ((NodeIdentifierWithPredicates) arg).getKeyValues().entrySet()) {
                    sb.append('[');
                    appendQName(sb, entry.getKey());
                    sb.append("='");
                    sb.append(String.valueOf(entry.getValue()));
                    sb.append("']");
                }
            } else if (arg instanceof NodeWithValue) {
                sb.append("[.='");
                sb.append(((NodeWithValue) arg).getValue());
                sb.append("']");
            }
        }
        return sb.toString();
    }

    /**
     *
     * Returns DataSchemaContextTree associated with SchemaContext for which
     * serialization / deserialization occurs.
     *
     * Implementations MUST provide non-null Data Tree context, in order
     * for correct serialization / deserialization of PathArguments,
     * since XML representation does not have Augmentation arguments
     * and does not provide path arguments for cases.
     *
     * This effectively means same input XPath representation of Path Argument
     * may result in different YangInstanceIdentifiers if models are different
     * in uses of choices and cases.
     *
     * @return DataSchemaContextTree associated with SchemaContext for which
     * serialization / deserialization occurs.
     */
    protected abstract @Nonnull DataSchemaContextTree getDataContextTree();

    protected Object deserializeKeyValue(DataSchemaNode schemaNode, String value) {
        return value;
    }

    @Override
    public final YangInstanceIdentifier deserialize(final String data) {
        Preconditions.checkNotNull(data, "Data may not be null");
        XpathStringParsingPathArgumentBuilder builder = new XpathStringParsingPathArgumentBuilder(this, data);
        return YangInstanceIdentifier.create(builder.build());
    }

}

@@ -1686,31 +1686,190 @@
 d(arg);%0A
-%0A            if
+            Preconditions.checkArgument(current != null,%0A                    %22Invalid input %25s: schema for argument %25s (after %25s) not found%22, data, arg, sb);%0A%0A            if 
 (current
@@ -2071,16 +2071,18 @@
 ntifies 
+a 
 mixin (s
@@ -2092,14 +2092,18 @@
  as 
+the 
 pare
-t
 n
+t
  ele
@@ -2250,27 +2250,8 @@
 on.%0A
-                 *%0A
     
@@ -3928,16 +3928,22 @@
 eyValue(
+final 
 DataSche
@@ -3960,16 +3960,22 @@
 emaNode,
+ final
  String 

check if entire YangInstanceIdentifier is present in SchemaContext