test_class.file: oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/JournalEntryTest.java
test_class.identifier: JournalEntryTest
test_case.body: @Test
      public void applyTo() throws Exception {
          DiffCache cache = new MemoryDiffCache(new DocumentMK.Builder());
          List<Path> paths = Lists.newArrayList();
          addRandomPaths(paths);
          StringSort sort = JournalEntry.newSorter();
          add(sort, paths);
          RevisionVector from = new RevisionVector(new Revision(1, 0, 1));
          RevisionVector to = new RevisionVector(new Revision(2, 0, 1));
          sort.sort();
          JournalEntry.applyTo(sort, cache, Path.ROOT, from, to);
  
          for (Path p : paths) {
              String changes = cache.getChanges(from, to, p, null);
              assertNotNull("missing changes for " + p, changes);
              for (String c : getChildren(changes)) {
                  assertTrue(paths.contains(new Path(p, c)));
              }
          }
          sort.close();
      }
test_case.class_method_signature: JournalEntryTest.applyTo()
test_case.full_signature: @Test public void applyTo()
test_case.identifier: applyTo
test_case.invocations: newArrayList addRandomPaths newSorter add sort applyTo getChanges assertNotNull getChildren assertTrue contains close
test_case.modifiers: @Test public
test_case.parameters: ()
test_case.return: void
test_case.signature: void applyTo()
focal_class.declarator: LOG = LoggerFactory.getLogger(JournalEntry.class)
focal_class.modifier: private static final
focal_class.original_string: private static final Logger LOG = LoggerFactory.getLogger(JournalEntry.class);
focal_class.type: Logger
focal_class.var_name: LOG
focal_class.declarator: REVISION_FORMAT = "%d-%0" +
              Long.toHexString(Long.MAX_VALUE).length() + "x-%0" +
              Integer.toHexString(Integer.MAX_VALUE).length() + "x"
focal_class.modifier: private static final
focal_class.original_string: private static final String REVISION_FORMAT = "%d-%0" +
              Long.toHexString(Long.MAX_VALUE).length() + "x-%0" +
              Integer.toHexString(Integer.MAX_VALUE).length() + "x";
focal_class.type: String
focal_class.var_name: REVISION_FORMAT
focal_class.declarator: CHANGES = "_c"
focal_class.modifier: private static final
focal_class.original_string: private static final String CHANGES = "_c";
focal_class.type: String
focal_class.var_name: CHANGES
focal_class.declarator: CHANGE_SET = "_cs"
focal_class.modifier: private static final
focal_class.original_string: private static final String CHANGE_SET = "_cs";
focal_class.type: String
focal_class.var_name: CHANGE_SET
focal_class.declarator: BRANCH_COMMITS = "_bc"
focal_class.modifier: static final
focal_class.original_string: static final String BRANCH_COMMITS = "_bc";
focal_class.type: String
focal_class.var_name: BRANCH_COMMITS
focal_class.declarator: INVALIDATE_ONLY = "_inv"
focal_class.modifier: private static final
focal_class.original_string: private static final String INVALIDATE_ONLY = "_inv";
focal_class.type: String
focal_class.var_name: INVALIDATE_ONLY
focal_class.declarator: MODIFIED = "_modified"
focal_class.modifier: public static final
focal_class.original_string: public static final String MODIFIED = "_modified";
focal_class.type: String
focal_class.var_name: MODIFIED
focal_class.declarator: READ_CHUNK_SIZE = 100
focal_class.modifier: private static final
focal_class.original_string: private static final int READ_CHUNK_SIZE = 100;
focal_class.type: int
focal_class.var_name: READ_CHUNK_SIZE
focal_class.declarator: STRING_SORT_OVERFLOW_TO_DISK_THRESHOLD
              = Integer.getInteger("oak.overflowToDiskThreshold", StringSort.BATCH_SIZE)
focal_class.modifier: private static final
focal_class.original_string: private static final int STRING_SORT_OVERFLOW_TO_DISK_THRESHOLD
              = Integer.getInteger("oak.overflowToDiskThreshold", StringSort.BATCH_SIZE);
