Ly8gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vICBERVNDUklQVElPTgovLyAgQ3JlYXRlcyBVUF85ODIwNDIwNAovLyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCi8vCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFycwovLyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KLy8gIExvZ2dlcgpsZXQgbG9nID0gKGxvZ1ByZWZpeCwgbG9nTWVzc2FnZSkgPSZndDsgewogICAgbWUubG9nZ2VyKHsKICAgICAgICBsb2dQcmVmaXg6IGxvZ1ByZWZpeCwKICAgICAgICBsb2dNZXNzYWdlOiBsb2dNZXNzYWdlLAogICAgICAgIGxvZ0xldmVsOiAnZGVidWdHcmVlbicKICAgIH0pOwp9OwoKLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KY29uc3QgVVBfREIgPSBUaGluZ3NbJ0FHQ08uVVAuVGhpbmcuRGF0YWJhc2VTZXJ2aWNlcyddOwpjb25zdCBQUk9KRUNUID0gJ0FHQ08uVW5pY29ybi1QbGFubmluZy5EYXRhJzsKY29uc3QgQkFTRV9MT0dfUFJFRklYID0gbWUubmFtZSArICcuVXBkYXRlVVBub2RlcygpJzsKY29uc3QgVUVfR0VORVJJQ19TRVJWSUNFUyA9IFRoaW5nc1smcXVvdDtBR0NPLlVFLlRoaW5nLkdlbmVyaWNTZXJ2aWNlcyZxdW90O107CmNvbnN0IEVYQ0xVREVfRklFTERTID0gWyd0YWdzJywgJ3RoaW5nVGVtcGxhdGUnLCdkZXNjcmlwdGlvbicsJ25hbWUnLCdBcHBOYW1lJywnUGFydFZpZXcnXTsKCmxvZyhCQVNFX0xPR19QUkVGSVgsICdTdGFydGluZy4uLicpOwooKCkgPSZndDsgewogICAgJ3VzZSBzdHJpY3QnOwogICAgbGV0IGNvdW50ID0gMDsKICAgIGxldCBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTsKICAgIGxldCBjYWNoZVBhcnRzVG9DcmVhdGUgPSBbXTsKICAgIGxldCBwYXJ0c0NyZWF0ZWRTdWNjZXNzZnVsbHkgPSB0cnVlOwoKICAgIHRyeSB7CgogICAgICAgIGxldCBkYlBhcnRzPSBVUF9EQi5HZXRBbGxQYXJ0cyh7fSk7IC8vcmV0dXJucyBpZCBhbmQgcGFydG51bWJlcgogICAgICAgIAogICAgICAgIGRiUGFydHMucm93cy50b0FycmF5KCkuZm9yRWFjaCgobmV4dFBhcnQpID0mZ3Q7IHsKICAgICAgICAgICAgbm93Kys7CiAgICAgICAgICAgIGxldCB1bmljb3JuUGFydFZhbHMgPSB7fTsKICAgICAgICAgICAgbGV0IG5leHRQYXJ0TnVtYmVyID0gbmV4dFBhcnQucGFydG51bWJlcjsKICAgICAgICAgICAgbGV0IG5leHRQYXJ0SUQgPSBuZXh0UGFydC5pZDsKICAgICAgICAgICAgbGV0IG5ld1BhcnROdW1iZXIgPSAnVVBfJyArIG5vdzsKICAgICAgICAgICAgbGV0IExPR19QUkVGSVggPSBCQVNFX0xPR19QUkVGSVggKyAnLicgKyBuZXh0UGFydE51bWJlciArICc6ICc7CiAgICAgICAgICAgIGxvZyhMT0dfUFJFRklYLCAnYXBwbHlpbmcgdGhpbmcgc2hhcGUgdG8gcGFydDogJyArIG5leHRQYXJ0TnVtYmVyKTsKCiAgICAgICAgICAgIC8qIEdFVCBUSEUgVU5JQ09STiBEQiBWQUxVRVMgQU5EIEFERCBUTyBVUCBUSElORyBQUk9QRVJUSUVTICovCgogICAgICAgICAgICBsZXQgdW5pY29ybkF0dHJzVmFscyA9IFVQX0RCLlNRTEdldEF0dHJpYnV0ZUxpc3RXaXRoVmFsdWVCeVdUUGFydElEKHsKICAgICAgICAgICAgICAgIHd0cGFydF9pZDogbmV4dFBhcnRJRAogICAgICAgICAgICB9KTsgLy9vdXRwdXQ6IEFHQ08uVVAuZWRpdEF0dHJpYnV0ZUNvbGxlY3Rpb24KCgogICAgICAgICAgICBpZiAodW5pY29ybkF0dHJzVmFscyAmYW1wOyZhbXA7IHVuaWNvcm5BdHRyc1ZhbHMuZ2V0Um93Q291bnQoKSkgewogICAgICAgICAgICAgICAgdW5pY29ybkF0dHJzVmFscy5yb3dzLnRvQXJyYXkoKS5mb3JFYWNoKChuZXh0VmFsKSA9Jmd0OyB7CiAgICAgICAgICAgICAgICAgICAgbGV0IHNhZmVBdHRyTmFtZSA9ICgobmV4dFZhbC5hdHRyaWJ1dGVfbmFtZSkuc3BsaXQoJyAnKSkuam9pbignJyk7CiAgICAgICAgICAgICAgICAgICAgaWYgKG5leHRWYWwuYXR0cmlidXRlX3R5cGUgPT09ICZxdW90O0RhdGUmcXVvdDspIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHRWYWwuYXR0cmlidXRlX3ZhbHVlLmluZGV4T2YoJy0nKSAmbHQ7IDApIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkYXRlID0gVGhpbmdzWyZxdW90O0FHQ08uVVAuVGhpbmcuR2VuZXJpY1NlcnZpY2VzJnF1b3Q7XS5Db252ZXJ0VGltZVN0YW1wVG9EYXRlKHtpbnB1dGRhdGU6IG5leHRWYWwuYXR0cmlidXRlX3ZhbHVlfSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmljb3JuUGFydFZhbHNbc2FmZUF0dHJOYW1lXSA9IGRhdGU7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICB1bmljb3JuUGFydFZhbHNbc2FmZUF0dHJOYW1lXSA9IG5leHRWYWwuYXR0cmlidXRlX3ZhbHVlOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxvZyhMT0dfUFJFRklYLCAnIGZvdW5kIHVuaWNvcm4gcGFydCB2YWxzICcgKyBKU09OLnN0cmluZ2lmeSh1bmljb3JuUGFydFZhbHMpKTsKICAgICAgICAgICAgLyogQ1JFQVRFIFVQIFRISU5HIFdJVEggQklORElOR1MgVE8gV0lORENISUxMIFRISU5HICovCgogICAgICAgICAgICAvLyBhZGQgdGhpbmcgc2hhcGUgdG8gbWF0Y2hpbmcgdGhpbmcgaW4gY2xhc3NpZmljYXRpb24gdHJlZQogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgICAgbGV0IGltcGxlbWVudGVkUGFydCA9IFRoaW5nVGVtcGxhdGVzW25leHRQYXJ0TnVtYmVyXS5HZXRJbXBsZW1lbnRpbmdUaGluZ3NXaXRoRGF0YSgpOwogICAgICAgICAgICAgICAgbGV0IHVuaWNvcm5QYXJ0cyA9IFtdOwogICAgICAgICAgICAgICAgbGV0IHdpbmRjaGlsbFBhcnQ7CiAgICAgICAgICAgICAgICBsZXQgbmV3VVBUaGluZzsKCiAgICAgICAgICAgICAgICBpbXBsZW1lbnRlZFBhcnQucm93cy50b0FycmF5KCkuZm9yRWFjaChuZXh0VGhpbmcgPSZndDsgewogICAgICAgICAgICAgICAgICAgIGlmICgobmV4dFRoaW5nLm5hbWUpLnN0YXJ0c1dpdGgoJ1VQXycpKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHVuaWNvcm5QYXJ0cy5wdXNoKG5leHRUaGluZy5uYW1lKTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKChuZXh0VGhpbmcubmFtZSkuc3RhcnRzV2l0aCgnV0NfJykpIHsKICAgICAgICAgICAgICAgICAgICAgICAgd2luZGNoaWxsUGFydCA9IG5leHRUaGluZy5uYW1lOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgaWYgKHVuaWNvcm5QYXJ0cy5sZW5ndGgpIHsKICAgICAgICAgICAgICAgICAgICBsb2coTE9HX1BSRUZJWCwgdW5pY29yblBhcnRzLmxlbmd0aCArJyB0aGluZ3MgYWxyZWFkeSBleGlzdHMnKTsKCiAgICAgICAgICAgICAgICAgICAgdW5pY29yblBhcnRzLnNvcnQoKTsKICAgICAgICAgICAgICAgICAgICBsZXQgdW5pY29yblBhcnQgPSB1bmljb3JuUGFydHMucG9wKCk7CiAgICAgICAgICAgICAgICAgICAgdW5pY29yblBhcnRzLmZvckVhY2gob2xkVGhpbmcgPSZndDsgewogICAgICAgICAgICAgICAgICAgICAgICBSZXNvdXJjZXNbJnF1b3Q7RW50aXR5U2VydmljZXMmcXVvdDtdLkRlbGV0ZVRoaW5nKHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IG9sZFRoaW5nIC8qIFRISU5HTkFNRSAqLwogICAgICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICBuZXdVUFRoaW5nID0gVGhpbmdzW3VuaWNvcm5QYXJ0XTsKCiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIFJlc291cmNlcy5FbnRpdHlTZXJ2aWNlcy5DcmVhdGVUaGluZyh7CiAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU6IG5ld1BhcnROdW1iZXIsCiAgICAgICAgICAgICAgICAgICAgICAgIHRoaW5nVGVtcGxhdGVOYW1lOiBuZXh0UGFydE51bWJlciwKICAgICAgICAgICAgICAgICAgICAgICAgcHJvamVjdE5hbWU6IFBST0pFQ1QKICAgICAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAgICAgVGhpbmdzW25ld1BhcnROdW1iZXJdLkVuYWJsZVRoaW5nKCk7CiAgICAgICAgICAgICAgICAgICAgVGhpbmdzW25ld1BhcnROdW1iZXJdLlJlc3RhcnRUaGluZygpOwoKICAgICAgICAgICAgICAgICAgICBSZXNvdXJjZXMuRW50aXR5U2VydmljZXMuQWRkU2hhcGVUb1RoaW5nKHsKICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmV3UGFydE51bWJlciwKICAgICAgICAgICAgICAgICAgICAgICAgdGhpbmdTaGFwZU5hbWU6ICdBR0NPLlVQLlRoaW5nU2hhcGUuUGxhbm5pbmdQYXJ0Lk1hbmFnZWFibGVBdHRyaWJ1dGVzJwogICAgICAgICAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgICAgICAgICBSZXNvdXJjZXMuRW50aXR5U2VydmljZXMuQWRkU2hhcGVUb1RoaW5nKHsKICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmV3UGFydE51bWJlciwKICAgICAgICAgICAgICAgICAgICAgICAgdGhpbmdTaGFwZU5hbWU6ICdBR0NPLlVQLlRoaW5nU2hhcGUuUGxhbm5pbmdQYXJ0LlN5c3RlbUF0dHJpYnV0ZXMnCiAgICAgICAgICAgICAgICAgICAgfSk7CgogICAgICAgICAgICAgICAgICAgIFJlc291cmNlcy5FbnRpdHlTZXJ2aWNlcy5BZGRTaGFwZVRvVGhpbmcoewogICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiBuZXdQYXJ0TnVtYmVyLAogICAgICAgICAgICAgICAgICAgICAgICB0aGluZ1NoYXBlTmFtZTogJ0FHQ08uVVAuVGhpbmdTaGFwZS5QbGFubmluZ1BhcnQuV2luZGNoaWxsQXR0cmlidXRlcycKICAgICAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAgICAgbG9nKExPR19QUkVGSVgsICdhZGRlZCBzaGFwZSB0byB0aGluZywgdXBkYXRpbmcgcHJvcGVydGllcycpOwoKICAgICAgICAgICAgICAgICAgICBuZXdVUFRoaW5nID0gVGhpbmdzW25ld1BhcnROdW1iZXJdOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIG5ld1VQVGhpbmcuQXBwTmFtZSA9ICdVUCc7CiAgICAgICAgICAgICAgICBuZXdVUFRoaW5nLlBhcnRWaWV3ID0gJ0Rlc2lnbic7CgogICAgICAgICAgICAgICAgaWYgKHdpbmRjaGlsbFBhcnQpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgd2luZGNoaWxsUGFydFByb3BlcnRpZXMgPSBUaGluZ3Nbd2luZGNoaWxsUGFydF0uR2V0UHJvcGVydHlWYWx1ZXMoKTsKICAgICAgICAgICAgICAgICAgICBsZXQgd2luZGNoaWxsUGFydEZpZWxkcyA9IHdpbmRjaGlsbFBhcnRQcm9wZXJ0aWVzLmRhdGFTaGFwZS5maWVsZHM7CiAgICAgICAgICAgICAgICAgICAgbGV0IHdpbmRjaGlsbFBhcnRBdHRyc0FycmF5ID0gW107CiAgICAgICAgICAgICAgICAgICAgd2luZGNoaWxsUGFydEZpZWxkcy5mb3JFYWNoKChuZXh0RmllbGQpID0mZ3Q7IHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFFWENMVURFX0ZJRUxEUy5pbmNsdWRlcyh3aW5kY2hpbGxQYXJ0RmllbGRzW25leHRGaWVsZF1bJnF1b3Q7bmFtZSZxdW90O10pKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aW5kY2hpbGxQYXJ0QXR0cnNBcnJheS5wdXNoKHdpbmRjaGlsbFBhcnRGaWVsZHNbbmV4dEZpZWxkXVsmcXVvdDtuYW1lJnF1b3Q7XSk7ICAgCiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAgICAgbGV0IG5ld1VQVGhpbmdQcm9wZXJ0aWVzID0gbmV3VVBUaGluZy5HZXRQcm9wZXJ0eVZhbHVlcygpOwogICAgICAgICAgICAgICAgICAgIGxldCBuZXdVUFRoaW5nRmllbGRzID0gbmV3VVBUaGluZ1Byb3BlcnRpZXMuZGF0YVNoYXBlLmZpZWxkczsKCiAgICAgICAgICAgICAgICAgICAgbmV3VVBUaGluZ0ZpZWxkcy5mb3JFYWNoKChuZXh0QXR0cmlidXRlKSA9Jmd0OyB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUVYQ0xVREVfRklFTERTLmluY2x1ZGVzKG5ld1VQVGhpbmdGaWVsZHNbbmV4dEF0dHJpYnV0ZV1bJnF1b3Q7bmFtZSZxdW90O10pKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9pZiB0aGUgbmV3VVBUaGluZyBoYXMgYW4gYXR0cmlidXRlIHRoYXQgaXMgZm91bmQgaW4gdGhlIHdpbmRjaGlsbCBwYXJ0LCBhZGQgYSBsb2NhbCBiaW5kaW5nCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdpbmRjaGlsbFBhcnRBdHRyc0FycmF5LmluY2x1ZGVzKG5ld1VQVGhpbmdGaWVsZHNbbmV4dEF0dHJpYnV0ZV1bJnF1b3Q7bmFtZSZxdW90O10pKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vYWRkIHdpbmRjaGlsbCBjYWNoZSBsaW5rCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1VQVGhpbmcuU2V0TG9jYWxQcm9wZXJ0eUJpbmRpbmcoewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHlOYW1lOiBuZXdVUFRoaW5nRmllbGRzW25leHRBdHRyaWJ1dGVdWyZxdW90O25hbWUmcXVvdDtdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlVGhpbmdOYW1lOiB3aW5kY2hpbGxQYXJ0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlUHJvcGVydHlOYW1lOiBuZXdVUFRoaW5nRmllbGRzW25leHRBdHRyaWJ1dGVdWyZxdW90O25hbWUmcXVvdDtdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2coTE9HX1BSRUZJWCArICcgYXR0ZW1wdGluZyB0byBiaW5kIHRvICcgKyBuZXdVUFRoaW5nRmllbGRzW25leHRBdHRyaWJ1dGVdWyZxdW90O25hbWUmcXVvdDtdICsgJy4uJyk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1bmljb3JuUGFydFZhbHMuaGFzT3duUHJvcGVydHkobmV3VVBUaGluZ0ZpZWxkc1tuZXh0QXR0cmlidXRlXVsmcXVvdDtuYW1lJnF1b3Q7XSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3VVBUaGluZ1tuZXdVUFRoaW5nRmllbGRzW25leHRBdHRyaWJ1dGVdWyZxdW90O25hbWUmcXVvdDtdXSA9IHVuaWNvcm5QYXJ0VmFsc1tuZXdVUFRoaW5nRmllbGRzW25leHRBdHRyaWJ1dGVdWyZxdW90O25hbWUmcXVvdDtdXTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nKExPR19QUkVGSVggKyAnIGF0dGVtcHRpbmcgdG8gYWRkIHRvICcgKyBuZXdVUFRoaW5nRmllbGRzW25leHRBdHRyaWJ1dGVdWyZxdW90O25hbWUmcXVvdDtdICsgJyB3aXRoICcgKyB1bmljb3JuUGFydFZhbHNbbmV3VVBUaGluZ0ZpZWxkc1tuZXh0QXR0cmlidXRlXVsmcXVvdDtuYW1lJnF1b3Q7XV0gKyAnPy4nKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL2xvZyhMT0dfUFJFRklYICsgJyBubyBtYXRjaCBmb3IgJyArIG5ld1VQVGhpbmdGaWVsZHNbbmV4dEF0dHJpYnV0ZV1bJnF1b3Q7bmFtZSZxdW90O10pOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXIpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZyhMT0dfUFJFRklYLCAnZXJyb3IgdXBkYXRpbmcgPSAnICsgZXIgKyBuZXdVUFRoaW5nRmllbGRzW25leHRBdHRyaWJ1dGVdWyZxdW90O25hbWUmcXVvdDtdKTsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0pOwoKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgbG9nKExPR19QUkVGSVgsICcgbm8gd2NfKiB3aW5kY2hpbGwgcGFydCBmb3VuZCBmb3IgJyArIG5leHRQYXJ0TnVtYmVyKTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikgewogICAgICAgICAgICAgICAgbG9nKExPR19QUkVGSVgsICdlcnJvciBjcmVhdGluZyBVUCB0aGluZywgZXJyID0gJyArIGVycik7CiAgICAgICAgICAgIH0KCiAgICAgICAgfSk7CgogICAgICAgIHJlc3VsdCA9IHRydWU7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgIGxvZyhCQVNFX0xPR19QUkVGSVgsICc6IEVycm9yID0gJyArIGVycm9yLm1lc3NhZ2UpOwogICAgfQoKICAgIGxvZyhCQVNFX0xPR19QUkVGSVgsICc6IERvbmUuLi4nICsgY291bnQpOwp9KSgpOw==
// --------------------------------------------------------------------------------------
// DESCRIPTION
// Creates UP_98204204
// ---------------------------------------------------------------------------------------
//
// eslint-disable-next-line no-unused-vars
// --------------------------------------------------------------------------------------
// Logger
let log = (logPrefix, logMessage) => {
me.logger({
logPrefix: logPrefix,
logMessage: logMessage,
logLevel: 'debugGreen'
});
};
// --------------------------------------------------------------------------------------
const UP_DB = Things['AGCO.UP.Thing.DatabaseServices'];
const PROJECT = 'AGCO.Unicorn-Planning.Data';
const BASE_LOG_PREFIX = me.name + '.UpdateUPnodes()';
const UE_GENERIC_SERVICES = Things["AGCO.UE.Thing.GenericServices"];
const EXCLUDE_FIELDS = ['tags', 'thingTemplate','description','name','AppName','PartView'];
log(BASE_LOG_PREFIX, 'Starting...');
(() => {
'use strict';
let count = 0;
let now = new Date().getTime();
let cachePartsToCreate = [];
let partsCreatedSuccessfully = true;
try {
let dbParts= UP_DB.GetAllParts({}); //returns id and partnumber
dbParts.rows.toArray().forEach((nextPart) => {
now++;
let unicornPartVals = {};
let nextPartNumber = nextPart.partnumber;
let nextPartID = nextPart.id;
let newPartNumber = 'UP_' + now;
let LOG_PREFIX = BASE_LOG_PREFIX + '.' + nextPartNumber + ': ';
log(LOG_PREFIX, 'applying thing shape to part: ' + nextPartNumber);
/* GET THE UNICORN DB VALUES AND ADD TO UP THING PROPERTIES */
let unicornAttrsVals = UP_DB.SQLGetAttributeListWithValueByWTPartID({
wtpart_id: nextPartID
}); //output: AGCO.UP.editAttributeCollection
if (unicornAttrsVals && unicornAttrsVals.getRowCount()) {
unicornAttrsVals.rows.toArray().forEach((nextVal) => {
let safeAttrName = ((nextVal.attribute_name).split(' ')).join('');
if (nextVal.attribute_type === "Date") {
if (nextVal.attribute_value.indexOf('-') < 0) {
let date = Things["AGCO.UP.Thing.GenericServices"].ConvertTimeStampToDate({inputdate: nextVal.attribute_value});
unicornPartVals[safeAttrName] = date;
}
} else {
unicornPartVals[safeAttrName] = nextVal.attribute_value;
}
});
}
log(LOG_PREFIX, ' found unicorn part vals ' + JSON.stringify(unicornPartVals));
/* CREATE UP THING WITH BINDINGS TO WINDCHILL THING */
// add thing shape to matching thing in classification tree
try {
let implementedPart = ThingTemplates[nextPartNumber].GetImplementingThingsWithData();
let unicornParts = [];
let windchillPart;
let newUPThing;
implementedPart.rows.toArray().forEach(nextThing => {
if ((nextThing.name).startsWith('UP_')) {
unicornParts.push(nextThing.name);
} else if ((nextThing.name).startsWith('WC_')) {
windchillPart = nextThing.name;
}
});
if (unicornParts.length) {
log(LOG_PREFIX, unicornParts.length +' things already exists');
unicornParts.sort();
let unicornPart = unicornParts.pop();
unicornParts.forEach(oldThing => {
Resources["EntityServices"].DeleteThing({
name: oldThing /* THINGNAME */
});
});
newUPThing = Things[unicornPart];
} else {
Resources.EntityServices.CreateThing({
name: newPartNumber,
thingTemplateName: nextPartNumber,
projectName: PROJECT
});
Things[newPartNumber].EnableThing();
Things[newPartNumber].RestartThing();
Resources.EntityServices.AddShapeToThing({
name: newPartNumber,
thingShapeName: 'AGCO.UP.ThingShape.PlanningPart.ManageableAttributes'
});
Resources.EntityServices.AddShapeToThing({
name: newPartNumber,
thingShapeName: 'AGCO.UP.ThingShape.PlanningPart.SystemAttributes'
});
Resources.EntityServices.AddShapeToThing({
name: newPartNumber,
thingShapeName: 'AGCO.UP.ThingShape.PlanningPart.WindchillAttributes'
});
log(LOG_PREFIX, 'added shape to thing, updating properties');
newUPThing = Things[newPartNumber];
}
newUPThing.AppName = 'UP';
newUPThing.PartView = 'Design';
if (windchillPart) {
let windchillPartProperties = Things[windchillPart].GetPropertyValues();
let windchillPartFields = windchillPartProperties.dataShape.fields;
let windchillPartAttrsArray = [];
windchillPartFields.forEach((nextField) => {
if (!EXCLUDE_FIELDS.includes(windchillPartFields[nextField]["name"])) {
windchillPartAttrsArray.push(windchillPartFields[nextField]["name"]);
}
});
let newUPThingProperties = newUPThing.GetPropertyValues();
let newUPThingFields = newUPThingProperties.dataShape.fields;
newUPThingFields.forEach((nextAttribute) => {
try {
if (!EXCLUDE_FIELDS.includes(newUPThingFields[nextAttribute]["name"])) {
//if the newUPThing has an attribute that is found in the windchill part, add a local binding
if (windchillPartAttrsArray.includes(newUPThingFields[nextAttribute]["name"])) {
//add windchill cache link
newUPThing.SetLocalPropertyBinding({
propertyName: newUPThingFields[nextAttribute]["name"],
sourceThingName: windchillPart,
sourcePropertyName: newUPThingFields[nextAttribute]["name"]
});
log(LOG_PREFIX + ' attempting to bind to ' + newUPThingFields[nextAttribute]["name"] + '..');
} else if (unicornPartVals.hasOwnProperty(newUPThingFields[nextAttribute]["name"])) {
newUPThing[newUPThingFields[nextAttribute]["name"]] = unicornPartVals[newUPThingFields[nextAttribute]["name"]];
log(LOG_PREFIX + ' attempting to add to ' + newUPThingFields[nextAttribute]["name"] + ' with ' + unicornPartVals[newUPThingFields[nextAttribute]["name"]] + '?.');
} else {
//log(LOG_PREFIX + ' no match for ' + newUPThingFields[nextAttribute]["name"]);
}
}
} catch (er) {
log(LOG_PREFIX, 'error updating = ' + er + newUPThingFields[nextAttribute]["name"]);
}
});
} else {
log(LOG_PREFIX, ' no wc_* windchill part found for ' + nextPartNumber);
}
} catch (err) {
log(LOG_PREFIX, 'error creating UP thing, err = ' + err);
}
});
result = true;
} catch (error) {
log(BASE_LOG_PREFIX, ': Error = ' + error.message);
}
log(BASE_LOG_PREFIX, ': Done...' + count);
})();