text:
package org.apache.nifi.web;

import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.action.Action;
import org.apache.nifi.action.Component;
import org.apache.nifi.action.FlowChangeAction;
import org.apache.nifi.action.Operation;
import org.apache.nifi.action.component.details.FlowChangeExtensionDetails;
import org.apache.nifi.action.details.FlowChangeConfigureDetails;
import org.apache.nifi.admin.service.AuditService;
import org.apache.nifi.authorization.AuthorizeControllerServiceReference;
import org.apache.nifi.authorization.Authorizer;
import org.apache.nifi.authorization.ComponentAuthorizable;
import org.apache.nifi.authorization.RequestAction;
import org.apache.nifi.authorization.resource.Authorizable;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.cluster.coordination.ClusterCoordinator;
import org.apache.nifi.cluster.coordination.http.replication.RequestReplicator;
import org.apache.nifi.cluster.exception.NoClusterCoordinatorException;
import org.apache.nifi.cluster.manager.NodeResponse;
import org.apache.nifi.cluster.manager.exception.IllegalClusterStateException;
import org.apache.nifi.cluster.protocol.NodeIdentifier;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.controller.reporting.ReportingTaskProvider;
import org.apache.nifi.controller.service.ControllerServiceProvider;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.util.NiFiProperties;
import org.apache.nifi.web.api.ApplicationResource.ReplicationTarget;
import org.apache.nifi.web.api.dto.AllowableValueDTO;
import org.apache.nifi.web.api.dto.ControllerServiceDTO;
import org.apache.nifi.web.api.dto.FlowRegistryClientDTO;
import org.apache.nifi.web.api.dto.ParameterProviderDTO;
import org.apache.nifi.web.api.dto.ProcessorConfigDTO;
import org.apache.nifi.web.api.dto.ProcessorDTO;
import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
import org.apache.nifi.web.api.dto.ReportingTaskDTO;
import org.apache.nifi.web.api.dto.RevisionDTO;
import org.apache.nifi.web.api.entity.AllowableValueEntity;
import org.apache.nifi.web.api.entity.ControllerServiceEntity;
import org.apache.nifi.web.api.entity.FlowRegistryClientEntity;
import org.apache.nifi.web.api.entity.ParameterProviderEntity;
import org.apache.nifi.web.api.entity.ProcessorEntity;
import org.apache.nifi.web.api.entity.ReportingTaskEntity;
import org.apache.nifi.web.util.ClientResponseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Implements the NiFiWebConfigurationContext interface to support a context in both standalone and clustered environments.
 */
public class StandardNiFiWebConfigurationContext implements NiFiWebConfigurationContext {

    private static final Logger logger = LoggerFactory.getLogger(StandardNiFiWebConfigurationContext.class);

    private NiFiProperties properties;
    private NiFiServiceFacade serviceFacade;
    private ClusterCoordinator clusterCoordinator;
    private RequestReplicator requestReplicator;
    private ControllerServiceProvider controllerServiceProvider;
    private ReportingTaskProvider reportingTaskProvider;
    private AuditService auditService;
    private Authorizer authorizer;
    private VariableRegistry variableRegistry;

    private void authorizeFlowAccess(final NiFiUser user) {
        // authorize access
        serviceFacade.authorizeAccess(lookup -> {
            final Authorizable flow = lookup.getFlow();
            flow.authorize(authorizer, RequestAction.READ, user);
        });
    }

    @Override
    public ControllerService getControllerService(final String serviceIdentifier, final String componentId) {
        final NiFiUser user = NiFiUserUtils.getNiFiUser();
        authorizeFlowAccess(user);
        return controllerServiceProvider.getControllerServiceForComponent(serviceIdentifier, componentId);
    }

    @Override
    public void saveActions(final NiFiWebRequestContext requestContext, final Collection<ConfigurationAction> configurationActions) {
        Objects.requireNonNull(configurationActions, "Actions cannot be null.");

        // ensure the path could be
        if (requestContext.getExtensionType() == null) {
            throw new IllegalArgumentException("The UI extension type must be specified.");
        }

        Component componentType = null;
        switch (requestContext.getExtensionType()) {
            case ProcessorConfiguration:
                // authorize access
                serviceFacade.authorizeAccess(lookup -> {
                    final Authorizable authorizable = lookup.getProcessor(requestContext.getId()).getAuthorizable();
                    authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                });

                componentType = Component.Processor;
                break;
            case ControllerServiceConfiguration:
                // authorize access
                serviceFacade.authorizeAccess(lookup -> {
                    final Authorizable authorizable = lookup.getControllerService(requestContext.getId()).getAuthorizable();
                    authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                });

                componentType = Component.ControllerService;
                break;
            case ReportingTaskConfiguration:
                // authorize access
                serviceFacade.authorizeAccess(lookup -> {
                    final Authorizable authorizable = lookup.getReportingTask(requestContext.getId()).getAuthorizable();
                    authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                });

                componentType = Component.ReportingTask;
                break;
            case ParameterProviderConfiguration:
                // authorize access
                serviceFacade.authorizeAccess(lookup -> {
                    final Authorizable authorizable = lookup.getParameterProvider(requestContext.getId()).getAuthorizable();
                    authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                });

                componentType = Component.ParameterProvider;
                break;
            case FlowRegistryClientConfiguration:
                // authorize access
                serviceFacade.authorizeAccess(lookup -> {
                    final Authorizable authorizable = lookup.getFlowRegistryClient(requestContext.getId()).getAuthorizable();
                    authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
                });
                componentType = Component.FlowRegistryClient;
                break;
        }

        if (componentType == null) {
            throw new IllegalArgumentException("UI extension type must support Processor, ControllerService, or ReportingTask configuration.");
        }

        // - when running standalone or cluster ncm - actions from custom UIs are stored locally
        // - clustered nodes do not serve custom UIs directly to users so they should never be invoking this method
        final Date now = new Date();
        final Collection<Action> actions = new HashSet<>(configurationActions.size());
        for (final ConfigurationAction configurationAction : configurationActions) {
            final FlowChangeExtensionDetails extensionDetails = new FlowChangeExtensionDetails();
            extensionDetails.setType(configurationAction.getType());

            final FlowChangeConfigureDetails configureDetails = new FlowChangeConfigureDetails();
            configureDetails.setName(configurationAction.getName());
            configureDetails.setPreviousValue(configurationAction.getPreviousValue());
            configureDetails.setValue(configurationAction.getValue());

            final FlowChangeAction action = new FlowChangeAction();
            action.setTimestamp(now);
            action.setSourceId(configurationAction.getId());
            action.setSourceName(configurationAction.getName());
            action.setSourceType(componentType);
            action.setOperation(Operation.Configure);
            action.setUserIdentity(getCurrentUserIdentity());
            action.setComponentDetails(extensionDetails);
            action.setActionDetails(configureDetails);
            actions.add(action);
        }

        if (!actions.isEmpty()) {
            try {
                // record the operations
                auditService.addActions(actions);
            } catch (final Throwable t) {
                logger.warn("Unable to record actions: " + t.getMessage());
                if (logger.isDebugEnabled()) {
                    logger.warn(StringUtils.EMPTY, t);
                }
            }
        }
    }

    @Override
    public String getCurrentUserIdentity() {
        final NiFiUser user = NiFiUserUtils.getNiFiUser();
        authorizeFlowAccess(user);
        return user.getIdentity();
    }

