com.francetelecom.clara.cloud.logicalmodel.LogicalService.java Source code

Java tutorial

Introduction

Here is the source code for com.francetelecom.clara.cloud.logicalmodel.LogicalService.java

Source

/**
 * Copyright (C) 2015 Orange
 * Licensed 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 com.francetelecom.clara.cloud.logicalmodel;

import com.francetelecom.clara.cloud.commons.EqualsUtils;
import com.francetelecom.clara.cloud.commons.GuiClassMapping;
import com.francetelecom.clara.cloud.commons.GuiMapping;
import com.francetelecom.clara.cloud.commons.UUIDUtils;
import com.francetelecom.clara.cloud.commons.jaxb.AnyTypeAdapter;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import java.util.*;

/**
 * Base class for Service in the Logical Model.
 * Factors out common properties to all services that are attached to a {@link ProcessingNode}
 *
 * Note that this does not directly map to each entry in the service catalog PDF document.
 * @author APOG7416
 */
// @XmlRootElement
@Entity
@Table(name = "LOGICAL_SERVICE")
@XmlJavaTypeAdapter(AnyTypeAdapter.class)
public abstract class LogicalService extends LogicalModelItem {

    private static final long serialVersionUID = 1L;

    /**
     * logical deployment.
     */
    @XmlIDREF
    @XmlElement(name = "logicalDeploymentRef")
    @ManyToOne
    @NotNull
    @GuiMapping(status = GuiMapping.StatusType.NA)
    LogicalDeployment logicalDeployment;

