All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bidib.wizard.common.labels.DefaultWizardLabelFactory Maven / Gradle / Ivy

package org.bidib.wizard.common.labels;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOCase;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.bidib.jbidibc.core.schema.bidibbase.BaseLabel;
import org.bidib.jbidibc.core.schema.bidibbase.DefaultLabelsActionType;
import org.bidib.jbidibc.core.schema.bidibbase.PortType;
import org.bidib.jbidibc.core.schema.bidiblabels.AccessoryLabel;
import org.bidib.jbidibc.core.schema.bidiblabels.AccessoryLabels;
import org.bidib.jbidibc.core.schema.bidiblabels.FeedbackPortLabels;
import org.bidib.jbidibc.core.schema.bidiblabels.FeedbackPositionLabels;
import org.bidib.jbidibc.core.schema.bidiblabels.FlagLabels;
import org.bidib.jbidibc.core.schema.bidiblabels.LabelFactory;
import org.bidib.jbidibc.core.schema.bidiblabels.MacroLabels;
import org.bidib.jbidibc.core.schema.bidiblabels.NodeLabel;
import org.bidib.jbidibc.core.schema.bidiblabels.NodeLabels;
import org.bidib.jbidibc.core.schema.bidiblabels.PortLabel;
import org.bidib.jbidibc.core.schema.bidiblabels.PortLabels;
import org.bidib.jbidibc.core.schema.exception.InvalidSchemaException;
import org.bidib.jbidibc.messages.SoftwareVersion;
import org.bidib.jbidibc.messages.enums.PortModelEnum;
import org.bidib.jbidibc.messages.utils.ByteUtils;
import org.bidib.jbidibc.messages.utils.NodeUtils;
import org.bidib.wizard.api.locale.Resources;
import org.bidib.wizard.common.service.SettingsService;
import org.bidib.wizard.common.utils.SearchPathUtils;
import org.bidib.wizard.migration.migrator.WizardMigrator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