focal_class.type: int
focal_class.var_name: STRING_SORT_OVERFLOW_TO_DISK_THRESHOLD
focal_class.declarator: store
focal_class.modifier: private final
focal_class.original_string: private final DocumentStore store;
focal_class.type: DocumentStore
focal_class.var_name: store
focal_class.declarator: changeSetBuilder
focal_class.modifier: private final
focal_class.original_string: private final ChangeSetBuilder changeSetBuilder;
focal_class.type: ChangeSetBuilder
focal_class.var_name: changeSetBuilder
focal_class.declarator: journalPropertyHandler
focal_class.modifier: private final
focal_class.original_string: private final JournalPropertyHandler journalPropertyHandler;
focal_class.type: JournalPropertyHandler
focal_class.var_name: journalPropertyHandler
focal_class.declarator: changes = null
focal_class.modifier: private volatile
focal_class.original_string: private volatile TreeNode changes = null;
focal_class.type: TreeNode
focal_class.var_name: changes
focal_class.declarator: numChangedNodes = 0
focal_class.modifier: private volatile
focal_class.original_string: private volatile int numChangedNodes = 0;
focal_class.type: int
focal_class.var_name: numChangedNodes
focal_class.declarator: hasBranchCommits = false
focal_class.modifier: private
focal_class.original_string: private boolean hasBranchCommits = false;
focal_class.type: boolean
focal_class.var_name: hasBranchCommits
focal_class.declarator: concurrent
focal_class.modifier: private
focal_class.original_string: private boolean concurrent;
focal_class.type: boolean
focal_class.var_name: concurrent
focal_class.file: oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/JournalEntry.java
focal_class.identifier: JournalEntry
focal_class.class_method_signature: JournalEntry.JournalEntry(DocumentStore store)
focal_class.full_signature:   JournalEntry(DocumentStore store)
focal_class.identifier: JournalEntry
focal_class.parameters: (DocumentStore store)
focal_class.signature:  JournalEntry(DocumentStore store)
focal_class.class_method_signature: JournalEntry.JournalEntry(DocumentStore store, boolean concurrent, ChangeSetBuilder changeSetBuilder,
                   JournalPropertyHandler journalPropertyHandler)
focal_class.full_signature:   JournalEntry(DocumentStore store, boolean concurrent, ChangeSetBuilder changeSetBuilder,
                   JournalPropertyHandler journalPropertyHandler)
focal_class.identifier: JournalEntry
focal_class.parameters: (DocumentStore store, boolean concurrent, ChangeSetBuilder changeSetBuilder,
                   JournalPropertyHandler journalPropertyHandler)
focal_class.signature:  JournalEntry(DocumentStore store, boolean concurrent, ChangeSetBuilder changeSetBuilder,
                   JournalPropertyHandler journalPropertyHandler)
focal_class.class_method_signature: JournalEntry.newSorter()
focal_class.full_signature: static StringSort newSorter()
focal_class.identifier: newSorter
focal_class.modifiers: static
focal_class.parameters: ()
focal_class.return: StringSort
focal_class.signature: StringSort newSorter()
focal_class.class_method_signature: JournalEntry.applyTo(@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)
focal_class.full_signature: static void applyTo(@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)
focal_class.identifier: applyTo
focal_class.modifiers: static
focal_class.parameters: (@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)
focal_class.return: void
focal_class.signature: void applyTo(@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)
focal_class.class_method_signature: JournalEntry.inScope(TreeNode node, Path path)
focal_class.full_signature: private static boolean inScope(TreeNode node, Path path)
focal_class.identifier: inScope
focal_class.modifiers: private static
focal_class.parameters: (TreeNode node, Path path)
focal_class.return: boolean
focal_class.signature: boolean inScope(TreeNode node, Path path)
focal_class.class_method_signature: JournalEntry.fillExternalChanges(@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store)
focal_class.full_signature: static int fillExternalChanges(@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store)
focal_class.identifier: fillExternalChanges
focal_class.modifiers: static
focal_class.parameters: (@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store)
focal_class.return: int
focal_class.signature: int fillExternalChanges(@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store)
focal_class.class_method_signature: JournalEntry.fillExternalChanges(@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Path path,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store,
                                     @NotNull Consumer<JournalEntry> journalEntryConsumer,
                                     @Nullable ChangeSetBuilder changeSetBuilder,
                                     @Nullable JournalPropertyHandler journalPropertyHandler)
focal_class.full_signature: static int fillExternalChanges(@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Path path,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store,
                                     @NotNull Consumer<JournalEntry> journalEntryConsumer,
                                     @Nullable ChangeSetBuilder changeSetBuilder,
                                     @Nullable JournalPropertyHandler journalPropertyHandler)
focal_class.identifier: fillExternalChanges
focal_class.modifiers: static
focal_class.parameters: (@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Path path,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store,
                                     @NotNull Consumer<JournalEntry> journalEntryConsumer,
                                     @Nullable ChangeSetBuilder changeSetBuilder,
                                     @Nullable JournalPropertyHandler journalPropertyHandler)
