Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.compiler/share/classes/javax/lang/model/util/Elements.java
41161 views
1
/*
2
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package javax.lang.model.util;
27
28
import java.util.Collections;
29
import java.util.List;
30
import java.util.Map;
31
import java.util.Set;
32
import java.util.LinkedHashSet;
33
import java.util.Objects;
34
35
import javax.lang.model.AnnotatedConstruct;
36
import javax.lang.model.element.*;
37
38
39
/**
40
* Utility methods for operating on program elements.
41
*
42
* <p><b>Compatibility Note:</b> Methods may be added to this interface
43
* in future releases of the platform.
44
*
45
* @author Joseph D. Darcy
46
* @author Scott Seligman
47
* @author Peter von der Ah&eacute;
48
* @see javax.annotation.processing.ProcessingEnvironment#getElementUtils
49
* @since 1.6
50
*/
51
public interface Elements {
52
53
/**
54
* Returns a package given its fully qualified name if the package is uniquely
55
* determinable in the environment.
56
*
57
* If running with modules, packages of the given name are searched in a
58
* two-stage process:
59
* <ul>
60
* <li>find non-empty packages with the given name returned by
61
* {@link #getPackageElement(ModuleElement, CharSequence)},
62
* where the provided ModuleSymbol is any
63
* <a href="../../../../../java.base/java/lang/module/package-summary.html#root-modules">root module</a>,
64
* </li>
65
* <li>if the above yields an empty list, search
66
* {@link #getAllModuleElements() all modules} for observable
67
* packages with the given name
68
* </li>
69
* </ul>
70
*
71
* If this process leads to a list with a single element,
72
* the single element is returned, otherwise null is returned.
73
*
74
* @param name fully qualified package name,
75
* or an empty string for an unnamed package
76
* @return the specified package,
77
* or {@code null} if no package can be uniquely determined.
78
*/
79
PackageElement getPackageElement(CharSequence name);
80
81
/**
82
* Returns a package given its fully qualified name, as seen from the given module.
83
*
84
* @implSpec The default implementation of this method returns
85
* {@code null}.
86
*
87
* @param name fully qualified package name, or an empty string for an unnamed package
88
* @param module module relative to which the lookup should happen
89
* @return the specified package, or {@code null} if it cannot be found
90
* @see #getAllPackageElements
91
* @since 9
92
*/
93
default PackageElement getPackageElement(ModuleElement module, CharSequence name) {
94
return null;
95
}
96
97
/**
98
* Returns all package elements with the given canonical name.
99
*
100
* There may be more than one package element with the same canonical
101
* name if the package elements are in different modules.
102
*
103
* @implSpec The default implementation of this method calls
104
* {@link #getAllModuleElements() getAllModuleElements} and stores
105
* the result. If the set of modules is empty, {@link
106
* #getPackageElement(CharSequence) getPackageElement(name)} is
107
* called passing through the name argument. If {@code
108
* getPackageElement(name)} is {@code null}, an empty set of
109
* package elements is returned; otherwise, a single-element set
110
* with the found package element is returned. If the set of
111
* modules is nonempty, the modules are iterated over and any
112
* non-{@code null} results of {@link
113
* #getPackageElement(ModuleElement, CharSequence)
114
* getPackageElement(module, name)} are accumulated into a
115
* set. The set is then returned.
116
*
117
* @param name the canonical name
118
* @return the package elements, or an empty set if no package with the name can be found
119
* @see #getPackageElement(ModuleElement, CharSequence)
120
* @since 9
121
*/
122
default Set<? extends PackageElement> getAllPackageElements(CharSequence name) {
123
Set<? extends ModuleElement> modules = getAllModuleElements();
124
if (modules.isEmpty()) {
125
PackageElement packageElt = getPackageElement(name);
126
return (packageElt != null) ?
127
Collections.singleton(packageElt):
128
Collections.emptySet();
129
} else {
130
Set<PackageElement> result = new LinkedHashSet<>(1); // Usually expect at most 1 result
131
for (ModuleElement module: modules) {
132
PackageElement packageElt = getPackageElement(module, name);
133
if (packageElt != null)
134
result.add(packageElt);
135
}
136
return Collections.unmodifiableSet(result);
137
}
138
}
139
140
/**
141
* Returns a type element given its canonical name if the type element is uniquely
142
* determinable in the environment.
143
*
144
* If running with modules, type elements of the given name are
145
* searched in a two-stage process:
146
* <ul>
147
* <li>find type elements with the given name returned by
148
* {@link #getTypeElement(ModuleElement, CharSequence)},
149
* where the provided ModuleSymbol is any
150
* <a href="../../../../../java.base/java/lang/module/package-summary.html#root-modules">root module</a>,
151
* </li>
152
* <li>if the above yields an empty list, search
153
* {@link #getAllModuleElements() all modules} for observable
154
* type elements with the given name
155
* </li>
156
* </ul>
157
*
158
* If this process leads to a list with a single element,
159
* the single element is returned, otherwise null is returned.
160
*
161
* @param name the canonical name
162
* @return the named type element,
163
* or {@code null} if no type element can be uniquely determined.
164
*/
165
TypeElement getTypeElement(CharSequence name);
166
167
/**
168
* Returns a type element given its canonical name, as seen from the given module.
169
*
170
* @implSpec The default implementation of this method returns
171
* {@code null}.
172
*
173
* @param name the canonical name
174
* @param module module relative to which the lookup should happen
175
* @return the named type element, or {@code null} if it cannot be found
176
* @see #getAllTypeElements
177
* @since 9
178
*/
179
default TypeElement getTypeElement(ModuleElement module, CharSequence name) {
180
return null;
181
}
182
183
/**
184
* Returns all type elements with the given canonical name.
185
*
186
* There may be more than one type element with the same canonical
187
* name if the type elements are in different modules.
188
*
189
* @implSpec The default implementation of this method calls
190
* {@link #getAllModuleElements() getAllModuleElements} and stores
191
* the result. If the set of modules is empty, {@link
192
* #getTypeElement(CharSequence) getTypeElement(name)} is called
193
* passing through the name argument. If {@code
194
* getTypeElement(name)} is {@code null}, an empty set of type
195
* elements is returned; otherwise, a single-element set with the
196
* found type element is returned. If the set of modules is
197
* nonempty, the modules are iterated over and any non-{@code null}
198
* results of {@link #getTypeElement(ModuleElement,
199
* CharSequence) getTypeElement(module, name)} are accumulated
200
* into a set. The set is then returned.
201
*
202
* @param name the canonical name
203
* @return the type elements, or an empty set if no type with the name can be found
204
* @see #getTypeElement(ModuleElement, CharSequence)
205
* @since 9
206
*/
207
default Set<? extends TypeElement> getAllTypeElements(CharSequence name) {
208
Set<? extends ModuleElement> modules = getAllModuleElements();
209
if (modules.isEmpty()) {
210
TypeElement typeElt = getTypeElement(name);
211
return (typeElt != null) ?
212
Collections.singleton(typeElt):
213
Collections.emptySet();
214
} else {
215
Set<TypeElement> result = new LinkedHashSet<>(1); // Usually expect at most 1 result
216
for (ModuleElement module: modules) {
217
TypeElement typeElt = getTypeElement(module, name);
218
if (typeElt != null)
219
result.add(typeElt);
220
}
221
return Collections.unmodifiableSet(result);
222
}
223
}
224
225
/**
226
* Returns a module element given its fully qualified name.
227
*
228
* If the requested module cannot be found, {@code null} is
229
* returned. One situation where a module cannot be found is if
230
* the environment does not include modules, such as an annotation
231
* processing environment configured for a {@linkplain
232
* javax.annotation.processing.ProcessingEnvironment#getSourceVersion
233
* source version} without modules.
234
*
235
* @implSpec The default implementation of this method returns
236
* {@code null}.
237
*
238
* @param name the name, or an empty string for an unnamed module
239
* @return the named module element, or {@code null} if it cannot be found
240
* @see #getAllModuleElements
241
* @since 9
242
*/
243
default ModuleElement getModuleElement(CharSequence name) {
244
return null;
245
}
246
247
/**
248
* Returns all module elements in the current environment.
249
*
250
* If no modules are present, an empty set is returned. One
251
* situation where no modules are present occurs when the
252
* environment does not include modules, such as an annotation
253
* processing environment configured for a {@linkplain
254
* javax.annotation.processing.ProcessingEnvironment#getSourceVersion
255
* source version} without modules.
256
*
257
* @implSpec The default implementation of this method returns
258
* an empty set.
259
*
260
* @return the known module elements, or an empty set if there are no modules
261
* @see #getModuleElement(CharSequence)
262
* @since 9
263
*/
264
default Set<? extends ModuleElement> getAllModuleElements() {
265
return Collections.emptySet();
266
}
267
268
/**
269
* {@return the values of an annotation's elements, including defaults}
270
*
271
* @see AnnotationMirror#getElementValues()
272
* @param a annotation to examine
273
*/
274
Map<? extends ExecutableElement, ? extends AnnotationValue>
275
getElementValuesWithDefaults(AnnotationMirror a);
276
277
/**
278
* Returns the text of the documentation (&quot;Javadoc&quot;)
279
* comment of an element.
280
*
281
* <p> A documentation comment of an element is a comment that
282
* begins with "{@code /**}", ends with a separate
283
* "<code>*&#47;</code>", and immediately precedes the element,
284
* ignoring white space. Therefore, a documentation comment
285
* contains at least three "{@code *}" characters. The text
286
* returned for the documentation comment is a processed form of
287
* the comment as it appears in source code. The leading "{@code /**}"
288
* and trailing "<code>*&#47;</code>" are removed. For lines
289
* of the comment starting after the initial "{@code /**}",
290
* leading white space characters are discarded as are any
291
* consecutive "{@code *}" characters appearing after the white
292
* space or starting the line. The processed lines are then
293
* concatenated together (including line terminators) and
294
* returned.
295
*
296
* @param e the element being examined
297
* @return the documentation comment of the element, or {@code null}
298
* if there is none
299
* @jls 3.6 White Space
300
*/
301
String getDocComment(Element e);
302
303
/**
304
* {@return {@code true} if the element is deprecated, {@code false} otherwise}
305
*
306
* @param e the element being examined
307
*/
308
boolean isDeprecated(Element e);
309
310
/**
311
* {@return the <em>origin</em> of the given element}
312
*
313
* <p>Note that if this method returns {@link Origin#EXPLICIT
314
* EXPLICIT} and the element was created from a class file, then
315
* the element may not, in fact, correspond to an explicitly
316
* declared construct in source code. This is due to limitations
317
* of the fidelity of the class file format in preserving
318
* information from source code. For example, at least some
319
* versions of the class file format do not preserve whether a
320
* constructor was explicitly declared by the programmer or was
321
* implicitly declared as the <em>default constructor</em>.
322
*
323
* @implSpec The default implementation of this method returns
324
* {@link Origin#EXPLICIT EXPLICIT}.
325
*
326
* @param e the element being examined
327
* @since 9
328
*/
329
default Origin getOrigin(Element e) {
330
return Origin.EXPLICIT;
331
}
332
333
/**
334
* {@return the <em>origin</em> of the given annotation mirror}
335
*
336
* An annotation mirror is {@linkplain Origin#MANDATED mandated}
337
* if it is an implicitly declared <em>container annotation</em>
338
* used to hold repeated annotations of a repeatable annotation
339
* interface.
340
*
341
* <p>Note that if this method returns {@link Origin#EXPLICIT
342
* EXPLICIT} and the annotation mirror was created from a class
343
* file, then the element may not, in fact, correspond to an
344
* explicitly declared construct in source code. This is due to
345
* limitations of the fidelity of the class file format in
346
* preserving information from source code. For example, at least
347
* some versions of the class file format do not preserve whether
348
* an annotation was explicitly declared by the programmer or was
349
* implicitly declared as a <em>container annotation</em>.
350
*
351
* @implSpec The default implementation of this method returns
352
* {@link Origin#EXPLICIT EXPLICIT}.
353
*
354
* @param c the construct the annotation mirror modifies
355
* @param a the annotation mirror being examined
356
* @jls 9.6.3 Repeatable Annotation Types
357
* @jls 9.7.5 Multiple Annotations of the Same Interface
358
* @since 9
359
*/
360
default Origin getOrigin(AnnotatedConstruct c,
361
AnnotationMirror a) {
362
return Origin.EXPLICIT;
363
}
364
365
/**
366
* {@return the <em>origin</em> of the given module directive}
367
*
368
* <p>Note that if this method returns {@link Origin#EXPLICIT
369
* EXPLICIT} and the module directive was created from a class
370
* file, then the module directive may not, in fact, correspond to
371
* an explicitly declared construct in source code. This is due to
372
* limitations of the fidelity of the class file format in
373
* preserving information from source code. For example, at least
374
* some versions of the class file format do not preserve whether
375
* a {@code uses} directive was explicitly declared by the
376
* programmer or was added as a synthetic construct.
377
*
378
* <p>Note that an implementation may not be able to reliably
379
* determine the origin status of the directive if the directive
380
* is created from a class file due to limitations of the fidelity
381
* of the class file format in preserving information from source
382
* code.
383
*
384
* @implSpec The default implementation of this method returns
385
* {@link Origin#EXPLICIT EXPLICIT}.
386
*
387
* @param m the module of the directive
388
* @param directive the module directive being examined
389
* @since 9
390
*/
391
default Origin getOrigin(ModuleElement m,
392
ModuleElement.Directive directive) {
393
return Origin.EXPLICIT;
394
}
395
396
/**
397
* The <em>origin</em> of an element or other language model
398
* item. The origin of an element or item models how a construct
399
* in a program is declared in the source code, explicitly,
400
* implicitly, etc.
401
*
402
* <p>Note that it is possible additional kinds of origin values
403
* will be added in future versions of the platform.
404
*
405
* @jls 13.1 The Form of a Binary
406
* @since 9
407
*/
408
public enum Origin {
409
/**
410
* Describes a construct explicitly declared in source code.
411
*/
412
EXPLICIT,
413
414
/**
415
* A mandated construct is one that is not explicitly declared
416
* in the source code, but whose presence is mandated by the
417
* specification. Such a construct is said to be implicitly
418
* declared.
419
*
420
* One example of a mandated element is a <em>default
421
* constructor</em> in a class that contains no explicit
422
* constructor declarations.
423
*
424
* Another example of a mandated construct is an implicitly
425
* declared <em>container annotation</em> used to hold
426
* multiple annotations of a repeatable annotation interface.
427
*
428
* @jls 8.8.9 Default Constructor
429
* @jls 8.9.3 Enum Members
430
* @jls 9.6.3 Repeatable Annotation Types
431
* @jls 9.7.5 Multiple Annotations of the Same Interface
432
*/
433
MANDATED,
434
435
/**
436
* A synthetic construct is one that is neither implicitly nor
437
* explicitly declared in the source code. Such a construct is
438
* typically a translation artifact created by a compiler.
439
*/
440
SYNTHETIC;
441
442
/**
443
* Returns {@code true} for values corresponding to constructs
444
* that are implicitly or explicitly declared, {@code false}
445
* otherwise.
446
* @return {@code true} for {@link #EXPLICIT} and {@link #MANDATED},
447
* {@code false} otherwise.
448
*/
449
public boolean isDeclared() {
450
return this != SYNTHETIC;
451
}
452
}
453
454
/**
455
* {@return {@code true} if the executable element is a bridge
456
* method, {@code false} otherwise}
457
*
458
* @implSpec The default implementation of this method returns {@code false}.
459
*
460
* @param e the executable being examined
461
* @since 9
462
*/
463
default boolean isBridge(ExecutableElement e) {
464
return false;
465
}
466
467
/**
468
* {@return the <i>binary name</i> of a type element}
469
*
470
* @param type the type element being examined
471
*
472
* @see TypeElement#getQualifiedName
473
* @jls 13.1 The Form of a Binary
474
*/
475
Name getBinaryName(TypeElement type);
476
477
478
/**
479
* {@return the package of an element} The package of a package is
480
* itself.
481
* The package of a module is {@code null}.
482
*
483
* The package of a top-level class or interface is its {@linkplain
484
* TypeElement#getEnclosingElement enclosing package}. Otherwise,
485
* the package of an element is equal to the package of the
486
* {@linkplain Element#getEnclosingElement enclosing element}.
487
*
488
* @param e the element being examined
489
*/
490
PackageElement getPackageOf(Element e);
491
492
/**
493
* {@return the module of an element} The module of a module is
494
* itself.
495
*
496
* If a package has a module as its {@linkplain
497
* PackageElement#getEnclosingElement enclosing element}, that
498
* module is the module of the package. If the enclosing element
499
* of a package is {@code null}, {@code null} is returned for the
500
* package's module.
501
*
502
* (One situation where a package may have a {@code null} module
503
* is if the environment does not include modules, such as an
504
* annotation processing environment configured for a {@linkplain
505
* javax.annotation.processing.ProcessingEnvironment#getSourceVersion
506
* source version} without modules.)
507
*
508
* Otherwise, the module of an element is equal to the module
509
* {@linkplain #getPackageOf(Element) of the package} of the
510
* element.
511
*
512
* @implSpec The default implementation of this method returns
513
* {@code null}.
514
*
515
* @param e the element being examined
516
* @since 9
517
*/
518
default ModuleElement getModuleOf(Element e) {
519
return null;
520
}
521
522
/**
523
* Returns all members of a type element, whether inherited or
524
* declared directly. For a class the result also includes its
525
* constructors, but not local or anonymous classes.
526
*
527
* @apiNote Elements of certain kinds can be isolated using
528
* methods in {@link ElementFilter}.
529
*
530
* @param type the type being examined
531
* @return all members of the type
532
* @see Element#getEnclosedElements
533
*/
534
List<? extends Element> getAllMembers(TypeElement type);
535
536
/**
537
* Returns all annotations <i>present</i> on an element, whether
538
* directly present or present via inheritance.
539
*
540
* <p>Note that any annotations returned by this method are
541
* declaration annotations.
542
*
543
* @param e the element being examined
544
* @return all annotations of the element
545
* @see Element#getAnnotationMirrors
546
* @see javax.lang.model.AnnotatedConstruct
547
*/
548
List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e);
549
550
/**
551
* Tests whether one type, method, or field hides another.
552
*
553
* @param hider the first element
554
* @param hidden the second element
555
* @return {@code true} if and only if the first element hides
556
* the second
557
* @jls 8.4.8 Inheritance, Overriding, and Hiding
558
*/
559
boolean hides(Element hider, Element hidden);
560
561
/**
562
* Tests whether one method, as a member of a given class or interface,
563
* overrides another method.
564
* When a non-abstract method overrides an abstract one, the
565
* former is also said to <i>implement</i> the latter.
566
*
567
* <p> In the simplest and most typical usage, the value of the
568
* {@code type} parameter will simply be the class or interface
569
* directly enclosing {@code overrider} (the possibly-overriding
570
* method). For example, suppose {@code m1} represents the method
571
* {@code String.hashCode} and {@code m2} represents {@code
572
* Object.hashCode}. We can then ask whether {@code m1} overrides
573
* {@code m2} within the class {@code String} (it does):
574
*
575
* <blockquote>
576
* {@code assert elements.overrides(m1, m2,
577
* elements.getTypeElement("java.lang.String")); }
578
* </blockquote>
579
*
580
* A more interesting case can be illustrated by the following example
581
* in which a method in class {@code A} does not override a
582
* like-named method in interface {@code B}:
583
*
584
* <blockquote>
585
* {@code class A { public void m() {} } }<br>
586
* {@code interface B { void m(); } }<br>
587
* ...<br>
588
* {@code m1 = ...; // A.m }<br>
589
* {@code m2 = ...; // B.m }<br>
590
* {@code assert ! elements.overrides(m1, m2,
591
* elements.getTypeElement("A")); }
592
* </blockquote>
593
*
594
* When viewed as a member of a third class {@code C}, however,
595
* the method in {@code A} does override the one in {@code B}:
596
*
597
* <blockquote>
598
* {@code class C extends A implements B {} }<br>
599
* ...<br>
600
* {@code assert elements.overrides(m1, m2,
601
* elements.getTypeElement("C")); }
602
* </blockquote>
603
*
604
* @param overrider the first method, possible overrider
605
* @param overridden the second method, possibly being overridden
606
* @param type the class or interface of which the first method is a member
607
* @return {@code true} if and only if the first method overrides
608
* the second
609
* @jls 8.4.8 Inheritance, Overriding, and Hiding
610
* @jls 9.4.1 Inheritance and Overriding
611
*/
612
boolean overrides(ExecutableElement overrider, ExecutableElement overridden,
613
TypeElement type);
614
615
/**
616
* Returns the text of a <i>constant expression</i> representing a
617
* primitive value or a string.
618
* The text returned is in a form suitable for representing the value
619
* in source code.
620
*
621
* @param value a primitive value or string
622
* @return the text of a constant expression
623
* @throws IllegalArgumentException if the argument is not a primitive
624
* value or string
625
*
626
* @see VariableElement#getConstantValue()
627
*/
628
String getConstantExpression(Object value);
629
630
/**
631
* Prints a representation of the elements to the given writer in
632
* the specified order. The main purpose of this method is for
633
* diagnostics. The exact format of the output is <em>not</em>
634
* specified and is subject to change.
635
*
636
* @param w the writer to print the output to
637
* @param elements the elements to print
638
*/
639
void printElements(java.io.Writer w, Element... elements);
640
641
/**
642
* {@return a name with the same sequence of characters as the
643
* argument}
644
*
645
* @param cs the character sequence to return as a name
646
*/
647
Name getName(CharSequence cs);
648
649
/**
650
* {@return {@code true} if the type element is a functional
651
* interface, {@code false} otherwise}
652
*
653
* @param type the type element being examined
654
* @jls 9.8 Functional Interfaces
655
* @since 1.8
656
*/
657
boolean isFunctionalInterface(TypeElement type);
658
659
/**
660
* {@return {@code true} if the module element is an automatic
661
* module, {@code false} otherwise}
662
*
663
* @implSpec
664
* The default implementation of this method returns {@code
665
* false}.
666
*
667
* @param module the module element being examined
668
* @jls 7.7.1 Dependences
669
* @since 17
670
*/
671
default boolean isAutomaticModule(ModuleElement module) {
672
return false;
673
}
674
675
/**
676
* Returns the record component for the given accessor. Returns null if the
677
* given method is not a record component accessor.
678
*
679
* @implSpec The default implementation of this method checks if the element
680
* enclosing the accessor has kind {@link ElementKind#RECORD RECORD} if that is
681
* the case, then all the record components on the accessor's enclosing element
682
* are retrieved by invoking {@link ElementFilter#recordComponentsIn(Iterable)}.
683
* If the accessor of at least one of the record components retrieved happen to
684
* be equal to the accessor passed as a parameter to this method, then that
685
* record component is returned, in any other case {@code null} is returned.
686
*
687
* @param accessor the method for which the record component should be found.
688
* @return the record component, or null if the given method is not an record
689
* component accessor
690
* @since 16
691
*/
692
default RecordComponentElement recordComponentFor(ExecutableElement accessor) {
693
if (accessor.getEnclosingElement().getKind() == ElementKind.RECORD) {
694
for (RecordComponentElement rec : ElementFilter.recordComponentsIn(accessor.getEnclosingElement().getEnclosedElements())) {
695
if (Objects.equals(rec.getAccessor(), accessor)) {
696
return rec;
697
}
698
}
699
}
700
return null;
701
}
702
}
703
704