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