    @Override
    public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) throws ResourceNotFoundException, ClusterRequestException {
        final String id = requestContext.getId();

        if (StringUtils.isBlank(id)) {
            throw new ResourceNotFoundException(String.format("Configuration request context config did not have a component ID."));
        }

        // ensure the path could be
        if (requestContext.getExtensionType() == null) {
            throw new IllegalArgumentException("The UI extension type must be specified.");
        }

        // get the component facade for interacting directly with that type of object
        ComponentFacade componentFacade = null;
        switch (requestContext.getExtensionType()) {
            case ProcessorConfiguration:
                componentFacade = new ProcessorFacade();
                break;
            case ControllerServiceConfiguration:
                componentFacade = new ControllerServiceFacade();
                break;
            case ReportingTaskConfiguration:
                componentFacade = new ReportingTaskFacade();
                break;
            case ParameterProviderConfiguration:
                componentFacade = new ParameterProviderFacade();
                break;
            case FlowRegistryClientConfiguration:
                componentFacade = new FlowRegistryClientFacade();
        }

        if (componentFacade == null) {
            throw new IllegalArgumentException("UI extension type must support Processor, ControllerService, or ReportingTask configuration.");
        }

        return componentFacade.getComponentDetails(requestContext);
    }

    @Override
    public ComponentDetails updateComponent(final NiFiWebConfigurationRequestContext requestContext, final String annotationData, Map<String, String> properties)
            throws ResourceNotFoundException, InvalidRevisionException, ClusterRequestException {

        final String id = requestContext.getId();

        if (StringUtils.isBlank(id)) {
            throw new ResourceNotFoundException(String.format("Configuration request context did not have a component ID."));
        }

        // ensure the path could be
        if (requestContext.getExtensionType() == null) {
            throw new IllegalArgumentException("The UI extension type must be specified.");
        }

        // get the component facade for interacting directly with that type of object
        ComponentFacade componentFacade = null;
        switch (requestContext.getExtensionType()) {
            case ProcessorConfiguration:
                componentFacade = new ProcessorFacade();
                break;
            case ControllerServiceConfiguration:
                componentFacade = new ControllerServiceFacade();
                break;
            case ReportingTaskConfiguration:
                componentFacade = new ReportingTaskFacade();
                break;
        }

        if (componentFacade == null) {
            throw new IllegalArgumentException("UI extension type must support Processor, ControllerService, or ReportingTask configuration.");
        }

        // if we're clustered, ensure this node is not disconnected
        if (StandardNiFiWebConfigurationContext.this.properties.isClustered() && clusterCoordinator != null && !clusterCoordinator.isConnected()) {
            // if we are disconnected, ensure the disconnection is acknowledged
            if (!Boolean.TRUE.equals(requestContext.isDisconnectionAcknowledged())) {
                throw new IllegalArgumentException("This node is disconnected from its configured cluster. The requested change "
                        + "will only be allowed if the flag to acknowledge the disconnected node is set.");
            }
        }

        return componentFacade.updateComponent(requestContext, annotationData, properties);
    }

    private ReplicationTarget getReplicationTarget() {
        return clusterCoordinator.isActiveClusterCoordinator() ? ReplicationTarget.CLUSTER_NODES : ReplicationTarget.CLUSTER_COORDINATOR;
    }

    private NodeResponse replicate(final String method, final URI uri, final Object entity, final Map<String, String> headers) throws InterruptedException {
        // Determine whether we should replicate only to the cluster coordinator, or if we should replicate directly
        // to the cluster nodes themselves.
        if (getReplicationTarget() == ReplicationTarget.CLUSTER_NODES) {
            return requestReplicator.replicate(method, uri, entity, headers).awaitMergedResponse();
        } else {
            final NodeIdentifier coordinatorNode = clusterCoordinator.getElectedActiveCoordinatorNode();
            if (coordinatorNode == null) {
                throw new NoClusterCoordinatorException();
            }

            return requestReplicator.forwardToCoordinator(coordinatorNode, method, uri, entity, headers).awaitMergedResponse();
        }
    }

    /**
     * Facade over accessing different types of NiFi components.
     */
    private interface ComponentFacade {

        /**
         * Gets the component details using the specified request context.
         *
         * @param requestContext context
         * @return the component details using the specified request context
         */
        ComponentDetails getComponentDetails(NiFiWebRequestContext requestContext);

        /**
         * Sets the annotation data using the specified request context.
         *
         * @param requestContext context
         * @param annotationData data
         * @param properties properties
         * @return details
         */
        ComponentDetails updateComponent(NiFiWebConfigurationRequestContext requestContext, String annotationData, Map<String, String> properties);
    }

    /**
     * Interprets the request/response with the underlying Processor model.
     */
    private class ProcessorFacade implements ComponentFacade {

        @Override
        public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) {
            final String id = requestContext.getId();

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                final Authorizable authorizable = lookup.getProcessor(id).getAuthorizable();
                authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
            });

            final ProcessorDTO processor;
            if (properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    final String path = "/nifi-api/processors/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // set the request parameters
                final MultivaluedMap<String, String> parameters = new MultivaluedHashMap();

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.GET, requestUrl, parameters, getHeaders(requestContext));
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return processor
                ProcessorEntity entity = (ProcessorEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ProcessorEntity.class);
                }
                processor = entity.getComponent();
            } else {
                processor = serviceFacade.getProcessor(id).getComponent();
            }

            // return the processor info
            return getComponentConfiguration(processor);
        }

        @Override
        public ComponentDetails updateComponent(final NiFiWebConfigurationRequestContext requestContext, final String annotationData, Map<String, String> properties) {
            final NiFiUser user = NiFiUserUtils.getNiFiUser();
            final Revision revision = requestContext.getRevision();
            final String id = requestContext.getId();

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                // authorize the processor
                final ComponentAuthorizable authorizable = lookup.getProcessor(id);
                authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());

                // authorize any referenced service
                AuthorizeControllerServiceReference.authorizeControllerServiceReferences(properties, authorizable, authorizer, lookup);
            });

            final ProcessorDTO processor;
            if (StandardNiFiWebConfigurationContext.this.properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    final String path = "/nifi-api/processors/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // create the revision
                final RevisionDTO revisionDto = new RevisionDTO();
                revisionDto.setClientId(revision.getClientId());
                revisionDto.setVersion(revision.getVersion());

                // create the processor entity
                final ProcessorEntity processorEntity = new ProcessorEntity();
                processorEntity.setRevision(revisionDto);

                // create the processor dto
                ProcessorDTO processorDto = buildProcessorDto(id,annotationData,properties);
                processorEntity.setComponent(processorDto);

                // set the content type to json
                final Map<String, String> headers = getHeaders(requestContext);
                headers.put("Content-Type", "application/json");

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.PUT, requestUrl, processorEntity, headers);
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return processor
                ProcessorEntity entity = (ProcessorEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ProcessorEntity.class);
                }
                processor = entity.getComponent();
            } else {
                // update processor within write lock
                ProcessorDTO processorDTO = buildProcessorDto(id, annotationData, properties);
                final ProcessorEntity entity = serviceFacade.updateProcessor(revision, processorDTO);
                processor = entity.getComponent();
            }

            // return the processor info
            return getComponentConfiguration(processor);
        }

        private ProcessorDTO buildProcessorDto(String id, final String annotationData, Map<String, String> properties){
            ProcessorDTO processorDto = new ProcessorDTO();
            processorDto.setId(id);
            ProcessorConfigDTO configDto = new ProcessorConfigDTO();
            processorDto.setConfig(configDto);
            configDto.setAnnotationData(annotationData);
            configDto.setProperties(properties);
            return  processorDto;

        }

        private ComponentDetails getComponentConfiguration(final ProcessorDTO processor) {
            final ProcessorConfigDTO processorConfig = processor.getConfig();
            return new ComponentDetails.Builder()
                    .id(processor.getId())
                    .name(processor.getName())
                    .type(processor.getType())
                    .state(processor.getState())
                    .annotationData(processorConfig.getAnnotationData())
                    .properties(processorConfig.getProperties())
                    .descriptors(buildComponentDescriptorMap(processorConfig))
                    .validateErrors(processor.getValidationErrors()).build();
        }

        private Map<String,ComponentDescriptor> buildComponentDescriptorMap(final ProcessorConfigDTO processorConfig){

            final Map<String, ComponentDescriptor> descriptors = new HashMap<>();

            for(String key : processorConfig.getDescriptors().keySet()){

                PropertyDescriptorDTO descriptor = processorConfig.getDescriptors().get(key);
                List<AllowableValueEntity> allowableValuesEntity = descriptor.getAllowableValues();
                Map<String,String> allowableValues = new HashMap<>();

                if(allowableValuesEntity != null) {
                    for (AllowableValueEntity allowableValueEntity : allowableValuesEntity) {
                        final AllowableValueDTO allowableValueDTO = allowableValueEntity.getAllowableValue();
                        allowableValues.put(allowableValueDTO.getValue(), allowableValueDTO.getDisplayName());
                    }
                }

                ComponentDescriptor componentDescriptor = new ComponentDescriptor.Builder()
                        .name(descriptor.getName())
                        .displayName(descriptor.getDisplayName())
                        .defaultValue(descriptor.getDefaultValue())
                        .allowableValues(allowableValues)
                        .build();

                descriptors.put(key,componentDescriptor);
            }

            return descriptors;
        }

    }

    /**
     * Interprets the request/response with the underlying ControllerService model.
     */
    private class ControllerServiceFacade implements ComponentFacade {

        @Override
        public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) {
            final String id = requestContext.getId();
            final ControllerServiceDTO controllerService;

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                final Authorizable authorizable = lookup.getControllerService(id).getAuthorizable();
                authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
            });

            if (properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/controller-services/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // set the request parameters
                final MultivaluedMap<String, String> parameters = new MultivaluedHashMap();

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.GET, requestUrl, parameters, getHeaders(requestContext));
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return controller service
                ControllerServiceEntity entity = (ControllerServiceEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ControllerServiceEntity.class);
                }
                controllerService = entity.getComponent();
            } else {
                controllerService = serviceFacade.getControllerService(id).getComponent();
            }

            // return the controller service info
            return getComponentConfiguration(controllerService);
        }

        @Override
        public ComponentDetails updateComponent(final NiFiWebConfigurationRequestContext requestContext, final String annotationData, Map<String, String> properties) {
            final NiFiUser user = NiFiUserUtils.getNiFiUser();
            final Revision revision = requestContext.getRevision();
            final String id = requestContext.getId();

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                // authorize the controller service
                final ComponentAuthorizable authorizable = lookup.getControllerService(id);
                authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());

                // authorize any referenced service
                AuthorizeControllerServiceReference.authorizeControllerServiceReferences(properties, authorizable, authorizer, lookup);
            });

            final ControllerServiceDTO controllerService;
            if (StandardNiFiWebConfigurationContext.this.properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/controller-services/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // create the revision
                final RevisionDTO revisionDto = new RevisionDTO();
                revisionDto.setClientId(revision.getClientId());
                revisionDto.setVersion(revision.getVersion());

                // create the controller service entity
                final ControllerServiceEntity controllerServiceEntity = new ControllerServiceEntity();
                controllerServiceEntity.setRevision(revisionDto);

                // create the controller service dto
                final ControllerServiceDTO controllerServiceDto = new ControllerServiceDTO();
                controllerServiceEntity.setComponent(controllerServiceDto);
                controllerServiceDto.setId(id);
                controllerServiceDto.setAnnotationData(annotationData);
                controllerServiceDto.setProperties(properties);

                // set the content type to json
                final Map<String, String> headers = getHeaders(requestContext);
                headers.put("Content-Type", "application/json");

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.PUT, requestUrl, controllerServiceEntity, headers);
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return controller service
                ControllerServiceEntity entity = (ControllerServiceEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ControllerServiceEntity.class);
                }
                controllerService = entity.getComponent();
            } else {
                final ControllerServiceDTO controllerServiceDto = new ControllerServiceDTO();
                controllerServiceDto.setId(id);
                controllerServiceDto.setAnnotationData(annotationData);
                controllerServiceDto.setProperties(properties);

                // update controller service
                final ControllerServiceEntity entity = serviceFacade.updateControllerService(revision, controllerServiceDto);
                controllerService = entity.getComponent();
            }

            // return the controller service info
            return getComponentConfiguration(controllerService);
        }

        private ComponentDetails getComponentConfiguration(final ControllerServiceDTO controllerService) {
            return new ComponentDetails.Builder()
                    .id(controllerService.getId())
                    .name(controllerService.getName())
                    .type(controllerService.getType())
                    .state(controllerService.getState())
                    .annotationData(controllerService.getAnnotationData())
                    .properties(controllerService.getProperties())
                    .validateErrors(controllerService.getValidationErrors()).build();
        }
    }

    /**
     * Interprets the request/response with the underlying ControllerService model.
     */
    private class ReportingTaskFacade implements ComponentFacade {

        @Override
        public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) {
            final String id = requestContext.getId();
            final ReportingTaskDTO reportingTask;

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                final Authorizable authorizable = lookup.getReportingTask(id).getAuthorizable();
                authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
            });

            if (properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/reporting-tasks/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // set the request parameters
                final MultivaluedMap<String, String> parameters = new MultivaluedHashMap();

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.GET, requestUrl, parameters, getHeaders(requestContext));
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return reporting task
                ReportingTaskEntity entity = (ReportingTaskEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ReportingTaskEntity.class);
                }
                reportingTask = entity.getComponent();
            } else {
                reportingTask = serviceFacade.getReportingTask(id).getComponent();
            }

            // return the reporting task info
            return getComponentConfiguration(reportingTask);
        }

        @Override
        public ComponentDetails updateComponent(final NiFiWebConfigurationRequestContext requestContext, final String annotationData, Map<String, String> properties) {
            final NiFiUser user = NiFiUserUtils.getNiFiUser();
            final Revision revision = requestContext.getRevision();
            final String id = requestContext.getId();

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                // authorize the reporting task
                final ComponentAuthorizable authorizable = lookup.getReportingTask(id);
                authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());

                // authorize any referenced service
                AuthorizeControllerServiceReference.authorizeControllerServiceReferences(properties, authorizable, authorizer, lookup);
            });

            final ReportingTaskDTO reportingTask;
            if (StandardNiFiWebConfigurationContext.this.properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/reporting-tasks/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // create the revision
                final RevisionDTO revisionDto = new RevisionDTO();
                revisionDto.setClientId(revision.getClientId());
                revisionDto.setVersion(revision.getVersion());

                // create the reporting task entity
                final ReportingTaskEntity reportingTaskEntity = new ReportingTaskEntity();
                reportingTaskEntity.setRevision(revisionDto);

                // create the reporting task dto
                final ReportingTaskDTO reportingTaskDto = new ReportingTaskDTO();
                reportingTaskEntity.setComponent(reportingTaskDto);
                reportingTaskDto.setId(id);
                reportingTaskDto.setAnnotationData(annotationData);
                reportingTaskDto.setProperties(properties);

                // set the content type to json
                final Map<String, String> headers = getHeaders(requestContext);
                headers.put("Content-Type", "application/json");

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.PUT, requestUrl, reportingTaskEntity, headers);
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return reporting task
                ReportingTaskEntity entity = (ReportingTaskEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ReportingTaskEntity.class);
                }
                reportingTask = entity.getComponent();
            } else {
                final ReportingTaskDTO reportingTaskDto = new ReportingTaskDTO();
                reportingTaskDto.setId(id);
                reportingTaskDto.setAnnotationData(annotationData);
                reportingTaskDto.setProperties(properties);

                // obtain write lock
                serviceFacade.verifyRevision(revision, user);
                final ReportingTaskEntity entity = serviceFacade.updateReportingTask(revision, reportingTaskDto);
                reportingTask = entity.getComponent();
            }

            // return the processor info
            return getComponentConfiguration(reportingTask);
        }

        private ComponentDetails getComponentConfiguration(final ReportingTaskDTO reportingTask) {
            return new ComponentDetails.Builder()
                    .id(reportingTask.getId())
                    .name(reportingTask.getName())
                    .type(reportingTask.getType())
                    .state(reportingTask.getState())
                    .annotationData(reportingTask.getAnnotationData())
                    .properties(reportingTask.getProperties())
                    .validateErrors(reportingTask.getValidationErrors()).build();
        }
    }

    /**
     * Interprets the request/response with the underlying ControllerService model.
     */
    private class ParameterProviderFacade implements ComponentFacade {

        @Override
        public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) {
            final String id = requestContext.getId();
            final ParameterProviderDTO parameterProvider;

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                final Authorizable authorizable = lookup.getParameterProvider(id).getAuthorizable();
                authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
            });

            if (properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/parameter-providers/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // set the request parameters
                final MultivaluedMap<String, String> parameters = new MultivaluedHashMap();

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.GET, requestUrl, parameters, getHeaders(requestContext));
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return parameter provider
                ParameterProviderEntity entity = (ParameterProviderEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ParameterProviderEntity.class);
                }
                parameterProvider = entity.getComponent();
            } else {
                parameterProvider = serviceFacade.getParameterProvider(id).getComponent();
            }

            // return the parameter provider info
            return getComponentConfiguration(parameterProvider);
        }

        @Override
        public ComponentDetails updateComponent(final NiFiWebConfigurationRequestContext requestContext, final String annotationData, final Map<String, String> properties) {
            final NiFiUser user = NiFiUserUtils.getNiFiUser();
            final Revision revision = requestContext.getRevision();
            final String id = requestContext.getId();

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                // authorize the parameter provider
                final ComponentAuthorizable authorizable = lookup.getParameterProvider(id);
                authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());

                // authorize any referenced service
                AuthorizeControllerServiceReference.authorizeControllerServiceReferences(properties, authorizable, authorizer, lookup);
            });

            final ParameterProviderDTO parameterProvider;
            if (StandardNiFiWebConfigurationContext.this.properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/parameter-providers/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // create the revision
                final RevisionDTO revisionDto = new RevisionDTO();
                revisionDto.setClientId(revision.getClientId());
                revisionDto.setVersion(revision.getVersion());

                // create the parameter provider entity
                final ParameterProviderEntity parameterProviderEntity = new ParameterProviderEntity();
                parameterProviderEntity.setRevision(revisionDto);

                // create the parameter provider dto
                final ParameterProviderDTO parameterProviderDto = new ParameterProviderDTO();
                parameterProviderEntity.setComponent(parameterProviderDto);
                parameterProviderDto.setId(id);
                parameterProviderDto.setAnnotationData(annotationData);
                parameterProviderDto.setProperties(properties);

                // set the content type to json
                final Map<String, String> headers = getHeaders(requestContext);
                headers.put("Content-Type", "application/json");

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.PUT, requestUrl, parameterProviderEntity, headers);
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return parameter provider
                ParameterProviderEntity entity = (ParameterProviderEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(ParameterProviderEntity.class);
                }
                parameterProvider = entity.getComponent();
            } else {
                final ParameterProviderDTO parameterProviderDto = new ParameterProviderDTO();
                parameterProviderDto.setId(id);
                parameterProviderDto.setAnnotationData(annotationData);
                parameterProviderDto.setProperties(properties);

                // obtain write lock
                serviceFacade.verifyRevision(revision, user);
                final ParameterProviderEntity entity = serviceFacade.updateParameterProvider(revision, parameterProviderDto);
                parameterProvider = entity.getComponent();
            }

            // return the processor info
            return getComponentConfiguration(parameterProvider);
        }

        private ComponentDetails getComponentConfiguration(final ParameterProviderDTO parameterProvider) {
            return new ComponentDetails.Builder()
                    .id(parameterProvider.getId())
                    .name(parameterProvider.getName())
                    .type(parameterProvider.getType())
                    .annotationData(parameterProvider.getAnnotationData())
                    .properties(parameterProvider.getProperties())
                    .validateErrors(parameterProvider.getValidationErrors()).build();
        }
    }

    /**
     * Interprets the request/response with the underlying FlowRegistryClient model.
     */
    private class FlowRegistryClientFacade implements ComponentFacade {

        @Override
        public ComponentDetails getComponentDetails(final NiFiWebRequestContext requestContext) {
            final String id = requestContext.getId();
            final FlowRegistryClientDTO flowRegistryClient;

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                final Authorizable authorizable = lookup.getParameterProvider(id).getAuthorizable();
                authorizable.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
            });

            if (properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/controller/registry-clients/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // set the request parameters
                final MultivaluedMap<String, String> parameters = new MultivaluedHashMap();

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.GET, requestUrl, parameters, getHeaders(requestContext));
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return flow registry client
                FlowRegistryClientEntity entity = (FlowRegistryClientEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(FlowRegistryClientEntity.class);
                }
                flowRegistryClient = entity.getComponent();
            } else {
                flowRegistryClient = serviceFacade.getRegistryClient(id).getComponent();
            }

            // return the flow registry client info
            return getComponentConfiguration(flowRegistryClient);
        }

        @Override
        public ComponentDetails updateComponent(final NiFiWebConfigurationRequestContext requestContext, final String annotationData, final Map<String, String> properties) {
            final NiFiUser user = NiFiUserUtils.getNiFiUser();
            final Revision revision = requestContext.getRevision();
            final String id = requestContext.getId();

            // authorize access
            serviceFacade.authorizeAccess(lookup -> {
                // authorize the flow registry client
                final ComponentAuthorizable authorizable = lookup.getParameterProvider(id);
                authorizable.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());

                // authorize any referenced service
                AuthorizeControllerServiceReference.authorizeControllerServiceReferences(properties, authorizable, authorizer, lookup);
            });

            final FlowRegistryClientDTO flowRegistryClient;
            if (StandardNiFiWebConfigurationContext.this.properties.isClustered() && clusterCoordinator != null && clusterCoordinator.isConnected()) {
                // create the request URL
                URI requestUrl;
                try {
                    String path = "/nifi-api/controller/registry-clients/" + URLEncoder.encode(id, "UTF-8");
                    requestUrl = new URI(requestContext.getScheme(), null, "localhost", 0, path, null, null);
                } catch (final URISyntaxException | UnsupportedEncodingException use) {
                    throw new ClusterRequestException(use);
                }

                // create the revision
                final RevisionDTO revisionDto = new RevisionDTO();
                revisionDto.setClientId(revision.getClientId());
                revisionDto.setVersion(revision.getVersion());

                // create the flow registry client entity
                final FlowRegistryClientEntity flowRegistryClientEntity = new FlowRegistryClientEntity();
                flowRegistryClientEntity.setRevision(revisionDto);

                // create the flow registry client dto
                final FlowRegistryClientDTO flowRegistryClientDTO = new FlowRegistryClientDTO();
                flowRegistryClientEntity.setComponent(flowRegistryClientDTO);
                flowRegistryClientDTO.setId(id);
                flowRegistryClientDTO.setAnnotationData(annotationData);
                flowRegistryClientDTO.setProperties(properties);

                // set the content type to json
                final Map<String, String> headers = getHeaders(requestContext);
                headers.put("Content-Type", "application/json");

                // replicate request
                NodeResponse nodeResponse;
                try {
                    nodeResponse = replicate(HttpMethod.PUT, requestUrl, flowRegistryClientEntity, headers);
                } catch (final InterruptedException e) {
                    throw new IllegalClusterStateException("Request was interrupted while waiting for response from node");
                }

                // check for issues replicating request
                checkResponse(nodeResponse, id);

                // return flow registry client
                FlowRegistryClientEntity entity = (FlowRegistryClientEntity) nodeResponse.getUpdatedEntity();
                if (entity == null) {
                    entity = nodeResponse.getClientResponse().readEntity(FlowRegistryClientEntity.class);
                }
                flowRegistryClient = entity.getComponent();
            } else {
                final FlowRegistryClientDTO flowRegistryClientDTO = new FlowRegistryClientDTO();
                flowRegistryClientDTO.setId(id);
                flowRegistryClientDTO.setAnnotationData(annotationData);
                flowRegistryClientDTO.setProperties(properties);

                // obtain write lock
                serviceFacade.verifyRevision(revision, user);
                final FlowRegistryClientEntity entity = serviceFacade.updateRegistryClient(revision, flowRegistryClientDTO);
                flowRegistryClient = entity.getComponent();
            }

            // return the processor info
            return getComponentConfiguration(flowRegistryClient);
        }

        private ComponentDetails getComponentConfiguration(final FlowRegistryClientDTO parameterProvider) {
            return new ComponentDetails.Builder()
                    .id(parameterProvider.getId())
                    .name(parameterProvider.getName())
                    .type(parameterProvider.getType())
                    .annotationData(parameterProvider.getAnnotationData())
                    .properties(parameterProvider.getProperties())
                    .validateErrors(parameterProvider.getValidationErrors()).build();
        }
    }

    /**
     * Gets the headers for the request to replicate to each node while clustered.
     */
    private Map<String, String> getHeaders(final NiFiWebRequestContext config) {
        final Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json,application/xml");
        return headers;
    }

    /**
     * Checks the specified response and drains the stream appropriately.
     */
    private void checkResponse(final NodeResponse nodeResponse, final String id) {
        if (nodeResponse.hasThrowable()) {
            ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
            throw new ClusterRequestException(nodeResponse.getThrowable());
        } else if (nodeResponse.getClientResponse().getStatus() == Response.Status.CONFLICT.getStatusCode()) {
            ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
            throw new InvalidRevisionException(String.format("NiFi is unable to process the request at this time."));
        } else if (nodeResponse.getClientResponse().getStatus() == Response.Status.NOT_FOUND.getStatusCode()) {
            ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
            throw new ResourceNotFoundException("Unable to find component with id: " + id);
        } else if (nodeResponse.getClientResponse().getStatus() != Response.Status.OK.getStatusCode()) {
            ClientResponseUtils.drainClientResponse(nodeResponse.getClientResponse());
            throw new ClusterRequestException("Method resulted in an unsuccessful HTTP response code: " + nodeResponse.getClientResponse().getStatus());
        }
    }

    public void setClusterCoordinator(final ClusterCoordinator clusterCoordinator) {
        this.clusterCoordinator = clusterCoordinator;
    }

    public void setRequestReplicator(final RequestReplicator requestReplicator) {
        this.requestReplicator = requestReplicator;
    }

    public void setProperties(final NiFiProperties properties) {
        this.properties = properties;
    }

    public void setServiceFacade(final NiFiServiceFacade serviceFacade) {
        this.serviceFacade = serviceFacade;
    }

    public void setAuditService(final AuditService auditService) {
        this.auditService = auditService;
    }

    public void setControllerServiceProvider(final ControllerServiceProvider controllerServiceProvider) {
        this.controllerServiceProvider = controllerServiceProvider;
    }

    public void setReportingTaskProvider(final ReportingTaskProvider reportingTaskProvider) {
        this.reportingTaskProvider = reportingTaskProvider;
    }

    public void setAuthorizer(final Authorizer authorizer) {
        this.authorizer = authorizer;
    }

    public void setVariableRegistry(final VariableRegistry variableRegistry){
        this.variableRegistry = variableRegistry;
    }
}

