/**
   * Resolve the specifier name in the class definition to a member definition, and create a
   * specifier node based on the member type.
   *
   * @param builder MXML tree builder.
   * @param specifierName Specifier name.
   * @return A MXML specifier node.
   */
  protected MXMLSpecifierNodeBase createSpecifierNode(
      MXMLTreeBuilder builder, String specifierName) {
    MXMLSpecifierNodeBase specifierNode = null;

    // Check if the attribute is a declared property, style, or event.
    FlexProject project = builder.getProject();
    IDefinition specifierDefinition = project.resolveSpecifier(classReference, specifierName);

    if (specifierDefinition instanceof ISetterDefinition
        || specifierDefinition instanceof IVariableDefinition) {
      specifierNode = new MXMLPropertySpecifierNode(this);
    } else if (specifierDefinition instanceof IEventDefinition) {
      specifierNode = new MXMLEventSpecifierNode(this);
    } else if (specifierDefinition instanceof IStyleDefinition) {
      specifierNode = new MXMLStyleSpecifierNode(this);
    } else if (specifierDefinition instanceof IEffectDefinition) {
      specifierNode = new MXMLEffectSpecifierNode(this);
    }

    if (specifierNode != null) {
      specifierNode.setDefinition(specifierDefinition); // TODO Move this logic
    }

    // If not, dynamic classes allow new properties to be set via attributes.
    else if (classReference.isDynamic()) {
      specifierNode = new MXMLPropertySpecifierNode(this);
      ((MXMLPropertySpecifierNode) specifierNode)
          .setDynamicName(specifierName); // TODO Move this logic
    }

    return specifierNode;
  }
  /** Sets the definition of the ActionScript class to which this node refers. */
  void setClassReference(FlexProject project, IClassDefinition classReference) {
    this.classReference = classReference;

    // TODO Optimize this by enumerating all interfaces one time.

    // Keep track of whether the class implements mx.core.IMXML,
    // because that affects code generation.
    String mxmlObjectInterface = project.getMXMLObjectInterface();
    isMXMLObject = classReference.isInstanceOf(mxmlObjectInterface, project);

    // Keep track of whether the class implements mx.core.IVisualElementContainer,
    // because that affects code generation.
    String visualElementContainerInterface = project.getVisualElementContainerInterface();
    isVisualElementContainer =
        classReference.isInstanceOf(visualElementContainerInterface, project);

    // Keep track of whether the class implements mx.core.IContainer,
    // because that affects code generation.
    String containerInterface = project.getContainerInterface();
    isContainer = classReference.isInstanceOf(containerInterface, project);

    // Keep track of whether the class implements mx.core.IDeferredInstantiationUIComponent
    // because that affects code generation.
    String deferredInstantiationUIComponentInterface =
        project.getDeferredInstantiationUIComponentInterface();
    isDeferredInstantiationUIComponent =
        classReference.isInstanceOf(deferredInstantiationUIComponentInterface, project);
  }
  /** Determines, and caches, the default property for the class to which this node refers. */
  private IVariableDefinition getDefaultPropertyDefinition(MXMLTreeBuilder builder) {
    if (!defaultPropertyDefinitionInitialized) {
      FlexProject project = builder.getProject();
      String defaultPropertyName = classReference.getDefaultPropertyName(project);
      if (defaultPropertyName != null) {
        defaultPropertyDefinition =
            (IVariableDefinition) project.resolveSpecifier(classReference, defaultPropertyName);
      }

      defaultPropertyDefinitionInitialized = true;
    }

    return defaultPropertyDefinition;
  }
 /**
  * Sets the definition of the ActionScript class to which this node refers, from its fully
  * qualified name.
  *
  * @param project An {@code ICompilerProject}, used for finding the class by name.
  * @param qname A fully qualified class name.
  */
 void setClassReference(FlexProject project, String qname) {
   ASProjectScope projectScope = (ASProjectScope) project.getScope();
   IDefinition definition = projectScope.findDefinitionByName(qname);
   // TODO This method is getting called by MXML tree-building
   // with an interface qname if there is a property whose type is an interface.
   // Until databinding is implemented, we need to protect against this.
   if (definition instanceof IClassDefinition)
     setClassReference(project, (IClassDefinition) definition);
 }
  @Override
  protected void initializationComplete(
      MXMLTreeBuilder builder, MXMLTagData tag, MXMLNodeInfo info) {
    super.initializationComplete(builder, tag, info);

    // If the last child unit was part of the default property,
    // we don't know to process the default property units
    // until we get here.
    processNonDefaultPropertyContentUnit(builder, info);

    setChildren(info.getChildNodeList().toArray(new IMXMLNode[0]));

    // If the class references by this node implements mx.core.IContainer,
    // add an expression dependency on mx.core.UIComponentDescriptor
    // because we'll have to codegen descriptors.
    if (isContainer) {
      FlexProject project = builder.getProject();
      builder.addExpressionDependency(project.getUIComponentDescriptorClass());
    }
  }