4367d9126cd8db6743ab11468e4ea7ab6bbe7333
[vxquery.git] / vxquery-core / src / main / java / org / apache / vxquery / datamodel / accessors / nodes / ElementNodePointable.java
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.vxquery.datamodel.accessors.nodes;
18
19 import org.apache.vxquery.datamodel.accessors.SequencePointable;
20 import org.apache.vxquery.datamodel.accessors.atomic.CodedQNamePointable;
21
22 import org.apache.hyracks.api.dataflow.value.ITypeTraits;
23 import org.apache.hyracks.data.std.api.IPointable;
24 import org.apache.hyracks.data.std.api.IPointableFactory;
25 import org.apache.hyracks.data.std.primitive.BytePointable;
26 import org.apache.hyracks.data.std.primitive.IntegerPointable;
27 import org.apache.hyracks.data.std.primitive.VoidPointable;
28
29 /*
30 * Element {
31 * ElementHeader header;
32 * NamePtr namePtr;
33 * NamePtr typePtr?;
34 * LocalNodeId nodeId?;
35 * NamespaceChunk nsChunk?;
36 * Sequence attrChunk?;
37 * Sequence childrenChunk?;
38 * }
39 *
40 * ElementHeader (padded) {
41 * bit nsChunkExists;
42 * bit attrChunkExists;
43 * bit childrenChunkExists;
44 * }
45 *
46 * NamePtr {
47 * int[3] stringPtrs;
48 * }
49 *
50 * LocalNodeId {
51 * int32 id;
52 * }
53 *
54 * NamespaceChunk {
55 * byte[size] chunkSizeInBytes; // size = decode(ElementHeader.nsChunkSizeSize)
56 * NamePtr[2][chunkSizeInBytes / (sizeof(NamePtr) * 2)] namespaces;
57 * }
58 */
59 public class ElementNodePointable extends AbstractNodePointable {
60 public static final byte NS_CHUNK_EXISTS_MASK = (0x1 << 0);
61 public static final byte ATTRIBUTES_CHUNK_EXISTS_MASK = (0x1 << 1);
62 public static final byte CHILDREN_CHUNK_EXISTS_MASK = (0x1 << 2);
63
64 private static final int HEADER_SIZE = 1;
65 private static final int LOCAL_NODE_ID_SIZE = 4;
66 private static final int NS_ENTRY_SIZE = 4 * 2;
67 private static final int NS_CHUNK_SIZE_SIZE = 4;
68 public static final IPointableFactory FACTORY = new IPointableFactory() {
69 private static final long serialVersionUID = 1L;
70
71 @Override
72 public ITypeTraits getTypeTraits() {
73 return VoidPointable.TYPE_TRAITS;
74 }
75
76 @Override
77 public IPointable createPointable() {
78 return new ElementNodePointable();
79 }
80 };
81
82 public boolean nsChunkExists() {
83 return (getHeader() & NS_CHUNK_EXISTS_MASK) != 0;
84 }
85
86 public boolean attributesChunkExists() {
87 return (getHeader() & ATTRIBUTES_CHUNK_EXISTS_MASK) != 0;
88 }
89
90 public boolean childrenChunkExists() {
91 return (getHeader() & CHILDREN_CHUNK_EXISTS_MASK) != 0;
92 }
93
94 public void getName(CodedQNamePointable name) {
95 name.set(bytes, getNameOffset(), getNameSize());
96 }
97
98 public void getTypeName(NodeTreePointable nodeTree, CodedQNamePointable typeName) {
99 if (nodeTree.typeExists()) {
100 typeName.set(bytes, getTypeOffset(), getTypeSize(nodeTree));
101 } else {
102 typeName.set(null, -1, -1);
103 }
104 }
105
106 public int getLocalNodeId(NodeTreePointable nodeTree) {
107 return nodeTree.nodeIdExists() ? IntegerPointable.getInteger(bytes, getLocalNodeIdOffset(nodeTree)) : -1;
108 }
109
110 public int getNamespaceEntryCount(NodeTreePointable nodeTree) {
111 return nsChunkExists() ? IntegerPointable.getInteger(bytes, getNamespaceChunkOffset(nodeTree)) : 0;
112 }
113
114 public int getNamespacePrefixCode(NodeTreePointable nodeTree, int nsEntryIdx) {
115 if (!nsChunkExists()) {
116 return -1;
117 }
118 if (getNamespaceEntryCount(nodeTree) <= nsEntryIdx) {
119 throw new IndexOutOfBoundsException(nsEntryIdx + " >= " + getNamespaceEntryCount(nodeTree));
120 }
121 return IntegerPointable.getInteger(bytes, getNamespaceChunkOffset(nodeTree) + NS_CHUNK_SIZE_SIZE
122 + NS_ENTRY_SIZE * nsEntryIdx);
123 }
124
125 public int getNamespaceURICode(NodeTreePointable nodeTree, int nsEntryIdx) {
126 if (!nsChunkExists()) {
127 return -1;
128 }
129 if (getNamespaceEntryCount(nodeTree) <= nsEntryIdx) {
130 throw new IndexOutOfBoundsException(nsEntryIdx + " >= " + getNamespaceEntryCount(nodeTree));
131 }
132 return IntegerPointable.getInteger(bytes, getNamespaceChunkOffset(nodeTree) + NS_CHUNK_SIZE_SIZE
133 + NS_ENTRY_SIZE * nsEntryIdx + 1);
134 }
135
136 public void getAttributeSequence(NodeTreePointable nodeTree, SequencePointable attributes) {
137 if (attributesChunkExists()) {
138 attributes.set(bytes, getAttributeChunkOffset(nodeTree), getAttributeChunkSize(nodeTree));
139 } else {
140 attributes.set(null, -1, -1);
141 }
142 }
143
144 public void getChildrenSequence(NodeTreePointable nodeTree, SequencePointable children) {
145 if (childrenChunkExists()) {
146 children.set(bytes, getChildrenChunkOffset(nodeTree), getChildrenChunkSize(nodeTree));
147 } else {
148 children.set(null, -1, -1);
149 }
150 }
151
152 private byte getHeader() {
153 return BytePointable.getByte(bytes, start);
154 }
155
156 private int getNameOffset() {
157 return start + HEADER_SIZE;
158 }
159
160 private int getNameSize() {
161 return CodedQNamePointable.SIZE;
162 }
163
164 private int getTypeOffset() {
165 return getNameOffset() + getNameSize();
166 }
167
168 private int getTypeSize(NodeTreePointable nodeTree) {
169 return nodeTree.typeExists() ? CodedQNamePointable.SIZE : 0;
170 }
171
172 protected int getLocalNodeIdOffset(NodeTreePointable nodeTree) {
173 return getTypeOffset() + getTypeSize(nodeTree);
174 }
175
176 private int getLocalNodeIdSize(NodeTreePointable nodeTree) {
177 return nodeTree.nodeIdExists() ? LOCAL_NODE_ID_SIZE : 0;
178 }
179
180 private int getNamespaceChunkOffset(NodeTreePointable nodeTree) {
181 return getLocalNodeIdOffset(nodeTree) + getLocalNodeIdSize(nodeTree);
182 }
183
184 private int getNamespaceChunkSize(NodeTreePointable nodeTree) {
185 return nsChunkExists() ? getNamespaceEntryCount(nodeTree) * NS_ENTRY_SIZE + NS_CHUNK_SIZE_SIZE : 0;
186 }
187
188 private int getAttributeChunkOffset(NodeTreePointable nodeTree) {
189 return getNamespaceChunkOffset(nodeTree) + getNamespaceChunkSize(nodeTree);
190 }
191
192 private int getAttributeChunkSize(NodeTreePointable nodeTree) {
193 return attributesChunkExists() ? SequencePointable.getSequenceLength(bytes, getAttributeChunkOffset(nodeTree))
194 : 0;
195 }
196
197 private int getChildrenChunkOffset(NodeTreePointable nodeTree) {
198 return getAttributeChunkOffset(nodeTree) + getAttributeChunkSize(nodeTree);
199 }
200
201 private int getChildrenChunkSize(NodeTreePointable nodeTree) {
202 return childrenChunkExists() ? SequencePointable.getSequenceLength(bytes, getChildrenChunkOffset(nodeTree)) : 0;
203 }
204 }