/*
* Copyright (c) 2015 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.parser.stmt.rfc6020;
import java.util.Collection;
import java.util.Iterator;
import javax.annotation.Nonnull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedNamespaceBehaviour;
import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
public class SchemaNodeIdentifierBuildNamespace extends
DerivedNamespaceBehaviour<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>, QName, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodes<?, ?>>
implements IdentifierNamespace<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>> {
@SuppressWarnings({"unchecked", "rawtypes"})
public SchemaNodeIdentifierBuildNamespace() {
super(SchemaNodeIdentifierBuildNamespace.class, (Class) ChildSchemaNodes.class);
}
@Override
public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> get(
@Nonnull final SchemaNodeIdentifier key) {
throw new UnsupportedOperationException("Direct access to namespace is not supported");
}
@SuppressWarnings("unchecked")
@Override
public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> getFrom(final NamespaceStorageNode storage, final SchemaNodeIdentifier key) {
final NamespaceStorageNode lookupStartStorage;
if (key.isAbsolute() || storage.getStorageNodeType() == StorageNodeType.ROOT_STATEMENT_LOCAL) {
lookupStartStorage = NamespaceBehaviour.findClosestTowardsRoot(storage, StorageNodeType.GLOBAL);
} else {
lookupStartStorage = storage;
}
final Iterator<QName> iterator = key.getPathFromRoot().iterator();
if (!iterator.hasNext()) {
if (lookupStartStorage instanceof StmtContext<?, ?, ?>) {
return (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage;
}
return null;
}
QName nextPath = iterator.next();
StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> current = lookupStartStorage
.getFromLocalStorage(ChildSchemaNodes.class, nextPath);
if (current == null && lookupStartStorage instanceof StmtContext<?, ?, ?>) {
return tryToFindUnknownStatement(nextPath.getLocalName(), (Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage);
}
while (current != null && iterator.hasNext()) {
nextPath = iterator.next();
final StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> nextNodeCtx = current
.getFromNamespace(ChildSchemaNodes.class, nextPath);
if (nextNodeCtx == null) {
return tryToFindUnknownStatement(nextPath.getLocalName(), current);
}
current = nextNodeCtx;
}
return current;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static Mutable<?, ?, EffectiveStatement<?, ?>> tryToFindUnknownStatement(final String localName,
final Mutable<?, ?, EffectiveStatement<?, ?>> current) {
final Collection<StmtContext<?, ?, ?>> unknownSubstatements = (Collection)StmtContextUtils.findAllSubstatements(current,
UnknownStatement.class);
for (final StmtContext<?, ?, ?> unknownSubstatement : unknownSubstatements) {
if (localName.equals(unknownSubstatement.rawStatementArgument())) {
return (Mutable<?, ?, EffectiveStatement<?, ?>>) unknownSubstatement;
}
}
return null;
}
@Override
public QName getSignificantKey(final SchemaNodeIdentifier key) {
return key.getLastComponent();
}
}