Fix #1562: support dependency scopes
diff --git a/addons/master/master.go b/addons/master/master.go
index bd69f22..7f00b35 100644
--- a/addons/master/master.go
+++ b/addons/master/master.go
@@ -194,6 +194,7 @@
 				childComponent := strings.ReplaceAll(parts[2], "/", "")
 				if artifact := e.CamelCatalog.GetArtifactByScheme(childComponent); artifact != nil {
 					dependencies = append(dependencies, artifact.GetDependencyID())
+					dependencies = append(dependencies, artifact.GetConsumerDependencyIDs(childComponent)...)
 				}
 			}
 		}
diff --git a/deploy/camel-catalog-1.6.0-SNAPSHOT.yaml b/deploy/camel-catalog-1.6.0-SNAPSHOT.yaml
index 6740a0d..56f15aa 100644
--- a/deploy/camel-catalog-1.6.0-SNAPSHOT.yaml
+++ b/deploy/camel-catalog-1.6.0-SNAPSHOT.yaml
@@ -2842,6 +2842,14 @@
       - id: knative
         http: true
         passive: false
+        producer:
+          dependencies:
+          - groupId: org.apache.camel.k
+            artifactId: camel-k-knative-producer
+        consumer:
+          dependencies:
+          - groupId: org.apache.camel.k
+            artifactId: camel-k-knative-consumer
     camel-k-master:
       groupId: org.apache.camel.k
       artifactId: camel-k-master
diff --git a/pkg/apis/camel/v1/camelcatalog_types.go b/pkg/apis/camel/v1/camelcatalog_types.go
index 89bceb9..e824943 100644
--- a/pkg/apis/camel/v1/camelcatalog_types.go
+++ b/pkg/apis/camel/v1/camelcatalog_types.go
@@ -23,9 +23,16 @@
 
 // CamelScheme --
 type CamelScheme struct {
-	ID      string `json:"id" yaml:"id"`
-	Passive bool   `json:"passive" yaml:"passive"`
-	HTTP    bool   `json:"http" yaml:"http"`
+	ID       string           `json:"id" yaml:"id"`
+	Passive  bool             `json:"passive" yaml:"passive"`
+	HTTP     bool             `json:"http" yaml:"http"`
+	Consumer CamelSchemeScope `json:"consumer,omitempty" yaml:"consumer,omitempty"`
+	Producer CamelSchemeScope `json:"producer,omitempty" yaml:"producer,omitempty"`
+}
+
+// CamelSchemeScope contains scoped information about a scheme
+type CamelSchemeScope struct {
+	Dependencies []CamelArtifactDependency `json:"dependencies,omitempty" yaml:"dependencies,omitempty"`
 }
 
 // CamelArtifactExclusion --
diff --git a/pkg/apis/camel/v1/camelcatalog_types_support.go b/pkg/apis/camel/v1/camelcatalog_types_support.go
index 83fcc68..85f6c98 100644
--- a/pkg/apis/camel/v1/camelcatalog_types_support.go
+++ b/pkg/apis/camel/v1/camelcatalog_types_support.go
@@ -18,6 +18,7 @@
 package v1
 
 import (
+	"fmt"
 	"strings"
 
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -75,3 +76,56 @@
 		return "mvn:" + in.GroupID + ":" + in.ArtifactID + ":" + in.Version
 	}
 }
+
+func (in *CamelArtifact) GetConsumerDependencyIDs(schemeID string) (deps []string) {
+	return in.getDependencyIDs(schemeID, consumerScheme)
+}
+
+func (in *CamelArtifact) GetProducerDependencyIDs(schemeID string) (deps []string) {
+	return in.getDependencyIDs(schemeID, producerScheme)
+}
+
+func (in *CamelArtifact) getDependencyIDs(schemeID string, scope func(CamelScheme) CamelSchemeScope) (deps []string) {
+	ads := in.getDependencies(schemeID, scope)
+	if ads == nil {
+		return deps
+	}
+	deps = make([]string, 0, len(ads))
+	for _, ad := range ads {
+		deps = append(deps, fmt.Sprintf("mvn:%s/%s", ad.GroupID, ad.ArtifactID))
+	}
+	return deps
+}
+
+func (in *CamelArtifact) GetConsumerDependencies(schemeID string) []CamelArtifactDependency {
+	return in.getDependencies(schemeID, consumerScheme)
+}
+
+func (in *CamelArtifact) GetProducerDependencies(schemeID string) []CamelArtifactDependency {
+	return in.getDependencies(schemeID, producerScheme)
+}
+
+func (in *CamelArtifact) getDependencies(schemeID string, scope func(CamelScheme) CamelSchemeScope) []CamelArtifactDependency {
+	scheme := in.GetScheme(schemeID)
+	if scheme == nil {
+		return nil
+	}
+	return scope(*scheme).Dependencies
+}
+
+func (in *CamelArtifact) GetScheme(schemeID string) *CamelScheme {
+	for _, scheme := range in.Schemes {
+		if scheme.ID == schemeID {
+			return &scheme
+		}
+	}
+	return nil
+}
+
+func consumerScheme(scheme CamelScheme) CamelSchemeScope {
+	return scheme.Consumer
+}
+
+func producerScheme(scheme CamelScheme) CamelSchemeScope {
+	return scheme.Producer
+}
diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go
index 8e496cc..3a9aa7f 100644
--- a/pkg/trait/cron.go
+++ b/pkg/trait/cron.go
@@ -228,6 +228,7 @@
 				return fmt.Errorf("no fallback artifact for scheme %q has been found in camel catalog", genericCronComponentFallbackScheme)
 			}
 			util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, fallbackArtifact.GetDependencyID())
