@Override protected void validateMergedComponent(final ObjectContent<FieldsInfo> objectContent) { final Map<String, FieldInfo<?>> fieldInfoMap = objectContent.getObject().getFieldConfig(); assertThat(fieldInfoMap.keySet(), hasSize(3)); assertThat(fieldInfoMap, hasKey("someField")); final FieldInfo<?> someField = fieldInfoMap.get("someField"); assertThat(someField.getNames(), hasSize(2)); assertEquals(FieldType.STRING, someField.getType()); assertEquals("SomeValue", someField.getValues().get(0).getValue()); assertEquals("Some Value", someField.getValues().get(0).getDisplayValue()); assertThat(fieldInfoMap, hasKey("someNumberField")); final FieldInfo<?> numberField = fieldInfoMap.get("someNumberField"); assertThat(numberField.getNames(), empty()); assertEquals(FieldType.STRING, numberField.getType()); assertFalse(numberField.isAdvanced()); }
@Override protected void validateMergedComponent(final ObjectContent<TimeLastRefreshedWidget> objectContent) { objectContent.assertThat().isEqualTo( TimeLastRefreshedWidget.builder() .name("Test Widget") .type("TimeLastRefreshedWidget") .x(1) .y(1) .width(1) .height(1) .widgetSettings(TimeLastRefreshedWidgetSettings.builder() .dateFormat("HH:mm z") .timeZone("Europe/London") .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<StaticContentWidget> objectContent) { objectContent.assertThat().isEqualTo( StaticContentWidget.builder() .name("") .type("StaticContentWidget") .x(1) .y(1) .width(2) .height(2) .widgetSettings(StaticContentWidgetSettings.builder() .html("<div><p style=\"font-weight: bold; font-style: italic\">I love cheese</p><p>cheese is the best</p></div>") .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<StaticContentWidget> objectContent) { objectContent.assertThat().isEqualTo( StaticContentWidget.builder() .name("Test Widget") .type("StaticContentWidget") .x(1) .y(1) .width(1) .height(1) .widgetSettings(StaticContentWidgetSettings.builder() .html("Hello World!") .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<SunburstWidget> objectContent) { objectContent.assertThat().isEqualTo( SunburstWidget.builder() .name("Sunburst Widget") .type("SunburstWidget") .x(0) .y(4) .width(5) .height(2) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(769L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(SunburstWidgetSettings.builder() .firstField(tagNameFactory.buildTagName("CONTENT-TYPE")) .secondField(tagNameFactory.buildTagName("AUTHOR")) .maxLegendEntries(7) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<SunburstWidget> objectContent) { objectContent.assertThat().isEqualTo( SunburstWidget.builder() .name("Test Widget") .type("SunburstWidget") .x(1) .y(1) .width(1) .height(1) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(123L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(SunburstWidgetSettings.builder() .firstField(tagNameFactory.buildTagName("CONTENT_TYPE")) .secondField(tagNameFactory.buildTagName("AUTHOR")) .maxLegendEntries(5) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<CurrentTimeWidget> objectContent) { objectContent.assertThat().isEqualTo( CurrentTimeWidget.builder() .name("Test Widget") .type("CurrentTimeWidget") .x(1) .y(1) .width(1) .height(1) .widgetSettings(CurrentTimeWidgetSettings.builder() .dateFormat("ll") .timeFormat("HH:mm z") .timeZone("Europe/London") .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<TopicMapWidget> objectContent) { objectContent.assertThat().isEqualTo( TopicMapWidget.builder() .name("TopicMap") .type("TopicMapWidget") .x(1) .y(1) .width(2) .height(2) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(97L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(TopicMapWidgetSettings.builder() .maxResults(1000) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<TopicMapWidget> objectContent) { objectContent.assertThat().isEqualTo( TopicMapWidget.builder() .name("Test Widget") .type("TopicMapWidget") .x(1) .y(1) .width(1) .height(1) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(123L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(TopicMapWidgetSettings.builder() .maxResults(1000) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<StaticImageWidget> objectContent) { objectContent.assertThat().isEqualTo( StaticImageWidget.builder() .name("Static Image") .type("StaticImageWidget") .x(1) .y(1) .width(2) .height(2) .widgetSettings(StaticImageWidgetSettings.builder() .url("http://placehold.it/800x300") .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<StaticImageWidget> objectContent) { objectContent.assertThat().isEqualTo( StaticImageWidget.builder() .name("Test Widget") .type("StaticImageWidget") .x(1) .y(1) .width(1) .height(1) .widgetSettings(StaticImageWidgetSettings.builder() .url("http://placehold.it/800x300") .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<SimpleWidget> objectContent) { objectContent.assertThat().isEqualTo( SimpleWidget.builder() .name("Test Widget") .type("StaticContentWidget") .x(1) .y(1) .width(1) .height(1) .displayWidgetName(WidgetNameSetting.always) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(123L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(SimpleWidgetSettings.builder() .widgetSetting("content", "Hello World!") .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<ResultsListWidget> objectContent) { objectContent.assertThat().isEqualTo( ResultsListWidget.builder() .name("List") .type("ResultsListWidget") .x(1) .y(1) .width(2) .height(2) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(97L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(ResultsListWidgetSettings.builder() .maxResults(6) .sort("random") .columnLayout(true) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<ResultsListWidget> objectContent) { objectContent.assertThat().isEqualTo( ResultsListWidget.builder() .name("Test Widget") .type("ResultsListWidget") .x(1) .y(1) .width(1) .height(1) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(123L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(ResultsListWidgetSettings.builder() .maxResults(6) .sort("random") .columnLayout(true) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<Dashboard> objectContent) { objectContent.assertThat().isEqualTo( Dashboard.builder() .dashboardName("My First Dashboard") .enabled(true) .width(5) .height(5) .widget(SimpleWidget.builder() .name("Sample Widget") .x(0) .y(0) .width(1) .height(1) .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<TemplatesConfig> objectContent) { assertThat(objectContent.getObject().getSearchResult(), hasItem(Template.builder() .file("some_file.tmpl") .triggers(Arrays.asList(Trigger.builder() .field("some_idol_field") .values(Collections.singletonList("some_value")) .build(), Trigger.builder() .field("some_other_idol_field") .values(Arrays.asList("some_value", "some_other_value")) .build())) .build() )); assertThat(objectContent.getObject().getPreviewPanel(), hasItem(Template.builder() .file("some_file.tmpl") .triggers(Arrays.asList(Trigger.builder() .field("some_idol_field") .values(Collections.singletonList("some_value")) .build(), Trigger.builder() .field("some_other_idol_field") .values(Arrays.asList("some_value", "some_other_value")) .build())) .build() )); }
@Override protected void validateParsedComponent(final ObjectContent<ViewConfig> objectContent) { objectContent.assertThat().hasFieldOrPropertyWithValue("protocol", AciServerDetails.TransportProtocol.HTTP); objectContent.assertThat().hasFieldOrPropertyWithValue("host", "localhost"); objectContent.assertThat().hasFieldOrPropertyWithValue("port", 9080); objectContent.assertThat().hasFieldOrPropertyWithValue("referenceField", "DREREFERENCE"); objectContent.assertThat().hasFieldOrPropertyWithValue("viewingMode", ViewingMode.FIELD); objectContent.assertThat().hasFieldOrPropertyWithValue("highlighting", true); assertThat(objectContent.getObject().getProductType(), hasSize(3)); final ServerConfig connector = objectContent.getObject().getConnector(); assertThat(connector.getProtocol(), is(AciServerDetails.TransportProtocol.HTTP)); assertThat(connector.getHost(), is("localhost")); assertThat(connector.getPort(), is(10000)); assertThat(Objects.toString(connector.getProductTypeRegex()), is(".*?CONNECTOR")); }
@Override protected void validateMergedComponent(final ObjectContent<ViewConfig> objectContent) { objectContent.assertThat().hasFieldOrPropertyWithValue("protocol", AciServerDetails.TransportProtocol.HTTPS); objectContent.assertThat().hasFieldOrPropertyWithValue("host", "localhost"); objectContent.assertThat().hasFieldOrPropertyWithValue("port", 9080); objectContent.assertThat().hasFieldOrPropertyWithValue("referenceField", "DREREFERENCE"); objectContent.assertThat().hasFieldOrPropertyWithValue("viewingMode", ViewingMode.CONNECTOR); objectContent.assertThat().hasFieldOrPropertyWithValue("highlighting", false); assertThat(objectContent.getObject().getProductType(), hasSize(3)); final ServerConfig connector = objectContent.getObject().getConnector(); assertThat(connector.getProtocol(), is(AciServerDetails.TransportProtocol.HTTP)); assertThat(connector.getHost(), is("localhost")); assertThat(connector.getPort(), is(10000)); assertThat(Objects.toString(connector.getProductTypeRegex()), is(".*?CONNECTOR")); }
@Override protected void validateParsedComponent(final ObjectContent<QueryManipulation> objectContent) { assertThat(objectContent.getObject().getServer().getProductType(), hasSize(3)); objectContent.assertThat().hasFieldOrPropertyWithValue("typeAheadMode", ModeParam.Index); objectContent.assertThat().hasFieldOrPropertyWithValue("expandQuery", true); objectContent.assertThat().hasFieldOrPropertyWithValue("blacklist", "ISO_BLACKLIST"); objectContent.assertThat().hasFieldOrPropertyWithValue("enabled", false); }
@Override protected void validateMergedComponent(final ObjectContent<QueryManipulation> objectContent) { assertThat(objectContent.getObject().getServer().getProductType(), hasSize(3)); objectContent.assertThat().hasFieldOrPropertyWithValue("typeAheadMode", ModeParam.Index); objectContent.assertThat().hasFieldOrPropertyWithValue("expandQuery", true); objectContent.assertThat().hasFieldOrPropertyWithValue("blacklist", "ISO_Blacklist"); objectContent.assertThat().hasFieldOrPropertyWithValue("enabled", true); }
@Override protected void validateParsedComponent(final ObjectContent<AnswerServerConfig> objectContent) { assertThat(objectContent.getObject().getServer().getProtocol(), is(AciServerDetails.TransportProtocol.HTTP)); assertThat(objectContent.getObject().getServer().getHost(), is("localhost")); assertThat(objectContent.getObject().getServer().getPort(), is(7700)); assertThat(objectContent.getObject().getServer().getProductType(), hasSize(1)); assertThat(objectContent.getObject().getSystemNames(), hasSize(1)); objectContent.assertThat().hasFieldOrPropertyWithValue("enabled", true); }
@Override protected void validateMergedComponent(final ObjectContent<AnswerServerConfig> objectContent) { assertThat(objectContent.getObject().getServer().getProtocol(), is(AciServerDetails.TransportProtocol.HTTP)); assertThat(objectContent.getObject().getServer().getHost(), is("localhost")); assertThat(objectContent.getObject().getServer().getPort(), is(7000)); assertThat(objectContent.getObject().getServer().getProductType(), hasSize(1)); assertThat(objectContent.getObject().getSystemNames(), hasSize(1)); objectContent.assertThat().hasFieldOrPropertyWithValue("enabled", true); }
@Override protected void validateParsedComponent(final ObjectContent<FieldsInfo> objectContent) { final Map<String, FieldInfo<?>> fieldInfoMap = objectContent.getObject().getFieldConfig(); assertThat(fieldInfoMap, hasKey("someField")); final FieldInfo<?> someField = fieldInfoMap.get("someField"); assertThat(someField.getNames(), hasSize(2)); assertEquals(FieldType.STRING, someField.getType()); assertEquals("SomeValue", someField.getValues().get(0).getValue()); assertEquals("Some Value", someField.getValues().get(0).getDisplayValue()); assertThat(fieldInfoMap, hasKey("someNumberField")); final FieldInfo<?> numberField = fieldInfoMap.get("someNumberField"); assertThat(numberField.getNames(), hasSize(1)); assertEquals(FieldType.NUMBER, numberField.getType()); assertTrue(numberField.isAdvanced()); }
@Test public void testDeserialize() throws Exception { ObjectContent<Submission> deserializedSub = this.json.parse(exampleJson); Submission actualSubmission = deserializedSub.getObject(); assertThat(actualSubmission.getTeam()) .isEqualTo(submissionEnvelope.getSubmission().getTeam()); assertThat(actualSubmission.getSubmitter()) .isEqualTo(submissionEnvelope.getSubmission().getSubmitter()); assertThat(actualSubmission.getSubmissionDate()) .isEqualTo(submissionEnvelope.getSubmission().getSubmissionDate()); }
@Override protected void validateParsedComponent(final ObjectContent<HodConfig> objectContent) { final HodConfig component = objectContent.getObject(); assertThat(component.getApiKey(), is(new ApiKey("api-key-123"))); assertThat(component.getPublicIndexesEnabled(), is(false)); assertThat(component.getActiveIndexes(), is(empty())); assertThat(component.getSsoPageGetUrl().toString(), is("https://dev.int.havenapps.io/sso.html")); assertThat(component.getEndpointUrl(), is(nullValue())); }
@Override protected void validateMergedComponent(final ObjectContent<HodConfig> objectContent) { final HodConfig mergedComponent = objectContent.getObject(); assertThat(mergedComponent.getApiKey(), is(new ApiKey("api-key-abc"))); assertThat(mergedComponent.getPublicIndexesEnabled(), is(true)); assertThat(mergedComponent.getActiveIndexes(), hasItem(ResourceName.WIKI_CHI)); assertThat(mergedComponent.getSsoPageGetUrl().toString(), is("https://dev.havenapps.io/sso.html")); assertThat(mergedComponent.getEndpointUrl().toString(), is("https://api.int.havenondemand.com")); }
@Override protected void validateParsedComponent(final ObjectContent<TimeLastRefreshedWidget> objectContent) { objectContent.assertThat().isEqualTo( TimeLastRefreshedWidget.builder() .name("Time Last Refreshed") .type("TimeLastRefreshedWidget") .x(1) .y(1) .width(1) .height(1) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<TrendingWidget> objectContent) { objectContent.assertThat().isEqualTo( TrendingWidget.builder() .name("Test trending chart") .type("TrendingWidget") .x(0) .y(4) .width(5) .height(2) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(769L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(TrendingWidgetSettings.builder() .parametricField(tagNameFactory.buildTagName("OVERALL_VIBE")) .dateField(tagNameFactory.buildTagName("AUTN_DATE")) .maxValues(7) .numberOfBuckets(10) .minDate(ZonedDateTime.parse("2009-04-05T00:00:00Z[UTC]")) .maxDate(ZonedDateTime.parse("2010-04-05T00:00:00Z[UTC]")) .values(Arrays.asList(new TrendingWidgetSettings.TrendingValue("POSITIVE", "green"), new TrendingWidgetSettings.TrendingValue("NEGATIVE", "red"))) .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<TrendingWidget> objectContent) { objectContent.assertThat().isEqualTo( TrendingWidget.builder() .name("Test Widget") .type("TrendingWidget") .x(1) .y(1) .width(1) .height(1) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(123L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(TrendingWidgetSettings.builder() .parametricField(tagNameFactory.buildTagName("CONTENT_TYPE")) .dateField(tagNameFactory.buildTagName("AUTN_DATE")) .maxValues(5) .numberOfBuckets(12) .minDate(ZonedDateTime.parse("2009-04-05T00:00:00Z")) .maxDate(ZonedDateTime.parse("2010-04-05T00:00:00Z")) .values(Arrays.asList(new TrendingWidgetSettings.TrendingValue("POSITIVE", "green"), new TrendingWidgetSettings.TrendingValue("NEGATIVE", "red"))) .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<CurrentTimeWidget> objectContent) { objectContent.assertThat().isEqualTo( CurrentTimeWidget.builder() .name("Current Time Date") .type("CurrentTimeWidget") .x(1) .y(1) .width(2) .height(2) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<VideoWidget> objectContent) { objectContent.assertThat().isEqualTo( VideoWidget.builder() .name("Video Widget") .type("VideoWidget") .x(1) .y(1) .width(2) .height(2) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(193L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(VideoWidgetSettings.builder() .loop(true) .audio(true) .searchResultNumber(1) .restrictSearch(true) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<VideoWidget> objectContent) { objectContent.assertThat().isEqualTo( VideoWidget.builder() .name("Test Widget") .type("VideoWidget") .x(1) .y(1) .width(1) .height(1) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(123L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(VideoWidgetSettings.builder() .loop(true) .audio(true) .searchResultNumber(1) .restrictSearch(true) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<MapWidget> objectContent) { objectContent.assertThat().isEqualTo( MapWidget.builder() .name("Map") .type("MapWidget") .x(1) .y(1) .width(2) .height(2) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(290L) .type(SavedSearchType.SNAPSHOT) .build()) .build()) .widgetSettings(MapWidgetSettings.builder() .maxResults(1000) .locationFieldPairs(Arrays.asList("DefaultLocation", "Secret Lair")) .centerCoordinates(new InitialLocation(51.5, 0.12)) .zoomLevel(3) .clusterMarkers(true) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<MapWidget> objectContent) { objectContent.assertThat().isEqualTo( MapWidget.builder() .name("Test Widget") .type("MapWidget") .x(1) .y(1) .width(1) .height(1) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(123L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(MapWidgetSettings.builder() .maxResults(1000) .locationFieldPairs(Arrays.asList("DefaultLocation", "Secret Lair")) .centerCoordinates(new InitialLocation(51.5, 0.12)) .zoomLevel(3) .clusterMarkers(true) .widgetSetting("testing", "testing") .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<SimpleWidget> objectContent) { objectContent.assertThat().isEqualTo( SimpleWidget.builder() .name("Default Widget") .type("ClockWidget") .x(0) .y(0) .width(1) .height(1) .displayWidgetName(WidgetNameSetting.never) .widgetSettings(SimpleWidgetSettings.builder().build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<Dashboard> objectContent) { objectContent.assertThat().isEqualTo( Dashboard.builder() .dashboardName("Default Dashboard") .enabled(false) .width(3) .height(3) .widget(SimpleWidget.builder() .name("Default Widget") .type("ClockWidget") .x(0) .y(0) .width(1) .height(1) .widgetSettings(SimpleWidgetSettings.builder().build()) .build()) .widget(SunburstWidget.builder() .name("star 769 (content type/author) 7 entries") .type("SunburstWidget") .x(0) .y(4) .width(5) .height(2) .datasource(SavedSearch.builder() .source("SavedSearch") .config(SavedSearchConfig.builder() .id(769L) .type(SavedSearchType.QUERY) .build()) .build()) .widgetSettings(SunburstWidgetSettings.builder() .firstField(tagNameFactory.buildTagName("CONTENT-TYPE")) .secondField(tagNameFactory.buildTagName("AUTHOR")) .maxLegendEntries(7) .build()) .build()) .build() ); }
@Override protected void validateParsedComponent(final ObjectContent<CustomApplication> objectContent) { objectContent.assertThat().isEqualTo( CustomApplication.builder() .applicationName("Application name") .url("http://example.url.com") .icon("hp-monitor") .openInNewTab(true) .enabled(true) .build() ); }
@Override protected void validateMergedComponent(final ObjectContent<CustomApplication> objectContent) { objectContent.assertThat().isEqualTo( CustomApplication.builder() .applicationName(APP_NAME) .url(EXAMPLE_URL) .icon("hp-app") .openInNewTab(false) .enabled(false) .build()); }
@Override protected void validateParsedComponent(final ObjectContent<TrendingConfiguration> objectContent) { objectContent.assertThat() .hasFieldOrPropertyWithValue("dateField", fieldPathNormaliser.normaliseFieldPath(ParametricValuesService.AUTN_DATE_FIELD)) .hasFieldOrPropertyWithValue("numberOfValues", 10) .hasFieldOrPropertyWithValue("maxNumberOfBuckets", 20) .hasFieldOrPropertyWithValue("minNumberOfBuckets", 10) .hasFieldOrPropertyWithValue("defaultNumberOfBuckets", 20); }
@Override protected void validateMergedComponent(final ObjectContent<TrendingConfiguration> objectContent) { objectContent.assertThat() .hasFieldOrPropertyWithValue("dateField", fieldPathNormaliser.normaliseFieldPath(ParametricValuesService.AUTN_DATE_FIELD)) .hasFieldOrPropertyWithValue("numberOfValues", 10) .hasFieldOrPropertyWithValue("maxNumberOfBuckets", 20) .hasFieldOrPropertyWithValue("minNumberOfBuckets", 10) .hasFieldOrPropertyWithValue("defaultNumberOfBuckets", 15); }