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