001package ball.upnp;
002/*-
003 * ##########################################################################
004 * UPnP/SSDP Implementation Classes
005 * %%
006 * Copyright (C) 2013 - 2022 Allen D. Ball
007 * %%
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *      http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 * ##########################################################################
020 */
021import ball.upnp.annotation.XmlNs;
022import java.net.URI;
023import java.util.LinkedHashMap;
024import java.util.LinkedHashSet;
025import java.util.List;
026import java.util.Map;
027import java.util.Set;
028import java.util.UUID;
029import java.util.function.Function;
030import java.util.stream.Stream;
031
032/**
033 * {@link.uri http://www.upnp.org/ UPnP} device interface.
034 *
035 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball}
036 */
037@XmlNs("urn:schemas-upnp-org:device-1-0")
038public interface Device extends Description, SSDP {
039
040    /**
041     * Method to get the URN ({@link URI}) describing {@link.this}
042     * {@link Device}'s device type.
043     *
044     * @return  The service type.
045     */
046    public URI getDeviceType();
047
048    /**
049     * Method to get {@link.this} {@link Device}'s {@link UUID}.
050     *
051     * @return  The {@link UUID}.
052     */
053    public UUID getUUID();
054
055    /**
056     * Method to get {@link.this} {@link Device}'s {@link Service}s.
057     *
058     * @return  The {@link List} of {@link Service}s.
059     */
060    public List<? extends Service> getServiceList();
061
062    /**
063     * Method to get {@link.this} {@link Device}'s {@link Device}s.
064     *
065     * @return  The {@link List} of {@link Device}s.
066     */
067    public List<? extends Device> getDeviceList();
068
069    /**
070     * Method to get {@link.this} {@link Device}'s UDN.
071     *
072     * @return  The UDN {@link URI}.
073     */
074    default URI getUDN() {
075        return URI.create("uuid:" + getUUID().toString().toUpperCase());
076    }
077
078    @Override
079    default Map<URI,Set<URI>> getUSNMap() {
080        LinkedHashMap<URI,Set<URI>> map = new LinkedHashMap<>();
081        Function<URI,Set<URI>> mapper = k -> new LinkedHashSet<>();
082
083        if (this instanceof RootDevice) {
084            map.computeIfAbsent(getUSN(RootDevice.NT), mapper)
085                .add(RootDevice.NT);
086        }
087
088        map.computeIfAbsent(getUSN(null), mapper)
089            .add(getUDN());
090        map.computeIfAbsent(getUSN(getDeviceType()), mapper)
091            .add(getDeviceType());
092
093        if (this instanceof RootDevice) {
094            Stream.concat(getServiceList().stream(), getDeviceList().stream())
095                .map(SSDP::getUSNMap)
096                .forEach(t -> t.forEach((k, v) -> map.computeIfAbsent(k, mapper).addAll(v)));
097        }
098
099        return map;
100    }
101
102    @Override
103    default URI getUSN(URI urn) {
104        URI usn = null;
105
106        if (urn != null) {
107            usn = URI.create(getUDN() + "::" + urn);
108        } else {
109            usn = getUDN();
110        }
111
112        return usn;
113    }
114}