001/*
002 * SPDX-License-Identifier: Apache-2.0
003 *
004 * Copyright 2023-2026 The Enola <https://enola.dev> Authors
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *     https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package dev.enola.core;
019
020import com.google.protobuf.Descriptors.Descriptor;
021import com.google.protobuf.Descriptors.GenericDescriptor;
022import com.google.protobuf.ExtensionRegistry;
023
024import dev.enola.common.io.resource.ResourceProvider;
025import dev.enola.common.protobuf.DescriptorProvider;
026import dev.enola.common.protobuf.TypeRegistryWrapper;
027import dev.enola.common.protobuf.TypeRegistryWrapper.Builder;
028import dev.enola.common.protobuf.ValidationException;
029import dev.enola.core.message.ProtoEnumValueToThingConnector;
030import dev.enola.core.message.ProtoFieldToThingConnector;
031import dev.enola.core.message.ProtoMessageToThingConnector;
032import dev.enola.core.thing.ThingConnector;
033import dev.enola.core.view.EnolaMessages;
034import dev.enola.thing.proto.Things;
035import dev.enola.thing.repo.EmptyThingsRepository;
036import dev.enola.thing.repo.ThingRepository;
037import dev.enola.thing.repo.ThingsProvider;
038
039public class EnolaServiceProvider {
040
041    private final TypeRegistryWrapper typeRegistry;
042    private final DescriptorProvider descriptorProvider =
043            new DescriptorProvider() {
044
045                @Override
046                public Descriptor getDescriptorForTypeUrl(String messageTypeURL) {
047                    return typeRegistry.getDescriptorForTypeUrl(messageTypeURL);
048                }
049
050                @Override
051                public GenericDescriptor findByName(String name) {
052                    return typeRegistry.findByName(name);
053                }
054            };
055
056    private final EnolaServiceRegistry enolaService;
057    private final EnolaMessages enolaMessages;
058
059    public EnolaServiceProvider(ResourceProvider rp) throws ValidationException, EnolaException {
060        this(new EmptyThingsRepository(), new EmptyThingsRepository(), rp);
061    }
062
063    public EnolaServiceProvider(
064            ThingsProvider thingsProvider, ThingRepository thingRepository, ResourceProvider rp)
065            throws ValidationException, EnolaException {
066        var esb = EnolaServiceRegistry.builder();
067        esb.register(thingRepository, thingsProvider);
068
069        var trb = TypeRegistryWrapper.newBuilder();
070        trb.add(Things.getDescriptor());
071
072        // Register a bunch of hard-coded built-in Thing Connectors
073        register(new ProtoMessageToThingConnector(descriptorProvider), esb, trb);
074        register(new ProtoFieldToThingConnector(descriptorProvider), esb, trb);
075        register(new ProtoEnumValueToThingConnector(descriptorProvider), esb, trb);
076
077        this.typeRegistry = trb.build();
078        this.enolaService = esb.build(rp);
079        this.enolaMessages = new EnolaMessages(typeRegistry, ExtensionRegistry.getEmptyRegistry());
080    }
081
082    private void register(
083            ThingConnector thingConnector, EnolaServiceRegistry.Builder esb, Builder trb)
084            throws EnolaException {
085        /* TODO !!!
086               var iri = thingConnector.iri();
087               var thingsRepository = new ThingsRepositoryAdapter(thingConnector);
088               esb.register(thingsRepository);
089        */
090        trb.add(thingConnector.getDescriptors());
091    }
092
093    public EnolaService getEnolaService() {
094        return enolaService;
095    }
096
097    public TypeRegistryWrapper getTypeRegistryWrapper() {
098        return typeRegistry;
099    }
100}