コード例 #1
0
  /** Creates an object represented by the given {@code typeId} and {@code id}. */
  public Object createObject(UUID typeId, UUID id) {
    bootstrapOnce.ensure();

    Class<?> objectClass = null;
    ObjectType type = null;
    if (typeId != null && !GLOBALS_ID.equals(id)) {

      if (typeId.equals(id)) {
        objectClass = ObjectType.class;

      } else {
        type = getTypeById(typeId);
        if (type != null) {
          objectClass = type.isAbstract() ? Record.class : type.getObjectClass();
        }
      }
    }

    boolean hasClass = true;
    if (objectClass == null) {
      objectClass = Record.class;
      hasClass = false;
    }

    Object object = SubstitutionUtils.newInstance(objectClass);
    State state;

    try {
      state = State.getInstance(object);

    } catch (IllegalArgumentException error) {
      object = TypeDefinition.getInstance(Record.class).newInstance();
      state = State.getInstance(object);
      hasClass = false;
    }

    state.setDatabase(getDatabase());
    state.setId(id);
    state.setTypeId(typeId);

    if (type != null) {
      if (!hasClass) {
        for (ObjectField field : type.getFields()) {
          Object defaultValue = field.getDefaultValue();
          if (defaultValue != null) {
            state.put(field.getInternalName(), defaultValue);
          }
        }
      }
    }

    return object;
  }
