You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ss...@apache.org on 2021/12/15 18:24:33 UTC

[sling-org-apache-sling-caconfig-impl] 01/02: cosmetic: eliminate some code warnings

This is an automated email from the ASF dual-hosted git repository.

sseifert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-caconfig-impl.git

commit 5ceec38a008eae891b5389f53b88e2c98edd026b
Author: Stefan Seifert <st...@users.noreply.github.com>
AuthorDate: Wed Dec 15 19:17:06 2021 +0100

    cosmetic: eliminate some code warnings
---
 .../impl/ConfigurationBuilderAdapterFactory.java   |  2 +-
 .../caconfig/impl/ConfigurationBuilderImpl.java    | 20 +++++++-----
 .../impl/metadata/AnnotationClassParser.java       | 38 ++++++++++++----------
 .../caconfig/management/impl/ValueInfoImpl.java    | 12 ++++---
 .../impl/console/CAConfigInventoryPrinter.java     | 25 +++++++-------
 .../ConfigurationBindingsValueProviderTest.java    |  2 ++
 .../caconfig/impl/metadata/BundleEventUtil.java    | 15 +++++----
 ...igurationManagerImplCustomPersistence2Test.java |  1 +
 ...tionPersistenceStrategyMultiplexerImplTest.java |  3 +-
 9 files changed, 64 insertions(+), 54 deletions(-)

