1d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets/* 21503d52153986fdcfe7e744795010708b7410892Ian Lake * Copyright 2018 The Android Open Source Project 3d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * 4d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * Licensed under the Apache License, Version 2.0 (the "License"); 5d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * you may not use this file except in compliance with the License. 6d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * You may obtain a copy of the License at 7d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * 8d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * http://www.apache.org/licenses/LICENSE-2.0 9d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * 10d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * Unless required by applicable law or agreed to in writing, software 11d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * distributed under the License is distributed on an "AS IS" BASIS, 12d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * See the License for the specific language governing permissions and 14d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets * limitations under the License. 15d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets */ 16d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets 171503d52153986fdcfe7e744795010708b7410892Ian Lakepackage androidx.navigation.safe.args.generator 18d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets 191503d52153986fdcfe7e744795010708b7410892Ian Lakeimport androidx.navigation.safe.args.generator.models.Argument 201503d52153986fdcfe7e744795010708b7410892Ian Lakeimport androidx.navigation.safe.args.generator.models.Destination 211503d52153986fdcfe7e744795010708b7410892Ian Lakeimport androidx.navigation.safe.args.generator.models.ResReference 22d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets 23d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinetsfun resolveArguments(rootDestination: Destination): Destination { 249ca584405af88767f97ec06fbb5f5e1b7e98b1b4Sergey Vasilinets val destinations = mutableMapOf<ResReference, Destination>() 25d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets 26d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets fun dfs(dest: Destination): Destination { 27d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets val nested = dest.nested.filter { it.id != null }.associateBy { it.id!! } 28d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets destinations.putAll(nested) 29d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets val resolvedActions = dest.actions.map { action -> 30d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets val actionDestination = destinations[action.destination] 31d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets if (actionDestination != null) { 32d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets action.copy(args = mergeArguments(action.args, actionDestination.args)) 33d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } else { 34d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets action 35d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } 36d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } 37d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets val result = dest.copy(nested = dest.nested.map(::dfs), actions = resolvedActions) 38d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets nested.keys.forEach { id -> destinations.remove(id) } 39d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets return result 40d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } 41d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets 42d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets return dfs(rootDestination) 43d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets} 44d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets 45d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinetsprivate fun mergeArguments(args1: List<Argument>, args2: List<Argument>) = 46d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets args2.fold(args1) { result, arg -> 47d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets val duplicate = result.find { it.name == arg.name } 48d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets if (duplicate != null) { 49d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets if (duplicate.type != arg.type) { 50d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets // TODO: needs context to print better exception 51d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets throw IllegalArgumentException("Incompatible types ${duplicate.type} and " + 52f49d36a214375ac9a735ab9af9e1b3a4b9d2a3cdSergey Vasilinets "${arg.type} of argument ${arg.name}") 53d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } 54d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets result 55d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } else { 56d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets result + arg 57d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } 58d88974530aa8463cd0d66cdc7ff8bf77ca7fca72Sergey Vasilinets } 59