2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.yangtools.yang.data.codec.xml;
11 import com.google.common.base.Preconditions;
12 import com.google.common.base.Verify;
13 import com.google.common.cache.CacheBuilder;
14 import com.google.common.cache.CacheLoader;
15 import com.google.common.cache.LoadingCache;
16 import javax.xml.stream.XMLStreamException;
17 import javax.xml.stream.XMLStreamWriter;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
19 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
20 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
21 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
24 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
28 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
29 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
30 import org.opendaylight.yangtools.yang.model.util.type.DerivedTypes;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 public final class XmlCodecFactory {
36 private static final Logger LOG = LoggerFactory.getLogger(XmlCodecFactory.class);
37 private static final XmlCodec<Object> NULL_CODEC = new XmlCodec<Object>() {
39 public Object deserialize(final String input) {
44 public String serialize(final Object input) {
49 public void serializeToWriter(final XMLStreamWriter writer, final Object value) throws XMLStreamException {
50 // NOOP since codec is unkwown.
51 LOG.warn("Call of the serializeToWriter method on XmlCodecFactory.NULL_CODEC object. No operation " +
56 private final LoadingCache<DataSchemaNode, XmlCodec<?>> codecs =
57 CacheBuilder.newBuilder().softValues().build(new CacheLoader<DataSchemaNode, XmlCodec<?>>() {
59 public XmlCodec<?> load(final DataSchemaNode key) throws Exception {
60 final TypeDefinition<?> type;
61 if (key instanceof LeafSchemaNode) {
62 type = ((LeafSchemaNode) key).getType();
63 } else if (key instanceof LeafListSchemaNode) {
64 type = ((LeafListSchemaNode) key).getType();
66 throw new IllegalArgumentException("Not supported node type " + key.getClass().getName());
68 return createCodec(key,type);
72 private final SchemaContext schemaContext;
73 private final XmlCodec<YangInstanceIdentifier> iidCodec;
75 private XmlCodecFactory(final SchemaContext context) {
76 this.schemaContext = Preconditions.checkNotNull(context);
77 iidCodec = new XmlStringInstanceIdentifierCodec(context, this);
81 * Instantiate a new codec factory attached to a particular context.
83 * @param context SchemaContext to which the factory should be bound
84 * @return A codec factory instance.
86 public static XmlCodecFactory create(final SchemaContext context) {
87 return new XmlCodecFactory(context);
90 private XmlCodec<?> createCodec(final DataSchemaNode key, final TypeDefinition<?> type) {
91 final TypeDefinition<?> normalizedType = DerivedTypes.derivedTypeBuilder(type, type.getPath()).build();
92 if (normalizedType instanceof LeafrefTypeDefinition) {
93 return createReferencedTypeCodec(key, (LeafrefTypeDefinition) normalizedType);
94 } else if (normalizedType instanceof IdentityrefTypeDefinition) {
95 final XmlCodec<?> xmlStringIdentityrefCodec =
96 new XmlStringIdentityrefCodec(schemaContext, key.getQName().getModule());
97 return xmlStringIdentityrefCodec;
99 return createFromSimpleType(normalizedType);
102 private XmlCodec<?> createReferencedTypeCodec(final DataSchemaNode schema, final LeafrefTypeDefinition type) {
103 // FIXME: Verify if this does indeed support leafref of leafref
104 final TypeDefinition<?> referencedType =
105 SchemaContextUtil.getBaseTypeForLeafRef(type, getSchemaContext(), schema);
106 Verify.verifyNotNull(referencedType, "Unable to find base type for leafref node '%s'.", schema.getPath());
107 return createCodec(schema, referencedType);
110 private XmlCodec<?> createFromSimpleType(final TypeDefinition<?> type) {
111 if (type instanceof InstanceIdentifierTypeDefinition) {
114 if (type instanceof EmptyTypeDefinition) {
115 return XmlEmptyCodec.INSTANCE;
118 final TypeDefinitionAwareCodec<Object, ?> codec = TypeDefinitionAwareCodec.from(type);
120 LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName().getLocalName());
123 return AbstractXmlCodec.create(codec);
126 SchemaContext getSchemaContext() {
127 return schemaContext;
130 XmlCodec<?> codecFor(final DataSchemaNode schema) {
131 return codecs.getUnchecked(schema);