001package de.deepamehta.contacts.migrations; 002 003import de.deepamehta.core.Topic; 004import de.deepamehta.core.model.AssociationDefinitionModel; 005import de.deepamehta.core.model.AssociationTypeModel; 006import de.deepamehta.core.model.ChildTopicsModel; 007import de.deepamehta.core.service.Migration; 008 009import java.util.ArrayList; 010import java.util.List; 011import java.util.logging.Logger; 012 013 014 015/** 016 * Changes Contacts model and converts content. 017 * Runs only in UPDATE mode. 018 * <p> 019 * Part of DM 4.6 020 */ 021public class Migration2 extends Migration { 022 023 // ---------------------------------------------------------------------------------------------- Instance Variables 024 025 private List<Entry> phoneEntries = new ArrayList(); 026 private List<Entry> addressEntries = new ArrayList(); 027 028 private Logger logger = Logger.getLogger(getClass().getName()); 029 030 // -------------------------------------------------------------------------------------------------- Public Methods 031 032 @Override 033 public void run() { 034 logger.info("########## Converting Phone Entry and Address Entry topics"); 035 // 036 // 1) prepare 037 // 038 bufferContentAndDeleteTypes(); 039 // 040 // 2) change model 041 // 042 dm4.createAssociationType(mf.newAssociationTypeModel("dm4.contacts.phone_entry", "Phone Entry", 043 "dm4.core.composite") 044 .addAssocDef(mf.newAssociationDefinitionModel("dm4.core.aggregation_def", 045 "dm4.contacts.phone_entry", "dm4.contacts.phone_label", "dm4.core.many", "dm4.core.one"))); 046 dm4.createAssociationType(mf.newAssociationTypeModel("dm4.contacts.address_entry", "Address Entry", 047 "dm4.core.composite") 048 .addAssocDef(mf.newAssociationDefinitionModel("dm4.core.aggregation_def", 049 "dm4.contacts.address_entry", "dm4.contacts.address_label", "dm4.core.many", "dm4.core.one"))); 050 dm4.getTopicType("dm4.contacts.person") 051 .addAssocDefBefore( 052 mf.newAssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.phone_entry", 053 "dm4.contacts.person", "dm4.contacts.phone_number", "dm4.core.one", "dm4.core.many"), 054 "dm4.contacts.email_address") 055 .addAssocDefBefore( 056 mf.newAssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.address_entry", 057 "dm4.contacts.person", "dm4.contacts.address", "dm4.core.one", "dm4.core.many"), 058 "dm4.contacts.notes"); 059 dm4.getTopicType("dm4.contacts.institution") 060 .addAssocDefBefore( 061 mf.newAssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.phone_entry", 062 "dm4.contacts.institution", "dm4.contacts.phone_number", "dm4.core.one", "dm4.core.many"), 063 "dm4.contacts.email_address") 064 .addAssocDefBefore( 065 mf.newAssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.address_entry", 066 "dm4.contacts.institution", "dm4.contacts.address", "dm4.core.one", "dm4.core.many"), 067 "dm4.contacts.notes"); 068 // 069 // 3) convert content 070 // 071 for (Entry entry : phoneEntries) convertPhoneEntry(entry); 072 for (Entry entry : addressEntries) convertAddressEntry(entry); 073 // 074 logger.info("########## Converting Phone Entry and Address Entry topics complete\n " + 075 "Phone entries converted: " + phoneEntries.size() + "\n " + 076 "Address entries converted: " + addressEntries.size()); 077 } 078 079 // ------------------------------------------------------------------------------------------------- Private Methods 080 081 private void bufferContentAndDeleteTypes() { 082 // 083 // 1) buffer entry topic content in memory 084 // 085 // Note: the actual conversion (as performed later) relies on the buffered content 086 for (Topic phoneEntry : dm4.getTopicsByType("dm4.contacts.phone_entry")) bufferPhoneEntry(phoneEntry); 087 for (Topic addressEntry : dm4.getTopicsByType("dm4.contacts.address_entry")) bufferAddressEntry(addressEntry); 088 // 089 // 2) temporarily change entry types 090 // 091 // Note: we change comp_def to aggr_def to avoid deleting childs when deleting the entry topics (next step). 092 // The childs are the Phone and Address topics we want keep and reassign later (while the actual conversion). 093 dm4.getTopicType("dm4.contacts.phone_entry").getAssocDef("dm4.contacts.phone_number") 094 .setTypeUri("dm4.core.aggregation_def"); 095 dm4.getTopicType("dm4.contacts.address_entry").getAssocDef("dm4.contacts.address") 096 .setTypeUri("dm4.core.aggregation_def"); 097 // 098 // 3) delete entry topics 099 // 100 // Note: deleting the entry types (next step) requires to delete all instances before. 101 for (Entry entry : phoneEntries) entry.topic.delete(); 102 for (Entry entry : addressEntries) entry.topic.delete(); 103 // 104 // 4) delete entry types 105 // 106 // Note: the entry topic types must be deleted as they are recreated as association types with the same URI. 107 dm4.deleteTopicType("dm4.contacts.phone_entry"); 108 dm4.deleteTopicType("dm4.contacts.address_entry"); 109 } 110 111 // --- 112 113 private void bufferPhoneEntry(Topic phoneEntry) { 114 Topic parent = phoneEntry.getRelatedTopic("dm4.core.composition", "dm4.core.child", "dm4.core.parent", null); 115 Topic phoneLabel = phoneEntry.getChildTopics().getTopic("dm4.contacts.phone_label"); 116 Topic phoneNumber = phoneEntry.getChildTopics().getTopic("dm4.contacts.phone_number"); 117 phoneEntries.add(new Entry(phoneEntry, parent, phoneLabel.getId(), phoneNumber.getId())); 118 } 119 120 private void bufferAddressEntry(Topic addressEntry) { 121 Topic parent = addressEntry.getRelatedTopic("dm4.core.composition", "dm4.core.child", "dm4.core.parent", null); 122 Topic addressLabel = addressEntry.getChildTopics().getTopic("dm4.contacts.address_label"); 123 Topic address = addressEntry.getChildTopics().getTopic("dm4.contacts.address"); 124 addressEntries.add(new Entry(addressEntry, parent, addressLabel.getId(), address.getId())); 125 } 126 127 // --- 128 129 private void convertPhoneEntry(Entry entry) { 130 entry.parent.getChildTopics().addRef("dm4.contacts.phone_number", entry.objectId, mf.newChildTopicsModel() 131 .putRef("dm4.contacts.phone_label", entry.labelId)); 132 } 133 134 private void convertAddressEntry(Entry entry) { 135 entry.parent.getChildTopics().addRef("dm4.contacts.address", entry.objectId, mf.newChildTopicsModel() 136 .putRef("dm4.contacts.address_label", entry.labelId)); 137 } 138 139 // --- 140 141 private class Entry { 142 143 private Topic topic; 144 private Topic parent; 145 private long labelId; 146 private long objectId; 147 148 private Entry(Topic topic, Topic parent, long labelId, long objectId) { 149 this.topic = topic; 150 this.parent = parent; 151 this.labelId = labelId; 152 this.objectId = objectId; 153 } 154 } 155}