diff --git a/fit/src/main/java/org/apache/olingo/fit/V4Services.java b/fit/src/main/java/org/apache/olingo/fit/V4Services.java index 6f11b19db..39d1fca93 100644 --- a/fit/src/main/java/org/apache/olingo/fit/V4Services.java +++ b/fit/src/main/java/org/apache/olingo/fit/V4Services.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.URI; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -994,11 +995,28 @@ public class V4Services extends AbstractServices { throw new UnsupportedMediaTypeException("Unsupported media type"); } + String derivedType = null; + if (containedEntitySetName.contains("/")) { + final String[] parts = containedEntitySetName.split("/"); + containedEntitySetName = parts[0]; + derivedType = parts[1]; + } + final InputStream feed = FSManager.instance(version). readFile(containedPath(entityId, containedEntitySetName).toString(), Accept.ATOM); final ResWrap container = atomDeserializer.read(feed, AtomEntitySetImpl.class); + if (derivedType != null) { + final List nonMatching = new ArrayList(); + for (Entity entity : container.getPayload().getEntities()) { + if (!derivedType.equals(entity.getType())) { + nonMatching.add(entity); + } + } + container.getPayload().getEntities().removeAll(nonMatching); + } + return xml.createResponse( null, xml.writeEntitySet(acceptType, container), diff --git a/fit/src/main/resources/V40/People/Microsoft.Test.OData.Services.ODataWCFService.Customer/feed.full.json b/fit/src/main/resources/V40/People/Microsoft.Test.OData.Services.ODataWCFService.Customer/feed.full.json new file mode 100644 index 000000000..6bd8c0243 --- /dev/null +++ b/fit/src/main/resources/V40/People/Microsoft.Test.OData.Services.ODataWCFService.Customer/feed.full.json @@ -0,0 +1,96 @@ +{ + "@odata.context": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/$metadata#People", + "value": [{ + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Customer", + "@odata.id": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)", + "@odata.editLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer", + "PersonID": 1, + "FirstName": "Bob", + "LastName": "Cat", + "MiddleName": null, + "HomeAddress": { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.HomeAddress", + "Street": "1 Microsoft Way", + "City": "London", + "PostalCode": "98052", + "FamilyName": "Cats" + }, + "Home@odata.type": "#GeographyPoint", + "Home": { + "type": "Point", + "coordinates": [23.1, 32.1], + "crs": { + "type": "name", + "properties": { + "name": "EPSG:4326" + } + } + }, + "Numbers@odata.type": "#Collection(String)", + "Numbers": ["111-111-1111", "012", "310", "bca", "ayz"], + "Emails@odata.type": "#Collection(String)", + "Emails": ["abc@abc.com"], + "City": "London", + "Birthday@odata.type": "#DateTimeOffset", + "Birthday": "1957-04-03T00:00:00Z", + "TimeBetweenLastTwoOrders@odata.type": "#Duration", + "TimeBetweenLastTwoOrders": "PT0.0000001S", + "Parent@odata.associationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent/$ref", + "Parent@odata.navigationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent", + "Orders@odata.associationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders/$ref", + "Orders@odata.navigationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders", + "Company@odata.associationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company/$ref", + "Company@odata.navigationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company", + "#Microsoft.Test.OData.Services.ODataWCFService.ResetAddress": { + "title": "Microsoft.Test.OData.Services.ODataWCFService.ResetAddress", + "target": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress" + }, + "#Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress": { + "title": "Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress", + "target": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress" + } + }, { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Customer", + "@odata.id": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)", + "@odata.editLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer", + "PersonID": 2, + "FirstName": "Jill", + "LastName": "Jones", + "MiddleName": null, + "HomeAddress": null, + "Home@odata.type": "#GeographyPoint", + "Home": { + "type": "Point", + "coordinates": [161.8, 15.0], + "crs": { + "type": "name", + "properties": { + "name": "EPSG:4326" + } + } + }, + "Numbers@odata.type": "#Collection(String)", + "Numbers": [], + "Emails@odata.type": "#Collection(String)", + "Emails": [], + "City": "Sydney", + "Birthday@odata.type": "#DateTimeOffset", + "Birthday": "1983-01-15T00:00:00Z", + "TimeBetweenLastTwoOrders@odata.type": "#Duration", + "TimeBetweenLastTwoOrders": "PT0.0000002S", + "Parent@odata.associationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent/$ref", + "Parent@odata.navigationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent", + "Orders@odata.associationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders/$ref", + "Orders@odata.navigationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders", + "Company@odata.associationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company/$ref", + "Company@odata.navigationLink": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company", + "#Microsoft.Test.OData.Services.ODataWCFService.ResetAddress": { + "title": "Microsoft.Test.OData.Services.ODataWCFService.ResetAddress", + "target": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress" + }, + "#Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress": { + "title": "Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress", + "target": "http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress" + } + }] +} diff --git a/fit/src/main/resources/V40/People/Microsoft.Test.OData.Services.ODataWCFService.Customer/feed.xml b/fit/src/main/resources/V40/People/Microsoft.Test.OData.Services.ODataWCFService.Customer/feed.xml new file mode 100644 index 000000000..51e36d580 --- /dev/null +++ b/fit/src/main/resources/V40/People/Microsoft.Test.OData.Services.ODataWCFService.Customer/feed.xml @@ -0,0 +1,103 @@ + + + + http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People + + <updated>2014-05-08T16:06:24Z</updated> + <entry> + <id>http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)</id> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.Customer" scheme="http://docs.oasis-open.org/odata/ns/scheme"/> + <link rel="edit" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/Orders" type="application/atom+xml;type=feed" title="Orders" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company"/> + <title/> + <updated>2014-05-08T16:06:24Z</updated> + <author> + <name/> + </author> + <content type="application/xml"> + <m:properties> + <d:PersonID m:type="Int32">1</d:PersonID> + <d:FirstName>Bob</d:FirstName> + <d:LastName>Cat</d:LastName> + <d:MiddleName m:null="true"/> + <d:HomeAddress m:type="#Microsoft.Test.OData.Services.ODataWCFService.HomeAddress"> + <d:Street>1 Microsoft Way</d:Street> + <d:City>London</d:City> + <d:PostalCode>98052</d:PostalCode> + <d:FamilyName>Cats</d:FamilyName> + </d:HomeAddress> + <d:Home m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>32.1 23.1</gml:pos> + </gml:Point> + </d:Home> + <d:Numbers m:type="#Collection(String)"> + <m:element>111-111-1111</m:element> + <m:element>012</m:element> + <m:element>310</m:element> + <m:element>bca</m:element> + <m:element>ayz</m:element> + </d:Numbers> + <d:Emails m:type="#Collection(String)"> + <m:element>abc@abc.com</m:element> + </d:Emails> + <d:City>London</d:City> + <d:Birthday m:type="DateTimeOffset">1957-04-03T00:00:00Z</d:Birthday> + <d:TimeBetweenLastTwoOrders m:type="Duration">PT0.0000001S</d:TimeBetweenLastTwoOrders> + </m:properties> + </content> + </entry> + <entry> + <id>http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)</id> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.Customer" scheme="http://docs.oasis-open.org/odata/ns/scheme"/> + <link rel="edit" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/Orders" type="application/atom+xml;type=feed" title="Orders" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders"/> + <link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://localhost:${cargo.servlet.port}/stub/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company"/> + <title/> + <updated>2014-05-08T16:06:24Z</updated> + <author> + <name/> + </author> + <content type="application/xml"> + <m:properties> + <d:PersonID m:type="Int32">2</d:PersonID> + <d:FirstName>Jill</d:FirstName> + <d:LastName>Jones</d:LastName> + <d:MiddleName m:null="true"/> + <d:HomeAddress m:null="true"/> + <d:Home m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>15 161.8</gml:pos> + </gml:Point> + </d:Home> + <d:Numbers m:type="#Collection(String)"/> + <d:Emails m:type="#Collection(String)"/> + <d:City>Sydney</d:City> + <d:Birthday m:type="DateTimeOffset">1983-01-15T00:00:00Z</d:Birthday> + <d:TimeBetweenLastTwoOrders m:type="Duration">PT0.0000002S</d:TimeBetweenLastTwoOrders> + </m:properties> + </content> + </entry> +</feed> diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/DerivedTypeTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/DerivedTypeTestITCase.java new file mode 100644 index 000000000..370c377fb --- /dev/null +++ b/fit/src/test/java/org/apache/olingo/fit/v4/DerivedTypeTestITCase.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.olingo.fit.v4; + +import static org.junit.Assert.assertEquals; + +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest; +import org.apache.olingo.client.api.uri.v4.URIBuilder; +import org.apache.olingo.commons.api.domain.v4.ODataEntity; +import org.apache.olingo.commons.api.domain.v4.ODataEntitySet; +import org.apache.olingo.commons.api.format.ODataPubFormat; +import org.junit.Test; + +public class DerivedTypeTestITCase extends AbstractTestITCase { + + private void read(final ODataPubFormat format) { + // 1. entity set + URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("People"). + appendDerivedEntityTypeSegment("Microsoft.Test.OData.Services.ODataWCFService.Customer"); + ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory(). + getEntitySetRequest(uriBuilder.build()); + req.setFormat(format); + + for (ODataEntity customer : req.execute().getBody().getEntities()) { + assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Customer", customer.getTypeName().toString()); + } + + // 2. contained entity set + uriBuilder = client.getURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("Accounts").appendKeySegment(101). + appendNavigationSegment("MyPaymentInstruments"). + appendDerivedEntityTypeSegment("Microsoft.Test.OData.Services.ODataWCFService.CreditCardPI"); + req = client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build()); + req.setFormat(format); + + for (ODataEntity customer : req.execute().getBody().getEntities()) { + assertEquals("Microsoft.Test.OData.Services.ODataWCFService.CreditCardPI", customer.getTypeName().toString()); + } + } + + @Test + public void readfromAtom() { + read(ODataPubFormat.ATOM); + } + + @Test + public void readfromJSON() { + read(ODataPubFormat.JSON_FULL_METADATA); + } +} diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/EntitySetTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/EntitySetTestITCase.java index 5c78127b8..c0449cc65 100644 --- a/fit/src/test/java/org/apache/olingo/fit/v4/EntitySetTestITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/v4/EntitySetTestITCase.java @@ -45,8 +45,7 @@ import org.junit.Test; public class EntitySetTestITCase extends AbstractTestITCase { private void rawRequest(final ODataPubFormat format) { - final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL); - uriBuilder.appendEntitySetSegment("People"); + final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("People"); final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build()); req.setFormat(format.toString(client.getServiceVersion())); @@ -70,8 +69,8 @@ public class EntitySetTestITCase extends AbstractTestITCase { } private void readWithInlineCount(final ODataClient client, final ODataPubFormat format) { - final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL); - uriBuilder.appendEntitySetSegment("People").count(true); + final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL). + appendEntitySetSegment("People").count(true); final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build()); req.setFormat(format.toString(client.getServiceVersion())); @@ -102,8 +101,7 @@ public class EntitySetTestITCase extends AbstractTestITCase { } private void readODataEntitySetIterator(final ODataPubFormat format) { - final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL); - uriBuilder.appendEntitySetSegment("People"); + final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("People"); final ODataEntitySetIteratorRequest<ODataEntitySet, ODataEntity> req = client.getRetrieveRequestFactory().getEntitySetIteratorRequest(uriBuilder.build()); @@ -145,8 +143,7 @@ public class EntitySetTestITCase extends AbstractTestITCase { } private void readEntitySetWithNextLink(final ODataPubFormat format) { - final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL); - uriBuilder.appendEntitySetSegment("People"); + final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("People"); final ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory(). getEntitySetRequest(uriBuilder.build()); diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java index ac0163287..5b0b53310 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/AbstractURIBuilder.java @@ -256,8 +256,6 @@ public abstract class AbstractURIBuilder<UB extends CommonURIBuilder<?>> impleme protected abstract char getBoundOperationSeparator(); - protected abstract char getDerivedEntityTypeSeparator(); - protected abstract String getOperationInvokeMarker(); @Override @@ -270,10 +268,6 @@ public abstract class AbstractURIBuilder<UB extends CommonURIBuilder<?>> impleme segmentsBuilder.append(getBoundOperationSeparator()); break; - case DERIVED_ENTITY_TYPE: - segmentsBuilder.append(getDerivedEntityTypeSeparator()); - break; - default: segmentsBuilder.append('/'); } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v3/URIBuilderImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v3/URIBuilderImpl.java index 94f64b1e1..4092b0277 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v3/URIBuilderImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v3/URIBuilderImpl.java @@ -49,11 +49,6 @@ public class URIBuilderImpl extends AbstractURIBuilder<URIBuilder> implements UR return '/'; } - @Override - protected char getDerivedEntityTypeSeparator() { - return '/'; - } - @Override protected String getOperationInvokeMarker() { return StringUtils.EMPTY; diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v4/URIBuilderImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v4/URIBuilderImpl.java index b53357b55..62bff9f5d 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v4/URIBuilderImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/uri/v4/URIBuilderImpl.java @@ -74,11 +74,6 @@ public class URIBuilderImpl extends AbstractURIBuilder<URIBuilder> implements UR return '.'; } - @Override - protected char getDerivedEntityTypeSeparator() { - return '.'; - } - @Override protected String getOperationInvokeMarker() { return "()"; diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/v4/URIBuilderTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/v4/URIBuilderTest.java index 70be6a471..777236d67 100644 --- a/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/v4/URIBuilderTest.java +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/uri/v4/URIBuilderTest.java @@ -127,8 +127,7 @@ public class URIBuilderTest extends AbstractTest { @Test public void derived() throws URISyntaxException { final URIBuilder uriBuilder = getClient().getURIBuilder(SERVICE_ROOT). - appendEntitySetSegment("Customers").appendNavigationSegment("Model"). - appendDerivedEntityTypeSegment("VipCustomer").appendKeySegment(1); + appendEntitySetSegment("Customers").appendDerivedEntityTypeSegment("Model.VipCustomer").appendKeySegment(1); assertEquals(new org.apache.http.client.utils.URIBuilder( SERVICE_ROOT + "/Customers/Model.VipCustomer(1)").build(), uriBuilder.build());