001package de.deepamehta.webclient.migrations;
002
003import de.deepamehta.core.DeepaMehtaType;
004import de.deepamehta.core.Topic;
005import de.deepamehta.core.ViewConfiguration;
006import de.deepamehta.core.model.TopicModel;
007import de.deepamehta.core.service.Migration;
008
009import java.util.List;
010import java.util.logging.Logger;
011
012
013
014/**
015 * Repairing types with missing "View Config" topic.
016 * Runs ALWAYS.
017 * <p>
018 * Note: while a "clean install" the Core types are repaired.
019 * While "update" all existing types are repaired, including the ones created by installed 3rd-party modules.
020 * <p>
021 * Part of DM 4.8.6
022 */
023public class Migration3 extends Migration {
024
025    private long deepaMehtaWorkspaceId;
026
027    private int[][] count = new int[2][2];
028
029    private Logger logger = Logger.getLogger(getClass().getName());
030
031    @Override
032    public void run() {
033        initDeepaMehtaWorkspaceId();
034        //
035        logger.info("########## Repairing types with missing \"View Config\" topic (" +
036            (deepaMehtaWorkspaceId == -1 ? "clean install" : "update") + " detected)");
037        //
038        repair(dm4.getAllTopicTypes(), 0);
039        repair(dm4.getAllAssociationTypes(), 1);
040        //
041        logger.info("########## Repairing types with missing \"View Config\" topic complete\n    " +
042            "Topic types repaired: " + count[0][1] + "/" + count[0][0] + "\n    " +
043            "Association types repaired: " + count[1][1] + "/" + count[1][0]);
044    }
045
046    private void repair(List<? extends DeepaMehtaType> types, int i) {
047        for (DeepaMehtaType type : types) {
048            // Note: no View Config can be associated to the type "View Configuration" itself as this would cause an
049            // endless recursion while fetching that type. Fetching a type involves fetching its view config, that is
050            // all its view config topics, including their child topics. Fetching child topics is driven by the topic's
051            // type (its assoc defs), here: "View Configuration" -- the one we're fetching just now.
052            if (type.getUri().equals("dm4.webclient.view_config")) {
053                continue;
054            }
055            //
056            repair(type, i);
057        }
058    }
059
060    private void repair(DeepaMehtaType type, int i) {
061        try {
062            ViewConfiguration viewConfig = type.getViewConfig();
063            Topic configTopic = viewConfig.getConfigTopic("dm4.webclient.view_config");
064            if (configTopic == null) {
065                // 1) create config topic
066                configTopic = viewConfig.addConfigTopic(mf.newTopicModel("dm4.webclient.view_config"));
067                //
068                // 2) assign workspace
069                // In case of a CLEAN_INSTALL the DeepaMehta workspace does not yet exist. The config topic gets its
070                // workspace assignment via type-introduction of the Workspaces module. The Workspaces module is
071                // activated *after* the Webclient module.
072                // In case of a UPDATE the DeepaMehta workspace exists already and we make the assignment here.
073                // Type-introduction of the Workspaces module will not perform as this module is installed already.
074                if (deepaMehtaWorkspaceId != -1 && isDeepaMehtaStandardType(type)) {
075                    dm4.getAccessControl().assignToWorkspace(configTopic, deepaMehtaWorkspaceId);
076                }
077                //
078                count[i][1]++;
079            }
080            count[i][0]++;
081        } catch (Exception e) {
082            throw new RuntimeException("Repairing type \"" + type.getUri() + "\" failed", e);
083        }
084    }
085
086    private void initDeepaMehtaWorkspaceId() {
087        Topic ws = dm4.getTopicByUri("dm4.workspaces.deepamehta");
088        deepaMehtaWorkspaceId = ws != null ? ws.getId() : -1;
089    }
090
091    // Copied from WorkspacePlugin.java
092    private boolean isDeepaMehtaStandardType(DeepaMehtaType type) {
093        return type.getUri().startsWith("dm4.");
094    }
095}