    /**
     * Logical Node using the logical Service. Use an assocation Entity. No xml
     * element for association (done on execution service side)
     */
    @XmlTransient
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "logicalService", orphanRemoval = true)
    @GuiMapping()
    protected List<LogicalNodeServiceAssociation> logicalNodeServiceAssociations = new ArrayList<LogicalNodeServiceAssociation>();

    // @TODO: remove label when transition is ended
    /**
     * Note: the logicalNodeServiceAssociation is kept, but ignores its link back to us (LogicalService)
     */
    private static final String[] EXCLUDED_EQUALS_FIELDS = EqualsUtils.mergeExcludedFieldLists(
            LogicalModelItem.EXCLUDED_EQUALS_FIELDS,
            new String[] { "logicalDeployment", "targetBasicatCode", "initialPopulationScript" });

    private static final String[] EXCLUDED_HIBERNATE_BROKEN_EQUALS_COLLECTIONS = new String[] {
            "logicalNodeServiceAssociations" };

    /**
     * Default constructor.
     */
    public LogicalService() {
        super();
    }

    /**
     * Logical Service constructor
     * 
     * @param label
     * @param logicalDeployment
      * @deprecated Should not be called anymore, use empty constructor instead
      * followed by {@link LogicalDeployment#addLogicalService(LogicalService)}
     */
    public LogicalService(String label, LogicalDeployment logicalDeployment) {
        super(UUIDUtils.generateUUID("ls"), label);
        this.logicalDeployment = logicalDeployment;

        // add the LogicalService to the global deployment List
        //FIXME: use logicalDeployment.addLogicalService(this) instead
        logicalDeployment.addLogicalService(this);
    }

    /**
     * list all ExecutionNode using this Service
     * 
     * @return
     */
    public Set<ProcessingNode> listDependentProcessingNodes() {
        HashSet<ProcessingNode> nodes = new HashSet<ProcessingNode>();
        for (LogicalNodeServiceAssociation association : this.logicalNodeServiceAssociations) {
            nodes.add(association.processingNode);
        }
        return Collections.unmodifiableSet(nodes);
    }

    /**
     * List all association to related LogicalExecution Node
     * 
     * @return
     */
    public List<LogicalNodeServiceAssociation> listLogicalServicesAssociations() {
        return Collections.unmodifiableList(this.logicalNodeServiceAssociations);
    }

    @Override
    public boolean equals(Object obj) {
        //See rationale for this specific impl in LogicalDeployment.equals()
        return equals(obj, false);
    }

    /**
     * Utility method to factor out logic between {@link #equals(Object)} and {@link #equalsShallow(LogicalService)}
     * @param obj The other object to compare
     * @param excludeAssociations set to true to exclude the {@link #logicalNodeServiceAssociations} in the comparison
     *                            or false to include them.
     * @return
     */
    protected boolean equals(Object obj, boolean excludeAssociations) {
        if (obj == null) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        if (obj.getClass() != getClass()) {
            return false;
        }
        LogicalService rhs = (LogicalService) obj;

        EqualsBuilder equalsBuilder = new EqualsBuilder().appendSuper(super.equals(obj, EqualsUtils
                .mergeExcludedFieldLists(EXCLUDED_EQUALS_FIELDS, EXCLUDED_HIBERNATE_BROKEN_EQUALS_COLLECTIONS)));

        if (!excludeAssociations) {
            List<LogicalNodeServiceAssociation> thisLogicalNodeServiceAssociations = new ArrayList<LogicalNodeServiceAssociation>(
                    logicalNodeServiceAssociations);
            Collections.sort(thisLogicalNodeServiceAssociations);
            List<LogicalNodeServiceAssociation> rhsLogicalNodeServiceAssociations = new ArrayList<LogicalNodeServiceAssociation>(
                    rhs.logicalNodeServiceAssociations);
            Collections.sort(rhsLogicalNodeServiceAssociations);
            equalsBuilder.append(thisLogicalNodeServiceAssociations, rhsLogicalNodeServiceAssociations);
        }

        return equalsBuilder.isEquals();
    }

    /**
     * Tests that two LogicalService are semantically equal, ignoring whether the object was connected to other
     * services. This is mainly used in tests (such as UI automated tests) 
     * @param logicalService
     * @return
     */
    public boolean equalsShallow(LogicalService logicalService) {
        return equals(logicalService, true);
    }

    @Override
    public int hashCode() {
        //Note: Same workarounds as for equals
        HashCodeBuilder builder = new HashCodeBuilder(13, 71).appendSuper(super.hashCode(EqualsUtils
                .mergeExcludedFieldLists(EXCLUDED_EQUALS_FIELDS, EXCLUDED_HIBERNATE_BROKEN_EQUALS_COLLECTIONS)));
        if (logicalNodeServiceAssociations != null) {
            //Hack: force eager fetch of associations
            logicalNodeServiceAssociations.size();
            builder.append(new ArrayList<LogicalNodeServiceAssociation>(logicalNodeServiceAssociations));
        }
        return builder.toHashCode();
    }

    /**
     * Utility method to list all supported classes
     * @return
     */
    public static Set<Class> listServicesClass() {
        Set<Class> classes = new HashSet<Class>();
        classes.add(LogicalWebGUIService.class);
        classes.add(LogicalQueueSendService.class);
        classes.add(LogicalQueueReceiveService.class);
        classes.add(LogicalRelationalService.class);
        classes.add(LogicalConfigService.class);
        classes.add(LogicalSoapConsumer.class);
        classes.add(LogicalSoapService.class);
        //TODO: add others

        return classes;
    }

    protected void setLogicalDeployment(LogicalDeployment logicalDeployment) {
        this.logicalDeployment = logicalDeployment;
    }

    public LogicalDeployment getLogicalDeployment() {
        return logicalDeployment;
    }

    @Override
    protected boolean isFieldExcludedFromToString(String fieldName) {
        return isFieldExcludedFromToString(fieldName, LogicalService.EXCLUDED_EQUALS_FIELDS);
    }

    @Override
    public int compareTo(LogicalModelItem o) {

        GuiClassMapping annotationOther = o.getClass().getAnnotation(GuiClassMapping.class);
        GuiClassMapping annotationThis = this.getClass().getAnnotation(GuiClassMapping.class);

        if (annotationThis != null && annotationOther != null) {
            if (annotationThis.isExternal() && annotationOther.isExternal()
                    || !annotationThis.isExternal() && !annotationOther.isExternal()) {
                return super.compareTo(o);
            } else if (annotationThis.isExternal() && !annotationOther.isExternal()) {
                return -1;
            } else {
                return 1;
            }
        } else {
            //If services are in same category, then sort based on class name and labels
            return super.compareTo(o);
        }
    }
}