001package de.deepamehta.plugins.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        dms.createAssociationType(new AssociationTypeModel("dm4.contacts.phone_entry", "Phone Entry",
043            "dm4.core.composite")
044            .addAssocDef(new AssociationDefinitionModel("dm4.core.aggregation_def",
045            "dm4.contacts.phone_entry", "dm4.contacts.phone_label", "dm4.core.many", "dm4.core.one")));
046        dms.createAssociationType(new AssociationTypeModel("dm4.contacts.address_entry", "Address Entry",
047            "dm4.core.composite")
048            .addAssocDef(new AssociationDefinitionModel("dm4.core.aggregation_def",
049            "dm4.contacts.address_entry", "dm4.contacts.address_label", "dm4.core.many", "dm4.core.one")));
050        dms.getTopicType("dm4.contacts.person")
051            .addAssocDefBefore(new AssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.phone_entry",
052            "dm4.contacts.person", "dm4.contacts.phone_number", "dm4.core.one", "dm4.core.many"),
053            "dm4.contacts.email_address")
054            .addAssocDefBefore(new AssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.address_entry",
055            "dm4.contacts.person", "dm4.contacts.address", "dm4.core.one", "dm4.core.many"),
056            "dm4.contacts.notes");
057        dms.getTopicType("dm4.contacts.institution")
058            .addAssocDefBefore(new AssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.phone_entry",
059            "dm4.contacts.institution", "dm4.contacts.phone_number", "dm4.core.one", "dm4.core.many"),
060            "dm4.contacts.email_address")
061            .addAssocDefBefore(new AssociationDefinitionModel("dm4.core.composition_def", "dm4.contacts.address_entry",
062            "dm4.contacts.institution", "dm4.contacts.address", "dm4.core.one", "dm4.core.many"),
063            "dm4.contacts.notes");
064        //
065        // 3) convert content
066        //
067        for (Entry entry : phoneEntries)   convertPhoneEntry(entry);
068        for (Entry entry : addressEntries) convertAddressEntry(entry);
069        //
070        logger.info("########## Converting Phone Entry and Address Entry topics complete.\n    " +
071            "Phone entries converted: " + phoneEntries.size() + "\n    " +
072            "Address entries converted: " + addressEntries.size());
073    }
074
075    // ------------------------------------------------------------------------------------------------- Private Methods
076
077    private void bufferContentAndDeleteTypes() {
078        //
079        // 1) buffer entry topic content in memory
080        //
081        // Note: the actual conversion (as performed later) relies on the buffered content
082        for (Topic phoneEntry   : dms.getTopics("dm4.contacts.phone_entry", 0))   bufferPhoneEntry(phoneEntry);
083        for (Topic addressEntry : dms.getTopics("dm4.contacts.address_entry", 0)) bufferAddressEntry(addressEntry);
084        //
085        // 2) temporarily change entry types
086        //
087        // Note: we change comp_def to aggr_def to avoid deleting childs when deleting the entry topics (next step).
088        // The childs are the Phone and Address topics we want keep and reassign later (while the actual conversion).
089        dms.getTopicType("dm4.contacts.phone_entry").getAssocDef("dm4.contacts.phone_number")
090            .setTypeUri("dm4.core.aggregation_def");
091        dms.getTopicType("dm4.contacts.address_entry").getAssocDef("dm4.contacts.address")
092            .setTypeUri("dm4.core.aggregation_def");
093        //
094        // 3) delete entry topics
095        //
096        // Note: deleting the entry types (next step) requires to delete all instances before.
097        for (Entry entry : phoneEntries)   entry.topic.delete();
098        for (Entry entry : addressEntries) entry.topic.delete();
099        //
100        // 4) delete entry types
101        //
102        // Note: the entry topic types must be deleted as they are recreated as association types with the same URI.
103        dms.deleteTopicType("dm4.contacts.phone_entry");
104        dms.deleteTopicType("dm4.contacts.address_entry");
105    }
106
107    // ---
108
109    private void bufferPhoneEntry(Topic phoneEntry) {
110        Topic parent = phoneEntry.getRelatedTopic("dm4.core.composition", "dm4.core.child", "dm4.core.parent", null);
111        Topic phoneLabel  = phoneEntry.getChildTopics().getTopic("dm4.contacts.phone_label");
112        Topic phoneNumber = phoneEntry.getChildTopics().getTopic("dm4.contacts.phone_number");
113        phoneEntries.add(new Entry(phoneEntry, parent, phoneLabel.getId(), phoneNumber.getId()));
114    }
115
116    private void bufferAddressEntry(Topic addressEntry) {
117        Topic parent = addressEntry.getRelatedTopic("dm4.core.composition", "dm4.core.child", "dm4.core.parent", null);
118        Topic addressLabel = addressEntry.getChildTopics().getTopic("dm4.contacts.address_label");
119        Topic address      = addressEntry.getChildTopics().getTopic("dm4.contacts.address");
120        addressEntries.add(new Entry(addressEntry, parent, addressLabel.getId(), address.getId()));
121    }
122
123    // ---
124
125    private void convertPhoneEntry(Entry entry) {
126        entry.parent.getChildTopics().addRef("dm4.contacts.phone_number", entry.objectId, new ChildTopicsModel()
127            .putRef("dm4.contacts.phone_label", entry.labelId));
128    }
129
130    private void convertAddressEntry(Entry entry) {
131        entry.parent.getChildTopics().addRef("dm4.contacts.address", entry.objectId, new ChildTopicsModel()
132            .putRef("dm4.contacts.address_label", entry.labelId));
133    }
134
135    // ---
136
137    private class Entry {
138
139        private Topic topic;
140        private Topic parent;
141        private long labelId;
142        private long objectId;
143
144        private Entry(Topic topic, Topic parent, long labelId, long objectId) {
145            this.topic = topic;
146            this.parent = parent;
147            this.labelId = labelId;
148            this.objectId = objectId;
149        }
150    }
151}