package org.swellrt.beta.model; import org.swellrt.beta.model.remote.SNodeRemote; import org.waveprotocol.wave.model.util.Preconditions; import org.waveprotocol.wave.model.wave.ParticipantId; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsonUtils; import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsProperty; import jsinterop.annotations.JsType; @JsType(namespace = "swellrt", name = "Primitive") public class SPrimitive extends SNodeRemote { private static final String SEPARATOR = ":"; private static final String STRING_TYPE_PREFIX = "s"; private static final String BOOLEAN_TYPE_PREFIX = "b"; private static final String INTEGER_TYPE_PREFIX = "i"; private static final String DOUBLE_TYPE_PREFIX = "d"; private static final String JSO_TYPE_PREFIX = "js"; private static final int TYPE_INT = 1; private static final int TYPE_DOUBLE = 2; private static final int TYPE_STRING = 3; private static final int TYPE_BOOL = 4; private static final int TYPE_JSO = 5; private final int type; private final int intValue; private final double doubleValue; private final String stringValue; private final Boolean boolValue; private final JavaScriptObject jsoValue; private final SNodeAccessControl accessControl; /** * the key associated with this value in its parent container * if it is a map. */ private String nameKey = null; @JsIgnore public static String asString(SNode node) { try{ if (node != null && node instanceof SPrimitive) { return (String) ((SPrimitive) node).get(); } } catch (ClassCastException e) { } return null; } @JsIgnore public static Double asDouble(SNode node) { try{ if (node != null && node instanceof SPrimitive) { return (double) ((SPrimitive) node).get(); } } catch (ClassCastException e) { } return null; } @JsIgnore public static Integer asInt(SNode node) { try{ if (node != null && node instanceof SPrimitive) { return (int) ((SPrimitive) node).get(); } } catch (ClassCastException e) { } return null; } @JsIgnore public static Boolean asBoolean(SNode node) { try{ if (node != null && node instanceof SPrimitive) { return (boolean) ((SPrimitive) node).get(); } } catch (ClassCastException e) { } return null; } /** * Deserialize a SPrimitive value * <p> * @param s the serialized representation of the primitive value. * @return the primitive value or null if is not a valid serialized string */ public static SPrimitive deserialize(String s) { Preconditions.checkArgument(s != null && !s.isEmpty(), "Null or empty string"); SNodeAccessControl acToken = null; if (SNodeAccessControl.isToken(s)) { int firstSepIndex = s.indexOf(SEPARATOR); acToken = SNodeAccessControl.deserialize(s.substring(0, firstSepIndex)); s = s.substring(firstSepIndex+1); } else { acToken = new SNodeAccessControl(); } if (s.startsWith(STRING_TYPE_PREFIX+SEPARATOR)) { return new SPrimitive(s.substring(2), acToken); } if (s.startsWith(INTEGER_TYPE_PREFIX+SEPARATOR)) { try { return new SPrimitive(Integer.parseInt(s.substring(2)), acToken); } catch (NumberFormatException e) { // Oops return null; } } if (s.startsWith(DOUBLE_TYPE_PREFIX+SEPARATOR)) { try { return new SPrimitive(Double.parseDouble(s.substring(2)), acToken); } catch (NumberFormatException e) { // Oops return null; } } if (s.startsWith(BOOLEAN_TYPE_PREFIX+SEPARATOR)) { return new SPrimitive(Boolean.parseBoolean(s.substring(2)), acToken); } if (s.startsWith(JSO_TYPE_PREFIX+SEPARATOR)) { return new SPrimitive(JsonUtils.<JavaScriptObject>safeEval(s.substring(3)), acToken); } return null; } public String serialize() { String token = accessControl.serialize(); if (!token.isEmpty()) token += SEPARATOR; if (type == TYPE_STRING) return token + STRING_TYPE_PREFIX+SEPARATOR+stringValue; if (type == TYPE_BOOL) return token + BOOLEAN_TYPE_PREFIX+SEPARATOR+Boolean.toString(boolValue); if (type == TYPE_INT) return token + INTEGER_TYPE_PREFIX+SEPARATOR+Integer.toString(intValue); if (type == TYPE_DOUBLE) return token + DOUBLE_TYPE_PREFIX+SEPARATOR+Double.toString(doubleValue); if (type == TYPE_JSO) return token + JSO_TYPE_PREFIX+SEPARATOR+JsonUtils.stringify(jsoValue); return null; } @JsIgnore public SPrimitive(int value, SNodeAccessControl token) { type = TYPE_INT; intValue = value; doubleValue = Double.NaN; stringValue = null; boolValue = null; jsoValue = null; accessControl = token; } @JsIgnore public SPrimitive(double value, SNodeAccessControl token) { type = TYPE_DOUBLE; intValue = Integer.MAX_VALUE; doubleValue = value; stringValue = null; boolValue = null; jsoValue = null; accessControl = token; } @JsIgnore public SPrimitive(String value, SNodeAccessControl token) { type = TYPE_STRING; intValue = Integer.MAX_VALUE; doubleValue = Double.NaN; stringValue = value; boolValue = null; jsoValue = null; accessControl = token; } @JsIgnore public SPrimitive(boolean value, SNodeAccessControl token) { type = TYPE_BOOL; intValue = Integer.MAX_VALUE; doubleValue = Double.NaN; stringValue = null; boolValue = value; jsoValue = null; accessControl = token; } @JsIgnore public SPrimitive(JavaScriptObject value, SNodeAccessControl token) { type = TYPE_JSO; intValue = Integer.MAX_VALUE; doubleValue = Double.NaN; stringValue = null; boolValue = null; jsoValue = value; accessControl = token; } @JsProperty public int getType() { return type; } public Object get() { if (type == TYPE_STRING) return stringValue; if (type == TYPE_INT) return intValue; if (type == TYPE_DOUBLE) return doubleValue; if (type == TYPE_BOOL) return boolValue; if (type == TYPE_JSO) return jsoValue; return null; } @Override public String toString() { return "Primitive Value ["+ serialize()+"]"; } @JsIgnore public void setNameKey(String nameKey) { this.nameKey = nameKey; } @JsIgnore public String getNameKey() { return this.nameKey; } /** * Check if this value can be written by a participant * @param node * @param participantId * @return */ @JsIgnore public boolean canWrite(ParticipantId participantId) { return accessControl.canWrite(participantId); } /** * Check if this value can be read by a participant * @param node * @param participantId * @return */ @JsIgnore public boolean canRead(ParticipantId participantId) { return accessControl.canRead(participantId); } protected SNodeAccessControl getNodeAccessControl() { return accessControl; } }