class WidgetResourceProvider extends AbstractControllerResourceProvider {

  @Override
  public RequestStatus createResources(final Request request)
      throws SystemException,
      UnsupportedPropertyException,
      ResourceAlreadyExistsException,
      NoSuchParentResourceException {

    Set<Resource> associatedResources = new HashSet<>();

    for (final Map<String, Object> properties : request.getProperties()) {
      WidgetEntity widgetEntity = createResources(new Command<WidgetEntity>() {

        @Override
        public WidgetEntity invoke() throws AmbariException {
          final String[] requiredProperties = {
              WIDGET_CLUSTER_NAME_PROPERTY_ID,
              WIDGET_WIDGET_NAME_PROPERTY_ID,
              WIDGET_WIDGET_TYPE_PROPERTY_ID,
              WIDGET_SCOPE_PROPERTY_ID
          };
          for (String propertyName: requiredProperties) {
            if (properties.get(propertyName) == null) {
              throw new AmbariException("Property " + propertyName + " should be provided");
            }
          }
          final WidgetEntity entity = new WidgetEntity();
          String clusterName = properties.get(WIDGET_CLUSTER_NAME_PROPERTY_ID).toString();
          String scope = properties.get(WIDGET_SCOPE_PROPERTY_ID).toString();

          if (!isScopeAllowedForUser(scope, clusterName)) {
            throw new AccessDeniedException("Only cluster operator can create widgets with cluster scope");
          }

          entity.setWidgetName(properties.get(WIDGET_WIDGET_NAME_PROPERTY_ID).toString());
          entity.setWidgetType(properties.get(WIDGET_WIDGET_TYPE_PROPERTY_ID).toString());
          entity.setClusterId(getManagementController().getClusters().getCluster(clusterName).getClusterId());
          entity.setScope(scope);

          String metrics = (properties.containsKey(WIDGET_METRICS_PROPERTY_ID)) ?
                  gson.toJson(properties.get(WIDGET_METRICS_PROPERTY_ID)) : null;
          entity.setMetrics(metrics);

          entity.setAuthor(getAuthorName(properties));

          String description = (properties.containsKey(WIDGET_DESCRIPTION_PROPERTY_ID)) ?
                  properties.get(WIDGET_DESCRIPTION_PROPERTY_ID).toString() : null;
          entity.setDescription(description);

          String values = (properties.containsKey(WIDGET_VALUES_PROPERTY_ID)) ?
                  gson.toJson(properties.get(WIDGET_VALUES_PROPERTY_ID)) : null;
          entity.setWidgetValues(values);

          Map<String, Object> widgetPropertiesMap = new HashMap<>();
          for (Map.Entry<String, Object> entry : properties.entrySet()) {
            if (PropertyHelper.getPropertyCategory(entry.getKey()).equals(WIDGET_PROPERTIES_PROPERTY_ID)) {
              widgetPropertiesMap.put(PropertyHelper.getPropertyName(entry.getKey()), entry.getValue());
            }
          }

          String widgetProperties = (widgetPropertiesMap.isEmpty()) ?
                  null : gson.toJson(widgetPropertiesMap);
          entity.setProperties(widgetProperties);

          if (properties.containsKey(WIDGET_TAG_PROPERTY_ID)){
            entity.setTag(properties.get(WIDGET_TAG_PROPERTY_ID).toString());
          }

          widgetDAO.create(entity);
          notifyCreate(Type.Widget, request);
          return entity;
        }
      });
      Resource resource = new ResourceImpl(Type.Widget);
      resource.setProperty(WIDGET_ID_PROPERTY_ID, widgetEntity.getId());
      associatedResources.add(resource);

    }

    return getRequestStatus(null, associatedResources);
  }

  public  WidgetResourceProvider(AmbariManagementController managementController);

}