class OpearFile implements Opear {

    static Result<OpearMetadata> validateOpearManifest(final @Nullable Manifest manifest) {
        return Result.success(manifest)
                .map(Optional::ofNullable)
                .flatMap(optMan -> optMan.map(Result::success).orElseGet(() ->
                        Result.failure("specified opear file does not contain manifest."))
                        .flatMap(man -> ofNullable(man.getMainAttributes().getValue(NAME_BUNDLE_SYMBOLICNAME))
                                .map(Result::success)
                                .orElseGet(() -> Result.failure("opear manifest does not specify "
                                        + NAME_BUNDLE_SYMBOLICNAME.toString()))
                                .map(bsn -> ofNullable(man.getMainAttributes().getValue(NAME_BUNDLE_VERSION))
                                        .map(bvn -> bsn + "_" + bvn).orElse(bsn))
                                .flatMap(bid ->
                                        validateUriHeaderValuesWithDefaultForMissing(man, NAME_CLASS_PATH, ".")
                                                .flatMap(planClassPath ->
                                                        validateUriHeaderValues(man, NAME_OAKPAL_PLAN).flatMap(plans ->
                                                                Result.success(new OpearMetadata(plans,
                                                                        planClassPath, false))
                                                        )))));
    }

      OpearFile(final File cacheDir, final OpearMetadata metadata);

}