WSO2 Governance Registry - Lifecycle Management Part 2 - Transition Validators

This is the second post of "WSO2 Governance Registry - Lifecycle Management" post series. In the first post - Part 1 - Check Items we gave a small introduction to lifecycle management in WSO2 Governance Registry and looked at how check items can be used and did a small sample on that. 

In this post we will look at Transition Validators as mentioned in the previous post. As mentioned in part 1 transition validations can be used within check items and it can also be used separately ( All the validators will be called only during a state transition, checking a check item will not call the validator ). we will take a look at the same config this time with two transition validation elements.

<aspect name="SimpleLifeCycle" class="org.wso2.carbon.governance.registry.extensions.aspects.DefaultLifeCycle">
    <configuration type="literal">
        <lifecycle>
            <scxml xmlns="http://www.w3.org/2005/07/scxml"
                   version="1.0"
                   initialstate="Development">
                <state id="Development">
                    <datamodel>
                        <data name="checkItems">
                            <item name="Code Completed" forEvent="Promote">
                               <permissions>
                                    <permission roles="wso2.eng,admin"/>
                                </permissions>
                                <validations>
                                  <validation forEvent="" class="">
                                          <parameter name="" value=""/>
                                 </validation>
                                </validations>
                            </item>
                            <item name="WSDL, Schema Created" forEvent="">
                            </item>
                            <item name="QoS Created" forEvent="">
                            </item>
                        </data>
                         <data name="transitionValidation">
                            <validation forEvent="" class="">
                                <parameter name="" value=""/>
                            </validation>
                        </data>
                    </datamodel>
                    <transition event="Promote" target="Tested"/>                  
                </state>
                <state id="Tested">
                    <datamodel>
                        <data name="checkItems">
                            <item name="Effective Inspection Completed" forEvent="">
                            </item>
                            <item name="Test Cases Passed" forEvent="">
                            </item>
                            <item name="Smoke Test Passed" forEvent="">
                            </item>
                        </data>
                    </datamodel>
                    <transition event="Promote" target="Production"/>
                    <transition event="Demote" target="Development"/>
                </state>
                <state id="Production">  
                    <transition event="Demote" target="Tested"/>
                </state>                
            </scxml>
        </lifecycle>
    </configuration>
</aspect>

The first transition validation is within an check item ( this part was commented out in the previous post). And the second one is as a separate element, both are supported.

Writing Validators

A validator is java class that implements  the "CustomValidations" interface there are several validators that are already implemented and it is also possible to write you own custom validator and add it. we will be looking at one of the validators that is shipped with the product. a custom validator will need to written similarly . Please refer Adding an Extension documentation to see how a new extension can be added into the Governance Registry through the GUI.

The following is a validator that is shipped with the WSO2 Governance Registry.

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.governance.api.common.dataobjects.GovernanceArtifact;
import org.wso2.carbon.governance.api.exception.GovernanceException;
import org.wso2.carbon.governance.api.util.GovernanceUtils;
import org.wso2.carbon.governance.registry.extensions.interfaces.CustomValidations;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext;
import org.wso2.carbon.registry.core.session.UserRegistry;

import java.util.Map;

public class AttributeExistenceValidator implements CustomValidations {

    private static final Log log = LogFactory.getLog(AttributeExistenceValidator.class);
    private String[] attributes = new String[0];

    public void init(Map parameterMap) {
        if (parameterMap != null) {
            String temp = (String) parameterMap.get("attributes");
            if (temp != null) {
                attributes = temp.split(",");
            }
        }
    }

    public boolean validate(RequestContext context) {
        if (attributes.length == 0) {
            return true;
        }
        String resourcePath = context.getResourcePath().getPath();
        int index = resourcePath.indexOf(RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH);
        if (index < 0) {
            log.warn("Unable to use Validator For Resource Path: " + resourcePath);
            return false;
        }
        index += RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH.length();
        if (resourcePath.length() <= index) {
            log.warn("Unable to use Validator For Resource Path: " + resourcePath);
            return false;
        }
        resourcePath = resourcePath.substring(index);
        try {
            UserRegistry registry = ((UserRegistry) context.getSystemRegistry())
                    .getChrootedRegistry(RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH);
            GovernanceArtifact governanceArtifact =
                    GovernanceUtils.retrieveGovernanceArtifactByPath(registry, resourcePath);
            for (String attribute : attributes) {
                if (!validateAttribute(governanceArtifact, attribute)) {
                    return false;
                }
            }
        } catch (RegistryException e) {
            log.error("Unable to obtain registry instance", e);
        }
        return true;
    }

    protected boolean validateAttribute(GovernanceArtifact governanceArtifact, String attribute)
            throws GovernanceException {
        return (governanceArtifact.getAttribute(attribute) != null);
    }
}

The "init" method is were the parameter that are defined under the validator tag is initialized. The "validate" method is were your validation logic goes this is the method that is called to do the validation. What this validator does is check whether the attributes names given as a parameter actually exist in the given aspect. If the attribute does not exist the validation will fail.

Configuring the Validator


<validation forEvent="Promote" class="org.wso2.carbon.governance.registry.extensions.validators.AttributeExistenceValidator">
    <parameter name="attributes" value="overview_version,overview_description"/>
</validation>

The fully qualified class name needs to be provided as the class name, the "forEvent" attribute specifies the action on which the validation needs to be triggered here it is set to Promote. For a complete list of validators that are available please refer to Supported Standard Validators documentation. Now you can add the validator configuration we commented out in the First Post and check out the functionality of validators.

Please leave a comment you need any more clarification. The next post of this series will cover transition permissions.

Comments

Popular posts from this blog

Writing Unit Tests to test JMS Queue listener code with ActiveMQ

Reading and Writing Binary files in java - Converting Endianness ( between Big-endian byte order and Little-endian byte order)

Setting up Heron Cluster with Apache Aurora Locally