示例#1
0
 /**
  * Simule la présence d'une valeur.
  *
  * <p>Seules les relations toOne sont supportées.
  *
  * @param property La propriété à simuler.
  */
 public void fake(String property) {
   // Test de la propriété
   ObjEntity ent = objEntity();
   ObjRelationship rel = (ObjRelationship) ent.getRelationship(property);
   if (rel == null) {
     throw new IllegalArgumentException("Pas de relation " + ent.getName() + "." + property);
   }
   if (rel.isToMany()) {
     throw new IllegalArgumentException(
         "La relation " + ent.getName() + "." + property + " n'est pas un toOne");
   }
   ObjEntity targetEntity = (ObjEntity) rel.getTargetEntity();
   // Ok, ajout.
   fakes.put(property, targetEntity.getJavaClass());
 }
示例#2
0
  /**
   * Creates a DataObject from DataRow.
   *
   * @see DataRow
   * @since 3.1
   */
  public <T extends Persistent> T objectFromDataRow(Class<T> objectClass, DataRow dataRow) {
    ObjEntity entity = this.getEntityResolver().getObjEntity(objectClass);

    if (entity == null) {
      throw new CayenneRuntimeException("Unmapped Java class: " + objectClass);
    }

    ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName());
    List<T> list = objectsFromDataRows(descriptor, Collections.singletonList(dataRow));
    return list.get(0);
  }
示例#3
0
  /**
   * Creates and registers a new persistent object.
   *
   * @since 1.2
   */
  @Override
  public <T> T newObject(Class<T> persistentClass) {
    if (persistentClass == null) {
      throw new NullPointerException("Null 'persistentClass'");
    }

    ObjEntity entity = getEntityResolver().getObjEntity(persistentClass);
    if (entity == null) {
      throw new IllegalArgumentException(
          "Class is not mapped with Cayenne: " + persistentClass.getName());
    }

    return (T) newObject(entity.getName());
  }
  protected void indexSubclassDescriptors(
      PersistentDescriptor descriptor, EntityInheritanceTree inheritanceTree) {

    if (inheritanceTree != null) {

      for (EntityInheritanceTree child : inheritanceTree.getChildren()) {
        ObjEntity childEntity = child.getEntity();
        descriptor.addSubclassDescriptor(
            childEntity.getClassName(), descriptorMap.getDescriptor(childEntity.getName()));

        indexSubclassDescriptors(descriptor, child);
      }
    }
  }
示例#5
0
  /**
   * Registers a transient object with the context, recursively registering all transient persistent
   * objects attached to this object via relationships.
   *
   * <p><i>Note that since 3.0 this method takes Object as an argument instead of a {@link
   * DataObject}.</i>
   *
   * @param object new object that needs to be made persistent.
   */
  @Override
  public void registerNewObject(Object object) {
    if (object == null) {
      throw new NullPointerException("Can't register null object.");
    }

    ObjEntity entity = getEntityResolver().getObjEntity((Persistent) object);
    if (entity == null) {
      throw new IllegalArgumentException(
          "Can't find ObjEntity for Persistent class: "
              + object.getClass().getName()
              + ", class is likely not mapped.");
    }

    final Persistent persistent = (Persistent) object;

    // sanity check - maybe already registered
    if (persistent.getObjectId() != null) {
      if (persistent.getObjectContext() == this) {
        // already registered, just ignore
        return;
      } else if (persistent.getObjectContext() != null) {
        throw new IllegalStateException(
            "Persistent is already registered with another DataContext. "
                + "Try using 'localObjects()' instead.");
      }
    } else {
      persistent.setObjectId(new ObjectId(entity.getName()));
    }

    ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName());
    if (descriptor == null) {
      throw new IllegalArgumentException("Invalid entity name: " + entity.getName());
    }

    injectInitialValue(object);

    // now we need to find all arc changes, inject missing value holders and
    // pull in
    // all transient connected objects

    descriptor.visitProperties(
        new PropertyVisitor() {

          public boolean visitToMany(ToManyProperty property) {
            property.injectValueHolder(persistent);

            if (!property.isFault(persistent)) {

              Object value = property.readProperty(persistent);
              Collection<Map.Entry> collection =
                  (value instanceof Map) ? ((Map) value).entrySet() : (Collection) value;

              Iterator<Map.Entry> it = collection.iterator();
              while (it.hasNext()) {
                Object target = it.next();

                if (target instanceof Persistent) {
                  Persistent targetDO = (Persistent) target;

                  // make sure it is registered
                  registerNewObject(targetDO);
                  getObjectStore()
                      .arcCreated(
                          persistent.getObjectId(), targetDO.getObjectId(), property.getName());
                }
              }
            }
            return true;
          }

          public boolean visitToOne(ToOneProperty property) {
            Object target = property.readPropertyDirectly(persistent);

            if (target instanceof Persistent) {

              Persistent targetDO = (Persistent) target;

              // make sure it is registered
              registerNewObject(targetDO);
              getObjectStore()
                  .arcCreated(persistent.getObjectId(), targetDO.getObjectId(), property.getName());
            }
            return true;
          }

          public boolean visitAttribute(AttributeProperty property) {
            return true;
          }
        });
  }
