Merge "Fixed dependent artifacts version in poms."
[yangtools.git] / yang / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / QName.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.yangtools.yang.common;
9
10 import java.io.Serializable;
11 import java.net.URI;
12 import java.net.URISyntaxException;
13 import java.text.SimpleDateFormat;
14 import java.util.Date;
15
16 import org.opendaylight.yangtools.concepts.Immutable;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
19
20 /**
21  * The QName from XML consists of local name of element and XML namespace, but
22  * for our use, we added module revision to it.
23  * 
24  * In YANG context QName is full name of defined node, type, procedure or
25  * notification. QName consists of XML namespace, YANG model revision and local
26  * name of defined type. It is used to prevent name clashes between nodes with
27  * same local name, but from different schemas.
28  * 
29  * <ul>
30  * <li><b>XMLNamespace</b> - the namespace assigned to the YANG module which
31  * defined element, type, procedure or notification.</li>
32  * <li><b>Revision</b> - the revision of the YANG module which describes the
33  * element</li>
34  * <li><b>LocalName</b> - the YANG schema identifier which were defined for this
35  * node in the YANG module</li>
36  * </ul>
37  * 
38  * 
39  */
40 public final class QName implements Immutable,Serializable {
41
42     private static final long serialVersionUID = 5398411242927766414L;
43
44     protected static final Logger LOGGER = LoggerFactory.getLogger(QName.class);
45
46     private SimpleDateFormat revisionFormat = new SimpleDateFormat("yyyy-MM-dd");
47
48     private final URI namespace;
49     private final String localName;
50     private final String prefix;
51     private final Date revision;
52
53     /**
54      * QName Constructor.
55      * 
56      * @param namespace
57      *            the namespace assigned to the YANG module
58      * @param revision
59      *            the revision of the YANG module
60      * @param prefix
61      *            locally defined prefix assigned to local name
62      * @param localName
63      *            YANG schema identifier
64      */
65     public QName(URI namespace, Date revision, String prefix, String localName) {
66         this.namespace = namespace;
67         this.localName = localName;
68         this.revision = revision;
69         this.prefix = prefix;
70     }
71
72     /**
73      * QName Constructor.
74      * 
75      * @param namespace
76      *            the namespace assigned to the YANG module
77      * @param localName
78      *            YANG schema identifier
79      */
80     public QName(URI namespace, String localName) {
81         this(namespace, null, "", localName);
82     }
83
84     /**
85      * QName Constructor.
86      * 
87      * @param namespace
88      *            the namespace assigned to the YANG module
89      * @param revision
90      *            the revision of the YANG module
91      * @param localName
92      *            YANG schema identifier
93      */
94     public QName(URI namespace, Date revision, String localName) {
95         this(namespace, revision, null, localName);
96     }
97
98     public QName(QName base, String localName) {
99         this(base.getNamespace(), base.getRevision(), base.getPrefix(), localName);
100     }
101
102     /**
103      * Returns XMLNamespace assigned to the YANG module.
104      * 
105      * @return XMLNamespace assigned to the YANG module.
106      */
107     public URI getNamespace() {
108         return namespace;
109     }
110
111     /**
112      * Returns YANG schema identifier which were defined for this node in the
113      * YANG module
114      * 
115      * @return YANG schema identifier which were defined for this node in the
116      *         YANG module
117      */
118     public String getLocalName() {
119         return localName;
120     }
121
122     /**
123      * Returns revision of the YANG module if the module has defined revision,
124      * otherwise returns <code>null</code>
125      * 
126      * @return revision of the YANG module if the module has defined revision,
127      *         otherwise returns <code>null</code>
128      */
129     public Date getRevision() {
130         return revision;
131     }
132
133     /**
134      * Returns locally defined prefix assigned to local name
135      * 
136      * @return locally defined prefix assigned to local name
137      */
138     public String getPrefix() {
139         return prefix;
140     }
141
142     @Override
143     public int hashCode() {
144         final int prime = 31;
145         int result = 1;
146         result = prime * result + ((localName == null) ? 0 : localName.hashCode());
147         result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
148         result = prime * result + ((revision == null) ? 0 : revision.hashCode());
149         return result;
150     }
151
152     @Override
153     public boolean equals(Object obj) {
154         if (this == obj) {
155             return true;
156         }
157         if (obj == null) {
158             return false;
159         }
160         if (getClass() != obj.getClass()) {
161             return false;
162         }
163         QName other = (QName) obj;
164         if (localName == null) {
165             if (other.localName != null) {
166                 return false;
167             }
168         } else if (!localName.equals(other.localName)) {
169             return false;
170         }
171         if (namespace == null) {
172             if (other.namespace != null) {
173                 return false;
174             }
175         } else if (!namespace.equals(other.namespace)) {
176             return false;
177         }
178         if (revision == null) {
179             if (other.revision != null) {
180                 return false;
181             }
182         } else if (!revision.equals(other.revision)) {
183             return false;
184         }
185         return true;
186     }
187
188     @Override
189     public String toString() {
190         StringBuilder sb = new StringBuilder();
191         if (namespace != null) {
192             sb.append("(" + namespace);
193
194             if (revision != null) {
195                 sb.append("?revision=" + revisionFormat.format(revision));
196             }
197             sb.append(")");
198         }
199         sb.append(localName);
200         return sb.toString();
201     }
202
203     /**
204      * Returns a namespace in form defined by section 5.6.4. of {@link https
205      * ://tools.ietf.org/html/rfc6020}, if namespace is not correctly defined,
206      * the method will return <code>null</code> <br>
207      * example "http://example.acme.com/system?revision=2008-04-01"
208      * 
209      * @return namespace in form defined by section 5.6.4. of {@link https
210      *         ://tools.ietf.org/html/rfc6020}, if namespace is not correctly
211      *         defined, the method will return <code>null</code>
212      * 
213      */
214     URI getRevisionNamespace() {
215
216         if (namespace == null) {
217             return null;
218         }
219
220         String query = "";
221         if (revision != null) {
222             query = "revision=" + revisionFormat.format(revision);
223         }
224
225         URI compositeURI = null;
226         try {
227             compositeURI = new URI(namespace.getScheme(), namespace.getUserInfo(), namespace.getHost(),
228                     namespace.getPort(), namespace.getPath(), query, namespace.getFragment());
229         } catch (URISyntaxException e) {
230             LOGGER.error("", e);
231         }
232         return compositeURI;
233     }
234 }