+			util.StringSliceUniqueConcat(&e.Integration.Status.Dependencies, fallbackArtifact.GetConsumerDependencyIDs(genericCronComponentFallbackScheme))
 		}
 	}
 
diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go
index 90a0051..6de2cb0 100644
--- a/pkg/util/source/inspector.go
+++ b/pkg/util/source/inspector.go
@@ -235,12 +235,27 @@
 
 // discoverDependencies returns a list of dependencies required by the given source code
 func (i *baseInspector) discoverDependencies(source v1.SourceSpec, meta *Metadata) {
-	uris := util.StringSliceJoin(meta.FromURIs, meta.ToURIs)
+	for _, uri := range meta.FromURIs {
+		candidateComp, scheme := i.decodeComponent(uri)
+		if candidateComp != nil {
+			i.addDependency(candidateComp.GetDependencyID(), meta)
+			if scheme != nil {
+				for _, dep := range candidateComp.GetConsumerDependencyIDs(scheme.ID) {
+					i.addDependency(dep, meta)
+				}
+			}
+		}
+	}
 
-	for _, uri := range uris {
-		candidateComp := i.decodeComponent(uri)
-		if candidateComp != "" {
-			i.addDependency(candidateComp, meta)
+	for _, uri := range meta.ToURIs {
+		candidateComp, scheme := i.decodeComponent(uri)
+		if candidateComp != nil {
+			i.addDependency(candidateComp.GetDependencyID(), meta)
+			if scheme != nil {
+				for _, dep := range candidateComp.GetProducerDependencyIDs(scheme.ID) {
+					i.addDependency(dep, meta)
+				}
+			}
 		}
 	}
 
@@ -280,16 +295,18 @@
 	meta.Dependencies.Add(dependency)
 }
 
-func (i *baseInspector) decodeComponent(uri string) string {
+func (i *baseInspector) decodeComponent(uri string) (*v1.CamelArtifact, *v1.CamelScheme) {
 	uriSplit := strings.SplitN(uri, ":", 2)
 	if len(uriSplit) < 2 {
-		return ""
+		return nil, nil
 	}
 	uriStart := uriSplit[0]
-	if component := i.catalog.GetArtifactByScheme(uriStart); component != nil {
-		return component.GetDependencyID()
+	scheme, ok := i.catalog.GetScheme(uriStart)
+	var schemeRef *v1.CamelScheme
+	if ok {
+		schemeRef = &scheme
 	}
-	return ""
+	return i.catalog.GetArtifactByScheme(uriStart), schemeRef
 }
 
 // hasOnlyPassiveEndpoints returns true if the source has no endpoint that needs to remain always active
diff --git a/pkg/util/source/inspector_yaml_test.go b/pkg/util/source/inspector_yaml_test.go
index 518b938..18960d0 100644
--- a/pkg/util/source/inspector_yaml_test.go
+++ b/pkg/util/source/inspector_yaml_test.go
@@ -37,6 +37,80 @@
 	}
 }
 
+const YAMLRouteConsumer = `
+- from:
+    uri: knative:endpoint/default
+    steps:
+      - to:
+          uri: "log:out"
+`
+
+const YAMLRouteProducer = `
+- from:
+    uri: timer:tick
+    steps:
+      - to:
+          uri: knative:endpoint/service
+`
+
+const YAMLRouteTransformer = `
+- from:
+    uri: knative:channel/mychannel
+    steps:
+      - to:
+          uri: knative:endpoint/service
+`
+
+func TestYAMLDependencies(t *testing.T) {
+	tests := []struct {
+		name                string
+		source              string
+		dependencies        []string
+		missingDependencies []string
+	}{
+		{
+			name:                "consumer",
+			source:              YAMLRouteConsumer,
+			dependencies:        []string{`mvn:org.apache.camel.k/camel-k-knative-consumer`},
+			missingDependencies: []string{`mvn:org.apache.camel.k/camel-k-knative-producer`},
+		},
+		{
+			name:                "producer",
+			source:              YAMLRouteProducer,
+			dependencies:        []string{`mvn:org.apache.camel.k/camel-k-knative-producer`},
+			missingDependencies: []string{`mvn:org.apache.camel.k/camel-k-knative-consumer`},
+		},
+		{
+			name:         "transformer",
+			source:       YAMLRouteTransformer,
+			dependencies: []string{`mvn:org.apache.camel.k/camel-k-knative-producer`, `mvn:org.apache.camel.k/camel-k-knative-consumer`},
+		},
+	}
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			code := v1.SourceSpec{
+				DataSpec: v1.DataSpec{
+					Name:    "route.yaml",
+					Content: test.source,
+				},
+				Language: v1.LanguageYaml,
+			}
+
+			meta := NewMetadata()
+			inspector := NewtestYAMLInspector(t)
+
+			err := inspector.Extract(code, &meta)
+			assert.Nil(t, err)
+			for _, dependency := range test.dependencies {
+				assert.Contains(t, meta.Dependencies.List(), dependency)
+			}
+			for _, missingDependency := range test.missingDependencies {
+				assert.NotContains(t, meta.Dependencies.List(), missingDependency)
+			}
+		})
+	}
+}
+
 const YAMLRestDSL = `
 - rest:
     verb: "post"