com.haulmont.cuba.core.sys.AppComponents.java Source code

Java tutorial

Introduction

Here is the source code for com.haulmont.cuba.core.sys.AppComponents.java

Source

/*
 * Copyright (c) 2008-2016 Haulmont.
 *
 * 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.haulmont.cuba.core.sys;

import com.google.common.base.Splitter;
import com.haulmont.bali.util.Dom4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Holds the list of {@link AppComponent}s.
 */
public class AppComponents {

    private final Logger log = LoggerFactory.getLogger(AppComponents.class);

    private final List<AppComponent> components = new ArrayList<>();

    private String block;

    /**
     * This constructor is used when no app components are specified.
     * @param block current application block (core, web, etc.)
     */
    public AppComponents(String block) {
        this.block = block;
    }

    /**
     * @param componentIds  identifiers of components to be used
     * @param block         current application block (core, web, etc.)
     */
    public AppComponents(List<String> componentIds, String block) {
        this(block);

        for (String compId : componentIds) {
            AppComponent component = get(compId);
            if (component == null) {
                component = new AppComponent(compId);
                load(component);
            }
            if (!components.contains(component))
                components.add(component);
        }

        components.sort((c1, c2) -> {
            int res = c1.compareTo(c2);
            if (res != 0)
                return res;
            else
                return componentIds.indexOf(c1.getId()) - componentIds.indexOf(c2.getId());
        });

        log.info("Using app components: {}", components);
    }

    /**
     * @return the name of the current application block
     */
    public String getBlock() {
        return block;
    }

    /**
     * @return the list of app components
     */
    public List<AppComponent> getComponents() {
        return Collections.unmodifiableList(components);
    }

    /**
     * Get an app component by Id.
     * @return app component or null if not found
     */
    @Nullable
    public AppComponent get(String componentId) {
        for (AppComponent component : components) {
            if (component.getId().equals(componentId))
                return component;
        }
        return null;
    }

    private void load(AppComponent component) {
        try {
            Document doc = getDescriptorDoc(component);

            String dependsOnAttr = doc.getRootElement().attributeValue("dependsOn");
            if (!StringUtils.isEmpty(dependsOnAttr)) {
                for (String depCompId : splitCommaSeparatedValue(dependsOnAttr)) {
                    AppComponent depComp = get(depCompId);
                    if (depComp == null) {
                        depComp = new AppComponent(depCompId);
                        load(depComp);
                        components.add(depComp);
                    }
                    component.addDependency(depComp);
                }
            }

            for (Element moduleEl : Dom4j.elements(doc.getRootElement(), "module")) {
                String blocksAttr = moduleEl.attributeValue("blocks");
                if (StringUtils.isEmpty(blocksAttr))
                    continue;
                List<String> blocks = splitCommaSeparatedValue(blocksAttr);
                if (blocks.contains("*") || blocks.contains(block)) {
                    for (Element propertyEl : Dom4j.elements(moduleEl, "property")) {
                        String name = propertyEl.attributeValue("name");
                        String value = propertyEl.attributeValue("value");
                        String existingValue = component.getProperty(name);

                        if (value.startsWith("\\+")) {
                            if (existingValue != null) {
                                log.debug("Overwrite value of property {} from {} to {}", name, existingValue,
                                        value);
                            }

                            component.setProperty(name, value.substring(1), false);
                            continue;
                        }

                        if (!value.startsWith("+")) {
                            if (existingValue != null) {
                                log.debug("Overwrite value of property {} from {} to {}", name, existingValue,
                                        value);
                            }

                            component.setProperty(name, value, false);
                            continue;
                        }

                        String cleanValue = value.substring(1);

                        if (existingValue != null) {

                            String newValue = existingValue;
                            Splitter splitter = Splitter.on(AppProperties.SEPARATOR_PATTERN).omitEmptyStrings();
                            List<String> existingParts = splitter.splitToList(existingValue);
                            for (String part : splitter.split(cleanValue)) {
                                if (!existingParts.contains(part))
                                    newValue += " " + part;
                            }
                            component.setProperty(name, newValue, true);
                        } else {
                            component.setProperty(name, cleanValue, true);
                        }
                    }
                }

            }
        } catch (IOException | DocumentException e) {
            throw new RuntimeException("Error loading app component '" + component + "'", e);
        }
    }

    private Document getDescriptorDoc(AppComponent component) throws IOException, DocumentException {
        String descriptorPath = component.getDescriptorPath();
        InputStream descrStream = getClass().getClassLoader().getResourceAsStream(descriptorPath);
        if (descrStream == null)
            throw new RuntimeException("App component descriptor was not found in '" + descriptorPath + "'");
        try {
            SAXReader reader = new SAXReader();
            return reader.read(new InputStreamReader(descrStream, StandardCharsets.UTF_8));
        } catch (DocumentException e) {
            throw new RuntimeException("Error reading app component descriptor '" + descriptorPath + "'", e);
        } finally {
            IOUtils.closeQuietly(descrStream);
        }
    }

    private List<String> splitCommaSeparatedValue(String value) {
        return Splitter.on(',').omitEmptyStrings().trimResults().splitToList(value);
    }

    /**
     * For tests only.
     */
    void add(AppComponent component) {
        components.add(component);
    }
}