現在、ツリー構造用のカーソル API を書き直しています。次のような方法があります。
/**
* Move cursor to parent node of currently selected node.
*
* @return the cursor instance
*/
INodeCursor moveToParent();
/**
* Move cursor to first child node of currently selected node.
*
* @return the cursor instance
*/
INodeCursor moveToFirstChild();
対応する boolean hasParent() および hasFirstChild()... メソッド。これまでは moveToX() メソッドもブール値を返していましたが、次のように考えています。
trx.moveToParent().moveToParent().insertFirstChild(...).moveToRightSibling()
...自分が何をしているのかを知っていれば、はるかに興味深いものです。ただし、失敗した場合の対処方法がわかりません (null を返して、すぐに NPE を生成しますか?)。おそらく、カーソル インスタンスを返すのが最善であり、呼び出し元は、カーソルがまったく移動されていない可能性があることに注意する必要があります。
提案をありがとう。
編集:これは Google Guava Optional のユースケースでもあるのでしょうか? このようにして、私は両方から最高のものを手に入れましたか?
trx.moveToRightSibling().get().moveToRightSibling().get().insertTextAsFirstChild("foo")
と
if (trx.moveToRightSibling.isPresent()) && trx.moveToRightSibling.isPresent() && "foo".equals(rtx.getValue) { ... }
さらに、追加の trx.hasRightSibling()... メソッド。したがって、セマンティクスはほぼ同じですが、名前が異なる自己作成の単純なラッパーかもしれません。
if (trx.moveToRightSibling().didSucceed() && ...)
と
trx.moveToRightSibling().get().moveToRightSibling().get() ...)
編集 2: たとえば:
/**
* Determines if the {@link INodeCursor} moved to a node or not. Based on the
* idea of providing a wrapper just like in Google Guava's {@link Optional}
* class.
*
* @author Johannes Lichtenberger
*
* @param <T>
* type parameter, the cursor
*/
public abstract class Move<T extends INodeCursor> {
/**
* Returns a {@link Moved} instance with no contained reference.
*/
@SuppressWarnings("unchecked")
public static <T extends INodeCursor> Move<T> notMoved() {
return (Move<T>) NotMoved.INSTANCE;
}
/**
* Returns a {@code Moved} instance containing the given non-null reference.
*/
public static <T extends INodeCursor> Moved<T> moved(final @Nonnull T pMoved) {
return new Moved<T>(checkNotNull(pMoved));
}
/**
* Determines if the cursor has moved.
*
* @return {@code true} if it has moved, {@code false} otherwise
*/
public abstract boolean hasMoved();
/**
* Get the cursor reference.
*
* @return cursor reference
*/
public abstract T get();
}
編集 3: および他のすべての moveToX() メソッドが基づいている私の moveTo(long) メソッド:
@Override
public Move<? extends INodeCursor> moveTo(final long pNodeKey) {
assertNotClosed();
if (pNodeKey == EFixed.NULL_NODE_KEY.getStandardProperty()) {
return Move.notMoved();
}
// Remember old node and fetch new one.
final INode oldNode = mCurrentNode;
Optional<? extends INodeBase> newNode;
try {
// Immediately return node from item list if node key negative.
if (pNodeKey < 0) {
if (mItemList.size() > 0) {
newNode = mItemList.getItem(pNodeKey);
} else {
newNode = Optional.absent();
}
} else {
final Optional<? extends INodeBase> node = mPageReadTrx.getNode(
pNodeKey, EPage.NODEPAGE);
newNode = node;
}
} catch (final SirixIOException e) {
newNode = Optional.absent();
}
if (newNode.isPresent()) {
mCurrentNode = (INode) newNode.get();
return Move.moved(this);
} else {
mCurrentNode = oldNode;
return Move.notMoved();
}
}