001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.impl;
018
019import java.util.Collection;
020import java.util.List;
021import java.util.Map;
022import java.util.Properties;
023import java.util.function.Function;
024
025import org.apache.camel.CamelContext;
026import org.apache.camel.Expression;
027import org.apache.camel.FailedToStartRouteException;
028import org.apache.camel.Predicate;
029import org.apache.camel.Processor;
030import org.apache.camel.Route;
031import org.apache.camel.ValueHolder;
032import org.apache.camel.builder.AdviceWith;
033import org.apache.camel.builder.AdviceWithRouteBuilder;
034import org.apache.camel.impl.engine.DefaultExecutorServiceManager;
035import org.apache.camel.impl.engine.RouteService;
036import org.apache.camel.impl.engine.SimpleCamelContext;
037import org.apache.camel.impl.engine.TransformerKey;
038import org.apache.camel.impl.engine.ValidatorKey;
039import org.apache.camel.model.DataFormatDefinition;
040import org.apache.camel.model.FaultToleranceConfigurationDefinition;
041import org.apache.camel.model.HystrixConfigurationDefinition;
042import org.apache.camel.model.Model;
043import org.apache.camel.model.ModelCamelContext;
044import org.apache.camel.model.ModelLifecycleStrategy;
045import org.apache.camel.model.ProcessorDefinition;
046import org.apache.camel.model.Resilience4jConfigurationDefinition;
047import org.apache.camel.model.RouteDefinition;
048import org.apache.camel.model.RouteDefinitionHelper;
049import org.apache.camel.model.RouteTemplateDefinition;
050import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition;
051import org.apache.camel.model.language.ExpressionDefinition;
052import org.apache.camel.model.rest.RestDefinition;
053import org.apache.camel.model.transformer.TransformerDefinition;
054import org.apache.camel.model.validator.ValidatorDefinition;
055import org.apache.camel.spi.BeanRepository;
056import org.apache.camel.spi.DataFormat;
057import org.apache.camel.spi.DataType;
058import org.apache.camel.spi.ExecutorServiceManager;
059import org.apache.camel.spi.ModelReifierFactory;
060import org.apache.camel.spi.PropertiesComponent;
061import org.apache.camel.spi.Registry;
062import org.apache.camel.spi.Transformer;
063import org.apache.camel.spi.Validator;
064import org.apache.camel.support.CamelContextHelper;
065import org.apache.camel.support.DefaultRegistry;
066import org.apache.camel.util.ObjectHelper;
067import org.slf4j.Logger;
068import org.slf4j.LoggerFactory;
069
070/**
071 * Represents the context used to configure routes and the policies to use.
072 */
073public class DefaultCamelContext extends SimpleCamelContext implements ModelCamelContext {
074
075    private static final Logger LOG = LoggerFactory.getLogger(DefaultCamelContext.class);
076
077    private Model model = new DefaultModel(this);
078
079    /**
080     * Creates the {@link ModelCamelContext} using {@link org.apache.camel.support.DefaultRegistry} as registry.
081     * <p/>
082     * Use one of the other constructors to force use an explicit registry.
083     */
084    public DefaultCamelContext() {
085        this(true);
086    }
087
088    /**
089     * Creates the {@link CamelContext} using the given {@link BeanRepository} as first-choice repository, and the
090     * {@link org.apache.camel.support.SimpleRegistry} as fallback, via the {@link DefaultRegistry} implementation.
091     *
092     * @param repository the bean repository.
093     */
094    public DefaultCamelContext(BeanRepository repository) {
095        this(new DefaultRegistry(repository));
096    }
097
098    /**
099     * Creates the {@link ModelCamelContext} using the given registry
100     *
101     * @param registry the registry
102     */
103    public DefaultCamelContext(Registry registry) {
104        this();
105        setRegistry(registry);
106    }
107
108    public DefaultCamelContext(boolean init) {
109        super(init);
110    }
111
112    @Override
113    public void disposeModel() {
114        LOG.debug("Disposing Model on CamelContext");
115        model = null;
116    }
117
118    @Override
119    public void addModelLifecycleStrategy(ModelLifecycleStrategy modelLifecycleStrategy) {
120        if (model == null && isLightweight()) {
121            throw new IllegalStateException("Access to model not supported in lightweight mode");
122        }
123        model.addModelLifecycleStrategy(modelLifecycleStrategy);
124    }
125
126    @Override
127    public List<ModelLifecycleStrategy> getModelLifecycleStrategies() {
128        if (model == null && isLightweight()) {
129            throw new IllegalStateException("Access to model not supported in lightweight mode");
130        }
131        return model.getModelLifecycleStrategies();
132    }
133
134    @Override
135    public List<RouteDefinition> getRouteDefinitions() {
136        if (model == null && isLightweight()) {
137            throw new IllegalStateException("Access to model not supported in lightweight mode");
138        }
139        return model.getRouteDefinitions();
140    }
141
142    @Override
143    public RouteDefinition getRouteDefinition(String id) {
144        if (model == null && isLightweight()) {
145            throw new IllegalStateException("Access to model not supported in lightweight mode");
146        }
147        return model.getRouteDefinition(id);
148    }
149
150    @Override
151    public void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
152        if (model == null && isLightweight()) {
153            throw new IllegalStateException("Access to model not supported in lightweight mode");
154        }
155        model.addRouteDefinitions(routeDefinitions);
156    }
157
158    @Override
159    public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception {
160        if (model == null && isLightweight()) {
161            throw new IllegalStateException("Access to model not supported in lightweight mode");
162        }
163        model.addRouteDefinition(routeDefinition);
164    }
165
166    @Override
167    public void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
168        if (model == null && isLightweight()) {
169            throw new IllegalStateException("Access to model not supported in lightweight mode");
170        }
171        model.removeRouteDefinitions(routeDefinitions);
172    }
173
174    @Override
175    public void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception {
176        if (model == null && isLightweight()) {
177            throw new IllegalStateException("Access to model not supported in lightweight mode");
178        }
179        model.removeRouteDefinition(routeDefinition);
180    }
181
182    @Override
183    public List<RouteTemplateDefinition> getRouteTemplateDefinitions() {
184        if (model == null && isLightweight()) {
185            throw new IllegalStateException("Access to model not supported in lightweight mode");
186        }
187        return model.getRouteTemplateDefinitions();
188    }
189
190    @Override
191    public RouteTemplateDefinition getRouteTemplateDefinition(String id) {
192        if (model == null && isLightweight()) {
193            throw new IllegalStateException("Access to model not supported in lightweight mode");
194        }
195        return model.getRouteTemplateDefinition(id);
196    }
197
198    @Override
199    public void addRouteTemplateDefinitions(Collection<RouteTemplateDefinition> routeTemplateDefinitions) throws Exception {
200        if (model == null && isLightweight()) {
201            throw new IllegalStateException("Access to model not supported in lightweight mode");
202        }
203        model.addRouteTemplateDefinitions(routeTemplateDefinitions);
204    }
205
206    @Override
207    public void addRouteTemplateDefinition(RouteTemplateDefinition routeTemplateDefinition) throws Exception {
208        if (model == null && isLightweight()) {
209            throw new IllegalStateException("Access to model not supported in lightweight mode");
210        }
211        model.addRouteTemplateDefinition(routeTemplateDefinition);
212    }
213
214    @Override
215    public void removeRouteTemplateDefinitions(Collection<RouteTemplateDefinition> routeTemplateDefinitions) throws Exception {
216        if (model == null && isLightweight()) {
217            throw new IllegalStateException("Access to model not supported in lightweight mode");
218        }
219        model.removeRouteTemplateDefinitions(routeTemplateDefinitions);
220    }
221
222    @Override
223    public void removeRouteTemplateDefinition(RouteTemplateDefinition routeTemplateDefinition) throws Exception {
224        if (model == null && isLightweight()) {
225            throw new IllegalStateException("Access to model not supported in lightweight mode");
226        }
227        model.removeRouteTemplateDefinition(routeTemplateDefinition);
228    }
229
230    @Override
231    public void addRouteTemplateDefinitionConverter(String templateIdPattern, RouteTemplateDefinition.Converter converter) {
232        if (model == null && isLightweight()) {
233            throw new IllegalStateException("Access to model not supported in lightweight mode");
234        }
235        model.addRouteTemplateDefinitionConverter(templateIdPattern, converter);
236    }
237
238    @Override
239    public String addRouteFromTemplate(String routeId, String routeTemplateId, Map<String, Object> parameters)
240            throws Exception {
241        if (model == null && isLightweight()) {
242            throw new IllegalStateException("Access to model not supported in lightweight mode");
243        }
244        return model.addRouteFromTemplate(routeId, routeTemplateId, parameters);
245    }
246
247    @Override
248    public List<RestDefinition> getRestDefinitions() {
249        if (model == null && isLightweight()) {
250            throw new IllegalStateException("Access to model not supported in lightweight mode");
251        }
252        return model.getRestDefinitions();
253    }
254
255    @Override
256    public void addRestDefinitions(Collection<RestDefinition> restDefinitions, boolean addToRoutes) throws Exception {
257        if (model == null && isLightweight()) {
258            throw new IllegalStateException("Access to model not supported in lightweight mode");
259        }
260        model.addRestDefinitions(restDefinitions, addToRoutes);
261    }
262
263    @Override
264    public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
265        if (model == null && isLightweight()) {
266            throw new IllegalStateException("Access to model not supported in lightweight mode");
267        }
268        model.setDataFormats(dataFormats);
269    }
270
271    @Override
272    public Map<String, DataFormatDefinition> getDataFormats() {
273        if (model == null && isLightweight()) {
274            throw new IllegalStateException("Access to model not supported in lightweight mode");
275        }
276        return model.getDataFormats();
277    }
278
279    @Override
280    public DataFormatDefinition resolveDataFormatDefinition(String name) {
281        if (model == null && isLightweight()) {
282            throw new IllegalStateException("Access to model not supported in lightweight mode");
283        }
284        return model.resolveDataFormatDefinition(name);
285    }
286
287    @Override
288    public ProcessorDefinition<?> getProcessorDefinition(String id) {
289        if (model == null && isLightweight()) {
290            throw new IllegalStateException("Access to model not supported in lightweight mode");
291        }
292        return model.getProcessorDefinition(id);
293    }
294
295    @Override
296    public <T extends ProcessorDefinition<T>> T getProcessorDefinition(String id, Class<T> type) {
297        if (model == null && isLightweight()) {
298            throw new IllegalStateException("Access to model not supported in lightweight mode");
299        }
300        return model.getProcessorDefinition(id, type);
301    }
302
303    @Override
304    public void setValidators(List<ValidatorDefinition> validators) {
305        if (model == null && isLightweight()) {
306            throw new IllegalStateException("Access to model not supported in lightweight mode");
307        }
308        model.setValidators(validators);
309    }
310
311    @Override
312    public HystrixConfigurationDefinition getHystrixConfiguration(String id) {
313        if (model == null && isLightweight()) {
314            throw new IllegalStateException("Access to model not supported in lightweight mode");
315        }
316        return model.getHystrixConfiguration(id);
317    }
318
319    @Override
320    public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) {
321        if (model == null && isLightweight()) {
322            throw new IllegalStateException("Access to model not supported in lightweight mode");
323        }
324        model.setHystrixConfiguration(configuration);
325    }
326
327    @Override
328    public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) {
329        if (model == null && isLightweight()) {
330            throw new IllegalStateException("Access to model not supported in lightweight mode");
331        }
332        model.setHystrixConfigurations(configurations);
333    }
334
335    @Override
336    public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) {
337        if (model == null && isLightweight()) {
338            throw new IllegalStateException("Access to model not supported in lightweight mode");
339        }
340        model.addHystrixConfiguration(id, configuration);
341    }
342
343    @Override
344    public Resilience4jConfigurationDefinition getResilience4jConfiguration(String id) {
345        if (model == null && isLightweight()) {
346            throw new IllegalStateException("Access to model not supported in lightweight mode");
347        }
348        return model.getResilience4jConfiguration(id);
349    }
350
351    @Override
352    public void setResilience4jConfiguration(Resilience4jConfigurationDefinition configuration) {
353        if (model == null && isLightweight()) {
354            throw new IllegalStateException("Access to model not supported in lightweight mode");
355        }
356        model.setResilience4jConfiguration(configuration);
357    }
358
359    @Override
360    public void setResilience4jConfigurations(List<Resilience4jConfigurationDefinition> configurations) {
361        if (model == null && isLightweight()) {
362            throw new IllegalStateException("Access to model not supported in lightweight mode");
363        }
364        model.setResilience4jConfigurations(configurations);
365    }
366
367    @Override
368    public void addResilience4jConfiguration(String id, Resilience4jConfigurationDefinition configuration) {
369        if (model == null && isLightweight()) {
370            throw new IllegalStateException("Access to model not supported in lightweight mode");
371        }
372        model.addResilience4jConfiguration(id, configuration);
373    }
374
375    @Override
376    public FaultToleranceConfigurationDefinition getFaultToleranceConfiguration(String id) {
377        if (model == null && isLightweight()) {
378            throw new IllegalStateException("Access to model not supported in lightweight mode");
379        }
380        return model.getFaultToleranceConfiguration(id);
381    }
382
383    @Override
384    public void setFaultToleranceConfiguration(FaultToleranceConfigurationDefinition configuration) {
385        if (model == null && isLightweight()) {
386            throw new IllegalStateException("Access to model not supported in lightweight mode");
387        }
388        model.setFaultToleranceConfiguration(configuration);
389    }
390
391    @Override
392    public void setFaultToleranceConfigurations(List<FaultToleranceConfigurationDefinition> configurations) {
393        if (model == null && isLightweight()) {
394            throw new IllegalStateException("Access to model not supported in lightweight mode");
395        }
396        model.setFaultToleranceConfigurations(configurations);
397    }
398
399    @Override
400    public void addFaultToleranceConfiguration(String id, FaultToleranceConfigurationDefinition configuration) {
401        if (model == null && isLightweight()) {
402            throw new IllegalStateException("Access to model not supported in lightweight mode");
403        }
404        model.addFaultToleranceConfiguration(id, configuration);
405    }
406
407    @Override
408    public List<ValidatorDefinition> getValidators() {
409        if (model == null && isLightweight()) {
410            throw new IllegalStateException("Access to model not supported in lightweight mode");
411        }
412        return model.getValidators();
413    }
414
415    @Override
416    public void setTransformers(List<TransformerDefinition> transformers) {
417        if (model == null && isLightweight()) {
418            throw new IllegalStateException("Access to model not supported in lightweight mode");
419        }
420        model.setTransformers(transformers);
421    }
422
423    @Override
424    public List<TransformerDefinition> getTransformers() {
425        if (model == null && isLightweight()) {
426            throw new IllegalStateException("Access to model not supported in lightweight mode");
427        }
428        return model.getTransformers();
429    }
430
431    @Override
432    public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) {
433        if (model == null && isLightweight()) {
434            throw new IllegalStateException("Access to model not supported in lightweight mode");
435        }
436        return model.getServiceCallConfiguration(serviceName);
437    }
438
439    @Override
440    public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) {
441        if (model == null && isLightweight()) {
442            throw new IllegalStateException("Access to model not supported in lightweight mode");
443        }
444        model.setServiceCallConfiguration(configuration);
445    }
446
447    @Override
448    public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) {
449        if (model == null && isLightweight()) {
450            throw new IllegalStateException("Access to model not supported in lightweight mode");
451        }
452        model.setServiceCallConfigurations(configurations);
453    }
454
455    @Override
456    public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) {
457        if (model == null && isLightweight()) {
458            throw new IllegalStateException("Access to model not supported in lightweight mode");
459        }
460        model.addServiceCallConfiguration(serviceName, configuration);
461    }
462
463    @Override
464    public void setRouteFilterPattern(String include, String exclude) {
465        if (model == null && isLightweight()) {
466            throw new IllegalStateException("Access to model not supported in lightweight mode");
467        }
468        model.setRouteFilterPattern(include, exclude);
469    }
470
471    @Override
472    public void setRouteFilter(Function<RouteDefinition, Boolean> filter) {
473        if (model == null && isLightweight()) {
474            throw new IllegalStateException("Access to model not supported in lightweight mode");
475        }
476        model.setRouteFilter(filter);
477    }
478
479    @Override
480    public Function<RouteDefinition, Boolean> getRouteFilter() {
481        if (model == null && isLightweight()) {
482            throw new IllegalStateException("Access to model not supported in lightweight mode");
483        }
484        return model.getRouteFilter();
485    }
486
487    @Override
488    public ModelReifierFactory getModelReifierFactory() {
489        if (model == null && isLightweight()) {
490            throw new IllegalStateException("Access to model not supported in lightweight mode");
491        }
492        return model.getModelReifierFactory();
493    }
494
495    @Override
496    public void setModelReifierFactory(ModelReifierFactory modelReifierFactory) {
497        if (model == null && isLightweight()) {
498            throw new IllegalStateException("Access to model not supported in lightweight mode");
499        }
500        model.setModelReifierFactory(modelReifierFactory);
501    }
502
503    @Override
504    protected void doStartStandardServices() {
505        super.doStartStandardServices();
506    }
507
508    @Override
509    protected void bindDataFormats() throws Exception {
510        // eager lookup data formats and bind to registry so the dataformats can
511        // be looked up and used
512        if (model != null) {
513            for (Map.Entry<String, DataFormatDefinition> e : model.getDataFormats().entrySet()) {
514                String id = e.getKey();
515                DataFormatDefinition def = e.getValue();
516                LOG.debug("Creating Dataformat with id: {} and definition: {}", id, def);
517                DataFormat df = model.getModelReifierFactory().createDataFormat(this, def);
518                addService(df, true);
519                getRegistry().bind(id, df);
520            }
521        }
522    }
523
524    @Override
525    protected synchronized void shutdownRouteService(RouteService routeService) throws Exception {
526        if (model != null) {
527            RouteDefinition rd = model.getRouteDefinition(routeService.getId());
528            if (rd != null) {
529                model.getRouteDefinitions().remove(rd);
530            }
531        }
532        super.shutdownRouteService(routeService);
533    }
534
535    @Override
536    protected boolean isStreamCachingInUse() throws Exception {
537        boolean streamCachingInUse = super.isStreamCachingInUse();
538        if (!streamCachingInUse) {
539            for (RouteDefinition route : model.getRouteDefinitions()) {
540                Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache());
541                if (routeCache != null && routeCache) {
542                    streamCachingInUse = true;
543                    break;
544                }
545            }
546        }
547        return streamCachingInUse;
548    }
549
550    @Override
551    public void startRouteDefinitions() throws Exception {
552        if (model == null && isLightweight()) {
553            throw new IllegalStateException("Access to model not supported in lightweight mode");
554        }
555        List<RouteDefinition> routeDefinitions = model.getRouteDefinitions();
556        if (routeDefinitions != null) {
557            startRouteDefinitions(routeDefinitions);
558        }
559    }
560
561    public void startRouteDefinitions(List<RouteDefinition> routeDefinitions) throws Exception {
562        if (model == null && isLightweight()) {
563            throw new IllegalStateException("Access to model not supported in lightweight mode");
564        }
565
566        // indicate we are staring the route using this thread so
567        // we are able to query this if needed
568        boolean alreadyStartingRoutes = isStartingRoutes();
569        if (!alreadyStartingRoutes) {
570            setStartingRoutes(true);
571        }
572
573        PropertiesComponent pc = getCamelContextReference().getPropertiesComponent();
574        try {
575            RouteDefinitionHelper.forceAssignIds(getCamelContextReference(), routeDefinitions);
576            for (RouteDefinition routeDefinition : routeDefinitions) {
577                // assign ids to the routes and validate that the id's is all unique
578                String duplicate = RouteDefinitionHelper.validateUniqueIds(routeDefinition, routeDefinitions);
579                if (duplicate != null) {
580                    throw new FailedToStartRouteException(
581                            routeDefinition.getId(),
582                            "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes.");
583                }
584
585                // if the route definition was created via a route template then we need to prepare its parameters when the route is being created and started
586                if (routeDefinition.isTemplate() != null && routeDefinition.isTemplate()
587                        && routeDefinition.getTemplateParameters() != null) {
588                    Properties prop = new Properties();
589                    prop.putAll(routeDefinition.getTemplateParameters());
590                    pc.setLocalProperties(prop);
591                }
592
593                // must ensure route is prepared, before we can start it
594                if (!routeDefinition.isPrepared()) {
595                    RouteDefinitionHelper.prepareRoute(getCamelContextReference(), routeDefinition);
596                    routeDefinition.markPrepared();
597                }
598
599                Route route = model.getModelReifierFactory().createRoute(this, routeDefinition);
600                RouteService routeService = new RouteService(route);
601                startRouteService(routeService, true);
602
603                // clear local after the route is created via the reifier
604                pc.setLocalProperties(null);
605            }
606        } finally {
607            if (!alreadyStartingRoutes) {
608                setStartingRoutes(false);
609            }
610            pc.setLocalProperties(null);
611        }
612    }
613
614    @Override
615    protected ExecutorServiceManager createExecutorServiceManager() {
616        return new DefaultExecutorServiceManager(this);
617    }
618
619    @Override
620    public Processor createErrorHandler(Route route, Processor processor) throws Exception {
621        if (model == null && isLightweight()) {
622            throw new IllegalStateException("Access to model not supported in lightweight mode");
623        }
624        return model.getModelReifierFactory().createErrorHandler(route, processor);
625    }
626
627    @Override
628    public Expression createExpression(ExpressionDefinition definition) {
629        if (model == null && isLightweight()) {
630            throw new IllegalStateException("Access to model not supported in lightweight mode");
631        }
632        return model.getModelReifierFactory().createExpression(this, definition);
633    }
634
635    @Override
636    public Predicate createPredicate(ExpressionDefinition definition) {
637        if (model == null && isLightweight()) {
638            throw new IllegalStateException("Access to model not supported in lightweight mode");
639        }
640        return model.getModelReifierFactory().createPredicate(this, definition);
641    }
642
643    @Override
644    public RouteDefinition adviceWith(RouteDefinition definition, AdviceWithRouteBuilder builder) throws Exception {
645        return AdviceWith.adviceWith(definition, this, builder);
646    }
647
648    @Override
649    public void registerValidator(ValidatorDefinition def) {
650        if (model == null && isLightweight()) {
651            throw new IllegalStateException("Access to model not supported in lightweight mode");
652        }
653        model.getValidators().add(def);
654        Validator validator = model.getModelReifierFactory().createValidator(this, def);
655        getValidatorRegistry().put(createValidatorKey(def), validator);
656    }
657
658    private static ValueHolder<String> createValidatorKey(ValidatorDefinition def) {
659        return new ValidatorKey(new DataType(def.getType()));
660    }
661
662    @Override
663    public void registerTransformer(TransformerDefinition def) {
664        if (model == null && isLightweight()) {
665            throw new IllegalStateException("Access to model not supported in lightweight mode");
666        }
667        model.getTransformers().add(def);
668        Transformer transformer = model.getModelReifierFactory().createTransformer(this, def);
669        getTransformerRegistry().put(createTransformerKey(def), transformer);
670    }
671
672    private static ValueHolder<String> createTransformerKey(TransformerDefinition def) {
673        return ObjectHelper.isNotEmpty(def.getScheme())
674                ? new TransformerKey(def.getScheme())
675                : new TransformerKey(new DataType(def.getFromType()), new DataType(def.getToType()));
676    }
677}