Can IndexConfiguration be made public?

IndexConfiguration is package-private in Java and Kotlin doesn’t play nicely with such visibility. The public Database API createIndex() uses the type in its parameters. The type is inherited by two public classes, FullTextIndexConfiguration and ValueIndexConfiguration, acting as their unifying type. IndexConfiguration's super type AbstractIndex is also itself public. Is there a reason for hiding IndexConfiguration's visibility?

For my use case, I’m creating a wrapper API in Kotlin and can’t declare the IndexConfiguration type unless its public.

Hey @jeff.lockhart : Is there a reason for making it public? Is there something, specific, that you want to do that you cannot do now?

The class is not public because it doesn’t contain anything that is part of the public API, and might provide access to things whose implementation will change. Unless there is a good reason to make it public, I’d rather not.

-blake

Hi, @blake.meike. Yes, allow me to elaborate. Without the type being public, I’m unable to declare it in my wrapper code. I’m working on a Kotlin Multiplatform API which wraps the underlying Kotlin/Java and Objective-C SDKs such that they can be used in a pure Kotlin KMM module. My wrapper API has a 1:1 representation of all types in the Couchbase Lite public API. This includes IndexConfiguration because it’s part of Database's public API as a parameter to createIndex().

I need to declare the IndexConfiguration type in order for my wrapper API to store an underlying IndexConfiguration value in order to pass to the underlying Database.createIndex() API. My wrapper IndexConfiguration type serves as the unifying super type to both FullTextIndexConfiguration and ValueIndexConfiguration, the same as it does in the wrapped Couchbase Lite API.

Currently I have to use the nearest accessible public super type to declare as the type in my wrapper API (at least this is AbstractIndex instead of Object). Then I have to check the actual type of the AbstractIndex value at runtime and cast it to either FullTextIndexConfiguration or ValueIndexConfiguration in order to pass to the underlying Database.createIndex() API as the necessary IndexConfiguration type.

Ideally, I should be able to declare the IndexConfiguration type directly in my code. I have no need to call any of the restricted constructors or methods, only the class itself needs to be made public. It makes sense it should be a public type, as it’s part of Database's public API.

It looks a bit odd too in the documentation as is. The method shows the parameter as type com.couchbase.lite.IndexConfiguration config, with no link to the type to figure out how to create such a value to pass to the API.

Additionally FullTextIndexConfiguration and ValueIndexConfiguration both indicate they extend AbstractIndex as their nearest public super type, with no indication they are actually both IndexConfigurations.

Alternatively, the Database.createIndex() API could take an AbstractIndex parameter instead, combining the two overloaded createIndex() methods which take either an Index or IndexConfiguration. This may or may not be preferable for this API.

I’d expect IndexConfiguration to behave similar to Index, which is the unifying super type of ValueIndex and FullTextIndex, which differentiates them from the *IndexConfiguration types that are also AbstractIndex subclasses. Index is a public class with no public constructors, properties, or methods.

Also of note, this isn’t an issue with wrapping the Objective-C API, as CBLIndexConfiguration is a public type.

Ok. Yeah, that’s plausible.

I’m going to ask a couple more philosophical questions, now:

  1. Why wrap the entire CBL platform? There are places that definitely need wrapping but I haven’t seen the need to wrap it all. What is the goal here.
  2. If you can provide evidence for the above, we are prepared to do the work… or to work with you to do it. We intend to support fully idiomatic Kotlin. What, specifically, can we do to make this platform better?

My goal is more than supporting idiomatic Kotlin on the JVM, but to be able to develop with CBL in a pure Kotlin KMM shared module, such that the code can be compiled to both Android/JVM and iOS/Native. The reason for wrapping the API is so that the compiler can utilize either the underlying Java or Objective-C SDK, depending on the compilation target. The Kotlin API is mostly replicated from the Java API, with only a few minor differences (like property accessors instead of getters/setters in some cases). I’m also including the KTX extension functions in the API as well.

The code utilizes the Kotlin expect/actual mechanism to create platform-specific wrapper implementations around the CBL SDKs. In some cases for the Java API this can be achieved with a simple typealias, if the underlying code matches the Kotlin API 1:1. But in other cases (like if there are static functions that need to become companion object functions or other KMM nuances) then the Java code must be wrapped similar to the ObjC. The ObjC wrapper also converts types to align properly with the underlying SDK.

My goal with the KMM wrapper API is to mirror as much of CBL’s original API as possible. There are a handful of API methods I haven’t been able to implement for one reason or another because there is no pure Kotlin unifying API to utilize, mostly I/O and Executor related functions. I mentioned some of these here a while back.

I’ve achieved good success having done this originally for v2.8.6. I’m now working on updating the API to v3.0.0. I’d like to look at open sourcing my code once it’s ready. It’d be great to partner more closely with you in this effort.

That’s pretty interesting. I have created CBL-3272 to track the issue. It is a (small) change in our API, so the proposal will have to survive API review.

1 Like