Generics / type does not match / interop with Java

Hi,

does anyone know, why the types don’t match?

Type mismatch. Required: Database<T> Found: Database<JsonResourceManager!>!

In the following function

fun <T, R, W> openDatabase(databaseName: String): Database<T> where T : ResourceManager<R, W>,
                                                                    R : NodeReadOnlyTrx,
                                                                    R : NodeCursor,
                                                                    W : NodeTrx,
                                                                    W : NodeCursor {
    val databaseType = Databases.getDatabaseType(location.resolve(databaseName).toAbsolutePath())
    val database: Database<T> =
        when (databaseType) {
            DatabaseType.JSON -> Databases.openJsonDatabase(location.resolve(databaseName))
            DatabaseType.XML -> Databases.openXmlDatabase(location.resolve(databaseName))
        }
    return database
}

In Java the Database interface is defined as

public interface Database<T extends ResourceManager<? extends NodeReadOnlyTrx, ? extends NodeTrx>>
extends AutoCloseable

public interface JsonResourceManager extends ResourceManager<JsonNodeReadOnlyTrx, JsonNodeTrx>

public final class LocalJsonDatabase extends AbstractLocalDatabase<JsonResourceManager>

public abstract class AbstractLocalDatabase<T extends ResourceManager<? extends NodeReadOnlyTrx, ? extends NodeTrx>>
implements Database<T>

and

Database.openJsonDatabase(Path) for instance returns Database<JsonResourceManager>.

In Java this class for instance works:

public final class AllTimeAxis<R extends NodeReadOnlyTrx & NodeCursor, W extends NodeTrx & NodeCursor>
extends AbstractTemporalAxis<R, W>

and a constructor defined as:

  /**
   * Constructor.
   *
   * @param resourceManager the resource manager
   * @param rtx the read only transactional cursor
   */
  public AllTimeAxis(final ResourceManager<R, W> resourceManager, final R rtx) {

works with new AllTimeAxis(jsonResourceManager, rtx) with a JsonResourceManager as parameter.

Kind regards
Johannes

If it helps, here are the Java classes: sirix/bundles/sirix-core at master · sirixdb/sirix · GitHub

The thing about generic functions and classes is that the caller chooses the actual type. The implementation then needs to be able to handle any type that the caller might choose. In you example, your function openDatabase has return type Database<T>. That means that the caller can choose what T should be. In particular, there is nothing preventing a caller from writing openDatabase<XmlResourceManager, SomeR, SomeW>("db.json"), or even openDatabase<Nothing, Nothing, Nothing>(...).

In your example, the solution would probably be to not make openDatabase generic, but instead return some common supertype of Database<JsonResourceManager> and Database<XmlResourceManager>, like a star projection. I would guess that the following signature would work:
fun openDatabase(databaseName: String): Database<*>

1 Like

Yes, indeed, thanks :slight_smile:

Afterwards, of course I can simply check the type:

https://github.com/sirixdb/sirix/blob/master/bundles/sirix-rest-api/src/main/kotlin/org/sirix/rest/crud/Diff.kt