/**
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a
 * copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.jasig.portal.tenants;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Defines the contract for Tenant operations vis-a-vis other subsystems.
 * 
 * @since uPortal 4.1
 * @author awills
 */
@Service
public final class TenantService {

    private static final String TENANT_NAME_VALIDATOR_REGEX = "^[\\w ]{5,32}$";
    private static final Pattern TENANT_NAME_VALIDATOR_PATTERN = Pattern.compile(TENANT_NAME_VALIDATOR_REGEX);
    private static final String TENANT_FNAME_VALIDATOR_REGEX = "^[a-z_0-9]{5,32}$";
    private static final Pattern TENANT_FNAME_VALIDATOR_PATTERN = Pattern.compile(TENANT_FNAME_VALIDATOR_REGEX);

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private ITenantDao tenantDao;

    @Resource(name="tenantOperationsListeners")
    private List<ITenantOperationsListener> tenantOperationsListeners;

    /**
     * Provides the complete collection of tenants in the system in the default
     * order (alphabetically by name).
     */
    public List<ITenant> getTenantsList() {
        List<ITenant> rslt = new ArrayList<ITenant>(tenantDao.getAllTenants());
        Collections.sort(rslt);
        return rslt;
    }

    public ITenant createTenant(final String name, final String fname, 
            final Map<String,String> attributes) {

        // Input validation
        if (!TENANT_NAME_VALIDATOR_PATTERN.matcher(name).matches()) {
            String msg = "Invalid tenant name '" + name +
                    "' --  names must be between 5 and 32 " +
                    "characters and may contain only a-z, A-Z, 0-9, spaces, " +
                    "and underscores";
            throw new IllegalArgumentException(msg);
        }
        if (!TENANT_FNAME_VALIDATOR_PATTERN.matcher(fname).matches()) {
            String msg = "Invalid tenant fname '" + fname +
                    "' -- fnames must be between 5 and 32 " +
                    "characters and may contain only lower case letters, numbers, " +
                    "and underscores";
            throw new IllegalArgumentException(msg);
        }

        // Create the concrete tenant object
        final ITenant rslt = new JpaTenant();
        rslt.setName(name);
        rslt.setFname(fname);
        for (Map.Entry<String,String> y : attributes.entrySet()) {
            rslt.setAttribute(y.getKey(), y.getValue());
        }

        if (log.isInfoEnabled()) {
            log.info("Creating new tenant:  " + rslt.toString());
        }

        // Invoke the listeners
        for (ITenantOperationsListener listener : this.tenantOperationsListeners) {
            try {
                listener.onCreate(rslt);
            } catch (Exception e) {
                log.error("Error invoking ITenantOperationsListener '{}' for tenant:  {}", 
                                    listener.getClass().getName(), rslt.toString(), e);
                if (listener.isFailOnError()) {
                    throw new RuntimeException(e);
                }
            }
        }

        return rslt;
    }

    public void deleteTenantByFName(String fname) {
        final ITenant tenant = tenantDao.getTenantByFName(fname);

        // Invoke the listeners
        for (ITenantOperationsListener listener : this.tenantOperationsListeners) {
            listener.onDelete(tenant);
        }
    }

}

@@ -971,16 +971,58 @@
 ource;%0A%0A
+import org.apache.commons.lang3.Validate;%0A
 import o
@@ -2455,29 +2455,44 @@
 ion%0A        
-if (!
+Validate.validState(
 TENANT_NAME_
@@ -2524,35 +2524,33 @@
 (name).matches()
-) %7B
+,
 %0A            Str
@@ -2542,36 +2542,27 @@
             
-String msg =
+   
  %22Invalid te
@@ -2576,45 +2576,15 @@
 me '
-%22 + name +%0A                    %22'
+%25s' 
  --
- 
  nam
@@ -2595,227 +2595,102 @@
 ust 
-be between 5 and 32 %22 +%0A                    %22characters and may contain only a-z, A-Z, 0-9, spaces, %22 +%0A                    %22and underscores%22;%0A            throw new IllegalArgumentException(msg);%0A        %7D%0A        if (!
+match %25s .%22, name, %0A                TENANT_NAME_VALIDATOR_REGEX);%0A        Validate.validState(
 TENA
@@ -2740,19 +2740,17 @@
 atches()
-) %7B
+,
 %0A       
@@ -2758,20 +2758,11 @@
     
-String msg =
+   
  %22In
@@ -2785,269 +2785,96 @@
 me '
-%22 + fname +%0A                    %22' -- fnames must be between 5 and 32 %22 +%0A                    %22characters and may contain only lower case letters, numbers, %22 +%0A                    %22and underscores%22;%0A            throw new IllegalArgumentException(msg);%0A        %7D
+%25s'  -- fnames must match %25s .%22, name, %0A                TENANT_FNAME_VALIDATOR_PATTERN);
 %0A%0A  

Use Validate from commons-lang