Skip to content
Permalink
Browse files

feat: Add JSON service for IdTags

  • Loading branch information...
rhwood committed May 6, 2019
1 parent 92bebac commit bd65dbbfdd973314aaf395899b5a3152c9be5b50
@@ -0,0 +1,111 @@
package jmri.server.json.idTag;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Locale;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

@ParametersAreNonnullByDefault
@CheckReturnValue
@SuppressFBWarnings(value = "NM_SAME_SIMPLE_NAME_AS_SUPERCLASS", justification = "Desired pattern is repeated class names with package-level access to members")

@javax.annotation.concurrent.Immutable

/**
* Provides standard access for resource bundles in a package.
*
* Convention is to provide a subclass of this name in each package, working off
* the local resource bundle name.
*
* @author Bob Jacobsen Copyright (C) 2012
* @since 3.3.1
*/
public class Bundle extends jmri.server.json.Bundle {

@Nullable
private static final String name = null; // no local resources

//
// below here is boilerplate to be copied exactly
//
/**
* Provides a translated string for a given key from the package resource
* bundle or parent.
* <p>
* Note that this is intentionally package-local access.
*
* @param key Bundle key to be translated
* @return Internationalized text
*/
static String getMessage(String key) {
return getBundle().handleGetMessage(key);
}

/**
* Provides a translated string for a given key in a given locale from the
* package resource bundle or parent.
* <p>
* Note that this is intentionally package-local access.
*
* @param locale The locale to be used
* @param key Bundle key to be translated
* @return Internationalized text
*/
static String getMessage(Locale locale, String key) {
return getBundle().handleGetMessage(locale, key);
}

/**
* Merges user data with a translated string for a given key from the
* package resource bundle or parent.
* <p>
* Uses the transformation conventions of the Java MessageFormat utility.
* <p>
* Note that this is intentionally package-local access.
*
* @see java.text.MessageFormat
* @param key Bundle key to be translated
* @param subs One or more objects to be inserted into the message
* @return Internationalized text
*/
static String getMessage(String key, Object... subs) {
return getBundle().handleGetMessage(key, subs);
}

/**
* Merges user data with a translated string for a given key in a given
* locale from the package resource bundle or parent.
* <p>
* Uses the transformation conventions of the Java MessageFormat utility.
* <p>
* Note that this is intentionally package-local access.
*
* @see java.text.MessageFormat
* @param locale The locale to be used
* @param key Bundle key to be translated
* @param subs One or more objects to be inserted into the message
* @return Internationalized text
*/
static String getMessage(Locale locale, String key, Object... subs) {
return getBundle().handleGetMessage(locale, key, subs);
}

private final static Bundle b = new Bundle();

@Override
@Nullable
protected String bundleName() {
return name;
}

protected static jmri.Bundle getBundle() {
return b;
}

@Override
protected String retry(Locale locale, String key) {
return super.getBundle().handleGetMessage(locale,key);
}

}
@@ -0,0 +1,21 @@
package jmri.server.json.idTag;

/**
* Constants used by the internal JMRI JSON IdTag service.
*
* @author Randall Wood (C) 2019
*/
public class JsonIdTag {

/**
* {@value #IDTAG}
*/
public static final String IDTAG = "idTag"; // NOI18N

/**
* Prevent instantiation, since this class only contains static values
*/
private JsonIdTag() {
throw new UnsupportedOperationException("There is no valid instance of this class");
}
}
@@ -0,0 +1,114 @@
package jmri.server.json.idTag;

import static jmri.server.json.idTag.JsonIdTag.IDTAG;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.util.StdDateFormat;

import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletResponse;
import jmri.IdTag;
import jmri.IdTagManager;
import jmri.InstanceManager;
import jmri.ProvidingManager;
import jmri.Reporter;
import jmri.ReporterManager;
import jmri.server.json.JSON;
import jmri.server.json.JsonException;
import jmri.server.json.JsonNamedBeanHttpService;
import jmri.server.json.reporter.JsonReporter;

/**
*
* @author Randall Wood Copyright 2019
*/
public class JsonIdTagHttpService extends JsonNamedBeanHttpService<IdTag> {

public JsonIdTagHttpService(ObjectMapper mapper) {
super(mapper);
}

@Override
public ObjectNode doGet(IdTag idTag, String name, String type, Locale locale, int id) throws JsonException {
ObjectNode root = this.getNamedBean(idTag, name, type, locale, id); // throws JsonException if idTag == null
ObjectNode data = root.with(JSON.DATA);
if (idTag != null) {
switch (idTag.getState()) {
case IdTag.UNKNOWN:
data.put(JSON.STATE, JSON.UNKNOWN);
break;
default:
data.put(JSON.STATE, idTag.getState());
}
Reporter reporter = idTag.getWhereLastSeen();
data.put(JsonReporter.REPORTER, reporter != null ? reporter.getSystemName() : null);
Date date = idTag.getWhenLastSeen();
data.put(JSON.TIME, date != null ? new StdDateFormat().format(date) : null);
}
return root;
}

@Override
public ObjectNode doPost(IdTag idTag, String name, String type, JsonNode data, Locale locale, int id) throws JsonException {
JsonNode node = data.path(JsonReporter.REPORTER);
if (node.isNull()) {
idTag.setWhereLastSeen(null);
} else if (node.isTextual()) {
Reporter reporter = InstanceManager.getDefault(ReporterManager.class).getBeanBySystemName(node.asText());
if (reporter != null) {
idTag.setWhereLastSeen(reporter);
} else {
throw new JsonException(HttpServletResponse.SC_NOT_FOUND, Bundle.getMessage(locale, "ErrorNotFound", JsonReporter.REPORTER, node.asText()), id);
}
}
return doGet(idTag, name, type, locale, id);
}

@Override
public void doDelete(String type, String name, JsonNode data, Locale locale, int id) throws JsonException {
IdTag bean = getManager().getBeanBySystemName(name);
if (bean != null) {
List<String> listeners = bean.getListenerRefs();
if (listeners.size() > 0 && !acceptForceDeleteToken(type, name, data.path(JSON.FORCE_DELETE).asText())) {
ArrayNode conflicts = mapper.createArrayNode();
listeners.forEach((listener) -> {
conflicts.add(listener);
});
throwDeleteConflictException(type, name, conflicts, locale, id);
} else {
getManager().deregister(bean);
}
} else {
throw new JsonException(HttpServletResponse.SC_NOT_FOUND, Bundle.getMessage(locale, "ErrorNotFound", type, name), id);
}
}

@Override
public JsonNode doSchema(String type, boolean server, Locale locale, int id) throws JsonException {
switch (type) {
case IDTAG:
return doSchema(type,
server,
"jmri/server/json/idTag/idTag-server.json",
"jmri/server/json/idTag/idTag-client.json",
id);
default:
throw new JsonException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, Bundle.getMessage(locale, "ErrorUnknownType", type), id);
}
}