redpajama_set_name: RedPajamaGithub


text:
STUDIO's Portraits: My City, Myself exhibition opens at Hunter College East Harlem Art Gallery
Rain was pouring down on a recent June evening but nothing could dampen the spirits of more than 100 young artists inside the Hunter College East Harlem Art Gallery who had come with their families, friends and teachers to the opening reception to celebrate their art, Portraits: My City, Myself. The year-end exhibition of artworks selected from all Studio in a School art programs covers the walls of the spacious new gallery at Hunter College's School of Social Work. A distinguished jury chose 140 imaginative paintings, drawings, collage, and sculpture from over 300 entries from public schools all over the five boroughs, including 28 from Harlem.
Large and colorful portraits of the city alternate with intense self-portraits in a variety of media. A group painting of
the New York City skyline features exuberant jazz artists playing trumpet and saxophone against a backdrop of bridges, a roller coaster, the Statue of Liberty, a gorilla on top of the Empire State Building, and huge ice cream cones. Read more and view images from the event.
Open Studio week continues with Julie Mehretu's visit to a class of third graders at PS 139 in Brooklyn
The third graders in artist/instructor Virginia Levie's STUDIO
art class at PS 139 in the Flatbush section of Brooklyn were bursting
with questions for their famous visiting artist, Julie Mehretu. The
students had seen images of some of Mehretu's dazzlingly intricate and monumental paintings that have been celebrated around the world, and when she arrived in their classroom they were eager to know everything.
"Why do you make some paintings so big?" was the first question. "So that you can feel like you can step into it," Mehretu said. "It looks like 3-D, right? With layers of different lines and paint."
The students at PS 139 come from many different worlds and seemed to connect with Mehretu (31 languages are spoken by the students at the school). "I come from two different worlds," Mehretu told them, "half from Ethiopia, half from Michigan. For me, making art is figuring out who I am in the world," Mehretu told them. "I put in traces of many places, many experiences and memories."
The students wanted to know about the architectural drawings that Mehretu delicately layers into her paintings
because they have been working on cityscapes and architectural shapes in their class in a variety of media (collage, oil pastel on paper, ink drawings). "I take places from different parts of the world that have meaning to me and use them as a realistic or representational aspect in my paintings; it's like a story… elements from the world are layered in.
I try to make sense of the world and figure it out in images."
The third graders then got to work figuring out their own worlds and images, as Mehretu moved around the classroom, observing and asking questions of the young artists. The students chose images from postcards their teacher had given them of various architectural structures and created ink drawings on watercolor and rice paper to explore different brush techniques and different ways to deal with structures in space. Many chose iconic skyscrapers and used creative brushwork to make windows, clouds, rain. Mehretu was impressed by their efforts: "The kids are so articulate, and their brushstrokes are so confident. This work with Studio in a School is so important."
The students asked when Mehretu had started painting and she said, "I always wanted to paint." Her parents were very supportive but she had never had a chance to study art in elementary school the way they do.
Mehretu's visit to PS 139 was her first visit to a school that partners with Studio in a School. Principal Mary McDonald brought STUDIO to her school 8 years ago, two years after she arrived, and chose Virginia Levie as the professional artist and teacher for her program. She described how STUDIO has changed her school – which now has an extensive arts program and an engaged parent body. "STUDIO started it all, was the catalyst for the creative and engaged spirit and engaged parent body."
At the end of the art class, McDonald told Mehretu she was honored by her visit and Mehretu replied, "I'm the one
who's honored. Thank you for changing their lives."
Mark di Suvero kicks off Open Studio week with a visit to the Neighborhood School
On a recent rainy morning in June, Mark di Suvero joined more
than 20 six- and seven-year-olds at a long table covered with mounds of rust-colored clay, and immediately got to work. He and all the children pounded, pulled, pinched, stretched and coaxed their clumps of clay. Soon a menagerie of strange and magical shapes appeared: a snake wrapped around a tree branch, a nest of chipmunks, a shark with a flashlight fin, a dog that meows, and from the special guest – a mask with a beaked nose and a tusk passing through the eyes.
Acclaimed sculptor Mark di Suvero usually works in a very different medium -- steel -- but he clearly relished his opportunity to be teacher for a day in any medium. Variously described as "America's Great Man of Steel" and a "steel whisperer" for his lyrical and monumental steel creations, di Suvero came to the Neighborhood School on Manhattan's Lower East Side to participate in Studio in a School's second annual Open Studio week. During the intense hour of art making, the children shared ideas and inspiration with their famous visitor,
who praised the creativity and exuberant spirit of his fellow artists. "To build, make art, with these kids is electrifying," di Suvero said. "It creates the energy of life."
The young artists were excited to meet Mark di Suvero because many had seen his work on Governor's Island, in Socrates Park, and at Storm King. They are the art students of Studio in a School artist/instructor Valerie Hammond, who has been teaching at the Neighborhood School for 20 years and, like all Studio instructors, is also a professional artist. Hammond works in a variety of media in her own art and in her teaching – drawing, painting, sculpture, wax. Her students' creations fill the walls – colorful mosaics of animals, multimedia ink drawings of trees overlaid with prints of butterflies and raindrops; a series of "fresco" pastel moon paintings. "My art informs my teaching and my teaching informs my art," says Hammond. She sometimes brings her own art into the classroom and says, "My students are often my best critics."
Di Suvero's sculptures appeal to children for their bright colors and interactive opportunities -- such as his swinging beds. When asked whether he intends a sense of playfulness in his work, di Suvero said, "I deeply believe in interactive art. Swinging is one of the most natural and primordial activities in human history. It restores our sense of balance and allows us to interact with the world. The structure of art, of architecture, of poetry, creates magnificent feelings."
Six-year-old Emerson brought a small rock he had found at Socrates Park to show di Suvero, and the artist suggested he incorporate it into his clay sculpture. Emerson proudly shared his creation at the end of the class – a clay disc balanced next to the rock wrapped in clay – and Di Suvero was delighted. "The hardest part of making art is to move from the moment of imagination, to make it grow…that's what these kids did here today. Most teachers don't know how to teach that. That's why Studio in a School is so important. To have a dream and be able to make it is the real pleasure of art."

