public static @NotNull RadComponent createComponent(final @NotNull ModuleProvider module,
                                                      final @NotNull LwComponent lwComponent,
                                                      final @NotNull ClassLoader loader,
                                                      final Locale stringDescriptorLocale) throws Exception{
    // Id
    final String id = lwComponent.getId();
    final RadComponent component;
    Class componentClass = null;

    if (lwComponent instanceof LwNestedForm nestedForm) {
      boolean recursiveNesting = false;
      try {
        Utils.validateNestedFormLoop(nestedForm.getFormFileName(), new PsiNestedFormLoader(module.getModule()));
      }
      catch(RecursiveFormNestingException ex) {
        recursiveNesting = true;
      }
      if (recursiveNesting) {
        component = RadErrorComponent.create(
          module,
          id,
          lwComponent.getComponentClassName(),
          lwComponent.getErrorComponentProperties(), UIDesignerBundle.message("error.recursive.form.nesting"));
      }
      else {
        component = new RadNestedForm(module, nestedForm.getFormFileName(), id);
      }
    }
    else {
      if (lwComponent.getErrorComponentProperties() == null) {
        componentClass = Class.forName(lwComponent.getComponentClassName(), true, loader);
      }

      if (lwComponent instanceof LwHSpacer) {
        component = new RadHSpacer(module, id);
      }
      else if (lwComponent instanceof LwVSpacer) {
        component = new RadVSpacer(module, id);
      }
      else if (lwComponent instanceof LwAtomicComponent) {
        if (componentClass == null) {
          component = createErrorComponent(module, id, lwComponent, loader);
        }
        else {
          RadComponent component1;
          try {
            if (JTable.class.isAssignableFrom(componentClass)) {
              component1 = new RadTable(module, componentClass, id);
            }
            else {
              component1 = new RadAtomicComponent(module, componentClass, id);
            }
          }
          catch (final Exception exc) {
            String errorDescription = UIDesignerBundle.message("error.class.cannot.be.instantiated", lwComponent.getComponentClassName());
            final String message = FormEditingUtil.getExceptionMessage(exc);
            if (message != null) {
              errorDescription += ": " + message;
            }
            component1 = RadErrorComponent.create(
              module,
              id,
              lwComponent.getComponentClassName(),
              lwComponent.getErrorComponentProperties(),
              errorDescription
            );
          }
          component = component1;
        }
      }
      else if (lwComponent instanceof LwScrollPane) {
        component = new RadScrollPane(module, componentClass, id);
      }
      else if (lwComponent instanceof LwTabbedPane) {
        component = new RadTabbedPane(module, componentClass, id);
      }
      else if (lwComponent instanceof LwSplitPane) {
        component = new RadSplitPane(module, componentClass, id);
      }
      else if (lwComponent instanceof LwToolBar) {
        component = new RadToolBar(module, componentClass, id);
      }
      else if (lwComponent instanceof LwContainer lwContainer) {
        LayoutManager layout = lwContainer.getLayout();
        if (layout instanceof XYLayoutManager) {
          // replace stub layout with the real one
          final XYLayoutManagerImpl xyLayoutManager = new XYLayoutManagerImpl();
          layout = xyLayoutManager;
          xyLayoutManager.setPreferredSize(lwComponent.getBounds().getSize());
        }
        if (componentClass == null) {
          component = createErrorComponent(module, id, lwComponent, loader);
        }
        else {
          if (lwContainer instanceof LwRootContainer) {
            component = new RadRootContainer(module, id);
            if (stringDescriptorLocale != null) {
              ((RadRootContainer) component).setStringDescriptorLocale(stringDescriptorLocale);
            }
          }
          else {
            component = new RadContainer(module, componentClass, id);

            String layoutManagerName = lwContainer.getLayoutManager();
            if (layoutManagerName == null || layoutManagerName.isEmpty()) {
              if (layout instanceof XYLayoutManager) {
                layoutManagerName = UIFormXmlConstants.LAYOUT_XY;
              }
              else {
                layoutManagerName = UIFormXmlConstants.LAYOUT_INTELLIJ;
              }
            }

            RadLayoutManager layoutManager = LayoutManagerRegistry.createLayoutManager(layoutManagerName);
            RadContainer container = (RadContainer)component;
            layoutManager.readLayout(lwContainer, container);
            container.setLayoutManager(layoutManager);
          }
          ((RadContainer)component).setLayout(layout);
        }
      }
      else {
        throw new IllegalArgumentException("unexpected component: " + lwComponent);
      }
    }

    // binding
    component.setBinding(lwComponent.getBinding());
    component.setCustomCreate(lwComponent.isCustomCreate());
    component.setDefaultBinding(lwComponent.isDefaultBinding());

    // bounds
    component.setBounds(lwComponent.getBounds());

    // properties
    if (stringDescriptorLocale != null) {
      component.putClientProperty(RadComponent.CLIENT_PROP_LOAD_TIME_LOCALE, stringDescriptorLocale);
    }
    final LwIntrospectedProperty[] properties = lwComponent.getAssignedIntrospectedProperties();
    if (componentClass != null) {
      final Palette palette = Palette.getInstance(module.getProject());
      for (final LwIntrospectedProperty lwProperty : properties) {
        final IntrospectedProperty property = palette.getIntrospectedProperty(component, lwProperty.getName());
        if (property == null) {
          continue;
        }
        component.loadLwProperty(lwComponent, lwProperty, property);
      }
    }

    // GridConstraints
    component.getConstraints().restore(lwComponent.getConstraints());

    component.setCustomLayoutConstraints(lwComponent.getCustomLayoutConstraints());

    HashMap clientProps = lwComponent.getDelegeeClientProperties();
    for(Object o: clientProps.entrySet()) {
      Map.Entry entry = (Map.Entry) o;
      Object value = entry.getValue();
      if (value instanceof StringDescriptor) {
        value = ((StringDescriptor) value).getValue();
      }
      component.getDelegee().putClientProperty(entry.getKey(), value);
    }

    if (component instanceof RadContainer container) {
      final LwContainer lwContainer = (LwContainer)lwComponent;

      copyBorder(container, lwContainer);

      // add children
      for (int i=0; i < lwContainer.getComponentCount(); i++){
        container.addComponent(createComponent(module, (LwComponent)lwContainer.getComponent(i), loader, stringDescriptorLocale));
      }
    }

    if (component instanceof RadRootContainer radRootContainer) {
      final LwRootContainer lwRootContainer = (LwRootContainer)lwComponent;
      radRootContainer.setClassToBind(lwRootContainer.getClassToBind());
      radRootContainer.setMainComponentBinding(lwRootContainer.getMainComponentBinding());
      radRootContainer.setButtonGroups(lwRootContainer.getButtonGroups());
      radRootContainer.setInspectionSuppressions(lwRootContainer.getInspectionSuppressions());
      radRootContainer.getDelegee().setBackground(new JBColor(Color.WHITE, UIUtil.getListBackground()));
    }

    component.doneLoadingFromLw();
    component.putClientProperty(RadComponent.CLIENT_PROP_LOAD_TIME_LOCALE, null);
    return component;
  }
public static @NotNull RadComponent createComponent(final @NotNull ModuleProvider module,
                                                      final @NotNull LwComponent lwComponent,
                                                      final @NotNull ClassLoader loader,
                                                      final Locale stringDescriptorLocale)