示例#1
1
  private Prop findRelProperty(Class<?> fromCls, String rel, Class<?> toCls) {
    Object entity = !fromCls.isInterface() ? data.constructor.create(fromCls) : null;

    for (Prop prop : Beany.propertiesOf(fromCls).select(data.relPropSelector)) {

      String relName = null;

      if (!fromCls.isInterface()) {
        Object value = prop.getRaw(entity);
        if (hasEntityLinks(value)) {
          EntityLinks links = entityLinks(value);
          relName = links.relationName();
        }
      } else {
        Rel relation = prop.getAnnotation(Rel.class);
        if (relation != null) {
          relName = relation.value();
        }
      }

      if (relName != null && relName.equals(rel)) {
        if (prop.getRawTypeArg(0).equals(toCls)) {
          return prop;
        }
      }
    }

    Log.warn(
        "Didn't find inverse relation property!", "relation", rel, "from", fromCls, "to", toCls);
    return null;
  }
示例#2
0
  private void deleteRelsFor(Object entity) {
    for (Prop prop : Beany.propertiesOf(entity).select(data.relPropSelector)) {
      Object value = prop.getRaw(entity);

      if (hasEntityLinks(value)) {
        EntityLinks links = entityLinks(value);
        long fromId = links.fromId();
        propageteRelChanges(entity, prop, links, fromId, null, links.allRelIds());
      }
    }
  }
示例#3
0
  private RelPair getRelPair(Object entity, Prop prop, String rel, boolean inverse) {

    Class<?> cls = prop.getRawTypeArg(0);
    Class<? extends Object> entCls = Cls.unproxy(entity.getClass());

    Class<?> srcType = inverse ? cls : entCls;
    Class<?> destType = inverse ? entCls : cls;

    Tuple key = new Tuple(rel, srcType, destType);
    RelPair relPair = data.relPairs.get(key);

    Prop srcProp, destProp;

    if (relPair != null) {
      srcProp = relPair.srcProp;
      destProp = relPair.destProp;
    } else {
      String invRel = inverse ? rel : "^" + rel;
      Prop p = findRelProperty(cls, invRel, entCls);
      srcProp = inverse ? p : prop;
      destProp = inverse ? prop : p;

      relPair = new RelPair(rel, srcType, destType, srcProp, destProp);
      data.relPairs.putIfAbsent(key, relPair);

      if (srcType == null || srcProp == null || destType == null || destProp == null) {
        Log.warn("Incomplete relation pair!", "relation", relPair);
      }
    }

    return relPair;
  }
示例#4
0
 private void relUnlink(String relation, Prop srcProp, long fromId, Prop destProp, long toId) {
   if (srcProp != null && destProp != null) {
     Object from = get_(fromId, true);
     EntityLinks srcRels = entityLinks(srcProp.getRaw(from));
     srcRels.removeRelTo(toId);
     update_(fromId, from, false, false);
   }
 }
示例#5
0
  private void update_(long id, Object record, boolean reflectRelChanges, boolean checkSecurity) {

    failIfReadonlyTx();
    validateId(id);

    Rec old = data.data.get(id);
    Object entity = obj(old);

    if (checkSecurity) {
      secureUpdate(entity);
    }

    // Optimistic concurrency control through the "version" property
    Long oldVersion = U.or(Beany.getPropValueOfType(entity, VERSION, Long.class, null), 0L);
    Long recordVersion = U.or(Beany.getPropValueOfType(record, VERSION, Long.class, null), 0L);

    occErrorIf(
        !U.eq(oldVersion, recordVersion),
        "Concurrent modification occured while updating the object with ID=%s!",
        id);

    Beany.setId(record, id);

    if (!sudo && checkSecurity) {
      boolean canUpdate = false;
      for (Prop prop : Beany.propertiesOf(record)) {
        if (!Secure.getPropertyPermissions(username(), entity.getClass(), entity, prop.getName())
            .change) {
          prop.set(record, prop.get(entity));
        } else {
          canUpdate = true;
        }
      }
      U.secure(
          canUpdate,
          "Not enough privileges to update any column of %s!",
          entity.getClass().getSimpleName());
    }

    // Optimistic concurrency control through the "version" property
    if (Beany.hasProperty(record, VERSION)) {
      Beany.setPropValue(record, VERSION, oldVersion + 1);
    }

    if (checkSecurity) {
      secureUpdate(record);
    }

    if (Beany.hasProperty(record, LAST_UPDATED_BY)) {
      Beany.setPropValue(record, LAST_UPDATED_BY, username());
    }

    if (Beany.hasProperty(record, LAST_UPDATED_ON)) {
      Beany.setPropValue(record, LAST_UPDATED_ON, new Date());
    }

    boolean updated = data.data.replace(id, old, rec(record));

    occErrorIf(
        !updated, "Concurrent modification occured while updating the object with ID=%s!", id);

    if (data.insideTx.get()) {
      data.txChanges.putIfAbsent(id, old);
    }

    if (old == null) {
      throw new IllegalStateException("Cannot update non-existing record with ID=" + id);
    }

    if (reflectRelChanges) {
      updateChangesFromRels(record);
    }

    data.lastChangedOn.set(System.currentTimeMillis());

    Log.audit("Updated DB record", "id", id);
  }
示例#6
0
 @Override
 public boolean eval(Prop prop) throws Exception {
   return Cls.isAssignableTo(
       prop.getType(), Number.class, String.class, Boolean.class, Enum.class, Date.class);
 }