redpajama_set_name: RedPajamaCommonCrawl


text:
foster & fit
September 26, 2017 by A.
Pinoy Pride Monthly: 4 Filipina Women You Should Know
I've been dragging my feet on this entry because it has been a long, hard month in my home country. Just to name a few of the heartbreaks:
3 teenagers dead (allegedly at the hands of police – "End of the Drug War?" – The Atlantic; but then: "Kids Keep Getting Killed" – Washington Post)
The President wasting time "Chewbacca defending" his way around the opposition ("Duterte says he made up wrong account number to fool Trillanes" – GMA News),
Up to 13,000 deaths from Duterte's drug war (see Atlantic article above), a 1,000 peso budget proposed from Congress for the Energy Regulatory Commission, National Commission on Indigenous Peoples, and Commission on Human Rights ("Vote to slash budget of agency investigating drug war to 15 GBP/1,000 PHP" – The Guardian)
Tons of fake news in circulation thanks to Duterte's ovepaid underqualified trolls (I mean) comms team
And: Congress is requesting exemption from "minor traffic violations" on the grounds of their position (because if legislators can make the rules, they sure as hell should be allowed to break them #amiright????) ("MMDA backs traffic exemption for Congress but has to get nod from mayors" – Philippine Daily Inquirer)
So you can imagine, amidst the corrupt circus/joke that is the Philippine political landscape, pride in my country is not the first emotion I can call up. I considered skipping this month entirely, but I believe in counting blessings and finding good despite the bad. So I've decided to do a short one this month: a profile on 4 Filipina women you should know (chosen on the basis of 50% familiarity and 50% surprise == aka, 2 of these women I knew nothing about until I researched, and the other 2 have been – and continue to be, sources of inspiration for me):
First up, we have Josefa Llanes Escoda (1898-1945)
Josefa was known as the "Florence Nightingale of the Philippines." She was a leader in the struggle for women's rights in the Philippines (particularly fighting for women's suffrage), war hero (smuggling food, medicines, and provisions to Filipino and American war prisoners during WWII), and a youth advocate (founding Girl Scouts of the Philippines).
In August 1944, she was captured by the Japanese. She was last seen alive in January 1945, when she was being placed into a Japanese transport truck. At this sighting, she showed signs of beating, torture, and weakness. She is presumed to have been executed shortly thereafter and buried in an unmarked grave.
Shortly before her internment, in a letter to Lt. Jose L. Llanes, she is quoted as saying:
"I have done my duty to my country and God! To my mind the most I have done is having helped with the little I could do to save the lives of the surrendered soldiers of Bataan and Corregidor. I have offered myself as a guarantor for men later released by the enemy, that they commit no anti-Japanese act, men who, if they had the guts left would continue their resistance. I have acted as guarantors not only for the sake of humanity but also to encourage them to fight again. If you happen to survive, and I fail, tell our people that the women of the Philippines did their part also in making the ember sparks of truth and liberty alive till the last moment."
Second, is Tandang Sora (1812-1919)
Born Melchora Aquino in 1812, this woman became known as "Tandang (Elder, in Filipino) Sora" because of her age, and "Mother of Balintawak" and "Grand Woman of the Revolution" for her role in the Philippine Revolution against the Spanish.
She was the wife of the cabeza de barrio (village leader), but when he died quite young, she stepped up to the plate as hermana mayor (working village fiestas, baptisms, weddings, etc), and single mother of 6. And as if that wasn't enough, when the revolutionaries (Katipuneros) began working toward revolution, she became their adoptive mother too. She hosted secret meetings in her home, dressed their wounds, prayed with and for them, offered them moral and medical support, fed them, clothed them, and more.
When the Spaniards got wind of her dealings with the revolutionaries, they captured her and questioned her, but she never caved – leading to her exile on Guam. After the Americans took over, she was able to return back home to the Philippines and live til a ripe old age of 107, going down in history forever as one of the mothers of our young nation.
Third, is Whang-Od (1917 – )
Whang-Od Oogay is a 100-year-old living, breathing legend: an indigenous Filipina tattoo artist from Kalinga, believed to be the last traditional tattooist of her kind. She has been honing and owning this craft for over 80 years – first tattooing warriors, headhunters, and indigenous women particularly across her own tribe (the Butbut people); and now (that the warriors no longer exist), she offers her talent to visiting locals and tourists alike.
She is, herself, extensively tattooed. Each of her full arms sleeves took a day to complete (paid for when she was a teenager with sacks of rice). To celebrate completing these tattoos (sort of like rights of passage), her father would slaughter a pig. She's come far since then, becoming the last tattoo artist of her kind. Her skills are well-known throughout the country, and beyond, and she is widely sought after. Despite that, she continues to live amongst her people, abiding by the rules, traditions, and customs of her tribe.
Though she is yet to be nominated or instated officially, she is eligible both for a National Artists Award, and a National Living Treasures Award.
Next, is Lourdes Castro (1926-2011)
Civil rights activist, war hero, wife, matriarch, and guerilla. Lourdes is one of only 2 officially inducted Filipina veterans of the US Army for her service during WWII in the recognized guerilla forces, Philippine Commonwealth Army, medical corps, and as courier for US soldiers. During the war, her contributions included: participating in the liberation of prisoners of war in Los Baños, Laguna concentration camp; as well as pulling a Desmond Doss (seen Hacksaw Ridge?) risking life and limb to haul soldiers off the battlefield and treating their injuries as a first responder.
As a member of the American Legion Northside Post 858 in San Jose, CA; she was instrumental in kickstarting the veterans' organization, and later on in getting US Congress to pass an important bill into law in February 2009: "Filipino Veterans Equity Compensation Act" (FVEC) in the American Recovery and Reinvestment Act. This law helped give many "forgotten Filipino heroes" their due recognition and support.
You can read more about her and her background in this lovely tribute article by Ben Menor and Marissa Castro Otto for the Philippine Daily Inquirer (December 2011).
Hope you enjoyed this little profile. If you are interested in learning about similar women (more Filipinas, as well as women from all over the globe), go visit my friend Sabrina's Facebook page: Women In Badassery. and get ready to be inspired!
Disclaimers: All drawings above are mine based on source material from Wikipedia, and Filipinknow.
This entry was posted in fun and tagged filipino, girl power, heroes, heroines, josefa llanes escoda, lourdes castro, melchora aquino, philippines, pinay, pinoy pride, pinoy pride monthly, tandang sora, war, warriors, whang-od, women. Bookmark the permalink.
Prepping for D-Day with Baby #2
[BOOK NOTES & REVIEW] Grace Based Parenting by Tim Kimmel
Follow foster & fit on WordPress.com