diff --git a/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderAdapterFactory.java b/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderAdapterFactory.java
index 464b574..099a331 100644
--- a/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderAdapterFactory.java
+++ b/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderAdapterFactory.java
@@ -38,7 +38,7 @@ public class ConfigurationBuilderAdapterFactory implements AdapterFactory {
     private ConfigurationResolver resolver;
 
     @Override
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({ "unchecked", "null" })
     public <AdapterType> AdapterType getAdapter(@NotNull final Object adaptable, @NotNull final Class<AdapterType> type) {
         if (adaptable instanceof Resource && type == ConfigurationBuilder.class) {
             return (AdapterType) resolver.get((Resource) adaptable);
diff --git a/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java b/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
index 307de4e..c8e092e 100644
--- a/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
+++ b/src/main/java/org/apache/sling/caconfig/impl/ConfigurationBuilderImpl.java
@@ -66,7 +66,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
     private final String configName;
 
     private static final Logger log = LoggerFactory.getLogger(ConfigurationBuilderImpl.class);
-    
+
     public ConfigurationBuilderImpl(final Resource resource,
             final ConfigurationResolver configurationResolver,
             final ConfigurationResourceResolvingStrategy configurationResourceResolvingStrategy,
@@ -158,7 +158,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
     private <T> Collection<T> getConfigResourceCollection(String configName, Class<T> clazz, Converter<T> converter) {
         if (this.contentResource != null) {
            validateConfigurationName(configName);
-           
+
            // get all possible colection parent config names
            Collection<String> collectionParentConfigNames = configurationPersistenceStrategy.getAllCollectionParentConfigNames(configName);
            List<Iterator<Resource>> resourceInheritanceChains = new ArrayList<>();
@@ -183,7 +183,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
             return Collections.emptyList();
         }
     }
-    
+
     @SuppressWarnings("unchecked")
     private <T> T convert(final Iterator<Resource> resourceInhertianceChain, final Class<T> clazz, final Converter<T> converter,
             final String name, final boolean isCollection) {
@@ -223,15 +223,15 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
             log.trace("+ Found config resource for context path " + contentResource.getPath() + ": " + configResource.getPath() + " "
                     + MapUtil.traceOutput(configResource.getValueMap()));
         }
-        
+
         // if no config resource found still check for overrides
         if (configResource == null && contentResource != null) {
             configResource = configurationOverrideMultiplexer.overrideProperties(contentResource.getPath(), name, (Resource)null, contentResource.getResourceResolver());
         }
-        
+
         return converter.convert(configResource, clazz, conversionName, isCollection);
     }
-    
+
     /**
      * Apply default values from configuration metadata (where no real data is present).
      * @param resource Resource
@@ -248,7 +248,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
         }
         return new ConfigurationResourceWrapper(resource, new ValueMapDecorator(updatedMap));
     }
-    
+
     /**
      * Apply default values from configuration metadata (where no real data is present).
      * @param props Properties
@@ -283,6 +283,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
     // --- Annotation class support ---
 
     @Override
+    @SuppressWarnings("null")
     public @NotNull <T> T as(@NotNull final Class<T> clazz) {
         final String name = getConfigurationNameForAnnotationClass(clazz);
         if (log.isDebugEnabled()) {
@@ -336,7 +337,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
             });
         }
     }
-    
+
     // --- ValueMap support ---
 
     @Override
@@ -368,7 +369,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
             }
         }
     }
-    
+
     // --- Adaptable support ---
 
     @Override
@@ -388,6 +389,7 @@ class ConfigurationBuilderImpl implements ConfigurationBuilder {
     }
 
     private class AdaptableConverter<T> implements Converter<T> {
+        @SuppressWarnings("null")
         @Override
         public T convert(Resource resource, Class<T> clazz, String configName, boolean isCollection) {
             if (resource == null || clazz == ConfigurationBuilder.class) {
diff --git a/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java b/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java
index 38cfb7f..8b2520c 100644
--- a/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java
+++ b/src/main/java/org/apache/sling/caconfig/impl/metadata/AnnotationClassParser.java
@@ -39,9 +39,9 @@ import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
  * Helper methods for parsing metadata from configuration annotation classes.
  */
 public final class AnnotationClassParser {
-    
+
     private static final Pattern METHOD_NAME_MAPPING = Pattern.compile("(\\$\\$)|(\\$)|(__)|(_)");
-    
+
     private AnnotationClassParser() {
         // static methods only
     }
@@ -55,12 +55,13 @@ public final class AnnotationClassParser {
     public static boolean isContextAwareConfig(Class<?> clazz) {
         return clazz.isAnnotation() && clazz.isAnnotationPresent(Configuration.class);
     }
-    
+
     /**
      * Get configuration name for given configuration annotation class.
      * @param clazz Annotation class
      * @return Configuration name
      */
+    @SuppressWarnings("unused")
     public static String getConfigurationName(Class<?> clazz) {
         Configuration configAnnotation = clazz.getAnnotation(Configuration.class);
         if (configAnnotation == null) {
@@ -111,18 +112,19 @@ public final class AnnotationClassParser {
         matcher.appendTail(mappedName);
         return mappedName.toString();
     }
-    
+
     /**
      * Build configuration metadata by parsing the given annotation interface class and it's configuration annotations.
      * @param clazz Configuration annotation class
      * @return Configuration metadata
      */
+    @SuppressWarnings("unused")
     public static ConfigurationMetadata buildConfigurationMetadata(Class<?> clazz) {
         Configuration configAnnotation = clazz.getAnnotation(Configuration.class);
         if (configAnnotation == null) {
             throw new IllegalArgumentException("Class has not @Configuration annotation: " + clazz.getName());
         }
-        
+
         // configuration metadata and property metadata
         String configName = getConfigurationName(clazz, configAnnotation);
         ConfigurationMetadata configMetadata = new ConfigurationMetadata(configName,
@@ -131,10 +133,10 @@ public final class AnnotationClassParser {
                 .label(emptyToNull(configAnnotation.label()))
                 .description(emptyToNull(configAnnotation.description()))
                 .properties(propsArrayToMap(configAnnotation.property()));
-        
+
         return configMetadata;
     }
-    
+
     /**
      * Build configuration metadata by parsing the given annotation interface class which is used for nested configurations.
      * @param clazz Configuration annotation class
@@ -145,7 +147,7 @@ public final class AnnotationClassParser {
                 buildConfigurationMetadata_PropertyMetadata(clazz),
                 collection);
     }
-    
+
     private static Collection<PropertyMetadata<?>> buildConfigurationMetadata_PropertyMetadata(Class<?> clazz) {
         // sort properties by order number, or alternatively by label, name
         SortedSet<PropertyMetadata<?>> propertyMetadataSet = new TreeSet<>(new Comparator<PropertyMetadata<?>>() {
@@ -167,11 +169,11 @@ public final class AnnotationClassParser {
         }
         return propertyMetadataSet;
     }
-    
-    @SuppressWarnings("unchecked")
+
+    @SuppressWarnings({ "unchecked", "unused" })
     private static <T> PropertyMetadata<T> buildPropertyMetadata(Method propertyMethod, Class<T> type) {
         String propertyName = getPropertyName(propertyMethod.getName());
-        
+
         PropertyMetadata<?> propertyMetadata;
         if (type.isArray() && type.getComponentType().isAnnotation()) {
             ConfigurationMetadata nestedConfigMetadata = buildConfigurationMetadata_Nested(type.getComponentType(), propertyName, true);
@@ -184,12 +186,12 @@ public final class AnnotationClassParser {
                     .configurationMetadata(nestedConfigMetadata);
         }
         else {
-            propertyMetadata = new PropertyMetadata<>(propertyName, type)            
+            propertyMetadata = new PropertyMetadata<>(propertyName, type)
                     .defaultValue((T)propertyMethod.getDefaultValue());
         }
-        
+
         Property propertyAnnotation = propertyMethod.getAnnotation(Property.class);
-        if (propertyAnnotation != null) {            
+        if (propertyAnnotation != null) {
             propertyMetadata.label(emptyToNull(propertyAnnotation.label()))
                 .description(emptyToNull(propertyAnnotation.description()))
                 .properties(propsArrayToMap(propertyAnnotation.property()))
@@ -199,10 +201,10 @@ public final class AnnotationClassParser {
             Map<String,String> emptyMap = Collections.emptyMap();
             propertyMetadata.properties(emptyMap);
         }
-        
+
         return (PropertyMetadata)propertyMetadata;
     }
-    
+
     private static String emptyToNull(String value) {
         if (StringUtils.isEmpty(value)) {
             return null;
@@ -211,7 +213,7 @@ public final class AnnotationClassParser {
             return value;
         }
     }
-    
+
     private static Map<String,String> propsArrayToMap(String[] properties) {
         Map<String,String> props = new HashMap<>();
         for (String property : properties) {
@@ -224,5 +226,5 @@ public final class AnnotationClassParser {
         }
         return props;
     }
-    
+
 }
diff --git a/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java b/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java
index 4860080..ba4d16a 100644
--- a/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java
+++ b/src/main/java/org/apache/sling/caconfig/management/impl/ValueInfoImpl.java
@@ -31,7 +31,7 @@ import org.apache.sling.caconfig.spi.metadata.PropertyMetadata;
 import org.jetbrains.annotations.NotNull;
 
 final class ValueInfoImpl<T> implements ValueInfo<T> {
-    
+
     private final String name;
     private final T value;
     private final T effectiveValue;
@@ -44,7 +44,8 @@ final class ValueInfoImpl<T> implements ValueInfo<T> {
     private final String configName;
     private final ConfigurationOverrideMultiplexer configurationOverrideMultiplexer;
     private final boolean isAllOverridden;
-    
+
+    @SuppressWarnings("null")
     public ValueInfoImpl(String name, T value, T effectiveValue, PropertyMetadata<T> propertyMetadata,
             Resource resolvedConfigurationResource, Resource writebackConfigurationResource,
             List<Resource> configurationResourceInheritanceChain,
@@ -63,12 +64,12 @@ final class ValueInfoImpl<T> implements ValueInfo<T> {
         this.configurationOverrideMultiplexer = configurationOverrideMultiplexer;
         this.isAllOverridden = isAllOverridden;
     }
-    
+
     @Override
     public @NotNull String getName() {
         return name;
     }
- 
+
     @Override
     public PropertyMetadata<T> getPropertyMetadata() {
         return propertyMetadata;
@@ -132,7 +133,7 @@ final class ValueInfoImpl<T> implements ValueInfo<T> {
             }
         }
     }
-    
+
     private Resource getResourceFromInheritanceChain() {
         if (configurationResourceInheritanceChain == null) {
             return null;
@@ -140,6 +141,7 @@ final class ValueInfoImpl<T> implements ValueInfo<T> {
         return getResourceFromInheritanceChain(configurationResourceInheritanceChain.iterator());
     }
 
+    @SuppressWarnings("null")
     private Resource getResourceFromInheritanceChain(Iterator<Resource> inheritanceChain) {
         if (!inheritanceChain.hasNext()) {
             return null;
diff --git a/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java b/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java
index d477b2b..e2ec366 100644
--- a/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java
+++ b/src/main/java/org/apache/sling/caconfig/management/impl/console/CAConfigInventoryPrinter.java
@@ -58,14 +58,14 @@ public class CAConfigInventoryPrinter implements InventoryPrinter {
 
     public static final String NAME = "slingcaconfig";
     public static final String TITLE = "Sling Context-Aware Configuration";
-    
+
     private BundleContext bundleContext;
-    
+
     @Activate
     private void activate(BundleContext bundleContext) {
         this.bundleContext = bundleContext;
     }
-    
+
     @Override
     public void print(PrintWriter pw, Format format, boolean isZip) {
         if (format != Format.TEXT) {
@@ -83,20 +83,20 @@ public class CAConfigInventoryPrinter implements InventoryPrinter {
         printSPISection(pw, ConfigurationOverrideProvider.class, "Configuration Override Providers",
                 new ConfigurationOverridePrinter());
     }
-    
+
     @SafeVarargs
     private final <T> void printSPISection(PrintWriter pw, Class<T> clazz, String title, ServiceConfigurationPrinter<T>... serviceConfigPrinters) {
         Collection<ServiceReference<T>> serviceReferences = getServiceReferences(clazz);
 
         pw.println(title);
         pw.println(StringUtils.repeat('-', title.length()));
-        
+
         if (serviceReferences.isEmpty()) {
             pw.println("(none)");
         }
         else {
             for (ServiceReference<T> serviceReference : serviceReferences) {
-                pw.print(ServiceConfigurationPrinter.BULLET); 
+                pw.print(ServiceConfigurationPrinter.BULLET);
                 pw.print(getServiceClassName(serviceReference));
                 pw.print(" [");
                 pw.print(getServiceRanking(serviceReference));
@@ -112,7 +112,7 @@ public class CAConfigInventoryPrinter implements InventoryPrinter {
         }
         pw.println();
     }
-    
+
     private <T> Collection<ServiceReference<T>> getServiceReferences(Class<T> clazz) {
         try {
             SortedMap<Comparable<Object>,ServiceReference<T>> sortedServices = new TreeMap<>();
@@ -121,7 +121,7 @@ public class CAConfigInventoryPrinter implements InventoryPrinter {
                 Map<String,Object> props = new HashMap<>();
                 for (String property : serviceReference.getPropertyKeys()) {
                     props.put(property, serviceReference.getProperty(property));
-                } 
+                }
                 sortedServices.put(
                         ServiceUtil.getComparableForServiceRanking(props, Order.DESCENDING),
                         serviceReference
@@ -133,14 +133,15 @@ public class CAConfigInventoryPrinter implements InventoryPrinter {
             throw new RuntimeException(ex);
         }
     }
-    
+
+    @SuppressWarnings("null")
     private <T> String getServiceClassName(ServiceReference<T> serviceReference) {
         Object service = bundleContext.getService(serviceReference);
         String serviceClassName = service.getClass().getName();
         bundleContext.ungetService(serviceReference);
         return serviceClassName;
     }
-    
+
     private <T> int getServiceRanking(ServiceReference<T> serviceReference) {
         Object serviceRanking = serviceReference.getProperty(Constants.SERVICE_RANKING);
         if (serviceRanking == null) {
@@ -157,10 +158,10 @@ public class CAConfigInventoryPrinter implements InventoryPrinter {
     }
 
     private <T> boolean isEnabled(ServiceReference<T> serviceReference) {
-        Object enabledObject = (Object)serviceReference.getProperty("enabled");
+        Object enabledObject = serviceReference.getProperty("enabled");
         if (enabledObject != null) {
             if (enabledObject instanceof Boolean) {
-                return ((Boolean)enabledObject).booleanValue();            
+                return ((Boolean)enabledObject).booleanValue();
             }
             else {
                 return BooleanUtils.toBoolean(enabledObject.toString());
diff --git a/src/test/java/org/apache/sling/caconfig/impl/ConfigurationBindingsValueProviderTest.java b/src/test/java/org/apache/sling/caconfig/impl/ConfigurationBindingsValueProviderTest.java
index c4836f5..3f14b1b 100644
--- a/src/test/java/org/apache/sling/caconfig/impl/ConfigurationBindingsValueProviderTest.java
+++ b/src/test/java/org/apache/sling/caconfig/impl/ConfigurationBindingsValueProviderTest.java
@@ -80,6 +80,7 @@ public class ConfigurationBindingsValueProviderTest {
     private ConfigurationBindingsValueProvider underTest;
 
     @Before
+    @SuppressWarnings("null")
     public void setUp() {
         context.registerInjectActivateService(new ConfigurationMetadataProviderMultiplexerImpl());
         context.registerService(ConfigurationMetadataProvider.class, configMetadataProvider);
@@ -114,6 +115,7 @@ public class ConfigurationBindingsValueProviderTest {
     }
 
     @Test
+    @SuppressWarnings("null")
     public void testNoResource() {
         when(request.getResource()).thenReturn(null);
         underTest = context.registerInjectActivateService(new ConfigurationBindingsValueProvider(), "enabled", true);
diff --git a/src/test/java/org/apache/sling/caconfig/impl/metadata/BundleEventUtil.java b/src/test/java/org/apache/sling/caconfig/impl/metadata/BundleEventUtil.java
index 84edd30..6c15294 100644
--- a/src/test/java/org/apache/sling/caconfig/impl/metadata/BundleEventUtil.java
+++ b/src/test/java/org/apache/sling/caconfig/impl/metadata/BundleEventUtil.java
@@ -46,15 +46,15 @@ import org.osgi.framework.Version;
  * Helper methods for simulating events when deploying bundles with configuration annotation classes.
  */
 final class BundleEventUtil {
-    
-    private static final AtomicLong BUNDLE_COUNTER = new AtomicLong(); 
-    
+
+    private static final AtomicLong BUNDLE_COUNTER = new AtomicLong();
+
     private BundleEventUtil() {
         // static methods only
     }
 
     /**
-     * Simulate a bundle STARTED event with a given set of classes simulated to be found in the bundle's classpath. 
+     * Simulate a bundle STARTED event with a given set of classes simulated to be found in the bundle's classpath.
      */
     public static Bundle startDummyBundle(BundleContext bundleContext, Class... classes) {
         DummyBundle bundle = new DummyBundle(bundleContext, classes);
@@ -65,7 +65,7 @@ final class BundleEventUtil {
     }
 
     /**
-     * Simulate a bundle STARTED event with a given set of classes simulated to be found in the bundle's classpath. 
+     * Simulate a bundle STARTED event with a given set of classes simulated to be found in the bundle's classpath.
      */
     public static void stopDummyBundle(Bundle bundle) {
         ((DummyBundle)bundle).setState(Bundle.RESOLVED);
@@ -85,7 +85,7 @@ final class BundleEventUtil {
             this.bundleContext = bundleContext;
             this.classes = classes;
             this.bundleId = BUNDLE_COUNTER.incrementAndGet();
-            
+
             StringBuilder sb = new StringBuilder();
             for (Class clazz : classes) {
                 sb.append(clazz.getName()).append(",");
@@ -97,7 +97,7 @@ final class BundleEventUtil {
         public int getState() {
             return this.state;
         }
-        
+
         public void setState(int state) {
             this.state = state;
         }
@@ -247,6 +247,7 @@ final class BundleEventUtil {
         }
 
         @Override
+        @SuppressWarnings("null")
         public <A> A adapt(Class<A> type) {
             return null;
         }
diff --git a/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence2Test.java b/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence2Test.java
index 739dba8..0f4f4ff 100644
--- a/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence2Test.java
+++ b/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationManagerImplCustomPersistence2Test.java
@@ -38,6 +38,7 @@ import org.osgi.service.cm.ConfigurationAdmin;
 public class ConfigurationManagerImplCustomPersistence2Test extends ConfigurationManagerImplTest {
 
     @Override
+    @SuppressWarnings("null")
     protected void provideCustomOsgiConfig() throws Exception {
         // provide custom lookup resource name for collection properties
         ConfigurationAdmin configAdmin = context.getService(ConfigurationAdmin.class);
diff --git a/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImplTest.java b/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImplTest.java
index dddec63..2319db1 100644
--- a/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImplTest.java
+++ b/src/test/java/org/apache/sling/caconfig/management/impl/ConfigurationPersistenceStrategyMultiplexerImplTest.java
@@ -30,7 +30,6 @@ import org.apache.sling.caconfig.impl.def.DefaultConfigurationPersistenceStrateg
 import org.apache.sling.caconfig.management.multiplexer.ConfigurationPersistenceStrategyMultiplexer;
 import org.apache.sling.caconfig.spi.ConfigurationCollectionPersistData;
 import org.apache.sling.caconfig.spi.ConfigurationPersistData;
-import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy;
 import org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy2;
 import org.apache.sling.testing.mock.osgi.MapUtil;
 import org.apache.sling.testing.mock.osgi.MockOsgi;
@@ -97,7 +96,7 @@ public class ConfigurationPersistenceStrategyMultiplexerImplTest {
     public void testMultipleStrategies() {
 
         // strategy 1 (using old ConfigurationPersistenceStrategy with bridge to ConfigurationPersistenceStrategy2)
-        ConfigurationPersistenceStrategy oldStrategy = context.registerService(org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy.class,
+        org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy oldStrategy = context.registerService(org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy.class,
                 new org.apache.sling.caconfig.spi.ConfigurationPersistenceStrategy() {
             @Override
             public Resource getResource(@NotNull Resource resource) {