C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

ファイルの親子関係を取得したい2

こちらの続きです。
ファイルの親子関係を取得したい1 - C#ATIA

結局、非再帰処理が思い付かず、再帰処理で考えました。
まぁ、関数にしておいて思い付いたら差し替えれば良いんでは
無いかと・・・。(多分、考えない)

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core
import json


def run(context):
    ui: adsk.core.UserInterface = None
    try:
        app: adsk.core.Application = adsk.core.Application.get()
        ui = app.userInterface

        # クリア
        app.log(u'TextCommandWindow.Clear')

        # 実行可能か?確認
        msg = checkExec()
        if len(msg) > 0:
            ui.messageBox(msg)
            return

        # 全トップレベル取得
        dataFile: adsk.core.DataFile = app.activeDocument.dataFile
        roots = getRootDataFiles(dataFile)

        # トップレベル毎に関連ファイルの取得
        lst = [getAllChildrenReferences(df) for df in roots]

        # ダンプ
        app.log(
            json.dumps(
                {(i + 1): lst[i] for i in range(0, len(lst))},
                indent=4
            )
        )

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def getAllChildrenReferences(
    dataFile: adsk.core.DataFile) -> list:

    # 対象拡張子
    targetFileExtension = [
        'f3d',
    ]
    drawFileExtension = [
        'f2d',
    ]

    # サポート関数
    def getHasDrawDataFile(
        datafile: adsk.core.DataFile) -> list:

        if not datafile.hasParentReferences:
            return []

        return [d for d in datafile.parentReferences.asArray() 
            if d.fileExtension in drawFileExtension]

    def getHasChildrenDataFile(
        datafile: adsk.core.DataFile) -> list:

        if not datafile.hasChildReferences:
            return []

        return [d for d in datafile.childReferences.asArray() 
            if d.fileExtension in targetFileExtension]

    def initDataDict(
        datafile: adsk.core.DataFile):

        return {
            'name': getDataFileFullName(datafile),
            'children': []
        }

    def getChildrenReferences(dataDict, datafile):

        # 2d
        draws = getHasDrawDataFile(datafile)
        dataDict['children'] = [initDataDict(d) for d in draws]

        # 3d
        children = getHasChildrenDataFile(datafile)
        if len(children) < 1:
            return

        dictLst = [initDataDict(d) for d in children]
        dataDict['children'].extend(dictLst)

        for dict, child in zip(dictLst, children):
            getChildrenReferences(dict, child)

        return dataDict

    # *********
    if not dataFile:
        return []

    return getChildrenReferences(
        initDataDict(dataFile),
        dataFile
    )

# datafileからファイル名取得
def getDataFileFullName(
    datafile: adsk.core.DataFile) -> str:

    return f'{datafile.name}.{datafile.fileExtension}'

# 実行前チェック
def checkExec() -> str:
    app: adsk.core.Application = adsk.core.Application.get()

    # オフラインチェック
    if app.isOffLine:
        return 'オフラインモードではチェック出来ません!!'

    # datafileチェック
    actData: adsk.core.DataFile = app.activeDocument.dataFile
    if not actData:
        return  '関連ドキュメントは有りません!'

    return ''

# topデータファイルを取得
def getRootDataFiles(
    datafile: adsk.core.DataFile,) -> list:
    
    # 対象拡張子
    targetFileExtension = [
        'f3d',
    ]

    # サポート関数
    def getHasParentDataFile(
        datafile: adsk.core.DataFile) -> list:

        if not datafile.hasParentReferences:
            return []

        return getHasExtensionDataFile(
            datafile,
            targetFileExtension
        )

    def getHasExtensionDataFile(
        datafile: adsk.core.DataFile,
        extensionLst: list) -> list:

        if not datafile.hasParentReferences:
            return []

        return [d for d in datafile.parentReferences.asArray() 
            if d.fileExtension in extensionLst]


    # *********
    if not datafile:
        return []

    checkDatas: list  = [datafile]

    rootDatas: list = []
    df: adsk.core.DataFile
    while len(checkDatas) > 0:
        hasParentDatas: list  = []
        for df in checkDatas:
            # 3d
            parents: list  = getHasParentDataFile(df)
            if len(parents) < 1:
                rootDatas.append(df)
            else:
                hasParentDatas.extend(parents)

        if len(hasParentDatas) > 0:
            checkDatas = hasParentDatas
        else:
            checkDatas = []

    return rootDatas

パッと渡されたら何やっているか分からないかも・・・。
特にダンプ処理部分が分かりにくい、良く読めばわかるかな?

再帰部分はgetChildrenReferencesです。
f3dは子供なんですが、f2dは親なんですよね。
"何で?" と思うのですが、削除出来る出来ないの関係だと思います。

それなりのデータを開いて、スクリプトを実行した結果が
こちらです。

 {
    "1": {
        "name": "Part_G.f3d",
        "children": [
            {
                "name": "Part_D.f3d",
                "children": [
                    {
                        "name": "Draw_D.f2d",
                        "children": []
                    }
                ]
            }
        ]
    },
    "2": {
        "name": "Part_F.f3d",
        "children": [
            {
                "name": "Part_D.f3d",
                "children": [
                    {
                        "name": "Draw_D.f2d",
                        "children": []
                    }
                ]
            }
        ]
    },
    "3": {
        "name": "TopLevelAssy.f3d",
        "children": [
            {
                "name": "Draw_TopLevel.f2d",
                "children": []
            },
            {
                "name": "SubAssy_C.f3d",
                "children": [
                    {
                        "name": "Part_E.f3d",
                        "children": []
                    }
                ]
            },
            {
                "name": "SubAssy_B.f3d",
                "children": [
                    {
                        "name": "Draw_B.f2d",
                        "children": []
                    },
                    {
                        "name": "Part_D.f3d",
                        "children": [
                            {
                                "name": "Draw_D.f2d",
                                "children": []
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

えぇ "だから?" と言うレベルです。