001package systems.dmx.contacts.migrations; 002 003import systems.dmx.core.Topic; 004import systems.dmx.core.model.AssociationDefinitionModel; 005import systems.dmx.core.model.AssociationTypeModel; 006import systems.dmx.core.model.ChildTopicsModel; 007import systems.dmx.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 dmx.createAssociationType(mf.newAssociationTypeModel("dmx.contacts.phone_entry", "Phone Entry", 043 "dmx.core.identity") 044 .addAssocDef(mf.newAssociationDefinitionModel("dmx.core.aggregation_def", 045 "dmx.contacts.phone_entry", "dmx.contacts.phone_label", "dmx.core.many", "dmx.core.one"))); 046 dmx.createAssociationType(mf.newAssociationTypeModel("dmx.contacts.address_entry", "Address Entry", 047 "dmx.core.identity") 048 .addAssocDef(mf.newAssociationDefinitionModel("dmx.core.aggregation_def", 049 "dmx.contacts.address_entry", "dmx.contacts.address_label", "dmx.core.many", "dmx.core.one"))); 050 dmx.getTopicType("dmx.contacts.person") 051 .addAssocDefBefore( 052 mf.newAssociationDefinitionModel("dmx.core.composition_def", "dmx.contacts.phone_entry", false, false, 053 "dmx.contacts.person", "dmx.contacts.phone_number", "dmx.core.one", "dmx.core.many"), 054 "dmx.contacts.email_address") 055 .addAssocDefBefore( 056 mf.newAssociationDefinitionModel("dmx.core.composition_def", "dmx.contacts.address_entry", false, false, 057 "dmx.contacts.person", "dmx.contacts.address", "dmx.core.one", "dmx.core.many"), 058 "dmx.contacts.notes"); 059 dmx.getTopicType("dmx.contacts.institution") 060 .addAssocDefBefore( 061 mf.newAssociationDefinitionModel("dmx.core.composition_def", "dmx.contacts.phone_entry", false, false, 062 "dmx.contacts.institution", "dmx.contacts.phone_number", "dmx.core.one", "dmx.core.many"), 063 "dmx.contacts.email_address") 064 .addAssocDefBefore( 065 mf.newAssociationDefinitionModel("dmx.core.composition_def", "dmx.contacts.address_entry", false, false, 066 "dmx.contacts.institution", "dmx.contacts.address", "dmx.core.one", "dmx.core.many"), 067 "dmx.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 : dmx.getTopicsByType("dmx.contacts.phone_entry")) bufferPhoneEntry(phoneEntry); 087 for (Topic addressEntry : dmx.getTopicsByType("dmx.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 dmx.getTopicType("dmx.contacts.phone_entry").getAssocDef("dmx.contacts.phone_number") 094 .setTypeUri("dmx.core.aggregation_def"); 095 dmx.getTopicType("dmx.contacts.address_entry").getAssocDef("dmx.contacts.address") 096 .setTypeUri("dmx.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 dmx.deleteTopicType("dmx.contacts.phone_entry"); 108 dmx.deleteTopicType("dmx.contacts.address_entry"); 109 } 110 111 // --- 112 113 private void bufferPhoneEntry(Topic phoneEntry) { 114 Topic parent = phoneEntry.getRelatedTopic("dmx.core.composition", "dmx.core.child", "dmx.core.parent", null); 115 Topic phoneLabel = phoneEntry.getChildTopics().getTopic("dmx.contacts.phone_label"); 116 Topic phoneNumber = phoneEntry.getChildTopics().getTopic("dmx.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("dmx.core.composition", "dmx.core.child", "dmx.core.parent", null); 122 Topic addressLabel = addressEntry.getChildTopics().getTopic("dmx.contacts.address_label"); 123 Topic address = addressEntry.getChildTopics().getTopic("dmx.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("dmx.contacts.phone_number", entry.objectId, mf.newChildTopicsModel() 131 .putRef("dmx.contacts.phone_label", entry.labelId)); 132 } 133 134 private void convertAddressEntry(Entry entry) { 135 entry.parent.getChildTopics().addRef("dmx.contacts.address", entry.objectId, mf.newChildTopicsModel() 136 .putRef("dmx.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}