text:
4 Crystals To Help Manifest Clarity and Focus
by Tanisha Carter
As people are breaking away from organized (sometimes less tolerant) religion, spirituality is taking its place! People are flocking to their local apothecary to stock up on books, oils, and incense to balance chakras, stay positive, and manifest their wildest dreams! At the crux of it, all are stones, affectionately known as crystals.
A post shared by Mental Sugar (@mental_sugar) on Jan 7, 2019 at 8:24am PST
On a physical level, crystals are just fossilized resin that has been embedded in the Earth for thousands of years. On a spiritual level, crystals act as conduits for healing and manifesting. Believed to hold healing energy, crystals have been used to aid in everything from childbirth to transitioning to the afterlife (Have you heard of a Death Doula?)
Holding crystals near or placing them on your body is thought to promote physical, emotional and spiritual healing. Crystals supposedly do this by positively interacting with your body's energy field known as chakra. While some crystals are said to alleviate stress, others purportedly improve focus, creativity, and organization making them the best tool to manifest your deepest desires.
Manifesting wealth, health and dreams takes patience, focus, and clarity and below are a few crystals that are believed to bring this level of concentration into your life while assisting in manifesting big!
A post shared by Crystal Shop (@soulfulvibesco) on Jan 2, 2019 at 5:00am PST
Known as the perfect "everything" stone, once you have set your intentions (Try: "My path is clear, my mind is focused") it will be filled with the energy you wish to carry throughout the day. This stone encourages you to repeat your set intention (just having it with you will do the trick) therefore clearing anything that may be hindering you as well as amplifying the energy you put into it! Because this stone's amplifying and attracting energy is so strong it is suggested to keep a grounding/calming stone with you as those feelings can become overwhelming for some.
Paired great with: Black tourmaline, amethyst
A post shared by ARTHUR & LIVINGSTON JEWELRY (@arthurandlivingston) on Feb 24, 2019 at 3:59am PST
Although this is not recognized as a focus/clarity stone, its protection properties help to ward off negativity. So much so that it is believed to create a strong energetic barrier around the carrier that can even block possible negative phone calls and emails. By warding off these types of entities this stone keeps your surroundings clear enough to make strong positive decisions and even aids in creativity.
A post shared by healing.angels.melbourne (@healing.angels.melbourne) on Feb 25, 2019 at 1:25pm PST
This is the best stone for mental focus/clarity. As a balancing and grounding stone ,it enhances your concentration and gives structure to your chaotic thoughts. So much so that you are able to make clear and precise decisions. Even the shape of Fluorite aids in sharping your focus. If your Fluorite comes in an obelisk or pyramid shape, this helps to create "laser-like' concentration. Great for manifesting clearly and quickly!
A post shared by Crystal Shop (@soulfulvibesco) on Feb 13, 2019 at 8:30am PST
"Known as the "student's stone it can improve organization, memory, and attention" states Corinne Kenner, author of Crystals for Beginners: A Guide to Collecting & Using Stones & Crystals. To accompany those effects this stone also boosts confidence and alleviates stress.
Extensive testing has taken place to prove the healing theory and although science cannot confirm its success, scientists like Christopher French, a professor of psychology at Goldsmiths, University of London believes that the "…. effects reported were a result of the power of suggestion, not the power of the crystals."
Although the scientific hypothesis of whether crystals heal fell short, it is scientifically proven that crystals hold within them over 5,000 years of intentions. I'd like to believe that these thousands of years of intentions allow positive joyous loving manifesting energy to flow into the body as negative, disease-causing energy flows out.
Tanisha Carter is a Richmond, VA based poet using her weekly podcast, The Honey Files and self-directed show, Yeye: A One-Woman Journey, to assist in the collective efforts to change the narrative of black people involving issues such as women's rights, cultural/self-awareness, and community. Find her at @thehoneyfilespodcast and @_tanishacarter
Back to Mind
Shipping, Returns, & Refunds
The Black Wellness Community
© 2020, The Black Wellness Community Powered by Shopify


