001package systems.dmx.webclient.migrations;
002
003import systems.dmx.core.DMXType;
004import systems.dmx.core.Topic;
005import systems.dmx.core.ViewConfiguration;
006import systems.dmx.core.model.TopicModel;
007import systems.dmx.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, and other types created before Webclient is activated, 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        // This migration creates View Config topics without any child topics.
034        // Now with the ValueIntegrator we can't create empty composites.
035        // See also addDefaultViewConfig() in WebclientPlugin.java
036        // ### TODO: rethink about this.
037        /*
038        initDMXWorkspaceId();
039        //
040        logger.info("########## Repairing types with missing \"View Config\" topic (" +
041            (deepaMehtaWorkspaceId == -1 ? "clean install" : "update") + " detected)");
042        //
043        repair(dmx.getAllTopicTypes(), 0);
044        repair(dmx.getAllAssociationTypes(), 1);
045        //
046        logger.info("########## Repairing types with missing \"View Config\" topic complete\n    " +
047            "Topic types repaired: " + count[0][1] + "/" + count[0][0] + "\n    " +
048            "Association types repaired: " + count[1][1] + "/" + count[1][0]);
049        */
050    }
051
052    private void repair(List<? extends DMXType> types, int i) {
053        for (DMXType type : types) {
054            // Note: no View Config can be associated to the type "View Configuration" itself as this would cause an
055            // endless recursion while fetching that type. Fetching a type involves fetching its view config, that is
056            // all its view config topics, including their child topics. Fetching child topics is driven by the topic's
057            // type (its assoc defs), here: "View Configuration" -- the one we're fetching just now.
058            if (type.getUri().equals("dmx.webclient.view_config")) {
059                continue;
060            }
061            //
062            repair(type, i);
063        }
064    }
065
066    private void repair(DMXType type, int i) {
067        try {
068            ViewConfiguration viewConfig = type.getViewConfig();
069            Topic configTopic = viewConfig.getConfigTopic("dmx.webclient.view_config");
070            if (configTopic == null) {
071                // 1) create config topic
072                configTopic = viewConfig.addConfigTopic(mf.newTopicModel("dmx.webclient.view_config"));
073                //
074                // 2) assign workspace
075                // In case of a CLEAN_INSTALL the DMX workspace does not yet exist. The config topic gets its
076                // workspace assignment via type-introduction of the Workspaces module. The Workspaces module is
077                // activated *after* the Webclient module.
078                // In case of a UPDATE the DMX workspace exists already and we make the assignment here.
079                // Type-introduction of the Workspaces module will not perform as this module is installed already.
080                if (deepaMehtaWorkspaceId != -1 && isDMXStandardType(type)) {
081                    dmx.getAccessControl().assignToWorkspace(configTopic, deepaMehtaWorkspaceId);
082                }
083                //
084                count[i][1]++;
085            }
086            count[i][0]++;
087        } catch (Exception e) {
088            throw new RuntimeException("Repairing type \"" + type.getUri() + "\" failed", e);
089        }
090    }
091
092    private void initDMXWorkspaceId() {
093        Topic ws = dmx.getTopicByUri("dmx.workspaces.deepamehta");
094        deepaMehtaWorkspaceId = ws != null ? ws.getId() : -1;
095    }
096
097    // Copied from WorkspacePlugin.java
098    private boolean isDMXStandardType(DMXType type) {
099        return type.getUri().startsWith("dmx.");
100    }
101}