@Override
protected String getType() {
return IDTAG;
}

@Override
protected ProvidingManager<IdTag> getManager() throws UnsupportedOperationException {
return InstanceManager.getDefault(IdTagManager.class);
}
}
@@ -0,0 +1,33 @@
package jmri.server.json.idTag;

import static jmri.server.json.idTag.JsonIdTag.IDTAG;

import com.fasterxml.jackson.databind.ObjectMapper;
import jmri.server.json.JsonConnection;
import jmri.spi.JsonServiceFactory;
import org.openide.util.lookup.ServiceProvider;

/**
*
* @author Randall Wood Copyright 2019
*/
@ServiceProvider(service = JsonServiceFactory.class)
public class JsonIdTagServiceFactory implements JsonServiceFactory<JsonIdTagHttpService, JsonIdTagSocketService> {


@Override
public String[] getTypes() {
return new String[]{IDTAG};
}

@Override
public JsonIdTagSocketService getSocketService(JsonConnection connection) {
return new JsonIdTagSocketService(connection);
}

@Override
public JsonIdTagHttpService getHttpService(ObjectMapper mapper) {
return new JsonIdTagHttpService(mapper);
}

}
@@ -0,0 +1,16 @@
package jmri.server.json.idTag;

import jmri.IdTag;
import jmri.server.json.JsonConnection;
import jmri.server.json.JsonNamedBeanSocketService;

/**
*
* @author Randall Wood Copyright 2019
*/
public class JsonIdTagSocketService extends JsonNamedBeanSocketService<IdTag, JsonIdTagHttpService> {

public JsonIdTagSocketService(JsonConnection connection) {
super(connection, new JsonIdTagHttpService(connection.getObjectMapper()));
}
}
@@ -0,0 +1,26 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "jmri-json-idTag-client-message",
"type": "object",
"description": "Schema data object in message from client to JMRI for type \"idTag\"",
"properties": {
"name": {
"type": "string",
"description": "System name of the idTag"
},
"userName": {
"type": "string",
"description": "If present, set the user name of the idTag"
},
"comment": {
"type": "string",
"description": "If present, set the comment for the idTag"
},
"reporter": {
"type": ["string", "null"],
"description": "If present, sets the reporter to have last seen the idTag"
}
},
"additionalProperties": false,
"required": ["name"]
}
@@ -0,0 +1,53 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "jmri-json-idTag-server-message",
"type": "object",
"description": "Data portion of message from JMRI to client for type \"idTag\"",
"properties": {
"name": {
"type": "string",
"description": "System name of the idTag"
},
"userName": {
"type": ["string", "null"],
"description": "User name of the idTag"
},
"comment": {
"type": ["string", "null"],
"description": "Comment for the idTag"
},
"properties": {
"type": "array",
"description": "NamedBean properties of the idTag",
"items": {
"type": "object",
"properties": {
"key": {
"type": "string",
"description": "Key by which property is accessed"
},
"value": {
"type": ["string", "null"],
"description": "String value of property or null"
}
}
},
"additionalProperties": false,
"required": ["name", "value"]
},
"state": {
"type": "integer",
"description": "The state of the idTag; 0 if unknown; 2 if seen; 3 if not seen yet"
},
"reporter": {
"type": ["string", "null"],
"description": "The system name of the last reporter to have seen the tag or null if not seen yet"
},
"time": {
"type": ["string", "null"],
"description": "The time of the last reported sighting of the tag or null if not seen yet"
}
},
"additionalProperties": false,
"required": ["name", "userName", "comment", "properties", "reporter", "time"]
}
@@ -23,6 +23,7 @@
BundleTest.class,
jmri.server.json.block.PackageTest.class,
jmri.server.json.consist.PackageTest.class,
jmri.server.json.idTag.PackageTest.class,
jmri.server.json.layoutblock.PackageTest.class,
jmri.server.json.light.PackageTest.class,
jmri.server.json.memory.PackageTest.class,

0 comments on commit bd65dbb

Please sign in to comment.
You can’t perform that action at this time.