@Override public @NonNull URL getUrl(final @NonNull NodesTransaction txn, final @NonNull NodeId nodeId) { final Datum datum = txn.getDatum(nodeId); if (!(datum instanceof StringDatum)) throw new DataTypeException(nodeId, datum.getType(), StringDatumType.INSTANCE, getNodeId()); final StringDatum stringDatum = (StringDatum) datum; final String string = stringDatum.getValue(); try { return new URL(string); } catch (final MalformedURLException e) { throw new RuntimeException(e); } }
@Override public void validateDatum( final @NonNull NodesTransaction txn, final @NonNull NodeId nodeId, final @NonNull Datum datum) { if (!(datum instanceof StringDatum)) throw new DataTypeException(nodeId, datum.getType(), StringDatumType.INSTANCE, getNodeId()); }
@Override public void writeData(final @NonNull OutputChannel channel, final @NonNull Datum datum) { if (!(channel instanceof BdbOutputChannel)) throw new IllegalArgumentException("Not a BDB channel"); final BdbOutputChannel bdbChannel = (BdbOutputChannel) channel; if (!(datum instanceof ContextualStringDatum)) throw new IllegalArgumentException("Not an string datum"); final ContextualStringDatum stringDatum = (ContextualStringDatum) datum; try { bdbChannel.writeDatumType(datum.getType()); bdbChannel.dos.writeBoolean(stringDatum.unique); bdbChannel.writeNodeId(stringDatum.contextNodeId); bdbChannel.dos.writeUTF(stringDatum.value); } catch (final IOException e) { throw new FoobarError("Unable to save string data", e); } }
@Override public void writeKey(final @NonNull OutputChannel channel, final @NonNull Datum datum) { if (!(channel instanceof BdbOutputChannel)) throw new IllegalArgumentException("Not a BDB channel"); final BdbOutputChannel bdbChannel = (BdbOutputChannel) channel; if (!(datum instanceof ContextualStringDatum)) throw new IllegalArgumentException("Not an string datum"); final ContextualStringDatum stringDatum = (ContextualStringDatum) datum; try { bdbChannel.writeDatumType(datum.getType()); bdbChannel.dos.writeBoolean(stringDatum.unique); bdbChannel.writeNodeId(stringDatum.contextNodeId); // for the key we don't need to record the length because 1) it would // mess up the ordering and 2) we don't need to read it back final char[] chars = stringDatum.value.toCharArray(); for (final char c : chars) bdbChannel.dos.writeChar(c); } catch (final IOException e) { throw new FoobarError("Unable to save string key", e); } }
@Override public void updateIndex( final @NonNull NodesTransaction txn, final @NonNull NodeId nodeId, final boolean deferred) { final ValidatingKernel kernel = k1Reactor.getInstance(); final Queue queue = queueReactor.getInstance(); final WordMeaning wordMeaning = wordMeaningReactor.getInstance(); final WordParentMeaning wordParentMeaning = wordParentMeaningReactor.getInstance(); final MimeTypeMeaning mimeTypeMeaning = mimeTypeMeaningReactor.getInstance(); final LocaleMeaning localeMeaning = localeMeaningReactor.getInstance(); final Coordinator coordinator = coordReactor.getInstance(); final Reservation reservation = coordinator.reserve( CoordinatorUtil.makeSetOfRules(new BaseNodeRule(nodeId)), CoordinatorUtil.makeSetOfIntents(new BaseNodeIntent(nodeId))); try { final Datum datum = txn.getDatum(nodeId); final MimeType mimeType = mimeTypeMeaning.getMimeType(txn, nodeId); final Locale locale = localeMeaning.getLocale(txn, nodeId); final List<Stemmer> stemmers = StemmerUtil.getStemmers(bundleContext, locale); WordParser parser; if (mimeType != null) { parser = getParser(mimeType.toString()); } else if (datum instanceof StringDatum) { parser = getParser("text/plain"); } else { parser = null; } if (parser == null) return; Cursor<NodeId> cursor = null; final Map<String, NodeId> oldIndexEntries = new HashMap<String, NodeId>(); final Set<NodeId> oldNodesToDelete = new HashSet<NodeId>(); try { cursor = txn.fetchSourceNodes(nodeId, wordParentMeaning.getNodeId()); for (final NodeId linkNodeId : cursor) { if (linkNodeId != null) { final NodeId wordNodeId = txn.getTarget(linkNodeId, wordMeaning.getNodeId()); if (wordNodeId != null) { final Datum wordDatum = txn.getDatum(wordNodeId); if (wordDatum instanceof StringDatum) { final String indexEntry = ((StringDatum) wordDatum).getValue(); final NodeId oldLinkNodeId = oldIndexEntries.get(indexEntry); if (oldLinkNodeId != null) { // get rid of redundant link oldNodesToDelete.add(linkNodeId); } else { oldIndexEntries.put(indexEntry, linkNodeId); } } } } } } finally { if (cursor != null) cursor.close(); } // enqueue deletes for all redundant links for (final NodeId linkNodeId : oldNodesToDelete) { if (linkNodeId != null) { final QueueOperation op = new DeleteIndexLinkOperation( kernel, nodeId, linkNodeId, wordParentMeaning.getNodeId(), wordMeaning.getNodeId()); if (deferred) { queue.add(op, 0); queue.start(); } else op.execute(); } } Reader reader; try { reader = new InputStreamReader(datum.getInputStream()); } catch (final IOException e) { // TODO log something reader = null; } if (reader == null) return; final Set<String> newStemmedWords = new HashSet<String>(); Set<String> words = new HashSet<String>(); for (final String word : parser.parse(reader)) { if (word != null) { words.add(word); } } for (final Stemmer stemmer : stemmers) { if (stemmer != null) { words = stemmer.stem(words); } } newStemmedWords.addAll(words); for (final String word : newStemmedWords) { if (word != null) { final NodeId oldLinkNodeId = oldIndexEntries.get(word); if (oldLinkNodeId != null) { oldIndexEntries.remove(word); } else { final QueueOperation op = new IndexOperation( kernel, wicpReactor, coordReactor, word, nodeId, wordParentMeaning.getNodeId(), wordMeaning.getNodeId()); queue.add(op, 0); } } } // enqueue deletes for all old word links that no longer apply for (final NodeId linkNodeId : oldIndexEntries.values()) { if (linkNodeId != null) { final QueueOperation op = new DeleteIndexLinkOperation( kernel, nodeId, linkNodeId, wordParentMeaning.getNodeId(), wordMeaning.getNodeId()); if (deferred) queue.add(op, 0); else op.execute(); } } } finally { reservation.release(); } }