示例#6
0
  /**
   * Returns a DataRow reflecting current, possibly uncommitted, object state.
   *
   * <p><strong>Warning:</strong> This method will return a partial snapshot if an object or one of
   * its related objects that propagate their keys to this object have temporary ids. DO NOT USE
   * this method if you expect a DataRow to represent a complete object state.
   *
   * @since 1.1
   */
  public DataRow currentSnapshot(final Persistent object) {

    // for a HOLLOW object return snapshot from cache
    if (object.getPersistenceState() == PersistenceState.HOLLOW
        && object.getObjectContext() != null) {

      return getObjectStore().getSnapshot(object.getObjectId());
    }

    ObjEntity entity = getEntityResolver().getObjEntity(object);
    final ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName());
    final DataRow snapshot = new DataRow(10);
    snapshot.setEntityName(entity.getName());

    descriptor.visitProperties(
        new PropertyVisitor() {

          public boolean visitAttribute(AttributeProperty property) {
            ObjAttribute objAttr = property.getAttribute();

            // processing compound attributes correctly
            snapshot.put(objAttr.getDbAttributePath(), property.readPropertyDirectly(object));
            return true;
          }

          public boolean visitToMany(ToManyProperty property) {
            // do nothing
            return true;
          }

          public boolean visitToOne(ToOneProperty property) {
            ObjRelationship rel = property.getRelationship();

            // if target doesn't propagates its key value, skip it
            if (rel.isSourceIndependentFromTargetChange()) {
              return true;
            }

            Object targetObject = property.readPropertyDirectly(object);
            if (targetObject == null) {
              return true;
            }

            // if target is Fault, get id attributes from stored snapshot
            // to avoid unneeded fault triggering
            if (targetObject instanceof Fault) {
              DataRow storedSnapshot = getObjectStore().getSnapshot(object.getObjectId());
              if (storedSnapshot == null) {
                throw new CayenneRuntimeException(
                    "No matching objects found for ObjectId "
                        + object.getObjectId()
                        + ". Object may have been deleted externally.");
              }

              DbRelationship dbRel = rel.getDbRelationships().get(0);
              for (DbJoin join : dbRel.getJoins()) {
                String key = join.getSourceName();
                snapshot.put(key, storedSnapshot.get(key));
              }

              return true;
            }

            // target is resolved and we have an FK->PK to it,
            // so extract it from target...
            Persistent target = (Persistent) targetObject;
            Map<String, Object> idParts = target.getObjectId().getIdSnapshot();

            // this may happen in uncommitted objects - see the warning in
            // the JavaDoc
            // of
            // this method.
            if (idParts.isEmpty()) {
              return true;
            }

            DbRelationship dbRel = rel.getDbRelationships().get(0);
            Map<String, Object> fk = dbRel.srcFkSnapshotWithTargetSnapshot(idParts);
            snapshot.putAll(fk);
            return true;
          }
        });

    // process object id map
    // we should ignore any object id values if a corresponding attribute
    // is a part of relationship "toMasterPK", since those values have been
    // set above when db relationships where processed.
    Map<String, Object> thisIdParts = object.getObjectId().getIdSnapshot();
    if (thisIdParts != null) {

      // put only those that do not exist in the map
      for (Map.Entry<String, Object> entry : thisIdParts.entrySet()) {
        String nextKey = entry.getKey();
        if (!snapshot.containsKey(nextKey)) {
          snapshot.put(nextKey, entry.getValue());
        }
      }
    }

    return snapshot;
  }
  public void testForeignKey() throws Exception {
    dropTableIfPresent("NEW_TABLE");
    dropTableIfPresent("NEW_TABLE2");

    assertTokensAndExecute(0, 0);

    DbEntity dbEntity1 = new DbEntity("NEW_TABLE");

    DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
    e1col1.setMandatory(true);
    e1col1.setPrimaryKey(true);
    dbEntity1.addAttribute(e1col1);

    DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
    e1col2.setMaxLength(10);
    e1col2.setMandatory(false);
    dbEntity1.addAttribute(e1col2);

    map.addDbEntity(dbEntity1);

    DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
    DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
    e2col1.setMandatory(true);
    e2col1.setPrimaryKey(true);
    dbEntity2.addAttribute(e2col1);
    DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
    dbEntity2.addAttribute(e2col2);
    DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2);
    e2col3.setMaxLength(10);
    dbEntity2.addAttribute(e2col3);

    map.addDbEntity(dbEntity2);

    // create db relationships
    DbRelationship rel1To2 = new DbRelationship("rel1To2");
    rel1To2.setSourceEntity(dbEntity1);
    rel1To2.setTargetEntity(dbEntity2);
    rel1To2.setToMany(true);
    rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
    dbEntity1.addRelationship(rel1To2);
    DbRelationship rel2To1 = new DbRelationship("rel2To1");
    rel2To1.setSourceEntity(dbEntity2);
    rel2To1.setTargetEntity(dbEntity1);
    rel2To1.setToMany(false);
    rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
    dbEntity2.addRelationship(rel2To1);
    assertSame(rel1To2, rel2To1.getReverseRelationship());
    assertSame(rel2To1, rel1To2.getReverseRelationship());

    assertTokensAndExecute(4, 0);
    assertTokensAndExecute(0, 0);

    // create ObjEntities
    ObjEntity objEntity1 = new ObjEntity("NewTable");
    objEntity1.setDbEntity(dbEntity1);
    ObjAttribute oatr1 = new ObjAttribute("name");
    oatr1.setDbAttributePath(e1col2.getName());
    oatr1.setType("java.lang.String");
    objEntity1.addAttribute(oatr1);
    map.addObjEntity(objEntity1);
    ObjEntity objEntity2 = new ObjEntity("NewTable2");
    objEntity2.setDbEntity(dbEntity2);
    ObjAttribute o2a1 = new ObjAttribute("name");
    o2a1.setDbAttributePath(e2col3.getName());
    o2a1.setType("java.lang.String");
    objEntity2.addAttribute(o2a1);
    map.addObjEntity(objEntity2);

    // create ObjRelationships
    assertEquals(0, objEntity1.getRelationships().size());
    assertEquals(0, objEntity2.getRelationships().size());
    ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2");
    objRel1To2.addDbRelationship(rel1To2);
    objRel1To2.setSourceEntity(objEntity1);
    objRel1To2.setTargetEntity(objEntity2);
    objEntity1.addRelationship(objRel1To2);
    ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1");
    objRel2To1.addDbRelationship(rel2To1);
    objRel2To1.setSourceEntity(objEntity2);
    objRel2To1.setTargetEntity(objEntity1);
    objEntity2.addRelationship(objRel2To1);
    assertEquals(1, objEntity1.getRelationships().size());
    assertEquals(1, objEntity2.getRelationships().size());
    assertSame(objRel1To2, objRel2To1.getReverseRelationship());
    assertSame(objRel2To1, objRel1To2.getReverseRelationship());

    // remove relationship and fk from model, merge to db and read to model
    dbEntity2.removeRelationship(rel2To1.getName());
    dbEntity1.removeRelationship(rel1To2.getName());
    dbEntity2.removeAttribute(e2col2.getName());
    List<MergerToken> tokens = createMergeTokens();
    assertTokens(tokens, 2, 1);
    for (MergerToken token : tokens) {
      if (token.getDirection().isToDb()) {
        execute(token);
      }
    }
    assertTokensAndExecute(0, 0);
    dbEntity2.addRelationship(rel2To1);
    dbEntity1.addRelationship(rel1To2);
    dbEntity2.addAttribute(e2col2);

    // try do use the merger to remove the relationship in the model
    tokens = createMergeTokens();
    assertTokens(tokens, 2, 0);
    // TODO: reversing the following two tokens should also reverse the order
    MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
    MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
    if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel
        || token1 instanceof DropRelationshipToModel && token0 instanceof DropColumnToModel)) {
      fail();
    }
    execute(token0);
    execute(token1);

    // check after merging
    assertNull(dbEntity2.getAttribute(e2col2.getName()));
    assertEquals(0, dbEntity1.getRelationships().size());
    assertEquals(0, dbEntity2.getRelationships().size());
    assertEquals(0, objEntity1.getRelationships().size());
    assertEquals(0, objEntity2.getRelationships().size());

    // clear up
    dbEntity1.removeRelationship(rel1To2.getName());
    dbEntity2.removeRelationship(rel2To1.getName());
    map.removeObjEntity(objEntity1.getName(), true);
    map.removeDbEntity(dbEntity1.getName(), true);
    map.removeObjEntity(objEntity2.getName(), true);
    map.removeDbEntity(dbEntity2.getName(), true);
    resolver.refreshMappingCache();
    assertNull(map.getObjEntity(objEntity1.getName()));
    assertNull(map.getDbEntity(dbEntity1.getName()));
    assertNull(map.getObjEntity(objEntity2.getName()));
    assertNull(map.getDbEntity(dbEntity2.getName()));
    assertFalse(map.getDbEntities().contains(dbEntity1));
    assertFalse(map.getDbEntities().contains(dbEntity2));

    assertTokensAndExecute(2, 0);
    assertTokensAndExecute(0, 0);
  }