com.android.ddmlib.log.EventContainer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ddmlib Show documentation
Show all versions of ddmlib Show documentation
Library providing APIs to talk to Android devices
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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 com.android.ddmlib.log;
import com.android.ddmlib.log.LogReceiver.LogEntry;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Represents an event and its data.
*/
public class EventContainer {
/**
* Comparison method for {@link EventContainer#testValue(int, Object, com.android.ddmlib.log.EventContainer.CompareMethod)}
*
*/
public enum CompareMethod {
EQUAL_TO("equals", "=="),
LESSER_THAN("less than or equals to", "<="),
LESSER_THAN_STRICT("less than", "<"),
GREATER_THAN("greater than or equals to", ">="),
GREATER_THAN_STRICT("greater than", ">"),
BIT_CHECK("bit check", "&");
private final String mName;
private final String mTestString;
private CompareMethod(String name, String testString) {
mName = name;
mTestString = testString;
}
/**
* Returns the display string.
*/
@Override
public String toString() {
return mName;
}
/**
* Returns a short string representing the comparison.
*/
public String testString() {
return mTestString;
}
}
/**
* Type for event data.
*/
public static enum EventValueType {
UNKNOWN(0),
INT(1),
LONG(2),
STRING(3),
LIST(4),
TREE(5);
private static final Pattern STORAGE_PATTERN = Pattern.compile("^(\\d+)@(.*)$"); //$NON-NLS-1$
private int mValue;
/**
* Returns a {@link EventValueType} from an integer value, or null
if no match
* was found.
* @param value the integer value.
*/
static EventValueType getEventValueType(int value) {
for (EventValueType type : values()) {
if (type.mValue == value) {
return type;
}
}
return null;
}
/**
* Returns a storage string for an {@link Object} of type supported by
* {@link EventValueType}.
*
* Strings created by this method can be reloaded with
* {@link #getObjectFromStorageString(String)}.
*
* NOTE: for now, only {@link #STRING}, {@link #INT}, and {@link #LONG} are supported.
* @param object the object to "convert" into a storage string.
* @return a string storing the object and its type or null if the type was not recognized.
*/
public static String getStorageString(Object object) {
if (object instanceof String) {
return STRING.mValue + "@" + object; //$NON-NLS-1$
} else if (object instanceof Integer) {
return INT.mValue + "@" + object.toString(); //$NON-NLS-1$
} else if (object instanceof Long) {
return LONG.mValue + "@" + object.toString(); //$NON-NLS-1$
}
return null;
}
/**
* Creates an {@link Object} from a storage string created with
* {@link #getStorageString(Object)}.
* @param value the storage string
* @return an {@link Object} or null if the string or type were not recognized.
*/
public static Object getObjectFromStorageString(String value) {
Matcher m = STORAGE_PATTERN.matcher(value);
if (m.matches()) {
try {
EventValueType type = getEventValueType(Integer.parseInt(m.group(1)));
if (type == null) {
return null;
}
switch (type) {
case STRING:
return m.group(2);
case INT:
return Integer.valueOf(m.group(2));
case LONG:
return Long.valueOf(m.group(2));
}
} catch (NumberFormatException nfe) {
return null;
}
}
return null;
}
/**
* Returns the integer value of the enum.
*/
public int getValue() {
return mValue;
}
@Override
public String toString() {
return super.toString().toLowerCase(Locale.US);
}
private EventValueType(int value) {
mValue = value;
}
}
public int mTag;
public int pid; /* generating process's pid */
public int tid; /* generating process's tid */
public int sec; /* seconds since Epoch */
public int nsec; /* nanoseconds */
private Object mData;
/**
* Creates an {@link EventContainer} from a {@link LogEntry}.
* @param entry the LogEntry from which pid, tid, and time info is copied.
* @param tag the event tag value
* @param data the data of the EventContainer.
*/
EventContainer(LogEntry entry, int tag, Object data) {
getType(data);
mTag = tag;
mData = data;
pid = entry.pid;
tid = entry.tid;
sec = entry.sec;
nsec = entry.nsec;
}
/**
* Creates an {@link EventContainer} with raw data
*/
EventContainer(int tag, int pid, int tid, int sec, int nsec, Object data) {
getType(data);
mTag = tag;
mData = data;
this.pid = pid;
this.tid = tid;
this.sec = sec;
this.nsec = nsec;
}
/**
* Returns the data as an int.
* @throws InvalidTypeException if the data type is not {@link EventValueType#INT}.
* @see #getType()
*/
public final Integer getInt() throws InvalidTypeException {
if (getType(mData) == EventValueType.INT) {
return (Integer)mData;
}
throw new InvalidTypeException();
}
/**
* Returns the data as a long.
* @throws InvalidTypeException if the data type is not {@link EventValueType#LONG}.
* @see #getType()
*/
public final Long getLong() throws InvalidTypeException {
if (getType(mData) == EventValueType.LONG) {
return (Long)mData;
}
throw new InvalidTypeException();
}
/**
* Returns the data as a String.
* @throws InvalidTypeException if the data type is not {@link EventValueType#STRING}.
* @see #getType()
*/
public final String getString() throws InvalidTypeException {
if (getType(mData) == EventValueType.STRING) {
return (String)mData;
}
throw new InvalidTypeException();
}
/**
* Returns a value by index. The return type is defined by its type.
* @param valueIndex the index of the value. If the data is not a list, this is ignored.
*/
public Object getValue(int valueIndex) {
return getValue(mData, valueIndex, true);
}
/**
* Returns a value by index as a double.
* @param valueIndex the index of the value. If the data is not a list, this is ignored.
* @throws InvalidTypeException if the data type is not {@link EventValueType#INT},
* {@link EventValueType#LONG}, {@link EventValueType#LIST}, or if the item in the
* list at index valueIndex
is not of type {@link EventValueType#INT} or
* {@link EventValueType#LONG}.
* @see #getType()
*/
public double getValueAsDouble(int valueIndex) throws InvalidTypeException {
return getValueAsDouble(mData, valueIndex, true);
}
/**
* Returns a value by index as a String.
* @param valueIndex the index of the value. If the data is not a list, this is ignored.
* @throws InvalidTypeException if the data type is not {@link EventValueType#INT},
* {@link EventValueType#LONG}, {@link EventValueType#STRING}, {@link EventValueType#LIST},
* or if the item in the list at index valueIndex
is not of type
* {@link EventValueType#INT}, {@link EventValueType#LONG}, or {@link EventValueType#STRING}
* @see #getType()
*/
public String getValueAsString(int valueIndex) throws InvalidTypeException {
return getValueAsString(mData, valueIndex, true);
}
/**
* Returns the type of the data.
*/
public EventValueType getType() {
return getType(mData);
}
/**
* Returns the type of an object.
*/
public final EventValueType getType(Object data) {
if (data instanceof Integer) {
return EventValueType.INT;
} else if (data instanceof Long) {
return EventValueType.LONG;
} else if (data instanceof String) {
return EventValueType.STRING;
} else if (data instanceof Object[]) {
// loop through the list to see if we have another list
Object[] objects = (Object[])data;
for (Object obj : objects) {
EventValueType type = getType(obj);
if (type == EventValueType.LIST || type == EventValueType.TREE) {
return EventValueType.TREE;
}
}
return EventValueType.LIST;
}
return EventValueType.UNKNOWN;
}
/**
* Checks that the index
-th value of this event against a provided value.
* @param index the index of the value to test
* @param value the value to test against
* @param compareMethod the method of testing
* @return true if the test passed.
* @throws InvalidTypeException in case of type mismatch between the value to test and the value
* to test against, or if the compare method is incompatible with the type of the values.
* @see CompareMethod
*/
public boolean testValue(int index, Object value,
CompareMethod compareMethod) throws InvalidTypeException {
EventValueType type = getType(mData);
if (index > 0 && type != EventValueType.LIST) {
throw new InvalidTypeException();
}
Object data = mData;
if (type == EventValueType.LIST) {
data = ((Object[])mData)[index];
}
if (!data.getClass().equals(data.getClass())) {
throw new InvalidTypeException();
}
switch (compareMethod) {
case EQUAL_TO:
return data.equals(value);
case LESSER_THAN:
if (data instanceof Integer) {
return (((Integer)data).compareTo((Integer)value) <= 0);
} else if (data instanceof Long) {
return (((Long)data).compareTo((Long)value) <= 0);
}
// other types can't use this compare method.
throw new InvalidTypeException();
case LESSER_THAN_STRICT:
if (data instanceof Integer) {
return (((Integer)data).compareTo((Integer)value) < 0);
} else if (data instanceof Long) {
return (((Long)data).compareTo((Long)value) < 0);
}
// other types can't use this compare method.
throw new InvalidTypeException();
case GREATER_THAN:
if (data instanceof Integer) {
return (((Integer)data).compareTo((Integer)value) >= 0);
} else if (data instanceof Long) {
return (((Long)data).compareTo((Long)value) >= 0);
}
// other types can't use this compare method.
throw new InvalidTypeException();
case GREATER_THAN_STRICT:
if (data instanceof Integer) {
return (((Integer)data).compareTo((Integer)value) > 0);
} else if (data instanceof Long) {
return (((Long)data).compareTo((Long)value) > 0);
}
// other types can't use this compare method.
throw new InvalidTypeException();
case BIT_CHECK:
if (data instanceof Integer) {
return ((Integer) data & (Integer) value) != 0;
} else if (data instanceof Long) {
return ((Long) data & (Long) value) != 0;
}
// other types can't use this compare method.
throw new InvalidTypeException();
default :
throw new InvalidTypeException();
}
}
private final Object getValue(Object data, int valueIndex, boolean recursive) {
EventValueType type = getType(data);
switch (type) {
case INT:
case LONG:
case STRING:
return data;
case LIST:
if (recursive) {
Object[] list = (Object[]) data;
if (valueIndex >= 0 && valueIndex < list.length) {
return getValue(list[valueIndex], valueIndex, false);
}
}
}
return null;
}
private final double getValueAsDouble(Object data, int valueIndex, boolean recursive)
throws InvalidTypeException {
EventValueType type = getType(data);
switch (type) {
case INT:
return ((Integer)data).doubleValue();
case LONG:
return ((Long)data).doubleValue();
case STRING:
throw new InvalidTypeException();
case LIST:
if (recursive) {
Object[] list = (Object[]) data;
if (valueIndex >= 0 && valueIndex < list.length) {
return getValueAsDouble(list[valueIndex], valueIndex, false);
}
}
}
throw new InvalidTypeException();
}
private final String getValueAsString(Object data, int valueIndex, boolean recursive)
throws InvalidTypeException {
EventValueType type = getType(data);
switch (type) {
case INT:
return data.toString();
case LONG:
return data.toString();
case STRING:
return (String)data;
case LIST:
if (recursive) {
Object[] list = (Object[]) data;
if (valueIndex >= 0 && valueIndex < list.length) {
return getValueAsString(list[valueIndex], valueIndex, false);
}
} else {
throw new InvalidTypeException(
"getValueAsString() doesn't support EventValueType.TREE");
}
}
throw new InvalidTypeException(
"getValueAsString() unsupported type:" + type);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy