1 /*******************************************************************************
2 * Copyright (c) 2013, 2022 Obeo and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * Obeo - initial API and implementation
10 * Stefan Dirix - bug 466607
11 * Philip Langer - add support for setting initial file URIs to scope
12 * Martin Fleck - bug 512562
13 * Martin Fleck - bug 578422
14 *******************************************************************************/
15 package org
.eclipse
.emf
.compare
.ide
.ui
.internal
.logical
;
17 import static com
.google
.common
.base
.Preconditions
.checkNotNull
;
18 import static com
.google
.common
.collect
.Collections2
.transform
;
19 import static org
.eclipse
.emf
.compare
.ide
.ui
.internal
.util
.PlatformElementUtil
.findFile
;
20 import static org
.eclipse
.emf
.compare
.ide
.utils
.ResourceUtil
.createURIFor
;
22 import com
.google
.common
.base
.Function
;
23 import com
.google
.common
.base
.Predicate
;
24 import com
.google
.common
.collect
.Sets
;
26 import java
.util
.Arrays
;
27 import java
.util
.Collection
;
28 import java
.util
.LinkedHashSet
;
31 import org
.apache
.log4j
.Logger
;
32 import org
.eclipse
.compare
.ICompareContainer
;
33 import org
.eclipse
.compare
.IStreamContentAccessor
;
34 import org
.eclipse
.compare
.ITypedElement
;
35 import org
.eclipse
.core
.resources
.IFile
;
36 import org
.eclipse
.core
.resources
.IResource
;
37 import org
.eclipse
.core
.resources
.IStorage
;
38 import org
.eclipse
.core
.runtime
.Assert
;
39 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
40 import org
.eclipse
.core
.runtime
.OperationCanceledException
;
41 import org
.eclipse
.core
.runtime
.SubMonitor
;
42 import org
.eclipse
.emf
.common
.util
.BasicDiagnostic
;
43 import org
.eclipse
.emf
.common
.util
.Diagnostic
;
44 import org
.eclipse
.emf
.common
.util
.URI
;
45 import org
.eclipse
.emf
.compare
.DifferenceSource
;
46 import org
.eclipse
.emf
.compare
.ide
.EMFCompareIDEPlugin
;
47 import org
.eclipse
.emf
.compare
.ide
.internal
.hook
.ResourceSetHookRegistry
;
48 import org
.eclipse
.emf
.compare
.ide
.internal
.utils
.NotLoadingResourceSet
;
49 import org
.eclipse
.emf
.compare
.ide
.ui
.internal
.EMFCompareIDEUIMessages
;
50 import org
.eclipse
.emf
.compare
.ide
.ui
.internal
.EMFCompareIDEUIPlugin
;
51 import org
.eclipse
.emf
.compare
.ide
.ui
.internal
.util
.PlatformElementUtil
;
52 import org
.eclipse
.emf
.compare
.ide
.ui
.logical
.IModelMinimizer
;
53 import org
.eclipse
.emf
.compare
.ide
.ui
.logical
.IModelResolver
;
54 import org
.eclipse
.emf
.compare
.ide
.ui
.logical
.IStorageProviderAccessor
;
55 import org
.eclipse
.emf
.compare
.ide
.ui
.logical
.SynchronizationModel
;
56 import org
.eclipse
.emf
.compare
.ide
.utils
.ResourceUtil
;
57 import org
.eclipse
.emf
.compare
.ide
.utils
.StorageTraversal
;
58 import org
.eclipse
.emf
.compare
.scope
.DefaultComparisonScope
;
59 import org
.eclipse
.emf
.compare
.scope
.FilterComparisonScope
;
60 import org
.eclipse
.emf
.compare
.scope
.IComparisonScope
;
61 import org
.eclipse
.emf
.ecore
.resource
.Resource
;
62 import org
.eclipse
.emf
.ecore
.resource
.ResourceSet
;
63 import org
.eclipse
.emf
.ecore
.resource
.URIConverter
;
64 import org
.eclipse
.emf
.ecore
.resource
.impl
.ExtensibleURIConverterImpl
;
65 import org
.eclipse
.emf
.ecore
.util
.EcoreUtil
;
66 import org
.eclipse
.team
.core
.subscribers
.Subscriber
;
69 * This will be used by EMF Compare in order to construct its comparison scope given a "starting point".
71 * A single file is not always a single EMF model, nor is an EMF model always stored in a single file. This
72 * will be used to resolve all physical resources composing the logical model we are to compare, minimize this
73 * set to the potential changed candidates, and construct the actual comparison scope.
76 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
78 public final class ComparisonScopeBuilder
{
79 /** The instance that will be in charge of resolving our logical models. */
80 private final IModelResolver resolver
;
82 /** The instance that will be in charge of reducing the comparison scope. */
83 private final IModelMinimizer minimizer
;
85 /** The accessor that can be used to retrieve synchronization information between our resources. */
86 private final IStorageProviderAccessor storageAccessor
;
89 private static final Logger LOGGER
= Logger
.getLogger(ComparisonScopeBuilder
.class);
91 /** Function transforming an IResource into its URI. */
92 private static final Function
<IResource
, URI
> TO_FILE_URIS
= new Function
<IResource
, URI
>() {
93 public URI
apply(IResource input
) {
95 if (input
instanceof IStorage
) {
96 uri
= ResourceUtil
.asURI().apply((IStorage
)input
);
98 uri
= URI
.createPlatformResourceURI(input
.getFullPath().toString(), true);
105 * Constructs a builder given its model resolver and minimizer.
108 * The resolver we'll use to resolve the logical models of this scope.
110 * The minimizer that will be use to reduce the comparison scope before construction.
112 public ComparisonScopeBuilder(IModelResolver resolver
, IModelMinimizer minimizer
) {
113 this(resolver
, minimizer
, null);
117 * Constructs a builder given its model resolver and minimizer, along with the storage accessor for remote
121 * The resolver we'll use to resolve the logical models of this scope.
123 * The minimizer that will be use to reduce the comparison scope before construction.
124 * @param storageAccessor
125 * The storage accessor we'll use to access remote resource variants. May be <code>null</code>,
126 * in which case we'll only use local content.
128 public ComparisonScopeBuilder(IModelResolver resolver
, IModelMinimizer minimizer
,
129 IStorageProviderAccessor storageAccessor
) {
130 this.resolver
= checkNotNull(resolver
);
131 this.minimizer
= checkNotNull(minimizer
);
132 this.storageAccessor
= storageAccessor
;
136 * Builds a comparison scope from the given two starting elements.
139 * The element that will be used as the starting point to resolve the left logical model.
141 * Element that will be used as the starting point to resolve the left logical model.
143 * The monitor on which to report progress information to the user.
144 * @return The newly created comparison scope.
146 public IComparisonScope
build(ITypedElement left
, ITypedElement right
, IProgressMonitor monitor
) {
147 return build(left
, right
, null, monitor
);
151 * Builds a comparison scope from the given starting elements.
154 * The element that will be used as the starting point to resolve the left logical model.
156 * Element that will be used as the starting point to resolve the left logical model.
158 * The origin resource, starting point of the logical model we are to resolve as the origin
159 * one. Can be <code>null</code>.
161 * The monitor on which to report progress information to the user.
162 * @return The newly created comparison scope.
164 public IComparisonScope
build(ITypedElement left
, ITypedElement right
, ITypedElement origin
,
165 IProgressMonitor monitor
) {
166 SubMonitor subMonitor
= SubMonitor
.convert(monitor
, 100);
167 subMonitor
.subTask(EMFCompareIDEUIMessages
.getString("EMFSynchronizationModel.resolving")); //$NON-NLS-1$
169 final SynchronizationModel syncModel
;
170 if (storageAccessor
!= null) {
171 syncModel
= createSynchronizationModel(storageAccessor
, left
, right
, origin
,
172 subMonitor
.newChild(60));
174 syncModel
= createSynchronizationModel(left
, right
, origin
, subMonitor
.newChild(60));
177 return createMinimizedScope(left
, syncModel
, subMonitor
.newChild(40));
178 } catch (InterruptedException e
) {
179 Thread
.currentThread().interrupt();
180 EmptyComparisonScope scope
= new EmptyComparisonScope();
181 scope
.setDiagnostic(BasicDiagnostic
.toDiagnostic(e
));
187 * Resolves and minimizes the logical model for the given three typed element as would be done by
188 * {@link #build(ITypedElement, ITypedElement, ITypedElement, IProgressMonitor)}, but returns directly the
189 * SynchronizationModel DTO instead of the actual IComparisonScope.
191 * This internal API is only intended for use by the resource mapping mergers.
195 * The element that will be used as the starting point to resolve the left logical model.
197 * Element that will be used as the starting point to resolve the left logical model.
199 * The origin resource, starting point of the logical model we are to resolve as the origin
200 * one. Can be <code>null</code>.
202 * The monitor on which to report progress information to the user.
203 * @return The newly created SynchronizationModel.
204 * @throws InterruptedException
205 * In case of user interruption.
207 /* package */SynchronizationModel
buildSynchronizationModel(ITypedElement left
, ITypedElement right
,
208 ITypedElement origin
, IProgressMonitor monitor
) throws InterruptedException
{
209 if (LOGGER
.isDebugEnabled()) {
210 LOGGER
.debug("buildSynchronizationModel - START"); //$NON-NLS-1$
212 SubMonitor subMonitor
= SubMonitor
.convert(monitor
, 100);
213 subMonitor
.subTask(EMFCompareIDEUIMessages
.getString("EMFSynchronizationModel.resolving")); //$NON-NLS-1$
215 final SynchronizationModel syncModel
;
216 if (LOGGER
.isDebugEnabled()) {
217 LOGGER
.debug("buildSynchronizationModel - Creating sync model"); //$NON-NLS-1$
219 if (storageAccessor
!= null) {
220 syncModel
= createSynchronizationModel(storageAccessor
, left
, right
, origin
,
221 subMonitor
.newChild(90));
223 syncModel
= createSynchronizationModel(left
, right
, origin
, subMonitor
.newChild(90));
225 if (LOGGER
.isDebugEnabled()) {
226 LOGGER
.debug("buildSynchronizationModel - Minimizing model"); //$NON-NLS-1$
228 minimizer
.minimize(PlatformElementUtil
.findFile(left
), syncModel
, subMonitor
.newChild(10));
229 if (LOGGER
.isDebugEnabled()) {
230 LOGGER
.debug("buildSynchronizationModel - FINISH NORMALLY"); //$NON-NLS-1$
236 * Constructs the comparison scope corresponding to the given typed elements.
239 * Left of the compared elements.
241 * Right of the compared elements.
243 * Common ancestor of the <code>left</code> and <code>right</code> compared elements.
245 * Monitor to report progress on.
246 * @return The created comparison scope.
248 public static IComparisonScope
create(ICompareContainer container
, ITypedElement left
,
249 ITypedElement right
, ITypedElement origin
, IProgressMonitor monitor
) {
250 SubMonitor subMonitor
= SubMonitor
.convert(monitor
, 100);
251 Subscriber subscriber
= EMFCompareIDEUIPlugin
.getDefault().getSubscriberProviderRegistry()
252 .getSubscriber(container
, left
, right
, origin
, subMonitor
.split(10));
253 IStorageProviderAccessor storageAccessor
= null;
254 if (subscriber
!= null) {
255 storageAccessor
= new SubscriberStorageAccessor(subscriber
);
257 IStorage leftStorage
= PlatformElementUtil
.findFile(left
);
258 if (leftStorage
== null) {
259 leftStorage
= StreamAccessorStorage
.fromTypedElement(left
);
261 IModelResolver resolver
= EMFCompareIDEUIPlugin
.getDefault().getModelResolverRegistry()
262 .getBestResolverFor(leftStorage
);
263 final ComparisonScopeBuilder scopeBuilder
= new ComparisonScopeBuilder(resolver
,
264 EMFCompareIDEUIPlugin
.getDefault().getModelMinimizerRegistry().getCompoundMinimizer(),
266 return scopeBuilder
.build(left
, right
, origin
, subMonitor
.split(90));
270 * Creates the comparison scope corresponding to the given synchronization model, with no further
273 * This internal API is only intended for use by the resource mapping mergers and is not meant to be
277 * @param synchronizationModel
278 * The synchronization model describing the traversals for which a comparison scope is needed.
280 * Monitor on which to report progress information to the user.
281 * @return The created comparison scope.
282 * @throws OperationCanceledException
283 * if the user cancels (or has already canceled) the operation through the given
285 * @noreference This method is not intended to be referenced by clients.
287 public static IComparisonScope
create(SynchronizationModel synchronizationModel
, IProgressMonitor monitor
)
288 throws OperationCanceledException
{
289 if (monitor
.isCanceled()) {
290 throw new OperationCanceledException();
293 return createScope(synchronizationModel
, monitor
);
297 * Creates the synchronization model for the given three elements (left, right, and the common ancestor of
298 * the two). Since this comparison may concern either local or remote resources, all I/O operations should
299 * go through the given storage accessor.
302 * The accessor that can be used to retrieve synchronization information between our resources.
304 * Typed element used as the left side of this comparison.
306 * Typed element used as the right side of this comparison.
308 * Common ancestor of <code>left</code> and <code>right</code>.
310 * Monitor to report progress information on.
311 * @return The created synchronization model.
313 private SynchronizationModel
createSynchronizationModel(IStorageProviderAccessor accessor
,
314 ITypedElement left
, ITypedElement right
, ITypedElement origin
, IProgressMonitor monitor
)
315 throws InterruptedException
{
317 // Can we find a local file to associate a proper path to our storages?
318 final IFile localFile
= findFile(left
);
320 if (localFile
!= null) {
321 path
= localFile
.getFullPath().toString();
324 final IStorage leftStorage
= StreamAccessorStorage
.fromTypedElement(path
, left
);
325 final IStorage rightStorage
;
326 if (right
instanceof IStreamContentAccessor
) {
327 rightStorage
= StreamAccessorStorage
.fromTypedElement(path
, right
);
331 final IStorage originStorage
;
332 if (origin
instanceof IStreamContentAccessor
) {
333 originStorage
= StreamAccessorStorage
.fromTypedElement(path
, origin
);
335 originStorage
= null;
338 return resolver
.resolveModels(accessor
, leftStorage
, rightStorage
, originStorage
, monitor
);
342 * Creates the synchronization model for the given three elements (left, right, and their common
343 * ancestor). Since we have no remote data available, we'll consider that the three given files are either
344 * locally available, or that they have no logical model.
347 * Typed element used as the left side of this comparison.
349 * Typed element used as the right side of this comparison.
351 * Common ancestor of <code>left</code> and <code>right</code>.
353 * Monitor to report progress information on.
354 * @return The created synchronization model.
356 private SynchronizationModel
createSynchronizationModel(ITypedElement left
, ITypedElement right
,
357 ITypedElement origin
, IProgressMonitor monitor
) throws InterruptedException
{
358 // Is this a local comparison?
359 final IFile leftFile
= findFile(left
);
360 final IFile rightFile
= findFile(right
);
361 if (leftFile
!= null && rightFile
!= null) {
362 // assume origin is local or null
363 return resolver
.resolveLocalModels(leftFile
, rightFile
, findFile(origin
), monitor
);
366 // This is not a local comparison, and we've got no info on how to load remote revisions.
367 final IStorage leftStorage
= StreamAccessorStorage
.fromTypedElement(left
);
368 Assert
.isNotNull(leftStorage
);
369 final IStorage rightStorage
;
370 if (right
instanceof IStreamContentAccessor
) {
371 rightStorage
= StreamAccessorStorage
.fromTypedElement(right
);
375 final IStorage originStorage
;
376 if (origin
instanceof IStreamContentAccessor
) {
377 originStorage
= StreamAccessorStorage
.fromTypedElement(origin
);
379 originStorage
= null;
382 return loadSingleResource(leftStorage
, rightStorage
, originStorage
);
386 * We cannot resolve the logical model of these elements. Load them as single resources.
389 * Storage to be loaded as left.
391 * Storage to be loaded as right.
393 * Common ancestor of left and right, if any.
394 * @return The resolved synchronization model.
396 private SynchronizationModel
loadSingleResource(IStorage left
, IStorage right
, IStorage origin
) {
397 final StorageTraversal leftTraversal
= new StorageTraversal(
398 new LinkedHashSet
<IStorage
>(Arrays
.asList(left
)));
399 final StorageTraversal rightTraversal
;
401 rightTraversal
= new StorageTraversal(new LinkedHashSet
<IStorage
>(Arrays
.asList(right
)));
403 rightTraversal
= new StorageTraversal(Sets
.<IStorage
> newLinkedHashSet());
405 final StorageTraversal originTraversal
;
406 if (origin
!= null) {
407 originTraversal
= new StorageTraversal(new LinkedHashSet
<IStorage
>(Arrays
.asList(origin
)));
409 originTraversal
= new StorageTraversal(Sets
.<IStorage
> newLinkedHashSet());
412 return new SynchronizationModel(leftTraversal
, rightTraversal
, originTraversal
);
416 * Prepare the given synchronization model for use, then create the corresponding comparison scope.
419 * The element that has been used as the starting point to resolve the left logical model.
421 * The synchronization model describing our resource traversals.
423 * Monitor on which to report progress information to the user.
424 * @return The created comparison scope.
426 private IComparisonScope
createMinimizedScope(ITypedElement left
, SynchronizationModel syncModel
,
427 IProgressMonitor monitor
) {
428 if (monitor
.isCanceled()) {
429 throw new OperationCanceledException();
432 SubMonitor subMonitor
= SubMonitor
.convert(monitor
, 100);
433 // Minimize the traversals to non-read-only resources with no binary identical counterparts.
434 minimizer
.minimize(PlatformElementUtil
.findFile(left
), syncModel
, subMonitor
.newChild(10));
435 return createScope(syncModel
, subMonitor
.newChild(90));
439 * Constructs the actual comparison scope given the storage traversals from which to load the resources.
442 * The synchronization model describing our resource traversals.
444 * Monitor on which to report progress information to the user.
445 * @return The created comparison scope.
447 private static IComparisonScope
createScope(SynchronizationModel syncModel
, IProgressMonitor monitor
) {
448 SubMonitor progress
= SubMonitor
.convert(monitor
, 3);
449 progress
.subTask(EMFCompareIDEUIMessages
.getString("EMFSynchronizationModel.creatingScope")); //$NON-NLS-1$
451 final StorageTraversal leftTraversal
= syncModel
.getLeftTraversal();
452 final StorageTraversal rightTraversal
= syncModel
.getRightTraversal();
453 final StorageTraversal originTraversal
= syncModel
.getOriginTraversal();
455 final ResourceSet originResourceSet
;
456 ResourceSetHookRegistry resourceSetHookRegistry
= EMFCompareIDEPlugin
.getDefault()
457 .getResourceSetHookRegistry();
458 if (originTraversal
== null || originTraversal
.getStorages().isEmpty()) {
459 originResourceSet
= null;
460 progress
.setWorkRemaining(2);
462 originResourceSet
= NotLoadingResourceSet
.create(originTraversal
, progress
.newChild(1),
463 resourceSetHookRegistry
);
465 final ResourceSet leftResourceSet
= NotLoadingResourceSet
.create(leftTraversal
, progress
.newChild(1),
466 resourceSetHookRegistry
);
467 final ResourceSet rightResourceSet
= NotLoadingResourceSet
.create(rightTraversal
,
468 progress
.newChild(1), resourceSetHookRegistry
);
470 final URIConverter converter
= new ExtensibleURIConverterImpl();
471 final Set
<URI
> urisInScope
= Sets
.newLinkedHashSet();
472 for (IStorage left
: leftTraversal
.getStorages()) {
473 urisInScope
.add(converter
.normalize(createURIFor(left
)));
475 for (IStorage right
: rightTraversal
.getStorages()) {
476 urisInScope
.add(converter
.normalize(createURIFor(right
)));
478 if (originTraversal
!= null) {
479 for (IStorage origin
: originTraversal
.getStorages()) {
480 urisInScope
.add(converter
.normalize(createURIFor(origin
)));
484 final FilterComparisonScope scope
= new DefaultComparisonScope(leftResourceSet
, rightResourceSet
,
486 scope
.setResourceSetContentFilter(isInScope(urisInScope
));
488 final Set
<IResource
> involvedResources
= syncModel
.getAllInvolvedResources();
489 final Collection
<URI
> involvedResourceURIs
= transform(involvedResources
, TO_FILE_URIS
);
490 scope
.getAllInvolvedResourceURIs().addAll(involvedResourceURIs
);
492 Diagnostic syncModelDiagnostic
= syncModel
.getDiagnostic();
493 Diagnostic scopeDiagnostic
= computeDiagnostics(originResourceSet
, leftResourceSet
, rightResourceSet
);
495 BasicDiagnostic basicDiagnostic
= new BasicDiagnostic(Diagnostic
.OK
, EMFCompareIDEUIPlugin
.PLUGIN_ID
,
496 0, null, new Object
[0]);
498 basicDiagnostic
.add(syncModelDiagnostic
);
499 basicDiagnostic
.add(scopeDiagnostic
);
501 scope
.setDiagnostic(basicDiagnostic
);
505 private static Diagnostic
computeDiagnostics(final ResourceSet originResourceSet
,
506 final ResourceSet leftResourceSet
, final ResourceSet rightResourceSet
) {
507 final BasicDiagnostic originDiagnostic
;
508 if (originResourceSet
!= null) {
509 originDiagnostic
= getResourceSetDiagnostic(originResourceSet
, null, true);
511 originDiagnostic
= null;
513 BasicDiagnostic leftDiagnostic
= getResourceSetDiagnostic(leftResourceSet
, DifferenceSource
.LEFT
,
515 BasicDiagnostic rightDiagnostic
= getResourceSetDiagnostic(rightResourceSet
, DifferenceSource
.RIGHT
,
518 BasicDiagnostic diagnostic
= new BasicDiagnostic(Diagnostic
.OK
, EMFCompareIDEUIPlugin
.PLUGIN_ID
, 0,
519 EMFCompareIDEUIMessages
.getString("ComparisonScopeBuilder.comparisonScopeDiagnostic"), //$NON-NLS-1$
522 if (originDiagnostic
!= null) {
523 diagnostic
.add(originDiagnostic
);
525 diagnostic
.add(leftDiagnostic
);
526 diagnostic
.add(rightDiagnostic
);
532 * Compute the diagnotic on each resource of the given resource set and return a diagnostic composed of
537 * the resource set's side. null means origin
538 * @param includeWarning
539 * @return the composite diagnostic
541 private static BasicDiagnostic
getResourceSetDiagnostic(final ResourceSet resourceSet
,
542 DifferenceSource side
, boolean includeWarning
) {
543 final String sideStr
;
544 if (side
== DifferenceSource
.LEFT
) {
545 sideStr
= EMFCompareIDEUIMessages
.getString("ComparisonScopeBuilder.left"); //$NON-NLS-1$
546 } else if (side
== DifferenceSource
.RIGHT
) {
547 sideStr
= EMFCompareIDEUIMessages
.getString("ComparisonScopeBuilder.right"); //$NON-NLS-1$
549 sideStr
= EMFCompareIDEUIMessages
.getString("ComparisonScopeBuilder.ancestor"); //$NON-NLS-1$
551 BasicDiagnostic diagnostic
= new BasicDiagnostic(EMFCompareIDEUIPlugin
.PLUGIN_ID
, 0,
552 EMFCompareIDEUIMessages
.getString("ComparisonScopeBuilder.resourceSetDiagnostic", sideStr
), //$NON-NLS-1$
554 for (Resource resource
: resourceSet
.getResources()) {
555 Diagnostic resourceDiagnostic
= EcoreUtil
.computeDiagnostic(resource
, includeWarning
);
556 diagnostic
.merge(resourceDiagnostic
);
562 * Returns a predicate that can be applied to {@link Resource}s in order to check if their URI is
563 * contained in the given set.
566 * URIs that we consider to be in this scope.
567 * @return A useable Predicate.
569 private static Predicate
<Resource
> isInScope(final Set
<URI
> uris
) {
570 return new Predicate
<Resource
>() {
571 public boolean apply(Resource input
) {
572 final boolean result
;
574 URI inputUri
= input
.getURI();
575 if (uris
.contains(inputUri
)) {
577 } else if (input
.getResourceSet() != null
578 && input
.getResourceSet().getURIConverter() != null) {
579 // Tries to normalize the URI in case it is a pathmap uri that needs to be resolved
580 URI normalizedInputUri
= input
.getResourceSet().getURIConverter().normalize(inputUri
);
581 result
= uris
.contains(normalizedInputUri
);