focal_class.return: int
focal_class.signature: int fillExternalChanges(@NotNull StringSort externalChanges,
                                     @NotNull StringSort invalidate,
                                     @NotNull Path path,
                                     @NotNull Revision from,
                                     @NotNull Revision to,
                                     @NotNull DocumentStore store,
                                     @NotNull Consumer<JournalEntry> journalEntryConsumer,
                                     @Nullable ChangeSetBuilder changeSetBuilder,
                                     @Nullable JournalPropertyHandler journalPropertyHandler)
focal_class.class_method_signature: JournalEntry.fillFromJournalEntry(@NotNull StringSort externalChanges,
                                               @NotNull StringSort invalidate,
                                               @NotNull Path path,
                                               @Nullable ChangeSetBuilder changeSetBuilder,
                                               @Nullable JournalPropertyHandler journalPropertyHandler,
                                               @NotNull JournalEntry d,
                                               @NotNull Consumer<JournalEntry> journalEntryConsumer)
focal_class.full_signature: private static void fillFromJournalEntry(@NotNull StringSort externalChanges,
                                               @NotNull StringSort invalidate,
                                               @NotNull Path path,
                                               @Nullable ChangeSetBuilder changeSetBuilder,
                                               @Nullable JournalPropertyHandler journalPropertyHandler,
                                               @NotNull JournalEntry d,
                                               @NotNull Consumer<JournalEntry> journalEntryConsumer)
focal_class.identifier: fillFromJournalEntry
focal_class.modifiers: private static
focal_class.parameters: (@NotNull StringSort externalChanges,
                                               @NotNull StringSort invalidate,
                                               @NotNull Path path,
                                               @Nullable ChangeSetBuilder changeSetBuilder,
                                               @Nullable JournalPropertyHandler journalPropertyHandler,
                                               @NotNull JournalEntry d,
                                               @NotNull Consumer<JournalEntry> journalEntryConsumer)
focal_class.return: void
focal_class.signature: void fillFromJournalEntry(@NotNull StringSort externalChanges,
                                               @NotNull StringSort invalidate,
                                               @NotNull Path path,
                                               @Nullable ChangeSetBuilder changeSetBuilder,
                                               @Nullable JournalPropertyHandler journalPropertyHandler,
                                               @NotNull JournalEntry d,
                                               @NotNull Consumer<JournalEntry> journalEntryConsumer)
