public interface Path extends Comparable<Path>, Iterable<Path>, Watchable
Path は、特別な区切り文字で区切られた一連のディレクトリ名およびファイル名の要素で構成される階層構造のパスを表します。ルートコンポーネント (ファイルシステム階層を識別するもの) が存在する場合もあります。ディレクトリ階層のルートからもっとも遠い名前要素は、ファイルまたはディレクトリの名前です。その他の名前要素はディレクトリ名です。Path は、ルート、ルートと一連の名前、または単に 1 つまたは複数の名前要素のみを表すことができます。Path は、1 つの空の名前要素のみで構成される場合は空のパスとみなされます。空のパスを使用してファイルにアクセスすることは、ファイルシステムのデフォルトディレクトリにアクセスすることと同じです。Path は、パスコンポーネントまたはその名前要素のサブシーケンスにアクセスするための getFileName、getParent、getRoot、および subpath メソッドを定義します。
Path は、パスコンポーネントにアクセスするほかに、パスを結合するための resolve および resolveSibling メソッドも定義します。relativize メソッドを使用すると、2 つのパス間の相対パスを構築できます。startsWith および endWith メソッドを使用してパスを相互に比較したり、テストしたりできます。
このインタフェースは、Watchable インタフェースを拡張して、パスで検索されるディレクトリを WatchService と監視されるディレクトリ内のエントリに登録できます。
警告: このインタフェースは、カスタムファイルシステムの実装を開発する人によって実装されることのみを目的としています。将来のリリースでは、このインタフェースにメソッドが追加される可能性があります。
Files クラスで Path を使用することで、ファイル、ディレクトリ、およびその他の種類のファイルを操作できます。たとえば、BufferedReader でファイル「access.log」からテキストを読み取るとします。ファイルは、現在の作業ディレクトリからの相対ディレクトリ「logs」にあり、UTF-8 形式でエンコードされています。
Path path = FileSystems.getDefault().getPath("logs", "access.log");
BufferReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
デフォルトプロバイダに関連付けられた Path は通常、java.io.File クラスと相互運用可能です。ほかのプロバイダによって作成された Path は、java.io.File で表される抽象パス名と相互運用可能であることはまれです。toPath メソッドを使用すると、java.io.File オブジェクトで表される抽象パス名から Path を取得できます。結果の Path を使用すると、java.io.File オブジェクトと同じファイルを操作できます。さらに、toFile メソッドは、Path の String 表現から File を構築するのに役立ちます。
このインタフェースの実装は不変であり、複数の並行スレッドで安全に使用できます。
Paths| 修飾子と型 | メソッドと説明 |
|---|---|
int |
compareTo(Path other)
2 つの抽象パスを語彙的に比較します。
|
boolean |
endsWith(Path other)
このパスが、指定されたパスで終わるかどうかをテストします。
|
boolean |
endsWith(String other)
このパスが、
endsWith(Path) メソッドで指定されたとおりの方法で指定のパス文字列を変換することで構築される、Path で終わるかどうかをテストします。 |
boolean |
equals(Object other)
このパスが指定されたオブジェクトと等しいかどうかをテストします。
|
Path |
getFileName()
このパスが示すファイルまたはディレクトリの名前を
Path オブジェクトとして返します。 |
FileSystem |
getFileSystem()
このオブジェクトを作成したファイルシステムを返します。
|
Path |
getName(int index)
このパスの名前要素を
Path オブジェクトとして返します。 |
int |
getNameCount()
パス内の名前要素の数を返します。
|
Path |
getParent()
親のパスを返します。このパスが親を持たない場合は
null を返します。 |
Path |
getRoot()
このパスのルートコンポーネントを
Path オブジェクトとして返します。このパスがルートコンポーネントを持たない場合は null を返します。 |
int |
hashCode()
このパスのハッシュコードを計算します。
|
boolean |
isAbsolute()
このパスが絶対かどうかを通知します。
|
Iterator<Path> |
iterator()
このパスの名前要素を処理するイテレータを返します。
|
Path |
normalize()
このパスから冗長な名前要素を削除したパスを返します。
|
WatchKey |
register(WatchService watcher, WatchEvent.Kind<?>... events)
このパスで検出されたファイルを監視サービスに登録します。
|
WatchKey |
register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers)
このパスで検出されたファイルを監視サービスに登録します。
|
Path |
relativize(Path other)
このパスと指定されたパスとの間の相対パスを構築します。
|
Path |
resolve(Path other)
指定されたパスをこのパスに対して解決します。
|
Path |
resolve(String other)
|
Path |
resolveSibling(Path other)
指定されたパスをこのパスの
親パスに対して解決します。 |
Path |
resolveSibling(String other)
|
boolean |
startsWith(Path other)
このパスが、指定されたパスで始まるかどうかをテストします。
|
boolean |
startsWith(String other)
このパスが、
startsWith(Path) メソッドで指定されたとおりの方法で指定のパス文字列を変換することで構築される、Path で始まるかどうかをテストします。 |
Path |
subpath(int beginIndex, int endIndex)
このパスの名前要素のサブシーケンスである相対
Path を返します。 |
Path |
toAbsolutePath()
このパスの絶対パスを表す
Path オブジェクトを返します。 |
File |
toFile()
このパスを表す
File オブジェクトを返します。 |
Path |
toRealPath(LinkOption... options)
既存のファイルの実際のパスを返します。
|
String |
toString()
このパスの文字列表現を返します。
|
URI |
toUri()
このパスを表す URI を返します。
|
FileSystem getFileSystem()
boolean isAbsolute()
絶対パスは完全であり、ファイルを見つけるためにほかのパス情報と組み合わせる必要はありません。
truePath getRoot()
Path オブジェクトとして返します。このパスがルートコンポーネントを持たない場合は null を返します。nullPath getFileName()
Path オブジェクトとして返します。このファイル名は、ディレクトリ階層のルートからもっとも遠い要素です。nullPath getParent()
null を返します。
このパスオブジェクトの親は、このパスのルートコンポーネント (存在する場合) とパス内の各要素 (ディレクトリ階層のルートからもっとも遠い要素を除く) で構成されます。このメソッドはファイルシステムにアクセスしません。つまり、パスまたはその親が存在しない可能性があります。さらに、このメソッドでは一部の実装で使用できる「.」や「..」などの特殊な名前を削除しません。たとえば、UNIX では、「/a/b/c」の親は「/a/b」であり、「x/y/.」の親は「x/y」です。このメソッドを normalize メソッドとともに使用すると、シェルのようなナビゲーションが必要な場合に、冗長な名前を削除できます。
このパスに 1 つまたは複数の要素が含まれるが、ルートコンポーネントがない場合、このメソッドは次の式の評価と同等になります。
subpath(0, getNameCount()-1);
int getNameCount()
0Path getName(int index)
Path オブジェクトとして返します。
index パラメータは、返される名前要素のインデックスです。ディレクトリ階層のルートにもっとも近い要素のインデックスは 0 になります。そのルートからもっとも遠い要素のインデックスは、要素数 -1 になります。
index - 要素のインデックスIllegalArgumentException - index が負の値である場合、index が要素数と等しいか、それよりも大きい場合、またはこのパスに名前要素が含まれていない場合Path subpath(int beginIndex, int endIndex)
Path を返します。
beginIndex および endIndex パラメータは、名前要素のサブシーケンスを指定します。ディレクトリ階層のルートにもっとも近い名前のインデックスは 0 になります。そのルートからもっとも遠い名前のインデックスは、要素数 -1 になります。返される Path オブジェクトには、beginIndex から始まり、インデックス endIndex-1 の要素にまで及ぶ名前要素が含まれます。
beginIndex - 最初の要素のインデックス (これを含む)endIndex - 最後の要素のインデックス (これを含まない)Path の名前要素のサブシーケンスである新しい Path オブジェクトIllegalArgumentException - beginIndex が負の値である場合、またはそれが要素数に等しいか、それよりも大きい場合。endIndex が beginIndex に等しいか、それよりも小さい場合、またはそれが要素数よりも大きい場合。boolean startsWith(Path other)
このパスのルートコンポーネントが指定されたパスのルートコンポーネントで始まり、かつこのパスが指定されたパスと同じ名前要素で始まる場合、このパスは指定されたパスで始まります。指定されたパスにこのパスよりも多くの名前要素が含まれている場合は、false が返されます。
このパスのルートコンポーネントが指定されたパスのルートコンポーネントで始まるかどうかは、ファイルシステムに固有です。このパスにルートコンポーネントが含まれておらず、指定されたパスにルートコンポーネントが含まれている場合、このパスは指定されたパスで始まりません。
指定されたパスがこのパスとは異なる FileSystem に関連付けられている場合、false が返されます。
other - 指定されたパスtrue このパスが、指定されたパスで始まる場合 true、そうでない場合 falseboolean startsWith(String other)
startsWith(Path) メソッドで指定されたとおりの方法で指定のパス文字列を変換することで構築される、Path で始まるかどうかをテストします。たとえば、UNIX では、パス「foo/bar」は「foo」および「foo/bar」で始まります。それは「f」または「fo」では始まりません。other - 指定されたパス文字列true、それ以外の場合は falseInvalidPathException - パス文字列を Path に変換できない場合。boolean endsWith(Path other)
指定されたパスには N 個の要素が含まれていて、ルートコンポーネントがなく、このパスには N 個以上の要素が含まれている場合、ルートからもっとも遠い要素で始まる、各パスの最後の N 個の要素が等しければ、このパスは指定されたパスで終わります。
指定されたパスにルートコンポーネントがある場合、このパスのルートコンポーネントが指定されたパスのルートコンポーネントで終わり、両方のパスの対応する要素が等しければ、このパスは指定されたパスで終わります。このパスのルートコンポーネントが指定されたパスのルートコンポーネントで終わるかどうかは、ファイルシステムに固有です。このパスにルートコンポーネントが含まれず、指定されたパスにルートコンポーネントが含まれている場合、このパスは指定されたパスで終わりません。
指定されたパスがこのパスとは異なる FileSystem に関連付けられている場合、false が返されます。
other - 指定されたパスtrue、それ以外の場合は falseboolean endsWith(String other)
endsWith(Path) メソッドで指定されたとおりの方法で指定のパス文字列を変換することで構築される、Path で終わるかどうかをテストします。たとえば、UNIX では、パス「foo/bar」は「foo/bar」および「bar」で終わります。それは「r」または「/bar」では終わりません。末尾の区切り文字は考慮されないため、このメソッドを Path"foo/bar" に対して String "bar/" で呼び出すと、true が返されます。other - 指定されたパス文字列true このパスが、指定されたパスで始まる場合 true、そうでない場合 falseInvalidPathException - パス文字列を Path に変換できない場合。Path normalize()
このメソッドの正確な定義は実装に依存しますが、通常、それはこのパス (冗長な名前要素を含まないパス) から派生しています。多くのファイルシステムでは、「.」および「..」は現在のディレクトリおよび親ディレクトリを示すために使われる特殊な名前です。そのようなファイルシステムでは、「.」のオカレンスはすべて冗長とみなされます。「..」の直前に「..」以外の名前が存在する場合、その両方の名前が冗長とみなされます (そのような名前を識別するプロセスが該当しなくなるまで繰り返される)。
このメソッドはファイルシステムにアクセスしません。つまり、そのパスは存在しているファイルを検出しない可能性があります。「..」とそれに先行する名前をパスから削除すると、元のパスとは異なるファイルを検出するパスが生じる可能性があります。これは、先行する名前がシンボリックリンクの場合に発生することがあります。
getParent(), toRealPath(java.nio.file.LinkOption...)Path resolve(Path other)
other パラメータが絶対パスである場合、このメソッドは普通に other を返します。other が空のパスである場合、このメソッドは普通にこのパスを返します。それ以外の場合、このメソッドはこのパスをディレクトリとみなし、指定されたパスをこのパスに対して解決します。もっとも単純なのは、指定されたパスにルートコンポーネントがない場合です。その場合、このメソッドは指定されたパスをこのパスに結合し、指定されたパスで終わるパスを結果として返します。指定されたパスにルートコンポーネントがある場合、解決は実装に大きく依存するため、未指定です。
other - このパスに対して解決するパスrelativize(java.nio.file.Path)Path resolve(String other)
Path に変換してから、resolve メソッドで指定されたとおりの方法で、この Path に対して解決します。たとえば、名前区切り文字が「/」で、パスが「foo/bar」を表すとします。このメソッドをパス文字列「gus」で呼び出すと、結果は Path "foo/bar/gus" となります。other - このパスに対して解決するパス文字列InvalidPathException - パス文字列を Path に変換できない場合。FileSystem.getPath(java.lang.String, java.lang.String...)Path resolveSibling(Path other)
親パスに対して解決します。これは、ファイル名を別のファイル名に置き換える必要がある場合に役立ちます。たとえば、名前区切り文字が「/」で、パスが「dir1/dir2/foo」を表すとします。このメソッドを Path "bar" で呼び出すと、結果は Path "dir1/dir2/bar" となります。このパスに親パスが含まれていない場合、または other が絶対パスである場合、このメソッドは other を返します。other が空のパスである場合、このメソッドはこのパスの親を返し、このパスに親がない場合は、空のパスを返します。other - このパスの親に対して解決するパスresolve(Path)Path resolveSibling(String other)
other - このパスの親に対して解決するパス文字列InvalidPathException - パス文字列を Path に変換できない場合。FileSystem.getPath(java.lang.String, java.lang.String...)Path relativize(Path other)
相対化は、解決の逆です。このメソッドは、このパスに対して解決すると指定されたパスと同じファイルを検出するパスを生成する、相対パスを構築しようとします。たとえば、UNIX では、このパスが "/a/b" で、指定されたパスが "/a/b/c/d" である場合、結果となる相対パスは "c/d" になります。このパスと指定されたパスにルートコンポーネントがない場合は、相対パスを構築できます。それらのパスのどちらか一方だけにルートコンポーネントがある場合は、相対パスを構築できません。両方のパスにルートコンポーネントがある場合、相対パスを構築できるかどうかは実装に依存します。このパスと指定されたパスが等しい場合は、空のパスが返されます。
2 つの正規化されたパス p と q について (ここでの q にはルートコンポーネントがありません)、次が成り立ちます。
p.relativize(p.resolve(q)).equals(q)
シンボリックリンクがサポートされている場合、このパスに対して解決すると、結果となるパスが、other と同じファイルの検出に使用できるパスを生成するかどうかは実装に依存します。たとえば、このパスが "/a/b" で、指定されたパスが "/a/x" である場合、結果となる相対パスは "../x" になります。"b" がシンボリックリンクの場合、"a/b/../x" が "/a/x" と同じファイルを検出するかどうかは実装に依存します。
other - このパスに対して相対化するパスIllegalArgumentException - other がこのパスに対して相対化できる Path でない場合URI toUri()
このメソッドは、プロバイダを識別する URI スキームに等しいスキームを使用して、絶対 URI を構築します。スキーム固有の部分の正確な形式はプロバイダに大きく依存します。
デフォルトプロバイダの場合、URI は絶対であるパスコンポーネントを含む階層 URI です。クエリーおよびフラグメントコンポーネントは未定義です。機関コンポーネントが定義されているかどうかは、実装に依存します。URI が java.io.File の構築に使用できるという保証はありません。特に、このパスが汎用命名規則 (UNC) パスを表す場合は、UNC サーバー名を結果となる URI の機関コンポーネントでエンコードできます。デフォルトプロバイダで、ファイルが存在し、そのファイルがディレクトリであると判定できる場合、結果となる URI はスラッシュで終わります。
デフォルトプロバイダは同様のラウンドトリップの保証を File クラスに提供します。Path p が指定された場合は、次が保証されます。
この例の場合、元のPaths.get(p.toUri()).equals(p .toAbsolutePath())
Path、URI、および新しい Path は、同じ Java 仮想マシンの複数の呼び出しで作成する必要があります。ほかのプロバイダが保証を行うかどうかはプロバイダによって異なるため、未指定です。
ファイルの内容にファイルシステムとしてアクセスするためのファイルシステムが構築される場合、返される URI がそのファイルシステム内の指定されたパスを表すか、または包含するファイルシステムの URI をエンコードする複合 URI を表すかは、実装によって大きく異なります。このリリースでは、複合 URI の形式は定義されていません。そのようなスキームは、将来のリリースで追加される可能性があります。
IOError - 絶対パスの取得中に入出力エラーが発生した場合、またはファイルの内容にファイルシステムとしてアクセスするためのファイルシステムが構築され、包含するファイルシステムの URI を取得できない場合SecurityException - デフォルトプロバイダで、セキュリティーマネージャーがインストールされていて、その toAbsolutePath メソッドがセキュリティー例外をスローする場合。Path toAbsolutePath()
Path オブジェクトを返します。
このパスがすでに絶対である場合、このメソッドは単にこのパスを返すだけです。それ以外の場合、このメソッドはそのパスを実装に依存した方法で (通常はそのパスをファイルシステムのデフォルトディレクトリに対して解決することによって) 解決します。実装によっては、このメソッドはファイルシステムにアクセスできない場合に入出力エラーをスローすることがあります。
Path オブジェクトIOError - 入出力エラーが発生した場合SecurityException - デフォルトプロバイダで、セキュリティーマネージャーがインストールされていて、このパスが絶対でない場合、セキュリティーマネージャーの checkPropertyAccess メソッドが呼び出されてシステムプロパティー user.dir へのアクセスがチェックされるPath toRealPath(LinkOption... options) throws IOException
このメソッドの正確な定義は実装に依存しますが、通常、それはこのパス (このパスと同じファイルを検出するが、ディレクトリおよびファイルの実際の名前を表す名前要素を含む絶対パス) から派生しています。たとえば、ファイルシステムに対するファイル名の比較で大文字と小文字が区別されない場合、名前要素は大文字と小文字の違いを実際に合わせて名前を表します。また、結果となるパスからは冗長な名前要素が削除されています。
このパスが相対である場合は、toAbsolutePath メソッドを呼び出した場合と同様に、最初にその絶対パスが取得されます。
options 配列を使用すると、シンボリックリンクの処理方法を指定できます。デフォルトでは、シンボリックリンクはその最終ターゲットに解決されます。オプション NOFOLLOW_LINKS が存在する場合、このメソッドはシンボリックリンクを解決しません。
一部の実装では、「..」などの特殊な名前を使用して親ディレクトリを参照できます。実際のパスを取得しているときに、「..」 (また同等のもの) の直前に「..」以外の名前が存在する場合は、実装によって通常、両方の名前が削除されます。シンボリックリンクを解決していないときに、先行する名前がシンボリックリンクである場合は、結果となるパスがこのパスと同じファイルを検出することが保証されていれば、それらの名前は削除されます。
options - シンボリックリンクの処理方法を示すオプションIOException - ファイルが存在しないか、入出力エラーが発生した場合SecurityException - デフォルトプロバイダで、セキュリティーマネージャーがインストールされている場合は、その checkRead メソッドが呼び出されてファイルへの読み取りアクセスがチェックされ、このパスが絶対でない場合は、その checkPropertyAccess メソッドが呼び出されてシステムプロパティー user.dir へのアクセスがチェックされるFile toFile()
File オブジェクトを返します。この Path がデフォルトプロバイダに関連付けられている場合、このメソッドは、このパスの String 表現で構築された File オブジェクトを返すことと同等です。
このパスが File toPath メソッドを呼び出すことで作成された場合は、このメソッドによって返された File オブジェクトが元の File に等しいという保証はありません。
File オブジェクトUnsupportedOperationException - この Path がデフォルトプロバイダに関連付けられていない場合WatchKey register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers) throws IOException
このリリースでは、このパスは存在しているディレクトリを検出します。そのディレクトリは、ディレクトリ内のエントリを監視できるように監視サービスに登録されます。events パラメータは登録するイベントであり、次のイベントを含めることができます。
ENTRY_CREATE - エントリがディレクトリ内に作成または移動されたENTRY_DELETE - エントリがディレクトリから削除または取り出されたENTRY_MODIFY - ディレクトリ内のエントリが変更された これらのイベントのコンテキストは、このパスで検出されるディレクトリと、作成、削除、または変更されるディレクトリエントリを検出するパスとの間の相対パスになります。
イベントのセットには、列挙型の StandardWatchEventKinds で定義されない実装固有の追加のイベントを含めることができます。
modifiers パラメータは、ディレクトリの登録方法を修飾する修飾子を指定します。このリリースでは、標準修飾子は定義されていません。それには、実装固有の修飾子を含めることができます。
ファイルがシンボリックリンクによって監視サービスに登録される場合、登録後も監視がそのシンボリックリンクの存在に左右され続けるかどうかは実装に固有です。
register、インタフェース: Watchablewatcher - このオブジェクトを登録する監視サービスevents - このオブジェクトを登録するべきイベントmodifiers - オブジェクトの登録方法を修飾する修飾子 (ある場合)UnsupportedOperationException - 未サポートのイベントまたは修飾子が指定された場合IllegalArgumentException - イベントまたは修飾子の無効な組み合わせが指定された場合ClosedWatchServiceException - 監視サービスが閉じられている場合NotDirectoryException - ディレクトリ内のエントリを監視するようにファイルが登録されているが、そのファイルがディレクトリではない場合 (オプションの固有例外)IOException - 入出力エラーが発生した場合SecurityException - デフォルトプロバイダで、セキュリティーマネージャーがインストールされている場合は、checkRead メソッドが呼び出されてファイルへの読み取りアクセスがチェックされます。WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) throws IOException
このメソッド呼び出しの動作は、次の呼び出しの動作とまったく同一です。
watchable.register(watcher, events, new WatchEvent.Modifier[0]);
使用例: エントリの作成、削除、および変更イベント用にディレクトリを登録するとします。
Path dir = ...
WatchService watcher = ...
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
register、インタフェース: Watchablewatcher - このオブジェクトを登録する監視サービスevents - このオブジェクトを登録するべきイベントUnsupportedOperationException - サポートされていないイベントが指定された場合IllegalArgumentException - イベントの無効な組み合わせが指定された場合ClosedWatchServiceException - 監視サービスが閉じられている場合NotDirectoryException - ディレクトリ内のエントリを監視するようにファイルが登録されているが、そのファイルがディレクトリではない場合 (オプションの固有例外)IOException - 入出力エラーが発生した場合SecurityException - デフォルトプロバイダで、セキュリティーマネージャーがインストールされている場合は、checkRead メソッドが呼び出されてファイルへの読み取りアクセスがチェックされます。Iterator<Path> iterator()
イテレータによって返される最初の要素は、ディレクトリ階層のルートにもっとも近い名前要素を表し、2 番目の要素は次にもっとも近い名前要素となり、以降も同様です。返される最後の要素は、このパスで示されるファイルまたはディレクトリの名前です。イテレータでは、ルートコンポーネント (存在する場合) は返されません。
int compareTo(Path other)
このメソッドを使って異なるファイルシステムプロバイダに関連付けられているパスを比較することはできません。
compareTo、インタフェース: Comparable<Path>other - このパスと比較されるパス。等しい場合はゼロ。このパスが引数より語彙的に小さい場合は負の値。このパスが引数より語彙的に大きい場合は正の値ClassCastException - パスが異なるプロバイダに関連付けられている場合boolean equals(Object other)
指定されたオブジェクトが Path でないか、別の FileSystem に関連付けられた Path である場合、このメソッドは false を返します。
2 つのパスが等しいかどうかは、ファイルシステムの実装によって異なります。それらのパスは大文字小文字の区別なく比較される場合も、大文字小文字を区別して比較される場合もあります。このメソッドはファイルシステムにアクセスしないため、ファイルが存在していなくてもかまいません。必要な場合は、isSameFile メソッドを使用して 2 つのパスが同じファイルを検出するかどうかを確認できます。
このメソッドは Object.equals の汎用規約を満たします。
equals、クラス: Objectother - このオブジェクトと比較するオブジェクトPath と同じ Path である場合にのみ trueObject.hashCode(), HashMapint hashCode()
ハッシュコードは、パスのコンポーネントに基づいており、Object.hashCode メソッドの汎用規約を満たします。
hashCode、クラス: ObjectObject.equals(java.lang.Object), System.identityHashCode(java.lang.Object) バグまたは機能を送信
詳細な API リファレンスおよび開発者ドキュメントについては、Java SE のドキュメントを参照してください。そのドキュメントには、概念的な概要、用語の定義、回避方法、有効なコード例などの、開発者を対象にしたより詳細な説明が含まれています。
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.