public class DefaultWizardLabelFactory implements WizardLabelFactory, InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultWizardLabelFactory.class);

    private static final String BIDIB_DEFAULT_LABEL_SUBDIR = "labels";

    protected static final String BIDIB_DEFAULT_DEFAULTLABELS_SUBDIR = "data/defaultLabels";

    private final SettingsService settingsService;

    private final Object labelMapLock = new Object();

    private final Map nodeLabelsMap = new HashMap<>();

    private final LabelFactory labelFactory;

    private boolean skipMigration;

    private String defaultLabelsSubDir = BIDIB_DEFAULT_DEFAULTLABELS_SUBDIR;

    public DefaultWizardLabelFactory(final SettingsService settingsService) {
        LOGGER.info("Create the WizardLabelFactory instance.");
        this.settingsService = settingsService;

        // prepare the instance of labelFactory
        this.labelFactory = new LabelFactory();
    }

    /**
     * @return the skipMigration
     */
    public boolean isSkipMigration() {
        return skipMigration;
    }

    /**
     * @param skipMigration
     *            the skipMigration to set
     */
    public void setSkipMigration(boolean skipMigration) {
        this.skipMigration = skipMigration;

        LOGGER.warn("The migration is skipped by configuration!");
    }

    /**
     * @param defaultLabelsSubDir
     *            the default labels subdir to use
     */
    public void setDefaultLabelsSubDir(String defaultLabelsSubDir) {
        this.defaultLabelsSubDir = defaultLabelsSubDir;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        String bidibConfigDir = getBaseDir();
        LOGGER.info("Set the path to the application labels: {}", bidibConfigDir);
        Resources.setUserLocation(bidibConfigDir);

        LOGGER.info("Call check and perform migration.");
        try {
            // check if migration is pending
            checkAndPerformMigration();
        }
        catch (IllegalArgumentException ex) {
            LOGGER.warn("Check and perform migration failed.", ex);

            throw ex;
        }
        catch (Exception ex) {
            LOGGER.warn("Check and perform migration failed.", ex);
        }
    }

    private String getBaseDir() {
        return settingsService.getMiscSettings().getBidibConfigDir();
    }

    @Override
    public DefaultLabelsApplied getDefaultLabelsApplied(Long uniqueId, String... searchRoot) {

        // lookup the portLabelMap if the labels of the node are loaded already
        synchronized (labelMapLock) {

            // convert the uniqueId to ignore the classbits
            uniqueId = NodeUtils.getUniqueIdIgnoreClassbits(uniqueId);

            NodeLabels nodeLabels = nodeLabelsMap.get(uniqueId);

            if (nodeLabels == null) {
                try {
                    nodeLabels = loadLabelsFromSource(uniqueId, searchRoot);
                }
                catch (Exception ex) {
                    LOGGER.warn("Load labels to check if default lables are applied failed.", ex);
                }
            }
            if (nodeLabels != null) {
                return new DefaultLabelsApplied(nodeLabels.getDefaultLabelsApplied(),
                    StringUtils.isNotBlank(nodeLabels.getDefaultLabelsVersion())
                        ? SoftwareVersion.parse(nodeLabels.getDefaultLabelsVersion()) : null);
            }
        }
        return new DefaultLabelsApplied(DefaultLabelsActionType.UNKNOWN, null);
    }

    public static final class DefaultLabelsApplied {
        private final DefaultLabelsActionType defaultLabelsActionType;

        private final SoftwareVersion defaultLabelsVersion;

        public DefaultLabelsApplied(DefaultLabelsActionType defaultLabelsActionType,
            SoftwareVersion defaultLabelsVersion) {
            this.defaultLabelsActionType = defaultLabelsActionType;
            this.defaultLabelsVersion = defaultLabelsVersion;
        }

        /**
         * @return the defaultLabelsActionType
         */
        public DefaultLabelsActionType getDefaultLabelsActionType() {
            return defaultLabelsActionType;
        }

        /**
         * @return the defaultLabelsVersion
         */
        public SoftwareVersion getDefaultLabelsVersion() {
            return defaultLabelsVersion;
        }

        @Override
        public String toString() {
            return "DefaultLabelsApplied, defaultLabelsActionType: " + defaultLabelsActionType
                + ", defaultLabelsVersion: " + defaultLabelsVersion;
        }
    }

    @Override
    public void setDefaultLabelsApplied(
        long uniqueId, final SoftwareVersion softwareVersion, String lang, int relevantPidBits,
        final PortModelEnum portModel, DefaultLabelsActionType defaultLabelsAction, String... searchRoot) {
        synchronized (labelMapLock) {

            // convert the uniqueId to ignore the classbits
            uniqueId = NodeUtils.getUniqueIdIgnoreClassbits(uniqueId);

            NodeLabels nodeLabels = nodeLabelsMap.get(uniqueId);
            if (nodeLabels == null) {
                try {
                    nodeLabels = loadLabelsFromSource(uniqueId, searchRoot);
                }
                catch (Exception ex) {
                    LOGGER.warn("Get the labels from file failed.", ex);
                }
            }

            if (nodeLabels != null) {

                // load the default node labels if required
                VersionedDefaultNodeLabelsWrapper versionedDefaultNodeLabels = null;
                if (defaultLabelsAction == DefaultLabelsActionType.APPLIED) {
                    versionedDefaultNodeLabels = getDefaultLabels(uniqueId, softwareVersion, relevantPidBits, lang);
                }

                // merge the labels into the existing labels
                if (versionedDefaultNodeLabels != null && defaultLabelsAction == DefaultLabelsActionType.APPLIED) {

                    final NodeLabels defaultNodeLabels = versionedDefaultNodeLabels.getNodeLabels();

                    if (defaultNodeLabels.getNodeLabel() != null) {
                        String userName = defaultNodeLabels.getNodeLabel().getUserName();
                        if (StringUtils.isNotBlank(userName)) {
                            LOGGER.info("Set the default node label: {}", userName);
                            nodeLabels.getNodeLabel().setUserName(userName);
                        }
                    }

                    // apply the macro labels
                    if (defaultNodeLabels.getMacroLabels() != null
                        && CollectionUtils.isNotEmpty(defaultNodeLabels.getMacroLabels().getMacroLabel())) {

                        // merge the macro labels
                        if (nodeLabels.getMacroLabels() == null) {
                            nodeLabels.setMacroLabels(new MacroLabels());
                        }

                        for (BaseLabel macroLabel : defaultNodeLabels.getMacroLabels().getMacroLabel()) {

                            int macroId = macroLabel.getIndex();
                            BaseLabel existingLabel =
                                nodeLabels
                                    .getMacroLabels().getMacroLabel().stream()
                                    .filter(macro -> macro.getIndex() == macroId).findFirst().orElse(null);
                            if (existingLabel != null) {
                                nodeLabels.getMacroLabels().getMacroLabel().remove(existingLabel);
                            }
                            LOGGER.info("Set the default macro label: {}", macroLabel);
                            nodeLabels.getMacroLabels().getMacroLabel().add(macroLabel);
                        }
                    }

                    // apply the accessory labels
                    if (defaultNodeLabels.getAccessoryLabels() != null
                        && CollectionUtils.isNotEmpty(defaultNodeLabels.getAccessoryLabels().getAccessoryLabel())) {
                        // merge the accessory labels
                        if (nodeLabels.getAccessoryLabels() == null) {
                            nodeLabels.setAccessoryLabels(new AccessoryLabels());
                        }

                        for (AccessoryLabel accessoryLabel : defaultNodeLabels
                            .getAccessoryLabels().getAccessoryLabel()) {
                            int accessoryId = accessoryLabel.getIndex();
                            AccessoryLabel existingLabel =
                                nodeLabels
                                    .getAccessoryLabels().getAccessoryLabel().stream()
                                    .filter(accessory -> accessory.getIndex() == accessoryId).findFirst().orElse(null);
                            if (existingLabel != null) {
                                nodeLabels.getAccessoryLabels().getAccessoryLabel().remove(existingLabel);
                            }
                            LOGGER.info("Set the default accessory label: {}", accessoryLabel);
                            nodeLabels.getAccessoryLabels().getAccessoryLabel().add(accessoryLabel);
                        }
                    }

                    // apply the port labels
                    if (defaultNodeLabels.getPortLabels() != null
                        && CollectionUtils.isNotEmpty(defaultNodeLabels.getPortLabels().getPortLabel())) {
                        // merge the port labels
                        if (nodeLabels.getPortLabels() == null) {
                            nodeLabels.setPortLabels(new PortLabels());
                        }

                        for (PortLabel portLabel : defaultNodeLabels.getPortLabels().getPortLabel()) {

                            int portId = portLabel.getIndex();
                            PortLabel existingLabel = null;

                            if (portModel == PortModelEnum.type) {
                                PortType portType = portLabel.getType();
                                existingLabel =
                                    nodeLabels
                                        .getPortLabels().getPortLabel().stream()
                                        .filter(port -> port.getType() == portType)
                                        .filter(port -> port.getIndex() == portId).findFirst().orElse(null);
                            }
                            else {
                                existingLabel =
                                    nodeLabels
                                        .getPortLabels().getPortLabel().stream()
                                        .filter(port -> port.getIndex() == portId).findFirst().orElse(null);
                            }
                            if (existingLabel != null) {
                                nodeLabels.getPortLabels().getPortLabel().remove(existingLabel);
                            }
                            LOGGER.info("Set the default port label: {}", portLabel);
                            nodeLabels.getPortLabels().getPortLabel().add(portLabel);
                        }
                    }

                    // apply the flag labels
                    if (defaultNodeLabels.getFlagLabels() != null
                        && CollectionUtils.isNotEmpty(defaultNodeLabels.getFlagLabels().getFlagLabel())) {
                        // merge the flag labels
                        if (nodeLabels.getFlagLabels() == null) {
                            nodeLabels.setFlagLabels(new FlagLabels());
                        }

                        for (BaseLabel flagLabel : defaultNodeLabels.getFlagLabels().getFlagLabel()) {

                            int flagId = flagLabel.getIndex();
                            BaseLabel existingLabel =
                                nodeLabels
                                    .getFlagLabels().getFlagLabel().stream().filter(flag -> flag.getIndex() == flagId)
                                    .findFirst().orElse(null);
                            if (existingLabel != null) {
                                nodeLabels.getFlagLabels().getFlagLabel().remove(existingLabel);
                            }
                            LOGGER.info("Set the default flag label: {}", flagLabel);
                            nodeLabels.getFlagLabels().getFlagLabel().add(flagLabel);
                        }
                    }

                    // apply the feedbackPort labels
                    if (defaultNodeLabels.getFeedbackPortLabels() != null
                        && CollectionUtils.isNotEmpty(defaultNodeLabels.getFeedbackPortLabels().getPortLabel())) {
                        // merge the feedbackPort labels
                        if (nodeLabels.getFeedbackPortLabels() == null) {
                            nodeLabels.setFeedbackPortLabels(new FeedbackPortLabels());
                        }

                        for (BaseLabel portLabel : defaultNodeLabels.getFeedbackPortLabels().getPortLabel()) {

                            int portId = portLabel.getIndex();
                            BaseLabel existingLabel =
                                nodeLabels
                                    .getFeedbackPortLabels().getPortLabel().stream()
                                    .filter(port -> port.getIndex() == portId).findFirst().orElse(null);
                            if (existingLabel != null) {
                                nodeLabels.getFeedbackPortLabels().getPortLabel().remove(existingLabel);
                            }
                            LOGGER.info("Set the default feedbackPort label: {}", portLabel);
                            nodeLabels.getFeedbackPortLabels().getPortLabel().add(portLabel);
                        }

                    }

                    // apply the feedbackPosition labels
                    if (defaultNodeLabels.getFeedbackPositionLabels() != null
                        && CollectionUtils.isNotEmpty(defaultNodeLabels.getFeedbackPositionLabels().getPortLabel())) {
                        // merge the feedbackPort labels
                        if (nodeLabels.getFeedbackPositionLabels() == null) {
                            nodeLabels.setFeedbackPositionLabels(new FeedbackPositionLabels());
                        }

                        for (BaseLabel portLabel : defaultNodeLabels.getFeedbackPositionLabels().getPortLabel()) {

                            int portId = portLabel.getIndex();
                            BaseLabel existingLabel =
                                nodeLabels
                                    .getFeedbackPositionLabels().getPortLabel().stream()
                                    .filter(port -> port.getIndex() == portId).findFirst().orElse(null);
                            if (existingLabel != null) {
                                nodeLabels.getFeedbackPositionLabels().getPortLabel().remove(existingLabel);
                            }
                            LOGGER.info("Set the default feedbackPosition label: {}", portLabel);
                            nodeLabels.getFeedbackPositionLabels().getPortLabel().add(portLabel);
                        }
                    }
                }

                nodeLabels.setDefaultLabelsApplied(defaultLabelsAction);
                nodeLabels.setDefaultLabelsVersion(softwareVersion.toString());

                LOGGER.info("Save the labels after the default labels were applied.");
                saveLabels(uniqueId, searchRoot);
            }
            else {

                // load the default node labels if required
                // NodeLabels defaultNodeLabels = null;
                VersionedDefaultNodeLabelsWrapper versionedDefaultNodeLabels = null;
                if (defaultLabelsAction == DefaultLabelsActionType.APPLIED) {
                    versionedDefaultNodeLabels = getDefaultLabels(uniqueId, softwareVersion, relevantPidBits, lang);
                }

                LOGGER.warn("No nodeLabels found to set the defaultLabelsApplied: {}", defaultLabelsAction);
                if (versionedDefaultNodeLabels != null && defaultLabelsAction == DefaultLabelsActionType.APPLIED) {
                    LOGGER.info("Set the new default node labels as labels for the node.");

                    NodeLabels defaultNodeLabels = versionedDefaultNodeLabels.getNodeLabels();

                    defaultNodeLabels.setDefaultLabelsApplied(defaultLabelsAction);
                    defaultNodeLabels.setDefaultLabelsVersion(softwareVersion.toString());

                    if (defaultNodeLabels.getNodeLabel() == null) {
                        defaultNodeLabels.setNodeLabel(new NodeLabel());
                    }
                    defaultNodeLabels.getNodeLabel().setUniqueId(uniqueId);

                    nodeLabelsMap.put(uniqueId, defaultNodeLabels);

                    LOGGER.info("Save the labels after the default labels were applied.");
                    saveLabels(uniqueId, searchRoot);
                }
                else if (versionedDefaultNodeLabels == null && defaultLabelsAction == DefaultLabelsActionType.IGNORED) {
                    LOGGER.info("Create entry for ignored default labels.");

                    NodeLabels defaultNodeLabels = new NodeLabels();
                    defaultNodeLabels.setDefaultLabelsApplied(DefaultLabelsActionType.IGNORED);
                    defaultNodeLabels.setDefaultLabelsVersion(softwareVersion.toString());

                    defaultNodeLabels.setNodeLabel(new NodeLabel());
                    defaultNodeLabels.getNodeLabel().setUniqueId(uniqueId);

                    nodeLabelsMap.put(uniqueId, defaultNodeLabels);

                    LOGGER.info("Save the labels after the default labels were applied.");
                    saveLabels(uniqueId, searchRoot);
                }
            }
        }
    }

    @Override
    public NodeLabels loadLabels(Long uniqueId, String... searchRoot) {
        LOGGER.debug("Load labels for uniqueId: {}, searchRoot: {}", uniqueId, searchRoot);

        if (uniqueId == null) {
            return null;
        }

        // convert the uniqueId to ignore the classbits
        uniqueId = NodeUtils.getUniqueIdIgnoreClassbits(uniqueId);

        // lookup the portLabelMap if the labels of the node are loaded already
        synchronized (labelMapLock) {
            NodeLabels nodeLabels = nodeLabelsMap.get(uniqueId);

            if (nodeLabels == null) {
                nodeLabels = loadLabelsFromSource(uniqueId, searchRoot);
            }

            return nodeLabels;
        }
    }

    /**
     * Load the labels from the provided file.
     * 
     * @param labelsFile
     *            the file
     * @return the node labels
     */
    public NodeLabels loadLabelsFromSource(File labelsFile) {

        FileInputStream fis = null;
        NodeLabels nodeLabels = null;
        try {
            LOGGER.debug("Load labels from file: {}", labelsFile);

            fis = new FileInputStream(labelsFile);
            nodeLabels = labelFactory.loadLabels(fis);
        }
        catch (FileNotFoundException ex) {
            LOGGER.debug("Prepare file to load labels failed because file is not available: {}", ex.getMessage());
        }
        finally {
            if (fis != null) {
                try {
                    fis.close();
                }
                catch (Exception ex) {
                    LOGGER.warn("Close file input stream failed.", ex);
                }
            }
        }
        return nodeLabels;
    }

    private NodeLabels loadLabelsFromSource(Long uniqueId, String... searchRoot) {

        // prepare the node file location from the uniqueId
        NodeLabels nodeLabels = null;
        try {
            // prepare the filename without the class bits of the uniqueId
            String nodeFileName = LabelFactory.prepareLookupNodeFilename(uniqueId);

            LOGGER.debug("Search for labels of nodeFileName: {}, searchRoot: {}", nodeFileName, searchRoot);

            String path =
                (ArrayUtils.isNotEmpty(searchRoot) && StringUtils.isNotBlank(searchRoot[0]) ? searchRoot[0]
                    : getDefaultSearchRoot()[0]);
            LOGGER.debug("Prepared search path: {}", path);

            // search labels
            List labelFiles = SearchPathUtils.findFiles(nodeFileName, false, path);

            File labelsFile = null;
            if (CollectionUtils.isNotEmpty(labelFiles)) {
                String exactFilename = LabelFactory.prepareNodeFilename(uniqueId);
                // search the matching filename
                labelsFile = IterableUtils.find(labelFiles, new Predicate() {

                    @Override
                    public boolean evaluate(File other) {
                        return exactFilename.equals(other.getName());
                    }
                });

                if (labelsFile == null) {
                    labelsFile = labelFiles.get(0);
                    LOGGER.info("Use first matching labelsFile: {}", labelsFile.getPath());
                }
                else {
                    LOGGER.info("Found exact matching labelsFile: {}", labelsFile.getPath());
                }
            }
            else {
                nodeFileName = LabelFactory.prepareNodeFilename(uniqueId);
                labelsFile = new File(path, nodeFileName);

                LOGGER.info("Prepared matching labelsFile: {}", labelsFile.getPath());
            }

            nodeLabels = loadLabelsFromSource(labelsFile);

            if (nodeLabels == null) {
                LOGGER
                    .info("No stored node labels found for node: {}. Create new nodeLabels.",
                        ByteUtils.formatHexUniqueId(uniqueId));

                nodeLabels =
                    new NodeLabels()
                        .withDefaultLabelsApplied(DefaultLabelsActionType.UNKNOWN)
                        .withNodeLabel(new NodeLabel().withUniqueId(uniqueId));
            }

            if (nodeLabels != null) {

                LOGGER.info("Store nodeLabels in map, uniqueId: {}", ByteUtils.formatHexUniqueId(uniqueId));

                // store the labels in the map
                nodeLabelsMap.put(uniqueId, nodeLabels);
            }
            else {
                LOGGER.debug("No nodeLabels available for uniqueId: {}", ByteUtils.formatHexUniqueId(uniqueId));
            }
        }
        catch (InvalidSchemaException ex) {
            LOGGER.error("Prepare file to load labels failed.", ex);
            throw ex;
        }
        catch (Exception ex) {
            LOGGER.error("Prepare file to load labels failed.", ex);
            throw new RuntimeException(ex.getMessage());
        }
        return nodeLabels;
    }

    @Override
    public void saveLabels(Long uniqueId, String... searchRoot) {

        synchronized (labelMapLock) {

            // convert the uniqueId to ignore the classbits
            uniqueId = NodeUtils.getUniqueIdIgnoreClassbits(uniqueId);

            NodeLabels nodeLabels = nodeLabelsMap.get(uniqueId);
            if (nodeLabels != null) {
                LOGGER.info("Found nodeLabels to save for uniqueId: {}", uniqueId);

                if (nodeLabels.getNodeLabel() != null) {
                    if (nodeLabels.getNodeLabel().getUniqueId() != uniqueId.longValue()) {
                        LOGGER.info("Adjust the uniqueId: {}", uniqueId);
                        nodeLabels.getNodeLabel().setUniqueId(uniqueId.longValue());
                    }
                }

                String path =
                    (ArrayUtils.isNotEmpty(searchRoot) && StringUtils.isNotBlank(searchRoot[0]) ? searchRoot[0]
                        : getDefaultSearchRoot()[0]);

                // prepare the filename
                File file = new File(path, LabelFactory.prepareNodeFilename(uniqueId));

                LOGGER.info("Save nodeLabels to file: {}", file);

                labelFactory.saveNodeLabel(nodeLabels, file, false);
            }
            else {
                LOGGER.warn("Save node labels failed for node with uniqueId: {}", uniqueId);
            }
        }
    }

    @Override
    public void deleteLabels(Long uniqueId) {
        synchronized (labelMapLock) {

            // convert the uniqueId to ignore the classbits
            uniqueId = NodeUtils.getUniqueIdIgnoreClassbits(uniqueId);

            NodeLabels nodeLabels = nodeLabelsMap.remove(uniqueId);
            if (nodeLabels != null) {
                LOGGER.info("Found nodeLabels to delete for uniqueId: {}", uniqueId);

                nodeLabels = new NodeLabels().withNodeLabel(new NodeLabel().withUniqueId(uniqueId));
                nodeLabels.setDefaultLabelsApplied(DefaultLabelsActionType.UNKNOWN);
                nodeLabels.setDefaultLabelsVersion(null);
                nodeLabelsMap.put(uniqueId, nodeLabels);

                saveLabels(uniqueId);
            }
        }
    }

    /**
     * Save the default labels to the provided file.
     * 
     * @param nodeLabels
     *            the default labels
     * @param file
     *            the file
     */
    @Override
    public void saveDefaultLabels(final NodeLabels nodeLabels, final File file) {

        labelFactory.saveNodeLabel(nodeLabels, file, false);
    }

    protected String[] getDefaultSearchRoot() {

        String bidibConfigDir = getBaseDir();

        LOGGER.info("Current bidibConfigDir: {}", bidibConfigDir);

        File labelsDir = new File(bidibConfigDir, BIDIB_DEFAULT_LABEL_SUBDIR);
        // make sure the labels directory exists
        if (!labelsDir.exists()) {
            try {
                LOGGER.info("Create the labels directory: {}", labelsDir);
                FileUtils.forceMkdir(labelsDir);
            }
            catch (Exception ex) {
                LOGGER.warn("Create the basePath of the proposed directory failed.", ex);
            }
        }

        return new String[] { labelsDir.getPath() };
    }

    private void checkAndPerformMigration() {

        if (skipMigration) {
            LOGGER.warn("The check for migration is skipped by configuration!!!");
            return;
        }

        // check if the migration file exists
        String[] searchRoots = getDefaultSearchRoot();

        // check if the target path exists
        if (!new File(searchRoots[0]).exists()) {
            LOGGER.warn("The target path for migration does not exist. Skip migration!");
            return;
        }

        final WizardMigrator migrator = new WizardMigrator();
        File migrationLogFile = migrator.getMigrationLogfile(searchRoots[0]);
        File forcedBackupLogFile = migrator.getForcedBackupLogfile(searchRoots[0]);

        LOGGER
            .info("Check if the migration log exists under: {}, forcedBackupLogFile: {}", migrationLogFile,
                forcedBackupLogFile);
        if (migrationLogFile.exists() && forcedBackupLogFile.exists()) {
            LOGGER
                .info(
                    "The migration and forced backup was performed already, the migration log exists under: {}, the forcedBackupLogFile exists under: {}",
                    migrationLogFile, forcedBackupLogFile);

            return;
        }

        String targetPath = searchRoots[0];
        LOGGER.info("Prepared targetPath: {}, all searchRoots: {}", targetPath, searchRoots);

        if (!migrationLogFile.exists()) {
            LOGGER.info("Perform the migration.");

            // perform the migration
            String migrationTargetPath = null;
            try {
                migrationTargetPath = migrator.checkAndPerformMigration(targetPath, migrationLogFile, searchRoots);
            }
            catch (Exception ex) {
                LOGGER.warn("Check and perform lable migration failed.", ex);
            }

            // update the preferences if necessary
            if (StringUtils.isNotBlank(migrationTargetPath) && StringUtils.isBlank(getBaseDir())) {
                LOGGER.info("Migration returned migrationTargetPath: {}", migrationTargetPath);

                File file = new File(migrationTargetPath);
                migrationTargetPath = file.getParent();
                LOGGER.info("Update the LabelV2Path in preferences with labelPath: {}", migrationTargetPath);

                settingsService.getMiscSettings().setBidibConfigDir(migrationTargetPath);
                settingsService.storeSettings();
            }
        }

        if (!forcedBackupLogFile.exists()) {
            LOGGER.info("Perform the forced backup.");

            try {
                migrator.checkAndPerformForcedBackup(targetPath, forcedBackupLogFile);

                LOGGER.info("Check and perform forced label backup passed.");
            }
            catch (Exception ex) {
                LOGGER.warn("Check and perform forced label backup failed.", ex);
            }
        }
    }

    /**
     * Prepare the default labels.
     * 
     * @param uniqueId
     *            the uniqueId of the node
     * @return the node labels
     */
    @Override
    public NodeLabels prepareDefaultLabels(Long uniqueId) {
        NodeLabels nodeLabels = null;
        synchronized (labelMapLock) {

            // convert the uniqueId to ignore the classbits
            uniqueId = NodeUtils.getUniqueIdIgnoreClassbits(uniqueId);

            nodeLabels = nodeLabelsMap.get(uniqueId);
        }
        return nodeLabels;
    }

    @Override
    public VersionedDefaultNodeLabelsWrapper isDefaultLabelsAvailable(
        final String lang, Long uniqueId, final SoftwareVersion softwareVersion, int relevantPidBits) {
        LOGGER.info("Look for default labels for uniqueId: {}", ByteUtils.formatHexUniqueId(uniqueId));

        // convert the uniqueId to ignore the classbits
        uniqueId = NodeUtils.getUniqueIdIgnoreClassbits(uniqueId);

        String labelPath = settingsService.getMiscSettings().getBidibConfigDir();
        File searchPathLabelPath = new File(labelPath, defaultLabelsSubDir);

        File installationPath = getInstallationLookupPath();

        final List searchPaths = new LinkedList<>();
        if (searchPathLabelPath.exists()) {
            searchPaths.add(searchPathLabelPath);
        }
        if (installationPath.exists()) {
            searchPaths.add(installationPath);
        }

        if (CollectionUtils.isNotEmpty(searchPaths)) {

            final VersionedDefaultNodeLabelsWrapper defaultNodeLabels =
                getDefaultLabels(uniqueId, softwareVersion, relevantPidBits, lang);
            return defaultNodeLabels;
        }
        else {
            LOGGER.debug("The directory to search does not exist: {}", searchPathLabelPath.toString());
        }

        return null;
    }

    private File getInstallationLookupPath() {

        String installationPath = this.settingsService.getInstallationPath();
        LOGGER.info("Current installation path: {}", installationPath);

        File installationLookupPath = new File(installationPath);
        if (SystemUtils.IS_OS_MAC_OSX) {
            installationLookupPath =
                new File(installationLookupPath.getAbsoluteFile(), "Contents/Resources/" + defaultLabelsSubDir);
        }
        else {
            installationLookupPath = new File(installationLookupPath.getAbsoluteFile(), defaultLabelsSubDir);
        }
        return installationLookupPath;
    }

    private VersionedDefaultNodeLabelsWrapper getDefaultLabels(
        Long uniqueId, final SoftwareVersion softwareVersion, int relevantPidBits, String lang) {
        LOGGER.debug("Look for default labels for uniqueId: {}", ByteUtils.formatHexUniqueId(uniqueId));

        String labelPath = settingsService.getMiscSettings().getBidibConfigDir();
        File searchPathLabelPath = new File(labelPath, defaultLabelsSubDir);

        File installationPath = getInstallationLookupPath();

        final List searchPaths = new LinkedList<>();
        if (searchPathLabelPath.exists()) {
            searchPaths.add(searchPathLabelPath);
        }
        if (installationPath.exists()) {
            searchPaths.add(installationPath);
        }

        if (CollectionUtils.isNotEmpty(searchPaths)) {

            int pid = NodeUtils.getPid(uniqueId, relevantPidBits);
            int vid = NodeUtils.getVendorId(uniqueId);

            final String shortLang = StringUtils.substringBefore(lang, "-");

            if (softwareVersion != null) {
                String searchVersion = softwareVersion.toString();

                // use filename with version for search
                StringBuilder filenameSearchVersion = new StringBuilder("bidib-default-names-");
                filenameSearchVersion
                    .append(vid).append("-").append(pid).append("-").append(searchVersion).append("-*").append(".xml");
                IOFileFilter fileFilterVersion =
                    WildcardFileFilter
                        .builder().setWildcards(filenameSearchVersion.toString()).setIoCase(IOCase.INSENSITIVE).get();

                LOGGER.info("Try to find bidib-default-names with versioned filter: {}", filenameSearchVersion);

                VersionedDefaultNodeLabelsWrapper searchLabels =
                    searchNodeLabels(fileFilterVersion, shortLang, searchPaths.toArray(new File[0]));
                if (searchLabels != null) {
                    return searchLabels;
                }
            }

            // fallback and use filename with wildcards for search
            StringBuilder filenameSearch = new StringBuilder("bidib-default-names-");
            filenameSearch.append(vid).append("-").append(pid).append("-*").append(".xml");
            IOFileFilter fileFilter =
                WildcardFileFilter
                    .builder().setWildcards(filenameSearch.toString()).setIoCase(IOCase.INSENSITIVE).get();

            LOGGER.info("Try to find bidib-default-names with unversioned filter: {}", filenameSearch);

            return searchNodeLabels(fileFilter, shortLang, searchPaths.toArray(new File[0]));
        }
        else {
            LOGGER.debug("The directory to search does not exist: {}", searchPathLabelPath.toString());
        }

        return null;
    }

    private static final String FALLBACK_LANG = "de";

    public static final class VersionedDefaultNodeLabelsWrapper {

        private final SoftwareVersion defaultLabelsVersion;

        private final NodeLabels nodeLabels;

        public VersionedDefaultNodeLabelsWrapper(SoftwareVersion defaultLabelsVersion, NodeLabels nodeLabels) {
            this.defaultLabelsVersion = defaultLabelsVersion;
            this.nodeLabels = nodeLabels;
        }

        public SoftwareVersion getDefaultLabelsVersion() {
            return defaultLabelsVersion;
        }

        public NodeLabels getNodeLabels() {
            return nodeLabels;
        }

        @Override
        public String toString() {
            return "VersionedDefaultNodeLabelsWrapper[defaultLabelsVersion=" + defaultLabelsVersion + "]";
        }
    }

    private static final Pattern PATTERN_FILENAME =
        Pattern.compile("bidib-default-names-(\\d+)-(\\d+)-((\\d+)\\.(\\d+)\\.(\\d+))-(\\w+).xml");

    protected static String extractVersion(String version) {
        Matcher matcher = PATTERN_FILENAME.matcher(version);
        if (matcher.find()) {
            return matcher.group(3);
        }
        return null;
    }

    private VersionedDefaultNodeLabelsWrapper searchNodeLabels(
        final IOFileFilter fileFilter, String shortLang, File... searchPaths) {

        for (File searchPath : searchPaths) {
            Collection files = FileUtils.listFiles(searchPath, fileFilter, TrueFileFilter.INSTANCE);

            LOGGER.debug("Found matching files: {}", files);

            if (CollectionUtils.isNotEmpty(files)) {
                // search the labels for the correct language
                File labelsFile =
                    files
                        .stream().sorted((f1, f2) -> f2.getName().compareTo(f1.getName()))
                        .filter(file -> file.getName().endsWith(shortLang + ".xml")).findFirst().orElse(null);

                if (labelsFile != null) {

                    LOGGER.info("Found defaultLabels file: {}", labelsFile.getPath());

                    // get the version from the filename
                    String version = extractVersion(labelsFile.getName());

                    NodeLabels defaultNodeLabels = loadLabelsFromSource(labelsFile);

                    return new VersionedDefaultNodeLabelsWrapper(StringUtils.isNotBlank(version)
                        ? SoftwareVersion.parse(version) : SoftwareVersion.build(0, 0, 0), defaultNodeLabels);
                }
                else {
                    LOGGER
                        .warn("No default labels found for lang: {}. Try fallback to lang: {}", shortLang,
                            FALLBACK_LANG);

                    labelsFile =
                        files
                            .stream().sorted((f1, f2) -> f2.getName().compareTo(f1.getName()))
                            .filter(file -> file.getName().endsWith(FALLBACK_LANG + ".xml")).findFirst().orElse(null);

                    if (labelsFile != null) {

                        LOGGER.info("Found defaultLabels file with fallback lang: {}", labelsFile.getPath());

                        // get the version from the filename
                        String version = extractVersion(labelsFile.getName());

                        NodeLabels defaultNodeLabels = loadLabelsFromSource(labelsFile);

                        return new VersionedDefaultNodeLabelsWrapper(StringUtils.isNotBlank(version)
                            ? SoftwareVersion.parse(version) : SoftwareVersion.build(0, 0, 0), defaultNodeLabels);
                    }
                }
            }
        }
        return null;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy