org.pentaho.agilebi.modeler.models.annotations.ModelAnnotationGroup.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.agilebi.modeler.models.annotations.ModelAnnotationGroup.java

Source

/*! ******************************************************************************
 *
 * Pentaho Community Edition Project: pentaho-modeler
 *
 * Copyright (C) 2002-2016 by Pentaho : http://www.pentaho.com
 *
 * *******************************************************************************
 *
 * 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 org.pentaho.agilebi.modeler.models.annotations;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.pentaho.agilebi.modeler.ModelerException;
import org.pentaho.agilebi.modeler.ModelerWorkspace;
import org.pentaho.agilebi.modeler.models.annotations.data.DataProvider;
import org.pentaho.metastore.api.IMetaStore;
import org.pentaho.metastore.persist.MetaStoreAttribute;
import org.pentaho.metastore.persist.MetaStoreElementType;
import org.w3c.dom.Document;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

//import static org.pentaho.agilebi.modeler.models.annotations.ModelAnnotationGroup.ApplyStatus.*;

@MetaStoreElementType(name = "ModelAnnotationGroup", description = "ModelAnnotationGroup")
public class ModelAnnotationGroup extends ArrayList<ModelAnnotation> {

    @MetaStoreAttribute
    private String id;

    @MetaStoreAttribute
    private String name;

    @MetaStoreAttribute
    private String description;

    @MetaStoreAttribute
    private boolean sharedDimension;

    @MetaStoreAttribute
    private List<DataProvider> dataProviders = new ArrayList<DataProvider>();

    @MetaStoreAttribute
    private List<ModelAnnotation> modelAnnotations; // indicate to metastore to persist items (calls the getter/setter)

    public ModelAnnotationGroup() {
        super();
    }

    public ModelAnnotationGroup(ModelAnnotation... modelAnnotations) {
        super(Arrays.asList(modelAnnotations));
    }

    public String getId() {
        return id;
    }

    public void setId(final String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<ModelAnnotation> getModelAnnotations() {
        return this;
    }

    public void setModelAnnotations(List<ModelAnnotation> modelAnnotations) {
        removeRange(0, this.size()); // remove all
        if (modelAnnotations != null) {
            addAll(modelAnnotations);
        }
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public boolean isSharedDimension() {
        return sharedDimension;
    }

    public void setSharedDimension(boolean sharedDimension) {
        this.sharedDimension = sharedDimension;
    }

    public List<DataProvider> getDataProviders() {
        return dataProviders;
    }

    public void setDataProviders(List<DataProvider> dataProviders) {
        this.dataProviders = dataProviders;
    }

    @Override
    public boolean equals(Object obj) {

        try {
            if (!EqualsBuilder.reflectionEquals(this, obj)) {
                return false;
            }

            // manually check annotations
            ModelAnnotationGroup objGroup = (ModelAnnotationGroup) obj;
            if (this.size() != objGroup.size()) {
                return false;
            }

            for (int i = 0; i < this.size(); i++) {
                if (!this.get(i).equals(objGroup.get(i))) {
                    return false;
                }
            }

            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public enum ApplyStatus {
        SUCCESS, FAILED, NULL_ANNOTATION
    }

    private interface AnnotateStrategy {
        boolean apply(ModelAnnotation modelAnnotation) throws ModelerException;

        Map<ApplyStatus, List<ModelAnnotation>> applyAll(ModelAnnotationGroup modelAnnotations)
                throws ModelerException;

        boolean isEmptyModel();
    }

    public Map<ApplyStatus, List<ModelAnnotation>> applyAnnotations(final Document mondrianSchema)
            throws ModelerException {
        return applyAnnotations(mondrianSchema, this);
    }

    private Map<ApplyStatus, List<ModelAnnotation>> applyAnnotations(final Document mondrianSchema,
            final ModelAnnotationGroup toApply) throws ModelerException {
        AnnotateStrategy strategy = new AnnotateStrategy() {

            @Override
            public boolean apply(final ModelAnnotation modelAnnotation) throws ModelerException {
                return modelAnnotation.apply(mondrianSchema);
            }

            @Override
            public Map<ApplyStatus, List<ModelAnnotation>> applyAll(final ModelAnnotationGroup modelAnnotations)
                    throws ModelerException {
                return applyAnnotations(mondrianSchema, modelAnnotations);
            }

            @Override
            public boolean isEmptyModel() {
                return !mondrianSchema.hasChildNodes();
            }
        };
        return applyAnnotations(strategy, toApply);
    }

    public Map<ApplyStatus, List<ModelAnnotation>> applyAnnotations(final ModelerWorkspace model,
            final IMetaStore metaStore) throws ModelerException {
        return applyAnnotations(model, metaStore, this);
    }

    private Map<ApplyStatus, List<ModelAnnotation>> applyAnnotations(final ModelerWorkspace model,
            final IMetaStore metaStore, final ModelAnnotationGroup toApply) throws ModelerException {
        AnnotateStrategy strategy = new AnnotateStrategy() {

            @Override
            public boolean apply(final ModelAnnotation modelAnnotation) throws ModelerException {
                return modelAnnotation.apply(model, metaStore);
            }

            @Override
            public Map<ApplyStatus, List<ModelAnnotation>> applyAll(final ModelAnnotationGroup modelAnnotations)
                    throws ModelerException {
                return applyAnnotations(model, metaStore, modelAnnotations);
            }

            @Override
            public boolean isEmptyModel() {
                return model.getModel().getDimensions().size() == 0 && model.getModel().getMeasures().size() == 0;
            }
        };
        return applyAnnotations(strategy, toApply);
    }

    private Map<ApplyStatus, List<ModelAnnotation>> applyAnnotations(AnnotateStrategy strategy,
            final ModelAnnotationGroup toApply) throws ModelerException {
        if (strategy.isEmptyModel()) {
            //the model is empty so there is no use trying to apply annotations.
            //this usually happens when there is no data.
            return Collections.emptyMap();
        }
        Map<ApplyStatus, List<ModelAnnotation>> statusMap = initStatusMap();
        ModelAnnotationGroup failedAnnotations = new ModelAnnotationGroup();
        for (ModelAnnotation modelAnnotation : toApply) {
            if (modelAnnotation.getAnnotation() == null) {
                statusMap.get(ApplyStatus.NULL_ANNOTATION).add(modelAnnotation);
                continue;
            }
            boolean applied = strategy.apply(modelAnnotation);
            if (applied) {
                statusMap.get(ApplyStatus.SUCCESS).add(modelAnnotation);
            } else {
                failedAnnotations.add(modelAnnotation);
            }
        }
        if (failedAnnotations.size() < toApply.size()) {
            Map<ApplyStatus, List<ModelAnnotation>> recurStatusMap = strategy.applyAll(failedAnnotations);
            for (ApplyStatus applyStatus : ApplyStatus.values()) {
                statusMap.get(applyStatus).addAll(recurStatusMap.get(applyStatus));
            }
        } else if (failedAnnotations.size() > 0) {
            for (ModelAnnotation failedAnnotation : failedAnnotations) {
                statusMap.get(ApplyStatus.FAILED).add(failedAnnotation);
            }
        }
        return statusMap;
    }

    private Map<ApplyStatus, List<ModelAnnotation>> initStatusMap() {
        HashMap<ApplyStatus, List<ModelAnnotation>> statusMap = new HashMap<ApplyStatus, List<ModelAnnotation>>();
        for (ApplyStatus applyStatus : ApplyStatus.values()) {
            statusMap.put(applyStatus, new ArrayList<ModelAnnotation>());
        }
        return statusMap;
    }

    public void addInjectedAnnotations(List<? extends AnnotationType> annotations) {

        for (AnnotationType annotationType : annotations) {
            ModelAnnotation existingAnnotation = findExistingAnnotation(annotationType);
            ModelAnnotation ma = existingAnnotation == null ? new ModelAnnotation() : existingAnnotation;

            ma.setName(annotationType.getName());

            if (existingAnnotation == null) {
                ma.setAnnotation(annotationType);

                add(ma);
            } else {
                // set each of the specific values that are injected onto the existing annotation
                List<ModelProperty> modelProperties = annotationType.getModelProperties();
                modelProperties.stream().forEach(modelProperty -> {
                    try {
                        Object value = annotationType.getModelPropertyValueById(modelProperty.id());
                        if (value != null) {
                            ma.getAnnotation().setModelPropertyValueById(modelProperty.id(), value);
                        }
                    } catch (Exception e) {
                        // this shouldn't happen since we are iterating over the properties
                    }
                });

            }
        }
    }

    protected ModelAnnotation findExistingAnnotation(AnnotationType annotation) {
        List<ModelAnnotation> matches = stream().filter(ma -> ma.getAnnotation().equalsLogically(annotation))
                .collect(Collectors.toList());

        return CollectionUtils.isNotEmpty(matches) ? matches.get(0) : null;
    }
}