001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.camel.impl.cloud;
018
019import java.util.Collections;
020import java.util.HashMap;
021import java.util.Map;
022import java.util.Objects;
023import java.util.stream.Stream;
024
025import org.apache.camel.cloud.ServiceDefinition;
026import org.apache.camel.cloud.ServiceHealth;
027import org.apache.camel.util.CollectionHelper;
028import org.apache.camel.util.ObjectHelper;
029import org.apache.camel.util.StringHelper;
030
031public class DefaultServiceDefinition implements ServiceDefinition {
032    private static final ServiceHealth DEFAULT_SERVICE_HEALTH = new DefaultServiceHealth();
033
034    private final String id;
035    private final String name;
036    private final String host;
037    private final int port;
038    private final Map<String, String> meta;
039    private final ServiceHealth health;
040
041    public DefaultServiceDefinition(String name, String host, int port) {
042        this(null, name, host, port, Collections.emptyMap(), DEFAULT_SERVICE_HEALTH);
043    }
044
045    public DefaultServiceDefinition(String id, String name, String host, int port) {
046        this(id, name, host, port, Collections.emptyMap(), DEFAULT_SERVICE_HEALTH);
047    }
048
049    public DefaultServiceDefinition(String name, String host, int port, ServiceHealth health) {
050        this(null, name, host, port, Collections.emptyMap(), health);
051    }
052
053    public DefaultServiceDefinition(String id, String name, String host, int port, ServiceHealth health) {
054        this(id, name, host, port, Collections.emptyMap(), health);
055    }
056
057    public DefaultServiceDefinition(String name, String host, int port, Map<String, String> meta) {
058        this(null, name, host, port, meta, DEFAULT_SERVICE_HEALTH);
059    }
060
061    public DefaultServiceDefinition(String id, String name, String host, int port, Map<String, String> meta) {
062        this(id, name, host, port, meta, DEFAULT_SERVICE_HEALTH);
063    }
064
065    public DefaultServiceDefinition(String name, String host, int port, Map<String, String> meta, ServiceHealth health) {
066        this(null, name, host, port, meta, health);
067    }
068
069    public DefaultServiceDefinition(String id, String name, String host, int port, Map<String, String> meta, ServiceHealth health) {
070        this.id = id;
071        this.name = name;
072        this.host = host;
073        this.port = port;
074        this.meta = CollectionHelper.unmodifiableMap(meta);
075        this.health = ObjectHelper.supplyIfEmpty(health, () -> DEFAULT_SERVICE_HEALTH);
076    }
077
078    @Override
079    public String getId() {
080        return id;
081    }
082
083    @Override
084    public String getName() {
085        return name;
086    }
087
088    @Override
089    public String getHost() {
090        return host;
091    }
092
093    @Override
094    public int getPort() {
095        return port;
096    }
097
098    @Override
099    public ServiceHealth getHealth() {
100        return health;
101    }
102
103    @Override
104    public Map<String, String> getMetadata() {
105        return this.meta;
106    }
107
108    @Override
109    public String toString() {
110        return "DefaultServiceDefinition[" + id + "]";
111    }
112
113    @Override
114    public boolean equals(Object o) {
115        if (this == o) {
116            return true;
117        }
118        if (o == null || getClass() != o.getClass()) {
119            return false;
120        }
121
122        DefaultServiceDefinition that = (DefaultServiceDefinition) o;
123        return getPort() == that.getPort()
124            && Objects.equals(getId(), that.getId())
125            && Objects.equals(getName(), that.getName())
126            && Objects.equals(getHost(), that.getHost());
127    }
128
129    @Override
130    public int hashCode() {
131        return Objects.hash(getId(), getName(), getHost(), getPort());
132    }
133
134    // ***************************
135    // Builder
136    // ***************************
137
138    public static Stream<? extends ServiceDefinition> parse(String serverString) {
139        return Stream.of(serverString.split(","))
140            .map(part -> {
141                String serviceId = null;
142                String serviceName = StringHelper.before(part, "@");
143
144                if (serviceName != null) {
145                    serviceId = StringHelper.before(serviceName, "/");
146                    serviceName = StringHelper.after(serviceName, "/");
147
148                    if (serviceName == null) {
149                        serviceName = StringHelper.before(part, "@");
150                    }
151
152                    part = StringHelper.after(part, "@");
153                }
154
155                String serviceHost = StringHelper.before(part, ":");
156                String servicePort = StringHelper.after(part, ":");
157
158                if (ObjectHelper.isNotEmpty(serviceHost) && ObjectHelper.isNotEmpty(servicePort)) {
159                    return new DefaultServiceDefinition(serviceId, serviceName, serviceHost, Integer.valueOf(servicePort));
160                }
161
162                return null;
163            }
164        ).filter(Objects::nonNull);
165    }
166
167    public static Builder builder() {
168        return new Builder();
169    }
170
171    /**
172     * Fluent builder to construct ServiceDefinition.
173     */
174    public static class Builder {
175        private String id;
176        private String name;
177        private String host;
178        private Integer port;
179        private Map<String, String> meta;
180        private ServiceHealth health;
181
182        public Builder from(ServiceDefinition source) {
183            withId(source.getId());
184            withName(source.getName());
185            withHost(source.getHost());
186            withPort(source.getPort());
187            withMeta(source.getMetadata());
188            withHealth(source.getHealth());
189
190            return this;
191        }
192
193        public Builder from(Map<String, String> properties) {
194            ObjectHelper.ifNotEmpty(properties.get(ServiceDefinition.SERVICE_META_ID), this::withId);
195            ObjectHelper.ifNotEmpty(properties.get(ServiceDefinition.SERVICE_META_NAME), this::withName);
196            ObjectHelper.ifNotEmpty(properties.get(ServiceDefinition.SERVICE_META_HOST), this::withHost);
197            ObjectHelper.ifNotEmpty(properties.get(ServiceDefinition.SERVICE_META_PORT), this::withPort);
198
199            for (Map.Entry<String, String> entry : properties.entrySet()) {
200                if (!entry.getKey().startsWith(ServiceDefinition.SERVICE_META_PREFIX)) {
201                    continue;
202                }
203
204                addMeta(entry.getKey(), entry.getValue());
205            }
206
207            return this;
208        }
209
210        public Builder withId(String id) {
211            this.id = id;
212            return this;
213        }
214
215        public String id() {
216            return id;
217        }
218
219        public Builder withName(String name) {
220            this.name = name;
221            return this;
222        }
223
224        public String name() {
225            return name;
226        }
227
228        public Builder withHost(String host) {
229            this.host = host;
230            return this;
231        }
232
233        public String host() {
234            return host;
235        }
236
237        public Builder withPort(Integer port) {
238            this.port = port;
239            return this;
240        }
241
242        public Builder withPort(String port) {
243            if (port != null) {
244                withPort(Integer.parseInt(port));
245            }
246
247            return this;
248        }
249
250        public Integer port() {
251            return port;
252        }
253
254        public Builder withMeta(Map<String, String> meta) {
255            this.meta = new HashMap<>(meta);
256            return this;
257        }
258
259        public Builder addMeta(String key, String val) {
260            if (this.meta == null) {
261                this.meta = new HashMap<>();
262            }
263
264            this.meta.put(key, val);
265
266            return this;
267        }
268
269        public Builder addAllMeta(Map<String, String> meta) {
270            if (this.meta == null) {
271                this.meta = new HashMap<>();
272            }
273
274            this.meta.putAll(meta);
275
276            return this;
277        }
278
279        public Map<String, String> meta() {
280            return meta;
281        }
282
283        public Builder withHealth(ServiceHealth health) {
284            this.health = health;
285
286            return this;
287        }
288
289        public ServiceHealth health() {
290            return health;
291        }
292
293        public ServiceDefinition build() {
294            return new DefaultServiceDefinition(id, name, host, port != null ? port : -1, meta, health);
295        }
296    }
297}