I was at the sprint car races at our county fair last Saturday night. It's a once a year deal.
Sept. 15th is the night before our Rockford swap. Timing is everything.
The other thing is, I haven't sold on AB for a couple years. Just sayin.


Our passion has always been gaming, especially mobile platforms. We are all gamers at heart here at Pixel Knights so we know exactly what makes for a great game.
Our gaming portfolio is always increasing, and with the release of our latest game, Stackimals, brings our first tablet game to market.
Our team have worked on a number of huge projects for renowned clients, such as Microsoft, Credit Suisse, Ford Motor Company and the Metropolitan Police, so things aren't just play here at Pixel Knights HQ.
Pixel Knights was started in 2011 by Carl Jones, a renowned software developer, photographer and avid gamer from near Pwllheli, in North Wales.
From our base in rural North Wales, we find plenty of time for work, rest and lots of play. Our ethos has always been one where we encourage play and creativity, not just from our employees but from everyone we work with.
Recently we have also been working as part of the Coder Dojo and Code Club movement's in the UK to bring that level of enthusiasm to a younger audience, giving our time to teaching children the joys of prgramming (and specifically games programming) using Scratch.


Forgive to further your growth process. Forgive to regain your peace of mind.
Forgiveness doesn't mean staying in a bad situation that continually recycles itself, but the choice to learn the lessons and move forward with your life in a positive way.
Forgiveness isn't about making light of the hurt, it's moving beyond that moment. The circumstances and details surrounding the offense may be complex, but forgiveness is the catalyst for letting go of the pain. Approach life with open hands, instead of closed fists.
Don't base your forgiveness on the thought that the person who hurt you will change, because they may not. That's the revelation they'll have to come to on their own. Forgive to reclaim and walk in your freedom.