focal_class.class_method_signature: JournalEntry.getRevisionTimestamp()
focal_class.full_signature:  long getRevisionTimestamp()
focal_class.identifier: getRevisionTimestamp
focal_class.parameters: ()
focal_class.return: long
focal_class.signature: long getRevisionTimestamp()
focal_class.class_method_signature: JournalEntry.modified(Path path)
focal_class.full_signature:  void modified(Path path)
focal_class.identifier: modified
focal_class.parameters: (Path path)
focal_class.return: void
focal_class.signature: void modified(Path path)
focal_class.class_method_signature: JournalEntry.modified(Iterable<Path> paths)
focal_class.full_signature:  void modified(Iterable<Path> paths)
focal_class.identifier: modified
focal_class.parameters: (Iterable<Path> paths)
focal_class.return: void
focal_class.signature: void modified(Iterable<Path> paths)
focal_class.class_method_signature: JournalEntry.addChangeSet(@Nullable ChangeSet changeSet)
focal_class.full_signature:  void addChangeSet(@Nullable ChangeSet changeSet)
focal_class.identifier: addChangeSet
focal_class.parameters: (@Nullable ChangeSet changeSet)
focal_class.return: void
focal_class.signature: void addChangeSet(@Nullable ChangeSet changeSet)
focal_class.class_method_signature: JournalEntry.readFrom(CommitInfo info)
focal_class.full_signature: public void readFrom(CommitInfo info)
focal_class.identifier: readFrom
focal_class.modifiers: public
focal_class.parameters: (CommitInfo info)
focal_class.return: void
focal_class.signature: void readFrom(CommitInfo info)
focal_class.class_method_signature: JournalEntry.addTo(ChangeSetBuilder changeSetBuilder)
focal_class.full_signature: private void addTo(ChangeSetBuilder changeSetBuilder)
focal_class.identifier: addTo
focal_class.modifiers: private
focal_class.parameters: (ChangeSetBuilder changeSetBuilder)
focal_class.return: void
focal_class.signature: void addTo(ChangeSetBuilder changeSetBuilder)
focal_class.class_method_signature: JournalEntry.branchCommit(@NotNull Iterable<Revision> revisions)
focal_class.full_signature:  void branchCommit(@NotNull Iterable<Revision> revisions)
focal_class.identifier: branchCommit
focal_class.parameters: (@NotNull Iterable<Revision> revisions)
focal_class.return: void
focal_class.signature: void branchCommit(@NotNull Iterable<Revision> revisions)
focal_class.class_method_signature: JournalEntry.asUpdateOp(@NotNull Revision revision)
focal_class.full_signature:  UpdateOp asUpdateOp(@NotNull Revision revision)
focal_class.identifier: asUpdateOp
focal_class.parameters: (@NotNull Revision revision)
focal_class.return: UpdateOp
focal_class.signature: UpdateOp asUpdateOp(@NotNull Revision revision)
focal_class.class_method_signature: JournalEntry.invalidate(@NotNull Iterable<Revision> revisions)
focal_class.full_signature:  void invalidate(@NotNull Iterable<Revision> revisions)
focal_class.identifier: invalidate
focal_class.parameters: (@NotNull Iterable<Revision> revisions)
focal_class.return: void
focal_class.signature: void invalidate(@NotNull Iterable<Revision> revisions)
focal_class.class_method_signature: JournalEntry.addTo(final StringSort sort, Path path)
focal_class.full_signature:  void addTo(final StringSort sort, Path path)
focal_class.identifier: addTo
focal_class.parameters: (final StringSort sort, Path path)
focal_class.return: void
focal_class.signature: void addTo(final StringSort sort, Path path)
focal_class.class_method_signature: JournalEntry.getBranchCommits()
focal_class.full_signature: @NotNull Iterable<JournalEntry> getBranchCommits()
focal_class.identifier: getBranchCommits
focal_class.modifiers: @NotNull
focal_class.parameters: ()
focal_class.return: Iterable<JournalEntry>
focal_class.signature: Iterable<JournalEntry> getBranchCommits()
focal_class.class_method_signature: JournalEntry.getNumChangedNodes()
focal_class.full_signature:  int getNumChangedNodes()
focal_class.identifier: getNumChangedNodes
focal_class.parameters: ()
focal_class.return: int
focal_class.signature: int getNumChangedNodes()
focal_class.class_method_signature: JournalEntry.hasChanges()
focal_class.full_signature:  boolean hasChanges()
focal_class.identifier: hasChanges
focal_class.parameters: ()
focal_class.return: boolean
focal_class.signature: boolean hasChanges()
focal_class.class_method_signature: JournalEntry.hasInvalidateOnlyReferences()
focal_class.full_signature: private boolean hasInvalidateOnlyReferences()
focal_class.identifier: hasInvalidateOnlyReferences
focal_class.modifiers: private
focal_class.parameters: ()
focal_class.return: boolean
focal_class.signature: boolean hasInvalidateOnlyReferences()
focal_class.class_method_signature: JournalEntry.addInvalidateOnlyTo(final StringSort sort)
focal_class.full_signature: private void addInvalidateOnlyTo(final StringSort sort)
focal_class.identifier: addInvalidateOnlyTo
focal_class.modifiers: private
focal_class.parameters: (final StringSort sort)
focal_class.return: void
focal_class.signature: void addInvalidateOnlyTo(final StringSort sort)
focal_class.class_method_signature: JournalEntry.getInvalidateOnly()
focal_class.full_signature: @NotNull private Iterable<JournalEntry> getInvalidateOnly()
focal_class.identifier: getInvalidateOnly
focal_class.modifiers: @NotNull private
focal_class.parameters: ()
focal_class.return: Iterable<JournalEntry>
focal_class.signature: Iterable<JournalEntry> getInvalidateOnly()
focal_class.class_method_signature: JournalEntry.getLinkedEntries(final String name)
focal_class.full_signature: private Iterable<JournalEntry> getLinkedEntries(final String name)
focal_class.identifier: getLinkedEntries
focal_class.modifiers: private
focal_class.parameters: (final String name)
focal_class.return: Iterable<JournalEntry>
focal_class.signature: Iterable<JournalEntry> getLinkedEntries(final String name)
focal_class.class_method_signature: JournalEntry.getChanges(TreeNode node)
focal_class.full_signature: private static String getChanges(TreeNode node)
focal_class.identifier: getChanges
focal_class.modifiers: private static
focal_class.parameters: (TreeNode node)
focal_class.return: String
focal_class.signature: String getChanges(TreeNode node)
focal_class.class_method_signature: JournalEntry.asId(@NotNull Revision revision)
focal_class.full_signature: static String asId(@NotNull Revision revision)
focal_class.identifier: asId
focal_class.modifiers: static
focal_class.parameters: (@NotNull Revision revision)
focal_class.return: String
focal_class.signature: String asId(@NotNull Revision revision)
focal_class.class_method_signature: JournalEntry.getNode(Path path)
focal_class.full_signature: @Nullable private TreeNode getNode(Path path)
focal_class.identifier: getNode
focal_class.modifiers: @Nullable private
focal_class.parameters: (Path path)
focal_class.return: TreeNode
focal_class.signature: TreeNode getNode(Path path)
focal_class.class_method_signature: JournalEntry.getChanges()
focal_class.full_signature: @NotNull private TreeNode getChanges()
focal_class.identifier: getChanges
focal_class.modifiers: @NotNull private
focal_class.parameters: ()
focal_class.return: TreeNode
focal_class.signature: TreeNode getChanges()
focal_class.superclass: extends Document
focal_method.body: static void applyTo(@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to) throws IOException {
          LOG.debug("applyTo: starting for {} from {} to {}", path, from, to);
          // note that it is not de-duplicated yet
          LOG.debug("applyTo: sorting done.");
  
          final DiffCache.Entry entry = checkNotNull(diffCache).newEntry(from, to, false);
  
          final Iterator<String> it = changedPaths.iterator();
          if (!it.hasNext()) {
              // nothing at all? that's quite unusual..
  
              // we apply this diff as no change at the given path
              entry.append(path, "");
              entry.done();
              return;
          }
          String previousPath = it.next();
          TreeNode node = new TreeNode();
          node = node.getOrCreatePath(previousPath);
          int totalCnt = 0;
          int deDuplicatedCnt = 0;
          while (it.hasNext()) {
              totalCnt++;
              final String currentPath = it.next();
              if (previousPath.equals(currentPath)) {
                  // de-duplication
                  continue;
              }
              final TreeNode currentNode = node.getOrCreatePath(currentPath);
  
              // 'node' contains one hierarchy line, eg /a, /a/b, /a/b/c, /a/b/c/d
              // including the children on each level.
              // these children have not yet been appended to the diffCache entry
              // and have to be added as soon as the 'currentPath' is not
              // part of that hierarchy anymore and we 'move elsewhere'.
              // eg if 'currentPath' is /a/b/e, then we must flush /a/b/c/d and /a/b/c
              while (node != null && !node.isAncestorOf(currentNode)) {
                  // add parent to the diff entry if within scope
                  if (inScope(node, path)) {
                      entry.append(node.getPath(), getChanges(node));
                  }
                  deDuplicatedCnt++;
                  // clean up the hierarchy when we are done with this
                  // part of the tree to avoid excessive memory usage
                  node.children = TreeNode.NO_CHILDREN;
                  node = node.parent;
              }
  
              if (node == null) {
                  // we should never go 'passed' the root, hence node should
                  // never be null - if it becomes null anyway, start with
                  // a fresh root:
                  node = new TreeNode();
                  node = node.getOrCreatePath(currentPath);
              } else {
                  // this is the normal route: we add a direct or grand-child
                  // node to the current node:
                  node = currentNode;
              }
              previousPath = currentPath;
          }
  
          // once we're done we still have the last hierarchy line contained in 'node',
          // eg /x, /x/y, /x/y/z
          // and that one we must now append to the diff cache entry:
          while (node != null && inScope(node, path)) {
              entry.append(node.getPath(), getChanges(node));
              deDuplicatedCnt++;
              node = node.parent;
          }
  
          // and finally: mark the diff cache entry as 'done':
          entry.done();
          LOG.debug("applyTo: done. totalCnt: {}, deDuplicatedCnt: {}", totalCnt, deDuplicatedCnt);
      }
focal_method.class_method_signature: JournalEntry.applyTo(@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)
focal_method.full_signature: static void applyTo(@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)
focal_method.identifier: applyTo
focal_method.invocations: debug debug newEntry checkNotNull iterator hasNext append done next getOrCreatePath hasNext next equals getOrCreatePath isAncestorOf inScope append getPath getChanges getOrCreatePath inScope append getPath getChanges done debug
focal_method.modifiers: static
focal_method.parameters: (@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)
focal_method.return: void
focal_method.signature: void applyTo(@NotNull Iterable<String> changedPaths,
                          @NotNull DiffCache diffCache,
                          @NotNull Path path,
                          @NotNull RevisionVector from,
                          @NotNull RevisionVector to)