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}