1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.jcr;
25
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.Set;
30 import javax.jcr.nodetype.NodeDefinition;
31 import javax.jcr.nodetype.NodeType;
32 import net.jcip.annotations.Immutable;
33 import org.modeshape.graph.ExecutionContext;
34 import org.modeshape.graph.property.Name;
35 import org.modeshape.graph.property.ValueFactory;
36
37
38
39
40 @Immutable
41 class JcrNodeDefinition extends JcrItemDefinition implements NodeDefinition {
42
43
44 private final boolean allowsSameNameSiblings;
45
46
47
48
49
50 private final Name defaultPrimaryTypeName;
51
52
53 private Map<Name, JcrNodeType> requiredPrimaryTypesByName;
54
55 private JcrNodeType[] requiredPrimaryTypes;
56
57 private Name[] requiredPrimaryTypeNames;
58
59
60 private NodeDefinitionId id;
61
62
63 private final RepositoryNodeTypeManager nodeTypeManager;
64
65 JcrNodeDefinition( ExecutionContext context,
66 JcrNodeType declaringNodeType,
67 Name name,
68 int onParentVersion,
69 boolean autoCreated,
70 boolean mandatory,
71 boolean protectedItem,
72 boolean allowsSameNameSiblings,
73 Name defaultPrimaryTypeName,
74 Name[] requiredPrimaryTypeNames ) {
75 this(context, null, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem,
76 allowsSameNameSiblings, defaultPrimaryTypeName, requiredPrimaryTypeNames);
77 }
78
79 JcrNodeDefinition( ExecutionContext context,
80 RepositoryNodeTypeManager nodeTypeManager,
81 JcrNodeType declaringNodeType,
82 Name name,
83 int onParentVersion,
84 boolean autoCreated,
85 boolean mandatory,
86 boolean protectedItem,
87 boolean allowsSameNameSiblings,
88 Name defaultPrimaryTypeName,
89 Name[] requiredPrimaryTypeNames ) {
90 super(context, declaringNodeType, name, onParentVersion, autoCreated, mandatory, protectedItem);
91 this.nodeTypeManager = nodeTypeManager;
92 this.allowsSameNameSiblings = allowsSameNameSiblings;
93 this.defaultPrimaryTypeName = defaultPrimaryTypeName;
94 this.requiredPrimaryTypes = new JcrNodeType[requiredPrimaryTypeNames.length];
95 this.requiredPrimaryTypeNames = requiredPrimaryTypeNames;
96 }
97
98 private final String string( Name name ) {
99 if (name == null) return null;
100 if (this.context == null) return name.getString();
101
102 return name.getString(context.getNamespaceRegistry());
103 }
104
105
106
107
108
109
110
111
112
113 private void ensureRequiredPrimaryTypesLoaded() {
114 if (requiredPrimaryTypesByName != null) return;
115 this.requiredPrimaryTypes = new JcrNodeType[requiredPrimaryTypeNames.length];
116 for (int i = 0; i != requiredPrimaryTypeNames.length; ++i) {
117 this.requiredPrimaryTypes[i] = nodeTypeManager.getNodeType(requiredPrimaryTypeNames[i]);
118 }
119 Map<Name, JcrNodeType> requiredPrimaryTypesByName = new HashMap<Name, JcrNodeType>();
120 for (JcrNodeType requiredPrimaryType : requiredPrimaryTypes) {
121 requiredPrimaryTypesByName.put(requiredPrimaryType.getInternalName(), requiredPrimaryType);
122 }
123 this.requiredPrimaryTypesByName = Collections.unmodifiableMap(requiredPrimaryTypesByName);
124
125 }
126
127
128
129
130
131
132 public NodeDefinitionId getId() {
133 if (id == null) {
134
135 id = new NodeDefinitionId(this.declaringNodeType.getInternalName(), this.name, this.requiredPrimaryTypeNames);
136 }
137 return id;
138 }
139
140
141
142
143
144
145 public boolean allowsSameNameSiblings() {
146 return allowsSameNameSiblings;
147 }
148
149
150
151
152 final Name defaultPrimaryTypeName() {
153 return defaultPrimaryTypeName;
154 }
155
156
157
158
159
160
161 public NodeType getDefaultPrimaryType() {
162
163 if (defaultPrimaryTypeName == null) {
164 return null;
165 }
166
167 return nodeTypeManager.getNodeType(defaultPrimaryTypeName);
168 }
169
170
171
172
173
174
175 public NodeType[] getRequiredPrimaryTypes() {
176 ensureRequiredPrimaryTypesLoaded();
177 if (requiredPrimaryTypes.length == 0) {
178
179
180 NodeType[] result = new NodeType[1];
181 result[0] = nodeTypeManager.getNodeType(JcrNtLexicon.BASE);
182 return result;
183 }
184
185 NodeType[] result = new NodeType[requiredPrimaryTypes.length];
186 for (int i = 0; i != requiredPrimaryTypes.length; ++i) {
187 result[i] = requiredPrimaryTypes[i];
188 }
189 return result;
190 }
191
192
193
194
195
196
197
198 Name[] requiredPrimaryTypeNames() {
199 return this.requiredPrimaryTypeNames;
200 }
201
202
203
204
205
206
207 Set<Name> requiredPrimaryTypeNameSet() {
208 ensureRequiredPrimaryTypesLoaded();
209 return requiredPrimaryTypesByName.keySet();
210 }
211
212
213
214
215 public String[] getRequiredPrimaryTypeNames() {
216 if (requiredPrimaryTypeNames == null) return new String[0];
217
218 String[] rptNames = new String[requiredPrimaryTypeNames.length];
219 for (int i = 0; i < requiredPrimaryTypeNames.length; i++) {
220 rptNames[i] = string(requiredPrimaryTypeNames[i]);
221 }
222 return rptNames;
223 }
224
225
226
227
228 public String getDefaultPrimaryTypeName() {
229 return string(this.defaultPrimaryTypeName);
230 }
231
232
233
234
235
236
237
238
239
240
241 final boolean allowsChildWithType( JcrNodeType childPrimaryType ) {
242 if (childPrimaryType == null) {
243
244 if (defaultPrimaryTypeName != null) {
245 return true;
246 }
247 return false;
248 }
249 ensureRequiredPrimaryTypesLoaded();
250
251 for (Name requiredPrimaryTypeName : requiredPrimaryTypesByName.keySet()) {
252 if (!childPrimaryType.isNodeType(requiredPrimaryTypeName)) return false;
253 }
254 return true;
255 }
256
257
258
259
260
261
262
263
264
265 JcrNodeDefinition with( JcrNodeType declaringNodeType ) {
266 return new JcrNodeDefinition(this.context, declaringNodeType.nodeTypeManager(), declaringNodeType, name,
267 getOnParentVersion(), isAutoCreated(), isMandatory(), isProtected(),
268 allowsSameNameSiblings(), defaultPrimaryTypeName, requiredPrimaryTypeNames);
269 }
270
271 JcrNodeDefinition with( ExecutionContext context ) {
272 return new JcrNodeDefinition(context, this.nodeTypeManager, this.declaringNodeType, name, getOnParentVersion(),
273 isAutoCreated(), isMandatory(), isProtected(), allowsSameNameSiblings(),
274 defaultPrimaryTypeName, requiredPrimaryTypeNames);
275 }
276
277 JcrNodeDefinition with( RepositoryNodeTypeManager nodeTypeManager ) {
278 return new JcrNodeDefinition(this.context, nodeTypeManager, this.declaringNodeType, name, getOnParentVersion(),
279 isAutoCreated(), isMandatory(), isProtected(), allowsSameNameSiblings(),
280 defaultPrimaryTypeName, requiredPrimaryTypeNames);
281 }
282
283 @Override
284 public int hashCode() {
285 return getId().toString().hashCode();
286 }
287
288 @Override
289 public boolean equals( Object obj ) {
290 if (this == obj) return true;
291 if (obj == null) return false;
292 if (getClass() != obj.getClass()) return false;
293 JcrNodeDefinition other = (JcrNodeDefinition)obj;
294 if (id == null) {
295 if (other.id != null) return false;
296 } else if (!id.equals(other.id)) return false;
297 return true;
298 }
299
300
301
302
303
304
305 @Override
306 public String toString() {
307 ValueFactory<String> strings = context.getValueFactories().getStringFactory();
308 StringBuilder sb = new StringBuilder();
309 NodeDefinitionId id = getId();
310 sb.append(strings.create(id.getNodeTypeName()));
311 sb.append('/');
312 sb.append(strings.create(id.getChildDefinitionName()));
313 if (id.hasRequiredPrimaryTypes()) {
314 sb.append(" (required primary types = [");
315 boolean first = true;
316 for (Name requiredPrimaryType : id.getRequiredPrimaryTypes()) {
317 if (first) first = false;
318 else sb.append(',');
319 sb.append(requiredPrimaryType.getString());
320 }
321 sb.append("])");
322 }
323 return sb.toString();
324 }
325 }