35' 1998 Carver 350 Mariner One owner, professionally maintained, low hours, in very good condition. Includes: generator, radar, plotter and auto pilot.Trades considered.
It doesn't look like there are any Nitro boats for sale in Iowa that match all of your boat search criteria, but included some other boats that are displayed above. Boat Paradise has a lot of boats listed for sale on but some brands/locations might be a rare find. You might get a better luck if you broaden your search.


text:
Dis Manibus (lateinisch, den Totengeistern), abgekürzt D•M oder DD•MM, ist eine epigraphische Formel, die in Grabinschriften der Römischen Antike erscheint. Sie tritt häufig auch mit dem Zusatz Sacrum auf, abgekürzt dann D•M•S oder S•D•M, "den Totengeistern geweiht".

Nach dem Ergebnis der Untersuchungen von Santoro trat sie nicht vor der Zeit des Augustus auf und wurde erst in nachaugusteischer Zeit, dann auch in abgekürzter Form, allgemein gebräuchlich.

Positionierung
Die Formel kann als Inschrift ohne weiteren Zusatz erscheinen und kennzeichnet dann einen Ort allgemein als Grabstätte, in der Regel bildet sie jedoch nur einen Bestandteil einer Grabinschrift mit Nennung eines Verstorbenen, zuallermeist steht sie dort dann am Anfang, manchmal auch dem Namen des Verstorbenen nachgesetzt oder an das Ende der Inschrift gestellt, und in Einzelfällen erscheinen die Buchstaben D und M getrennt voneinander links und rechts oberhalb der Namensinschrift.

