protected GrailsClass addArtefact(
      String artefactType, Class<?> artefactClass, boolean overrideable) {
    ArtefactHandler handler = artefactHandlersByName.get(artefactType);
    if (handler.isArtefact(artefactClass)) {
      GrailsClass artefactGrailsClass = handler.newArtefactClass(artefactClass);
      artefactGrailsClass.setGrailsApplication(this);

      // Store the GrailsClass in cache
      DefaultArtefactInfo info = getArtefactInfo(artefactType, true);
      if (overrideable) {
        info.addOverridableGrailsClass(artefactGrailsClass);
      } else {
        info.addGrailsClass(artefactGrailsClass);
      }
      info.updateComplete();

      addToLoaded(artefactClass);

      if (isInitialised()) {
        initializeArtefacts(artefactType);
      }

      return artefactGrailsClass;
    }

    throw new GrailsConfigurationException(
        "Cannot add "
            + artefactType
            + " class ["
            + artefactClass
            + "]. It is not a "
            + artefactType
            + "!");
  }
 /**
  * Get or create the cache of classes for the specified artefact type.
  *
  * @param artefactType The name of an artefact type
  * @param create Set to true if you want non-existent caches to be created
  * @return The cache of classes for the type, or null if no cache exists and create is false
  */
 protected DefaultArtefactInfo getArtefactInfo(String artefactType, boolean create) {
   DefaultArtefactInfo cache = (DefaultArtefactInfo) artefactInfo.get(artefactType);
   if (cache == null && create) {
     cache = new DefaultArtefactInfo();
     artefactInfo.put(artefactType, cache);
     cache.updateComplete();
   }
   return cache;
 }
  /**
   * Configures the loaded classes within the GrailsApplication instance using the registered
   * ArtefactHandler instances.
   *
   * @param classes The classes to configure
   */
  protected void configureLoadedClasses(Class<?>[] classes) {

    initArtefactHandlers();

    artefactInfo.clear();
    allArtefactClasses.clear();
    allArtefactClassesArray = null;
    allClasses = classes;

    // first load the domain classes
    log.debug("Going to inspect artefact classes.");
    for (final Class<?> theClass : classes) {
      log.debug("Inspecting [" + theClass.getName() + "]");
      if (allArtefactClasses.contains(theClass)) {
        continue;
      }

      // check what kind of artefact it is and add to corrent data structure
      for (ArtefactHandler artefactHandler : artefactHandlers) {
        if (artefactHandler.isArtefact(theClass)) {
          log.debug("Adding artefact " + theClass + " of kind " + artefactHandler.getType());
          GrailsClass gclass = addArtefact(artefactHandler.getType(), theClass);
          // Also maintain set of all artefacts (!= all classes loaded)
          allArtefactClasses.add(theClass);

          // Update per-artefact cache
          DefaultArtefactInfo info = getArtefactInfo(artefactHandler.getType(), true);
          info.addGrailsClass(gclass);
          break;
        }
      }
    }

    refreshArtefactGrailsClassCaches();

    allArtefactClassesArray = allArtefactClasses.toArray(new Class[allArtefactClasses.size()]);

    // Tell all artefact handlers to init now we've worked out which classes are which artefacts
    for (ArtefactHandler artefactHandler : artefactHandlers) {
      initializeArtefacts(artefactHandler);
    }
  }
  /**
   * Adds an artefact of the given type for the given GrailsClass.
   *
   * @param artefactType The type of the artefact as defined by a ArtefactHandler instance
   * @param artefactGrailsClass A GrailsClass instance that matches the type defined by the
   *     ArtefactHandler
   * @return The GrailsClass if successful or null if it couldn't be added
   * @throws GrailsConfigurationException If the specified GrailsClass is not the same as the type
   *     defined by the ArtefactHandler
   * @see org.codehaus.groovy.grails.commons.ArtefactHandler
   */
  public GrailsClass addArtefact(String artefactType, GrailsClass artefactGrailsClass) {
    ArtefactHandler handler = artefactHandlersByName.get(artefactType);
    if (handler.isArtefactGrailsClass(artefactGrailsClass)) {
      // Store the GrailsClass in cache
      DefaultArtefactInfo info = getArtefactInfo(artefactType, true);
      info.addGrailsClass(artefactGrailsClass);
      info.updateComplete();

      initializeArtefacts(artefactType);

      return artefactGrailsClass;
    }

    throw new GrailsConfigurationException(
        "Cannot add "
            + artefactType
            + " class ["
            + artefactGrailsClass
            + "]. It is not a "
            + artefactType
            + "!");
  }
 /**
  * Tell all our artefact info objects to update their internal state after we've added a bunch of
  * classes.
  */
 protected void refreshArtefactGrailsClassCaches() {
   for (Object o : artefactInfo.values()) {
     ((DefaultArtefactInfo) o).updateComplete();
   }
 }