コード例 #2
0
    public static void writeContents(
        Database database,
        BootstrapPackage pkg,
        Set<ObjectType> additionalTypes,
        Writer writer,
        String projectName)
        throws IOException {
      boolean first = true;
      boolean needsObjectTypeMap = false;
      Set<ObjectType> typeMaps = new HashSet<ObjectType>();
      ObjectType objType = database.getEnvironment().getTypeByClass(ObjectType.class);
      Set<ObjectType> exportTypes = new HashSet<ObjectType>();
      Query<?> query = Query.fromAll().using(database);
      Set<ObjectType> allTypeMappableTypes = new HashSet<ObjectType>();
      Set<UUID> concreteTypeIds = new HashSet<UUID>();

      for (ObjectType type : database.getEnvironment().getTypes()) {
        if (!type.as(TypeData.class).getTypeMappableGroups().isEmpty()
            && type.as(TypeData.class).getTypeMappableUniqueKey() != null) {
          allTypeMappableTypes.add(type);
        }
      }

      // Package:
      writer.write(PACKAGE_NAME_HEADER + ": ");
      writer.write(pkg.getName());
      writer.write('\n');
      // Project:
      writer.write(PROJECT_HEADER + ": ");
      writer.write(projectName);
      writer.write('\n');
      // Date:
      writer.write(DATE_HEADER + ": ");
      writer.write(new DateTime().toString("yyyy-MM-dd HH:mm:ss z"));
      writer.write('\n');

      // Types:
      writer.write(TYPES_HEADER + ": ");
      if (pkg.isInit()) {
        writer.write(ALL_TYPES_HEADER_VALUE);
        writer.write('\n');
      } else {
        exportTypes.addAll(getAllTypes(database, pkg));
        exportTypes.addAll(getAllTypes(database, additionalTypes));
        for (ObjectType typeMappableType : allTypeMappableTypes) {
          GETTYPEMAPPABLETYPE:
          for (ObjectType type : exportTypes) {
            for (String group : typeMappableType.as(TypeData.class).getTypeMappableGroups()) {
              if (type.getGroups().contains(group)) {
                typeMaps.add(typeMappableType);
                break GETTYPEMAPPABLETYPE;
              }
            }
          }
        }
        GETOBJECTTYPE:
        for (ObjectType type : exportTypes) {
          for (ObjectField field : type.getFields()) {
            if (field.getTypes().contains(objType)) {
              needsObjectTypeMap = true;
              break GETOBJECTTYPE;
            }
          }
        }

        for (ObjectType exportType : exportTypes) {
          String clsName = exportType.getObjectClassName();
          if (!ObjectUtils.isBlank(clsName)) {
            for (ObjectType concreteType : database.getEnvironment().getTypesByGroup(clsName)) {
              if (!concreteType.isAbstract()) {
                concreteTypeIds.add(concreteType.getId());
              }
            }
          }
        }

        if (exportTypes.contains(objType)) {
          if (!first) {
            writer.write(',');
          } else {
            first = false;
          }
          writer.write(objType.getInternalName());
        }
        for (ObjectType type : exportTypes) {
          if (type.equals(objType)) {
            continue;
          }
          if (!first) {
            writer.write(',');
          } else {
            first = false;
          }
          writer.write(type.getInternalName());
        }
        writer.write('\n');
      }

      // Determine if there are any fields that need references followed
      Map<UUID, Map<String, ObjectType>> followReferences =
          new HashMap<UUID, Map<String, ObjectType>>();
      if (!pkg.isInit()) {
        for (ObjectType type : exportTypes) {
          for (String fieldName : type.as(TypeData.class).getFollowReferencesFields()) {
            ObjectField field = type.getField(fieldName);
            if (field != null) {
              for (ObjectType fieldType : field.getTypes()) {
                if (!exportTypes.contains(fieldType)) {
                  if (!followReferences.containsKey(type.getId())) {
                    followReferences.put(type.getId(), new HashMap<String, ObjectType>());
                  }
                  followReferences.get(type.getId()).put(fieldName, fieldType);
                }
              }
            }
          }
        }
      }

      if (!typeMaps.isEmpty()) {
        for (ObjectType typeMapType : typeMaps) {
          String clsName = typeMapType.getObjectClassName();
          if (!ObjectUtils.isBlank(clsName)) {
            for (ObjectType type : database.getEnvironment().getTypesByGroup(clsName)) {
              concreteTypeIds.remove(type.getId());
            }
          }
        }
      }

      // Mapping Types:
      if (pkg.isInit() || needsObjectTypeMap || !typeMaps.isEmpty()) {
        first = true;
        writer.write(TYPE_MAP_HEADER + ": ");
        if (pkg.isInit() || needsObjectTypeMap) {
          writer.write(objType.getInternalName());
          writer.write("/internalName");
          first = false;
        }
        for (ObjectType typeMapType : typeMaps) {
          if (!first) {
            writer.write(',');
          } else {
            first = false;
          }
          writer.write(typeMapType.getInternalName());
          writer.write('/');
          writer.write(typeMapType.as(TypeData.class).getTypeMappableUniqueKey());
        }
        writer.write('\n');
      }

      // Row Count:
      Long count = 0L;
      try {
        if (concreteTypeIds.isEmpty()) {
          count = Query.fromAll().using(database).noCache().count();
        } else {
          for (UUID concreteTypeId : concreteTypeIds) {
            long concreteCount =
                Query.fromAll()
                    .using(database)
                    .noCache()
                    .where("_type = ?", concreteTypeId)
                    .count();
            count = count + concreteCount;
          }
          if (needsObjectTypeMap) {
            long objectCount =
                Query.fromAll().using(database).noCache().where("_type = ?", objType).count();
            count = count + objectCount;
          }
          if (!typeMaps.isEmpty()) {
            for (ObjectType typeMapType : typeMaps) {
              long typeMapCount =
                  Query.fromAll().using(database).noCache().where("_type = ?", typeMapType).count();
              count = count + typeMapCount;
            }
          }
        }
        writer.write(ROW_COUNT_HEADER + ": ");
        writer.write(ObjectUtils.to(String.class, count));
        writer.write('\n');
      } catch (RuntimeException e) {
        // Count query timed out. Just don't write the row count header.
        count = null;
      }

      // blank line between headers and data
      writer.write('\n');
      writer.flush();

      // ObjectType records first
      if (exportTypes.isEmpty() || exportTypes.contains(objType) || needsObjectTypeMap) {
        for (Object r :
            Query.fromType(objType)
                .using(database)
                .noCache()
                .resolveToReferenceOnly()
                .iterable(100)) {
          writer.write(ObjectUtils.toJson(((Recordable) r).getState().getSimpleValues(true)));
          writer.write('\n');
        }
      }

      // Then other mapping types
      for (ObjectType typeMapType : typeMaps) {
        for (Object r :
            Query.fromType(typeMapType)
                .using(database)
                .noCache()
                .resolveToReferenceOnly()
                .iterable(100)) {
          writer.write(ObjectUtils.toJson(((Recordable) r).getState().getSimpleValues(true)));
          writer.write('\n');
        }
      }

      // Then everything else
      if (pkg.isInit()) {
        concreteTypeIds.clear(); // should already be empty
        concreteTypeIds.add(null);
      }
      UUID lastTypeId = null;
      Set<UUID> seenIds = new HashSet<UUID>();
      query.getOptions().put(SqlDatabase.USE_JDBC_FETCH_SIZE_QUERY_OPTION, false);
      for (UUID typeId : concreteTypeIds) {
        Query<?> concreteQuery = query.clone();
        if (typeId != null) {
          concreteQuery.where("_type = ?", typeId);
        }
        for (Object o : concreteQuery.noCache().resolveToReferenceOnly().iterable(100)) {
          if (o instanceof Recordable) {
            Recordable r = (Recordable) o;
            writer.write(ObjectUtils.toJson(r.getState().getSimpleValues(true)));
            writer.write('\n');
            if (!pkg.isInit()) {
              if (lastTypeId == null || !lastTypeId.equals(r.getState().getTypeId())) {
                seenIds.clear();
              } else if (seenIds.size() > MAX_SEEN_REFERENCE_IDS_SIZE) {
                seenIds.clear();
              }
              lastTypeId = r.getState().getTypeId();
              Map<String, ObjectType> followReferencesFieldMap;
              if ((followReferencesFieldMap = followReferences.get(r.getState().getTypeId()))
                  != null) {
                for (Map.Entry<String, ObjectType> entry : followReferencesFieldMap.entrySet()) {
                  Object reference = r.getState().getRawValue(entry.getKey());
                  Set<UUID> referenceIds = new HashSet<UUID>();
                  if (reference instanceof Collection) {
                    for (Object referenceObj : ((Collection<?>) reference)) {
                      if (referenceObj instanceof Recordable) {
                        UUID referenceUUID =
                            ObjectUtils.to(
                                UUID.class, ((Recordable) referenceObj).getState().getId());
                        if (referenceUUID != null) {
                          if (!seenIds.contains(referenceUUID)) {
                            referenceIds.add(referenceUUID);
                          }
                        }
                      }
                    }
                  } else if (reference instanceof Recordable) {
                    UUID referenceUUID =
                        ObjectUtils.to(UUID.class, ((Recordable) reference).getState().getId());
                    if (referenceUUID != null) {
                      if (!seenIds.contains(referenceUUID)) {
                        referenceIds.add(referenceUUID);
                      }
                    }
                  }
                  if (!referenceIds.isEmpty()) {
                    for (Object ref :
                        Query.fromType(entry.getValue())
                            .noCache()
                            .using(database)
                            .where("_id = ?", referenceIds)
                            .selectAll()) {
                      if (ref instanceof Recordable) {
                        Recordable refr = (Recordable) ref;
                        seenIds.add(refr.getState().getId());
                        writer.write(ObjectUtils.toJson(refr.getState().getSimpleValues(true)));
                        writer.write('\n');
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }

      writer.flush();
    }
コード例 #3
0
  /** Immediately refreshes all types using the backing database. */
  public synchronized void refreshTypes() {
    bootstrapOnce.ensure();

    Database database = getDatabase();
    try {

      TypesCache temporaryTypes = temporaryTypesLocal.get();
      if (temporaryTypes == null) {
        temporaryTypes = new TypesCache();
        temporaryTypesLocal.set(temporaryTypes);
      }

      List<ObjectType> types = Query.from(ObjectType.class).using(database).selectAll();
      int typesSize = types.size();
      LOGGER.info("Loading [{}] types from [{}]", typesSize, database.getName());

      // Load all types from the database first.
      for (ObjectType type : types) {
        type.getFields().size(); // Pre-fetch.
        temporaryTypes.add(type);
      }

      if (initializeClasses) {

        // Make sure that the root type exists.
        ObjectType rootType = getRootType();
        State rootTypeState;

        if (rootType != null) {
          rootTypeState = rootType.getState();

        } else {
          rootType = new ObjectType();
          rootTypeState = rootType.getState();
          rootTypeState.setDatabase(database);
        }

        Map<String, Object> rootTypeOriginals = rootTypeState.getSimpleValues();
        UUID rootTypeId = rootTypeState.getId();
        rootTypeState.setTypeId(rootTypeId);
        rootTypeState.clear();
        rootType.setObjectClassName(ObjectType.class.getName());
        rootType.initialize();
        temporaryTypes.add(rootType);

        try {
          database.beginWrites();

          // Make the new root type available to other types.
          temporaryTypes.add(rootType);
          if (rootTypeState.isNew()) {
            State globals = getGlobals();
            globals.put(ROOT_TYPE_FIELD, rootType);
            globals.save();

          } else if (!rootTypeState.getSimpleValues().equals(rootTypeOriginals)) {
            temporaryTypes.changed.add(rootTypeId);
          }

          Set<Class<? extends Recordable>> objectClasses =
              ClassFinder.findClasses(Recordable.class);

          for (Iterator<Class<? extends Recordable>> i = objectClasses.iterator(); i.hasNext(); ) {
            Class<? extends Recordable> objectClass = i.next();

            try {
              if (objectClass.isAnonymousClass()
                  || Substitution.class.isAssignableFrom(objectClass)) {
                i.remove();
              }

            } catch (IncompatibleClassChangeError error) {
              i.remove();
            }
          }

          Set<Class<?>> globalModifications = new HashSet<Class<?>>();
          Map<ObjectType, List<Class<?>>> typeModifications =
              new HashMap<ObjectType, List<Class<?>>>();

          // Make sure all types are accessible to the rest of the
          // system as soon as possible, so that references can be
          // resolved properly later.
          for (Class<?> objectClass : objectClasses) {
            ObjectType type = getTypeByClass(objectClass);

            if (type == null) {
              type = new ObjectType();
              type.getState().setDatabase(database);

            } else {
              type.getState().clear();
            }

            type.setObjectClassName(objectClass.getName());
            typeModifications.put(type, new ArrayList<Class<?>>());
            temporaryTypes.add(type);
          }

          // Separate out all modifications from regular types.
          for (Class<?> objectClass : objectClasses) {
            if (!Modification.class.isAssignableFrom(objectClass)) {
              continue;
            }

            @SuppressWarnings("unchecked")
            Set<Class<?>> modifiedClasses =
                Modification.Static.getModifiedClasses(
                    (Class<? extends Modification<?>>) objectClass);
            if (modifiedClasses.contains(Object.class)) {
              globalModifications.add(objectClass);
              continue;
            }

            for (Class<?> modifiedClass : modifiedClasses) {
              List<Class<?>> assignableClasses = new ArrayList<Class<?>>();

              for (Class<?> c : objectClasses) {
                if (modifiedClass.isAssignableFrom(c)) {
                  assignableClasses.add(c);
                }
              }

              for (Class<?> assignableClass : assignableClasses) {
                ObjectType type = getTypeByClass(assignableClass);

                if (type != null) {
                  List<Class<?>> modifications = typeModifications.get(type);
                  if (modifications == null) {
                    modifications = new ArrayList<Class<?>>();
                    typeModifications.put(type, modifications);
                  }
                  modifications.add(objectClass);
                }
              }
            }
          }

          // Apply global modifications.
          for (Class<?> modification : globalModifications) {
            ObjectType.modifyAll(database, modification);
          }

          // Initialize all types.
          List<Class<?>> rootTypeModifications = typeModifications.remove(rootType);
          initializeAndModify(temporaryTypes, rootType, rootTypeModifications);

          if (rootTypeModifications != null) {
            for (Class<?> modification : rootTypeModifications) {
              ObjectType t = getTypeByClass(modification);
              initializeAndModify(temporaryTypes, t, typeModifications.remove(t));
            }
          }

          ObjectType fieldType = getTypeByClass(ObjectField.class);
          List<Class<?>> fieldModifications = typeModifications.remove(fieldType);
          initializeAndModify(temporaryTypes, fieldType, fieldModifications);

          if (fieldModifications != null) {
            for (Class<?> modification : fieldModifications) {
              ObjectType t = getTypeByClass(modification);
              initializeAndModify(temporaryTypes, t, typeModifications.remove(t));
            }
          }

          for (Map.Entry<ObjectType, List<Class<?>>> entry : typeModifications.entrySet()) {
            initializeAndModify(temporaryTypes, entry.getKey(), entry.getValue());
          }

          database.commitWrites();

        } finally {
          database.endWrites();
        }
      }

      // Merge temporary types into new permanent types.
      TypesCache newPermanentTypes = new TypesCache();

      for (ObjectType type : permanentTypes.byId.values()) {
        newPermanentTypes.add(type);
      }

      for (ObjectType type : temporaryTypes.byId.values()) {
        newPermanentTypes.add(type);
      }

      newPermanentTypes.changed.addAll(temporaryTypes.changed);
      newPermanentTypes.changed.addAll(permanentTypes.changed);

      // If any types changed, clear all types' extras.
      if (!temporaryTypes.changed.isEmpty()) {
        for (ObjectType type : newPermanentTypes.byId.values()) {
          type.getState().getExtras().clear();
        }
      }

      permanentTypes = newPermanentTypes;
      lastTypesUpdate = new Date();

    } finally {
      temporaryTypesLocal.remove();
    }

    ObjectType singletonType = getTypeByClass(Singleton.class);

    if (singletonType != null) {
      for (ObjectType type : singletonType.findConcreteTypes()) {
        if (!Query.fromType(type).where("_type = ?", type).master().noCache().hasMoreThan(0)) {
          try {
            State.getInstance(type.createObject(null)).saveImmediately();
          } catch (Exception error) {
            LOGGER.warn(String.format("Can't save [%s] singleton!", type.getLabel()), error);
          }
        }
      }
    }

    for (ObjectType type : getTypes()) {
      Class<?> objectClass = type.getObjectClass();
      if (objectClass != null) {
        TypePostProcessorClasses tppcAnnotation =
            objectClass.getAnnotation(TypePostProcessorClasses.class);
        if (tppcAnnotation != null) {
          for (Class<? extends ObjectType.PostProcessor> processorClass : tppcAnnotation.value()) {
            ObjectType.PostProcessor processor =
                (ObjectType.PostProcessor) TYPE_POST_PROCESSORS.getUnchecked(processorClass);
            processor.process(type);
          }
        }
      }
    }
  }
コード例 #4
0
    public static void checkConsistency(
        Database database,
        BootstrapPackage pkg,
        Set<BootstrapPackage> allPackages,
        Set<ObjectType> additionalTypes) {
      Set<ObjectType> allMyTypes = getAllTypes(database, pkg);
      Set<ObjectType> allTypes = new HashSet<ObjectType>();
      for (BootstrapPackage otherPkg : allPackages) {
        allTypes.addAll(getAllTypes(database, otherPkg));
      }
      Map<ObjectField, ObjectType> checkFields = new HashMap<ObjectField, ObjectType>();
      for (ObjectType type : allMyTypes) {
        for (ObjectField field : type.getFields()) {
          for (ObjectType t : field.getTypes()) {
            if (!field.isEmbedded() && !t.isEmbedded()) {
              checkFields.put(field, t);
            }
          }
        }
      }

      if (additionalTypes != null) {
        for (ObjectType type : additionalTypes) {
          for (ObjectField field : type.getFields()) {
            for (ObjectType t : field.getTypes()) {
              if (!field.isEmbedded() && !t.isEmbedded()) {
                checkFields.put(field, t);
              }
            }
          }
        }
      }

      for (ObjectField field : database.getEnvironment().getFields()) {
        for (ObjectType t : field.getTypes()) {
          if (!field.isEmbedded() && !t.isEmbedded()) {
            checkFields.put(field, t);
          }
        }
      }

      for (Map.Entry<ObjectField, ObjectType> entry : checkFields.entrySet()) {
        ObjectField field = entry.getKey();
        ObjectType t = entry.getValue();
        if (field.getParentType() != null
            && field
                .getParentType()
                .as(TypeData.class)
                .getFollowReferencesFields()
                .contains(field.getInternalName())) {
          continue;
        }
        if (!allMyTypes.contains(t)) {
          if (allTypes.contains(t)) {
            if (!pkg.getTypesInOtherPackages().containsKey(t)) {
              pkg.getTypesInOtherPackages().put(t, new HashSet<BootstrapPackage>());
            }
            for (BootstrapPackage otherPkg : allPackages) {
              if (getAllTypes(database, otherPkg).contains(t)) {
                pkg.getTypesInOtherPackages().get(t).add(otherPkg);
              }
            }
          }
          if (t.as(TypeData.class).getTypeMappableGroups().isEmpty()
              || t.as(TypeData.class).getTypeMappableUniqueKey() == null) {
            if (!pkg.getMissingTypes().containsKey(t)) {
              pkg.getMissingTypes().put(t, new HashSet<ObjectField>());
            }
            pkg.getMissingTypes().get(t).add(field);
          }
        }
      }
    }