Sprachliche Deutung
Der Dativ Di(i)s Manibus wird so verstanden, dass mit dieser Formel die Grabstätte den di manes, den durch manes als 'gut, gnädig' gekennzeichneten Toten- oder Ahnengeistern, geweiht wird, wobei der dedizierende Charakter der Inschrift auch durch noch eindeutigere Formulierungen zum Ausdruck gebracht werden kann.  Ist sie mit dem Namen eines Verstorbenen verbunden, so steht dieser entweder im Genitiv, im Dativ oder im Nominativ. Die Formel DM + Genitiv wird hierbei so verstanden, dass die Widmung nicht an die Totengeister allgemein, sondern speziell an die Ahnengeister des Verstorbenen erfolgt, oder aber dass trotz der (bei Abkürzung nur mutmaßlichen) Pluralform mit den Manen des Verstorbenen der Geist dieses Verstorbenen, dessen Seele, als Empfänger der Widmung gemeint sei. Die Konstruktion DM + Dativ gilt demgegenüber als Dedikation an die Toten- oder Ahnengeister und den Verstorbenen selbst, wie es auch noch deutlicher angezeigt sein kann, wenn zusätzlich zu den Manen und unterschieden von ihnen der Geist des Verstorbenen als genius (bei Frauen als Iuno) und Empfänger der Widmung genannt ist. In der Konstruktion DM + Nominativ schließlich gilt DM als eine bloße Einleitungsformel, die die Widmung an die Manen dem Namen des Verstorbenen syntaktisch unverbunden voranstellt.

DM in jüdischen und christlichen Grabinschriften
Die ihrem Ursprung nach heidnische Formel tritt in abgekürzter Form auch in Inschriften für jüdische und christliche Verstorbene auf, wobei diejenigen für christliche Verstorbene zum Teil auch christliches Formelgut oder christliche Symbole aufweisen, während bei mutmaßlich jüdischen DM-Inschriften zumeist nur aus dem Namen oder Fundort und nur in vergleichsweise wenigen Fällen auch aus einem Namenszusatz wie Iudea Rückschlüsse auf die Religionszugehörigkeit möglich sind. Man hat diesen Befund so zu erklären versucht, dass die Formel in ihrem Sinn unverständlich geworden, synkretistisch angeeignet oder zu Deo Magno oder Deo Maximo umgedeutet worden sein könnte, oder dass es sich um Grabsteine bzw. Grabplatten mit einer vorgefertigten Inschrift gehandelt haben könnte. In einigen Fällen konnte von Rutgers anhand der Platzierung der Formel auf der Rückseite der Platte oder anhand von Bearbeitungsspuren auch plausibel gemacht werden, dass eine zuvor heidnisch verwendete Platte für einen jüdischen Verstorbenen wiederverwendet wurde.

Literatur
 John Edwin Sandys: Latin Epigraphy. An Introduction to the Study of Latin Inscriptions, 2., von Sidney G. Campbell revidierte Ausg., Cambridge University Press, Cambridge 1927, Repr. Ares, Chicago 1971, S. 62 f.
 Lawrence Keppie: Understanding Roman Inscriptions, The Johns Hopkins University Press, Baltimore 1991, S. 107.

Einzelnachweise

Bestattungsritual (Antike)
Römische Religion
Epigraphik
Lateinische Phrase

redpajama_set_name: RedPajamaWikipedia


text:
featured NFL Others
Olympic gymnast Simone Biles announces engagement to Houston Texans safety Jonathan Owens
Simone Biles is a bride to be!
The Olympic gold medalist gymnast and Houston Texans safety Jonathan Owens are engaged, the couple announced on social media Tuesday. The two shared beautiful photos from the Valentine's Day proposal in Houston, Texas, and a close-up look at the dazzling engagement ring.
In a post on Instagram, Owens wrote that Biles "really had no clue" he was going to pop the question.
The star-studded couple celebrated their one-year anniversary in August 2021 while Biles was in Tokyo, Japan, competing in the Summer Olympics.
"THE EASIEST YES," the 24-year-old world champion wrote on Instagram. "I can't wait to spend forever & ever with you, you're everything I dreamed of and more! let's get married FIANCÉ."
Biles publicly confirmed her relationship with Owens in 2020. In August 2021, she shared a post to celebrate that she and Owens had been dating for more than a year.
"So happy past 1 year to the best thing that's ever happened to you: ME," Biles wrote, with a laughing emoji.
In a recent interview with NET-A-PORTER's digital title PORTER, Biles spoke about how she is prioritizing her personal life at the moment.
She told the outlet she was "making sure I have the proper time to spend with my family, my friends and my boyfriend."
Credit: ABC