{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Link Records\n",
    "Create and edit smart and static links between records."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create a new record\n",
    "Connect to MI and get a database and table."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from datetime import datetime\n",
    "from GRANTA_MIScriptingToolkit import granta as mpy\n",
    "\n",
    "mi = mpy.connect('http://localhost/mi_servicelayer', autologon=True)\n",
    "db = mi.get_db(db_key='MI_Training')\n",
    "tab = db.get_table('Training Exercise for Import')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a new record in the subset *Materials*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "now = datetime.now().strftime(\"%c\")\n",
    "recordName = 'STK Example 16:{}'.format(now)\n",
    "rec = tab.create_record(recordName, subsets={'Materials'})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Smart links\n",
    "A smart link is configured in this database to link records with matching values for the attribute *Base*.\n",
    "Setting a value for *Base* on the new record will link it to all existing records with the same value for that attribute.\n",
    "\n",
    "Set the value of *Base* to *Oxide*, then write the changes to MI. At this point, the new record is created on the server."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "base = rec.attributes['Base']\n",
    "base.value = ['Oxide']\n",
    "rec.set_attributes([base])\n",
    "rec = mi.update([rec])[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "View the smart links that have just been created to the new record."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'MaterialUniverse': set(),\n",
       " 'Smart Link to MaterialUniverse': {<Record long name:Alumino silicate - 1720>,\n",
       "  <Record long name:Alumino silicate - 1723>,\n",
       "  <Record long name:Barium silicate>,\n",
       "  <Record long name:Lithium aluminosilicate>,\n",
       "  <Record long name:Soda barium glass>}}"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rec.links"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Static links\n",
    "A static link can be created between two existing records, including cross-database.\n",
    "\n",
    "Get a record from *MaterialUniverse* to link to your newly-created record."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "mu_rec = db.get_record_by_id(hguid='bf5e6054-6cad-4c9d-ad7a-adfa124c504b')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add the *MaterialUniverse* record to the link group on the new record."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_linked_recs = rec.links['MaterialUniverse']\n",
    "new_linked_recs.add(mu_rec)\n",
    "rec.set_links('MaterialUniverse', new_linked_recs)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Write your changes to MI (use `update_links()` for changes to links, not `update()`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "rec = mi.update_links([rec])[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "View your new link on the list of record links."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'MaterialUniverse': {<Record long name:Soda barium glass>}, 'Smart Link to MaterialUniverse': {<Record long name:Lithium aluminosilicate>, <Record long name:Soda barium glass>, <Record long name:Alumino silicate - 1720>, <Record long name:Barium silicate>, <Record long name:Alumino silicate - 1723>}}\n"
     ]
    }
   ],
   "source": [
    "print(rec.links)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Associated Records\n",
    "Associated Records are a way of traversing tabular links multiple steps at a time. This example finds all materials\n",
    "impacted by a certain legislation by building an associated record chain between three tables."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First define the starting table and record. The association chain starts on the relevant record in the *Legislations and\n",
    "Lists* table."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "starting_table = db.get_table('Legislations and Lists')\n",
    "starting_record = starting_table.get_record_by_lookup_value('Legislation ID', 'Candidate_AnnexXV')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, set the tabular attribute that forms the first step in the chain. In this case, it is the tabular attribute\n",
    "that links the *Restricted Substances* table to the *Legislations and Lists* table."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "rs_table = db.get_table('Restricted Substances')\n",
    "first_step = rs_table.attributes['Legislations restricting its use']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Then set the tabular attribute that forms the second step in the chain: *Restricted substances associated with this\n",
    "material*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "materialuniverse_table = db.get_table('MaterialUniverse')\n",
    "second_step = materialuniverse_table.attributes['Restricted substances associated with this material']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, use the `get_associated_records()` method on the `starting_record` **Record** object to extract the records at\n",
    "the end of the association chain."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<Record long name:PVC-elastomer (Shore A35)>,\n",
       " <Record long name:Barium silicate>]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "associated_records = starting_record.get_associated_records(materialuniverse_table,\n",
    "                                                   link_direction='Reverse',\n",
    "                                                   attribute_path=[first_step, second_step])\n",
    "associated_records"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
