Skip to content

Commit

Permalink
Merge fd27fad into 17161dd
Browse files Browse the repository at this point in the history
  • Loading branch information
vanitasvitae committed May 14, 2020
2 parents 17161dd + fd27fad commit 193f802
Show file tree
Hide file tree
Showing 21 changed files with 1,950 additions and 0 deletions.
1 change: 1 addition & 0 deletions documentation/extensions/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Smack Extensions and currently supported XEPs of smack-extensions
| Advanced Message Processing | [XEP-0079](https://xmpp.org/extensions/xep-0079.html) | n/a | Enables entities to request, and servers to perform, advanced processing of XMPP message stanzas. |
| User Location | [XEP-0080](https://xmpp.org/extensions/xep-0080.html) | n/a | Enabled communicating information about the current geographical or physical location of an entity. |
| XMPP Date Time Profiles | [XEP-0082](https://xmpp.org/extensions/xep-0082.html) | n/a | Standardization of Date and Time representation in XMPP. |
| User Avatar | [XEP-0084](https://xmpp.org/extensions/xep-0084.html) | 1.1.2 | Allows to exchange user avatars, which are small images or icons associated with human users. |
| Chat State Notifications | [XEP-0085](https://xmpp.org/extensions/xep-0085.html) | n/a | Communicating the status of a user in a chat session. |
| [Time Exchange](time.md) | [XEP-0090](https://xmpp.org/extensions/xep-0090.html) | n/a | Allows local time information to be shared between users. |
| Software Version | [XEP-0092](https://xmpp.org/extensions/xep-0092.html) | n/a | Retrieve and announce the software application of an XMPP entity. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.io.IOException;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
Expand Down Expand Up @@ -362,6 +363,13 @@ public XmlStringBuilder optAttribute(String name, Number number) {
return this;
}

public XmlStringBuilder optAttribute(String name, URL url) {
if (url != null) {
attribute(name, url.toExternalForm());
}
return this;
}

/**
* Add the given attribute if {@code value => 0}.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
*
* Copyright 2019 Paul Schaub
*
* Licensed 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.jivesoftware.smackx.avatar;

import org.jxmpp.jid.EntityBareJid;

/**
* The {@link AvatarMetadataStore} interface defines methods used by the {@link UserAvatarManager} to determine,
* whether the client already has a local copy of a published avatar or if the user needs to be informed about the
* update in order to download the image.
*/
public interface AvatarMetadataStore {

/**
* Determine, if the client already has a copy of the avatar with {@code itemId} available or not.
*
* @param jid {@link EntityBareJid} of the entity that published the avatar.
* @param itemId itemId of the avatar
*
* @return true if the client already has a local copy of the avatar, false otherwise
*/
boolean hasAvatarAvailable(EntityBareJid jid, String itemId);

/**
* Mark the tuple (jid, itemId) as available. This means that the client already has a local copy of the avatar
* available and wishes not to be notified about this particular avatar anymore.
*
* @param jid {@link EntityBareJid} of the entity that published the avatar.
* @param itemId itemId of the avatar
*/
void setAvatarAvailable(EntityBareJid jid, String itemId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
*
* Copyright 2020 Paul Schaub
*
* Licensed 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.jivesoftware.smackx.avatar;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.jivesoftware.smack.util.HashCode;
import org.jivesoftware.smack.util.Objects;

import org.jxmpp.jid.EntityBareJid;

public class MemoryAvatarMetadataStore implements AvatarMetadataStore {

private Map<Tuple<EntityBareJid, String>, Boolean> availabilityMap = new ConcurrentHashMap<>();

@Override
public boolean hasAvatarAvailable(EntityBareJid jid, String itemId) {
Boolean available = availabilityMap.get(new Tuple<>(jid, itemId));
return available != null && available;
}

@Override
public void setAvatarAvailable(EntityBareJid jid, String itemId) {
availabilityMap.put(new Tuple<>(jid, itemId), Boolean.TRUE);
}

private static class Tuple<A, B> {
private final A first;
private final B second;

Tuple(A first, B second) {
this.first = first;
this.second = second;
}

public A getFirst() {
return first;
}

public B getSecond() {
return second;
}

@Override
public int hashCode() {
return HashCode.builder()
.append(first)
.append(second)
.build();
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (!(obj instanceof Tuple)) {
return false;
}

@SuppressWarnings("unchecked") Tuple<A, B> other = (Tuple<A, B>) obj;
return Objects.equals(getFirst(), other.getFirst())
&& Objects.equals(getSecond(), other.getSecond());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
*
* Copyright 2017 Fernando Ramirez, 2019 Paul Schaub
*
* Licensed 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.jivesoftware.smackx.avatar;

import java.net.URL;

import org.jivesoftware.smack.datatypes.UInt16;
import org.jivesoftware.smack.datatypes.UInt32;
import org.jivesoftware.smack.util.StringUtils;

/**
* User Avatar metadata info model class.
*
* @author Fernando Ramirez
* @author Paul Schaub
* @see <a href="http://xmpp.org/extensions/xep-0084.html">XEP-0084: User
* Avatar</a>
*/
public class MetadataInfo {

public static final int MAX_HEIGHT = 65536;
public static final int MAX_WIDTH = 65536;

private final String id;
private final URL url;
private final UInt32 bytes;
private final String type;
private final UInt16 height;
private final UInt16 width;

/**
* MetadataInfo constructor.
*
* @param id SHA-1 hash of the image data
* @param url http(s) url of the image
* @param bytes size of the image in bytes
* @param type content type of the image
* @param pixelsHeight height of the image in pixels
* @param pixelsWidth width of the image in pixels
*/
public MetadataInfo(String id, URL url, long bytes, String type, int pixelsHeight, int pixelsWidth) {
this.id = StringUtils.requireNotNullNorEmpty(id, "ID is required.");
this.url = url;
if (bytes <= 0) {
throw new IllegalArgumentException("Number of bytes MUST be greater than 0.");
}
this.bytes = UInt32.from(bytes);
this.type = StringUtils.requireNotNullNorEmpty(type, "Content Type is required.");
if (pixelsHeight < 0 || pixelsHeight > MAX_HEIGHT) {
throw new IllegalArgumentException("Image height value must be between 0 and 65536.");
}
if (pixelsWidth < 0 || pixelsWidth > MAX_WIDTH) {
throw new IllegalArgumentException("Image width value must be between 0 and 65536.");
}
this.height = UInt16.from(pixelsHeight);
this.width = UInt16.from(pixelsWidth);
}

/**
* Get the id.
*
* @return the id
*/
public String getId() {
return id;
}

/**
* Get the url of the avatar image.
*
* @return the url
*/
public URL getUrl() {
return url;
}

/**
* Get the amount of bytes.
*
* @return the amount of bytes
*/
public UInt32 getBytes() {
return bytes;
}

/**
* Get the type.
*
* @return the type
*/
public String getType() {
return type;
}

/**
* Get the height in pixels.
*
* @return the height in pixels
*/
public UInt16 getHeight() {
return height;
}

/**
* Get the width in pixels.
*
* @return the width in pixels
*/
public UInt16 getWidth() {
return width;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
*
* Copyright 2017 Fernando Ramirez
*
* Licensed 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.jivesoftware.smackx.avatar;

import java.util.Map;

import org.jivesoftware.smack.util.StringUtils;

/**
* User Avatar metadata pointer model class.
* A pointer element is used to point to an avatar which is not published via PubSub or HTTP, but provided by a
* third-party service.
*
* @author Fernando Ramirez
* @see <a href="https://xmpp.org/extensions/xep-0084.html">XEP-0084: User Avatar</a>
*/
public class MetadataPointer {

private final String namespace;
private final Map<String, Object> fields;

/**
* Metadata Pointer constructor.
*
* The following example
* <pre>
* {@code
* <pointer>
* <x xmlns='http://example.com/virtualworlds'>
* <game>Ancapistan</game>
* <character>Kropotkin</character>
* </x>
* </pointer>
* }
* </pre>
* can be created by constructing the object like this:
* <pre>
* {@code
* Map fields = new HashMap<>();
* fields.add("game", "Ancapistan");
* fields.add("character", "Kropotkin");
* MetadataPointer pointer = new MetadataPointer("http://example.com/virtualworlds", fields);
* }
* </pre>
*
* @param namespace namespace of the child element of the metadata pointer.
* @param fields fields of the child element as key, value pairs.
*/
public MetadataPointer(String namespace, Map<String, Object> fields) {
this.namespace = StringUtils.requireNotNullNorEmpty(namespace, "Namespace MUST NOT be null, nor empty.");
this.fields = fields;
}

/**
* Get the namespace of the pointers child element.
*
* @return the namespace
*/
public String getNamespace() {
return namespace;
}

/**
* Get the fields of the pointers child element.
*
* @return the fields
*/
public Map<String, Object> getFields() {
return fields;
}

}

0 comments on commit 193f802

Please sign in to comment.