/** * Get the Java type of the object at which this path ends. * * <p> * The returned type will be as narrow as possible while still including all possibilities, but note that it's * possible for there to be multiple candidates for the "target type", none of which is a sub-type of any other. * To retrieve all such target types, use {@link #getTargetTypes}; this method just invokes * {@link Util#findLowestCommonAncestorOfClasses Util.findLowestCommonAncestorOfClasses()} on the result. * * @return the Java type at which this reference path ends */ public Class<?> getTargetType() { return Util.findLowestCommonAncestorOfClasses(this.getTargetTypes()).getRawType(); }
/** * Get the {@code byte[]} key in the underlying key/value store corresponding to the specified field in the specified object. * * <p> * Notes: * <ul> * <li>Complex fields utilize mutiple keys; the return value is the common prefix of all such keys.</li> * <li>The {@link io.permazen.kv.KVDatabase} should not be modified directly, otherwise behavior is undefined</li> * </ul> * * @param jobj Java model object * @param fieldName the name of a field in {@code jobj}'s type * @return the {@link io.permazen.kv.KVDatabase} key of the field in the specified object * @throws TypeNotInSchemaVersionException if the current schema version does not contain the object's type * @throws IllegalArgumentException if {@code jobj} does not contain the specified field * @throws IllegalArgumentException if {@code fieldName} is otherwise invalid * @throws IllegalArgumentException if either parameter is null * @see io.permazen.kv.KVTransaction#watchKey KVTransaction.watchKey() * @see io.permazen.core.Transaction#getKey(ObjId, int) Transaction.getKey() */ public byte[] getKey(JObject jobj, String fieldName) { Preconditions.checkArgument(jobj != null, "null jobj"); final Class<?> type = this.jdb.getJClass(jobj.getObjId()).type; final ReferencePath refPath = this.jdb.parseReferencePath(type, fieldName, true, false); if (refPath.getReferenceFields().length > 0) throw new IllegalArgumentException("invalid field name `" + fieldName + "'"); assert refPath.getTargetTypes().iterator().next().isInstance(jobj); return this.tx.getKey(jobj.getObjId(), refPath.targetFieldStorageId); }
valueChecks.add(new ValueCheck("target type", startType, path.getTargetTypes()));