示例#1
0
文件: DB.java 项目: o-nix/Kafra
  @SuppressWarnings("unchecked")
  protected Object unwrap(Object node) {
    Object result = node;

    if (node instanceof Map) {
      Map<String, Object> cast = (Map<String, Object>) node;

      ORecordId id;

      if (cast.containsKey("id")) {
        id = new ORecordId((String) cast.get("id"));
        cast.remove("id");
      } else id = new ORecordId();

      ODocument real;

      if (id.isNew()) {
        if (cast.containsKey("class")) {
          real = new ODocument((String) cast.get("class"));

          cast.remove("class");
        } else
          throw new RuntimeException(
              "Unknown class in newly created ODocument. Please provide 'class' property in every new object.");
      } else real = new ODocument(id);

      for (String key : cast.keySet()) real.field(key, unwrap(cast.get(key)));

      result = real;
    } else if (node instanceof List) {
      List<Object> cast = (List<Object>) node;

      for (int i = 0; i < cast.size(); i++) cast.set(i, unwrap(cast.get(i)));
    }

    return result;
  }
  public void executeSaveRecord(
      final ORecordInternal<?> iRecord,
      String iClusterName,
      final int iVersion,
      final byte iRecordType) {
    checkOpeness();

    if (!iRecord.isDirty()) return;

    final ORecordId rid = (ORecordId) iRecord.getIdentity();

    if (rid == null)
      throw new ODatabaseException(
          "Cannot create record because it has no identity. Probably is not a regular record or contains projections of fields rather than a full record");

    setCurrentDatabaseinThreadLocal();

    try {
      final boolean wasNew = rid.isNew();

      // STREAM.LENGTH == 0 -> RECORD IN STACK: WILL BE SAVED AFTER
      byte[] stream = iRecord.toStream();

      final boolean isNew = rid.isNew();
      if (isNew)
        // NOTIFY IDENTITY HAS CHANGED
        iRecord.onBeforeIdentityChanged(rid);
      else if (stream.length == 0)
        // ALREADY CREATED AND WAITING FOR THE RIGHT UPDATE (WE'RE IN A GRAPH)
        return;

      if (isNew && rid.clusterId < 0)
        rid.clusterId =
            iClusterName != null ? getClusterIdByName(iClusterName) : getDefaultClusterId();

      if (rid.clusterId > -1 && iClusterName == null)
        iClusterName = getClusterNameById(rid.clusterId);

      if (stream != null && stream.length > 0) {
        if (wasNew) {
          // CHECK ACCESS ON CLUSTER
          checkSecurity(ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_CREATE, iClusterName);
          if (callbackHooks(TYPE.BEFORE_CREATE, iRecord))
            // RECORD CHANGED IN TRIGGER, REACQUIRE IT
            stream = iRecord.toStream();
        } else {
          // CHECK ACCESS ON CLUSTER
          checkSecurity(ODatabaseSecurityResources.CLUSTER, ORole.PERMISSION_UPDATE, iClusterName);
          if (callbackHooks(TYPE.BEFORE_UPDATE, iRecord))
            // RECORD CHANGED IN TRIGGER, REACQUIRE IT
            stream = iRecord.toStream();
        }

        if (!iRecord.isDirty()) {
          // RECORD SAVED DURING PREVIOUS STREAMING PHASE: THIS HAPPENS FOR CIRCULAR REFERENCED
          // RECORDS
          // ADD/UPDATE IT IN CACHE IF IT'S ACTIVE
          getLevel1Cache().updateRecord(iRecord);
          return;
        }
      }

      // GET THE LATEST VERSION. IT COULD CHANGE BECAUSE THE RECORD COULD BE BEEN LINKED FROM OTHERS
      final int realVersion = iVersion == -1 || !mvcc ? -1 : iRecord.getVersion();

      // SAVE IT
      final long result = underlying.save(rid, stream, realVersion, iRecord.getRecordType());

      if (isNew) {
        // UPDATE INFORMATION: CLUSTER ID+POSITION
        ((ORecordId) iRecord.getIdentity()).copyFrom(rid);
        // NOTIFY IDENTITY HAS CHANGED
        iRecord.onAfterIdentityChanged(iRecord);
        // UPDATE INFORMATION: CLUSTER ID+POSITION
        iRecord.fill(rid, 0, stream, stream == null || stream.length == 0);
      } else {
        // UPDATE INFORMATION: VERSION
        iRecord.fill(rid, (int) result, stream, stream == null || stream.length == 0);
      }

      callbackHooks(wasNew ? TYPE.AFTER_CREATE : TYPE.AFTER_UPDATE, iRecord);

      if (stream != null && stream.length > 0)
        // ADD/UPDATE IT IN CACHE IF IT'S ACTIVE
        getLevel1Cache().updateRecord(iRecord);

    } catch (OException e) {
      // RE-THROW THE EXCEPTION
      throw e;

    } catch (Throwable t) {
      // WRAP IT AS ODATABASE EXCEPTION
      throw new ODatabaseException(
          "Error on saving record in cluster #" + iRecord.getIdentity().getClusterId(), t);
    }
  }