8d8ccd9fb732f2f6ceeb1d3b404cacf55a6384ec
[netconf.git] / netconf / netconf-netty-util / src / main / java / org / opendaylight / netconf / nettyutil / handler / exi / EXIParameters.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.nettyutil.handler.exi;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Preconditions;
12 import com.siemens.ct.exi.CodingMode;
13 import com.siemens.ct.exi.EXIFactory;
14 import com.siemens.ct.exi.EncodingOptions;
15 import com.siemens.ct.exi.FidelityOptions;
16 import com.siemens.ct.exi.exceptions.UnsupportedOption;
17 import com.siemens.ct.exi.helpers.DefaultEXIFactory;
18 import java.util.Objects;
19 import org.opendaylight.netconf.api.xml.XmlElement;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22 import org.w3c.dom.Element;
23 import org.w3c.dom.NodeList;
24
25 public final class EXIParameters {
26     private static final Logger LOG = LoggerFactory.getLogger(EXIParameters.class);
27
28     static final String EXI_PARAMETER_ALIGNMENT = "alignment";
29     private static final String EXI_PARAMETER_BYTE_ALIGNED = "byte-aligned";
30     private static final String EXI_PARAMETER_BIT_PACKED = "bit-packed";
31     private static final String EXI_PARAMETER_COMPRESSED = "compressed";
32     private static final String EXI_PARAMETER_PRE_COMPRESSION = "pre-compression";
33
34     static final String EXI_PARAMETER_FIDELITY = "fidelity";
35     private static final String EXI_FIDELITY_DTD = "dtd";
36     private static final String EXI_FIDELITY_LEXICAL_VALUES = "lexical-values";
37     private static final String EXI_FIDELITY_COMMENTS = "comments";
38     private static final String EXI_FIDELITY_PIS = "pis";
39     private static final String EXI_FIDELITY_PREFIXES = "prefixes";
40
41     private static final EncodingOptions ENCODING_OPTIONS;
42
43     static {
44         final EncodingOptions opts = EncodingOptions.createDefault();
45         try {
46             opts.setOption(EncodingOptions.RETAIN_ENTITY_REFERENCE);
47             opts.setOption(EncodingOptions.INCLUDE_OPTIONS);
48
49             /**
50              * NETCONF is XML environment, so the use of EXI cookie is not really needed. Adding it
51              * decreases efficiency of encoding by adding human-readable 4 bytes "EXI$" to the head
52              * of the stream. This is really useful, so let's output it now.
53              */
54             opts.setOption(EncodingOptions.INCLUDE_COOKIE);
55         } catch (final UnsupportedOption e) {
56             throw new ExceptionInInitializerError(e);
57         }
58
59         ENCODING_OPTIONS = opts;
60     }
61
62     private final FidelityOptions fidelityOptions;
63     private final CodingMode codingMode;
64
65     public EXIParameters(final CodingMode codingMode, final FidelityOptions fidelityOptions) {
66         this.fidelityOptions = Preconditions.checkNotNull(fidelityOptions);
67         this.codingMode = Preconditions.checkNotNull(codingMode);
68     }
69
70     @VisibleForTesting
71     public static EXIParameters empty() {
72         return new EXIParameters(CodingMode.BIT_PACKED, FidelityOptions.createDefault());
73     }
74
75     public static EXIParameters fromXmlElement(final XmlElement root) throws UnsupportedOption {
76         final CodingMode coding;
77         final NodeList alignmentElements = root.getElementsByTagName(EXI_PARAMETER_ALIGNMENT);
78         if (alignmentElements.getLength() > 0) {
79             final Element alignmentElement = (Element) alignmentElements.item(0);
80             final String alignmentTextContent = alignmentElement.getTextContent().trim();
81
82             switch (alignmentTextContent) {
83                 case EXI_PARAMETER_BYTE_ALIGNED:
84                     coding = CodingMode.BYTE_PACKED;
85                     break;
86                 case EXI_PARAMETER_COMPRESSED:
87                     coding = CodingMode.COMPRESSION;
88                     break;
89                 case EXI_PARAMETER_PRE_COMPRESSION:
90                     coding = CodingMode.PRE_COMPRESSION;
91                     break;
92                 case EXI_PARAMETER_BIT_PACKED:
93                     coding = CodingMode.BIT_PACKED;
94                     break;
95                 default:
96                     LOG.warn("Unexpected value in alignmentTextContent: {} , using default value",
97                             alignmentTextContent);
98                     coding = CodingMode.BIT_PACKED;
99                     break;
100             }
101         } else {
102             coding = CodingMode.BIT_PACKED;
103         }
104
105         final FidelityOptions fidelity = FidelityOptions.createDefault();
106         final NodeList fidelityElements = root.getElementsByTagName(EXI_PARAMETER_FIDELITY);
107         if (fidelityElements.getLength() > 0) {
108             final Element fidelityElement = (Element) fidelityElements.item(0);
109
110             fidelity.setFidelity(FidelityOptions.FEATURE_DTD,
111                 fidelityElement.getElementsByTagName(EXI_FIDELITY_DTD).getLength() > 0);
112             fidelity.setFidelity(FidelityOptions.FEATURE_LEXICAL_VALUE,
113                 fidelityElement.getElementsByTagName(EXI_FIDELITY_LEXICAL_VALUES).getLength() > 0);
114             fidelity.setFidelity(FidelityOptions.FEATURE_COMMENT,
115                 fidelityElement.getElementsByTagName(EXI_FIDELITY_COMMENTS).getLength() > 0);
116             fidelity.setFidelity(FidelityOptions.FEATURE_PI,
117                 fidelityElement.getElementsByTagName(EXI_FIDELITY_PIS).getLength() > 0);
118             fidelity.setFidelity(FidelityOptions.FEATURE_PREFIX,
119                 fidelityElement.getElementsByTagName(EXI_FIDELITY_PREFIXES).getLength() > 0);
120         }
121
122         return new EXIParameters(coding, fidelity);
123     }
124
125     public EXIFactory getFactory() {
126         final EXIFactory factory = DefaultEXIFactory.newInstance();
127         factory.setCodingMode(codingMode);
128         factory.setEncodingOptions(ENCODING_OPTIONS);
129         factory.setFidelityOptions(fidelityOptions);
130         return factory;
131     }
132
133     @Override
134     public int hashCode() {
135         return Objects.hash(fidelityOptions, codingMode);
136     }
137
138     @Override
139     public boolean equals(final Object obj) {
140         if (this == obj) {
141             return true;
142         }
143         if (!(obj instanceof EXIParameters)) {
144             return false;
145         }
146         final EXIParameters other = (EXIParameters) obj;
147         return codingMode == other.codingMode && fidelityOptions.equals(other.fidelityOptions);
148     }
149
150     String getAlignment() {
151         switch (codingMode) {
152             case BIT_PACKED:
153                 return EXI_PARAMETER_BIT_PACKED;
154             case BYTE_PACKED:
155                 return EXI_PARAMETER_BYTE_ALIGNED;
156             case COMPRESSION:
157                 return EXI_PARAMETER_COMPRESSED;
158             case PRE_COMPRESSION:
159                 return EXI_PARAMETER_PRE_COMPRESSION;
160             default:
161                 throw new IllegalStateException("Unhandled coding mode " + codingMode);
162         }
163     }
164
165     private String fidelityString(final String feature, final String string) {
166         return fidelityOptions.isFidelityEnabled(feature) ? string : null;
167     }
168
169     String getPreserveComments() {
170         return fidelityString(FidelityOptions.FEATURE_COMMENT, EXI_FIDELITY_COMMENTS);
171     }
172
173     String getPreserveDTD() {
174         return fidelityString(FidelityOptions.FEATURE_DTD, EXI_FIDELITY_DTD);
175     }
176
177     String getPreserveLexicalValues() {
178         return fidelityString(FidelityOptions.FEATURE_LEXICAL_VALUE, EXI_FIDELITY_LEXICAL_VALUES);
179     }
180
181     String getPreservePIs() {
182         return fidelityString(FidelityOptions.FEATURE_PI, EXI_FIDELITY_PIS);
183     }
184
185     String getPreservePrefixes() {
186         return fidelityString(FidelityOptions.FEATURE_PREFIX, EXI_FIDELITY_PREFIXES);
187     }
188 }