Skip to content
Snippets Groups Projects
Commit c3bc3f22 authored by Daniel Stonier's avatar Daniel Stonier
Browse files

started clearing out

parent 1a3195f8
Branches
Tags
No related merge requests found
Showing
with 0 additions and 2025 deletions
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.io.DirectoryWalker;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.ros.exception.RosRuntimeException;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class StringFileProvider {
private final Collection<File> directories;
private final Map<File, String> strings;
private final StringFileDirectoryWalker stringFileDirectoryWalker;
private final class StringFileDirectoryWalker extends DirectoryWalker {
private final Set<File> directories;
private StringFileDirectoryWalker(FileFilter filter, int depthLimit) {
super(filter, depthLimit);
directories = Sets.newHashSet();
}
// TODO(damonkohler): Update Apache Commons IO to the latest version.
@SuppressWarnings("rawtypes")
@Override
protected boolean handleDirectory(File directory, int depth, Collection results)
throws IOException {
File canonicalDirectory = directory.getCanonicalFile();
if (directories.contains(canonicalDirectory)) {
return false;
}
directories.add(canonicalDirectory);
return true;
}
@SuppressWarnings("rawtypes")
@Override
protected void handleFile(File file, int depth, Collection results) {
String content;
try {
content = FileUtils.readFileToString(file, "US-ASCII");
} catch (IOException e) {
throw new RosRuntimeException(e);
}
strings.put(file, content);
}
public void update(File directory) {
try {
walk(directory, null);
} catch (IOException e) {
throw new RosRuntimeException(e);
}
}
}
public StringFileProvider(IOFileFilter ioFileFilter) {
directories = Lists.newArrayList();
strings = Maps.newConcurrentMap();
IOFileFilter directoryFilter = FileFilterUtils.directoryFileFilter();
FileFilter fileFilter = FileFilterUtils.orFileFilter(directoryFilter, ioFileFilter);
stringFileDirectoryWalker = new StringFileDirectoryWalker(fileFilter, -1);
}
public void update() {
for (File directory : directories) {
stringFileDirectoryWalker.update(directory);
}
}
/**
* Adds a new directory to be scanned for topic definition files.
*
* @param directory
* the directory to add
*/
public void addDirectory(File directory) {
Preconditions.checkArgument(directory.isDirectory());
directories.add(directory);
}
public Map<File, String> getStrings() {
return ImmutableMap.copyOf(strings);
}
public String get(File file) {
if (!has(file)) {
throw new NoSuchElementException("File does not exist: " + file);
}
return strings.get(file);
}
public boolean has(File file) {
return strings.containsKey(file);
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.ros.exception.RosRuntimeException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.NoSuchElementException;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class StringResourceProvider {
private final Map<String, String> cache;
public StringResourceProvider() {
cache = Maps.newConcurrentMap();
}
public String get(String resourceName) {
if (!has(resourceName)) {
throw new NoSuchElementException("Resource does not exist: " + resourceName);
}
if (!cache.containsKey(resourceName)) {
InputStream in = getClass().getResourceAsStream(resourceName);
StringBuilder out = new StringBuilder();
Charset charset = Charset.forName("US-ASCII");
byte[] buffer = new byte[8192];
try {
for (int bytesRead; (bytesRead = in.read(buffer)) != -1;) {
out.append(new String(buffer, 0, bytesRead, charset));
}
} catch (IOException e) {
throw new RosRuntimeException("Failed to read resource: " + resourceName, e);
}
cache.put(resourceName, out.toString());
}
return cache.get(resourceName);
}
public boolean has(String resourceName) {
return cache.containsKey(resourceName) || getClass().getResource(resourceName) != null;
}
public Map<String, String> getCachedStrings() {
return ImmutableMap.copyOf(cache);
}
public void addStringToCache(String resourceName, String resourceContent) {
cache.put(resourceName, resourceContent);
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.context;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.ros.internal.message.field.FieldFactory;
import org.ros.message.MessageDeclaration;
import org.ros.message.MessageFactory;
import org.ros.message.MessageIdentifier;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Encapsulates the immutable metadata that describes a message type.
* <p>
* Note that this class is not thread safe.
*
* @author damonkohler@google.com (Damon Kohler)
*/
public class MessageContext {
private final MessageDeclaration messageDeclaration;
private final MessageFactory messageFactory;
private final Map<String, FieldFactory> fieldFactories;
private final Map<String, String> fieldGetterNames;
private final Map<String, String> fieldSetterNames;
private final List<String> fieldNames;
public MessageContext(MessageDeclaration messageDeclaration, MessageFactory messageFactory) {
this.messageDeclaration = messageDeclaration;
this.messageFactory = messageFactory;
this.fieldFactories = Maps.newHashMap();
this.fieldGetterNames = Maps.newHashMap();
this.fieldSetterNames = Maps.newHashMap();
this.fieldNames = Lists.newArrayList();
}
public MessageFactory getMessageFactory() {
return messageFactory;
}
public MessageIdentifier getMessageIdentifer() {
return messageDeclaration.getMessageIdentifier();
}
public String getType() {
return messageDeclaration.getType();
}
public String getPackage() {
return messageDeclaration.getPackage();
}
public String getName() {
return messageDeclaration.getName();
}
public String getDefinition() {
return messageDeclaration.getDefinition();
}
public void addFieldFactory(String name, FieldFactory fieldFactory) {
fieldFactories.put(name, fieldFactory);
fieldGetterNames.put(name, "get" + getJavaName(name));
fieldSetterNames.put(name, "set" + getJavaName(name));
fieldNames.add(name);
}
private String getJavaName(String name) {
String[] parts = name.split("_");
StringBuilder fieldName = new StringBuilder();
for (String part : parts) {
fieldName.append(part.substring(0, 1).toUpperCase() + part.substring(1));
}
return fieldName.toString();
}
public boolean hasField(String name) {
// O(1) instead of an O(n) check against the list of field names.
return fieldFactories.containsKey(name);
}
public String getFieldGetterName(String name) {
return fieldGetterNames.get(name);
}
public String getFieldSetterName(String name) {
return fieldSetterNames.get(name);
}
public FieldFactory getFieldFactory(String name) {
return fieldFactories.get(name);
}
/**
* @return a {@link List} of field names in the order they were added
*/
public List<String> getFieldNames() {
return Collections.unmodifiableList(fieldNames);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((messageDeclaration == null) ? 0 : messageDeclaration.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MessageContext other = (MessageContext) obj;
if (messageDeclaration == null) {
if (other.messageDeclaration != null)
return false;
} else if (!messageDeclaration.equals(other.messageDeclaration))
return false;
return true;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.context;
import com.google.common.base.Preconditions;
import org.ros.internal.message.definition.MessageDefinitionParser.MessageDefinitionVisitor;
import org.ros.internal.message.field.Field;
import org.ros.internal.message.field.FieldFactory;
import org.ros.internal.message.field.FieldType;
import org.ros.internal.message.field.MessageFieldType;
import org.ros.internal.message.field.PrimitiveFieldType;
import org.ros.message.MessageIdentifier;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
class MessageContextBuilder implements MessageDefinitionVisitor {
private final MessageContext messageContext;
public MessageContextBuilder(MessageContext context) {
this.messageContext = context;
}
private FieldType getFieldType(String type) {
Preconditions.checkArgument(!type.equals(messageContext.getType()),
"Message definitions may not be self-referential.");
FieldType fieldType;
if (PrimitiveFieldType.existsFor(type)) {
fieldType = PrimitiveFieldType.valueOf(type.toUpperCase());
} else {
fieldType =
new MessageFieldType(MessageIdentifier.of(type), messageContext.getMessageFactory());
}
return fieldType;
}
@Override
public void variableValue(String type, final String name) {
final FieldType fieldType = getFieldType(type);
messageContext.addFieldFactory(name, new FieldFactory() {
@Override
public Field create() {
return fieldType.newVariableValue(name);
}
});
}
@Override
public void variableList(String type, final int size, final String name) {
final FieldType fieldType = getFieldType(type);
messageContext.addFieldFactory(name, new FieldFactory() {
@Override
public Field create() {
return fieldType.newVariableList(name, size);
}
});
}
@Override
public void constantValue(String type, final String name, final String value) {
final FieldType fieldType = getFieldType(type);
messageContext.addFieldFactory(name, new FieldFactory() {
@Override
public Field create() {
return fieldType.newConstantValue(name, fieldType.parseFromString(value));
}
});
}
}
\ No newline at end of file
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.context;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import org.ros.internal.message.definition.MessageDefinitionParser;
import org.ros.internal.message.definition.MessageDefinitionParser.MessageDefinitionVisitor;
import org.ros.message.MessageDeclaration;
import org.ros.message.MessageFactory;
import java.util.Map;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class MessageContextProvider {
private final Map<MessageDeclaration, MessageContext> cache;
private final MessageFactory messageFactory;
public MessageContextProvider(MessageFactory messageFactory) {
Preconditions.checkNotNull(messageFactory);
this.messageFactory = messageFactory;
cache = Maps.newConcurrentMap();
}
public MessageContext get(MessageDeclaration messageDeclaration) {
MessageContext messageContext = cache.get(messageDeclaration);
if (messageContext == null) {
messageContext = new MessageContext(messageDeclaration, messageFactory);
MessageDefinitionVisitor visitor = new MessageContextBuilder(messageContext);
MessageDefinitionParser messageDefinitionParser = new MessageDefinitionParser(visitor);
messageDefinitionParser.parse(messageDeclaration.getType(),
messageDeclaration.getDefinition());
cache.put(messageDeclaration, messageContext);
}
return messageContext;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.definition;
import com.google.common.collect.Maps;
import org.ros.internal.message.StringFileProvider;
import org.apache.commons.io.FilenameUtils;
import org.ros.message.MessageDefinitionProvider;
import org.ros.message.MessageIdentifier;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class MessageDefinitionFileProvider implements MessageDefinitionProvider {
private final StringFileProvider stringFileProvider;
private final Map<String, Collection<MessageIdentifier>> messageIdentifiers;
private final Map<String, String> definitions;
public MessageDefinitionFileProvider(StringFileProvider stringFileProvider) {
this.stringFileProvider = stringFileProvider;
messageIdentifiers = Maps.newConcurrentMap();
definitions = Maps.newConcurrentMap();
}
private static String getParent(String filename) {
return FilenameUtils.getFullPathNoEndSeparator(filename);
}
protected static String getParentBaseName(String filename) {
return FilenameUtils.getBaseName(getParent(filename));
}
private static MessageIdentifier fileToMessageIdentifier(File file) {
String filename = file.getAbsolutePath();
String name = FilenameUtils.getBaseName(filename);
String pkg = getParentBaseName(getParent(filename));
return MessageIdentifier.of(pkg, name);
}
private void addDefinition(File file, String definition) {
MessageIdentifier topicType = fileToMessageIdentifier(file);
if (definitions.containsKey(topicType.getType())) {
// First definition wins.
return;
}
definitions.put(topicType.getType(), definition);
if (!messageIdentifiers.containsKey(topicType.getPackage())) {
messageIdentifiers.put(topicType.getPackage(), new HashSet<MessageIdentifier>());
}
messageIdentifiers.get(topicType.getPackage()).add(topicType);
}
/**
* Updates the topic definition cache.
*
* @see StringFileProvider#update()
*/
public void update() {
stringFileProvider.update();
for (Entry<File, String> entry : stringFileProvider.getStrings().entrySet()) {
addDefinition(entry.getKey(), entry.getValue());
}
}
/**
* @see StringFileProvider#addDirectory(File)
*/
public void addDirectory(File directory) {
stringFileProvider.addDirectory(directory);
}
@Override
public Collection<String> getPackages() {
return messageIdentifiers.keySet();
}
@Override
public Collection<MessageIdentifier> getMessageIdentifiersByPackage(String pkg) {
return messageIdentifiers.get(pkg);
}
@Override
public String get(String type) {
return definitions.get(type);
}
@Override
public boolean has(String type) {
return definitions.containsKey(type);
}
}
\ No newline at end of file
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.definition;
import com.google.common.base.Preconditions;
import org.ros.exception.RosRuntimeException;
import org.ros.internal.message.field.PrimitiveFieldType;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
/**
* Parses message definitions and invokes a {@link MessageDefinitionVisitor} for
* each field.
*
* @author damonkohler@google.com (Damon Kohler)
*/
public class MessageDefinitionParser {
private final MessageDefinitionVisitor visitor;
public interface MessageDefinitionVisitor {
/**
* Called for each constant in the message definition.
*
* @param type
* the type of the constant
* @param name
* the name of the constant
* @param value
* the value of the constant
*/
void constantValue(String type, String name, String value);
/**
* Called for each scalar in the message definition.
*
* @param type
* the type of the scalar
* @param name
* the name of the scalar
*/
void variableValue(String type, String name);
/**
* Called for each array in the message definition.
*
* @param type
* the type of the array
* @param size
* the size of the array or -1 if the size is unbounded
* @param name
* the name of the array
*/
void variableList(String type, int size, String name);
}
/**
* @param visitor
* the {@link MessageDefinitionVisitor} that will be called for each
* field
*/
public MessageDefinitionParser(MessageDefinitionVisitor visitor) {
this.visitor = visitor;
}
/**
* Parses the message definition
*
* @param messageType
* the type of message defined (e.g. std_msgs/String)
* @param messageDefinition
* the message definition (e.g. "string data")
*/
public void parse(String messageType, String messageDefinition) {
Preconditions.checkNotNull(messageType);
Preconditions.checkNotNull(messageDefinition);
BufferedReader reader = new BufferedReader(new StringReader(messageDefinition));
String line;
try {
while (true) {
line = reader.readLine();
if (line == null) {
break;
}
line = line.trim();
if (line.startsWith("#")) {
continue;
}
if (line.length() > 0) {
parseField(messageType, line);
}
}
} catch (IOException e) {
throw new RosRuntimeException(e);
}
}
private void parseField(String messageType, String fieldDefinition) {
// TODO(damonkohler): Regex input validation.
String[] typeAndName = fieldDefinition.split("\\s+", 2);
Preconditions.checkState(typeAndName.length == 2,
String.format("Invalid field definition: \"%s\"", fieldDefinition));
String type = typeAndName[0];
String name = typeAndName[1];
String value = null;
if (name.contains("=") && (!name.contains("#") || name.indexOf('#') > name.indexOf('='))) {
String[] nameAndValue = name.split("=", 2);
name = nameAndValue[0].trim();
value = nameAndValue[1].trim();
} else if (name.contains("#")) {
// Stripping comments from constants is deferred until we also know the
// type since strings are handled differently.
Preconditions.checkState(!name.startsWith("#"), String.format(
"Fields must define a name. Field definition in %s was: \"%s\"", messageType,
fieldDefinition));
name = name.substring(0, name.indexOf('#'));
name = name.trim();
}
boolean array = false;
int size = -1;
if (type.endsWith("]")) {
int leftBracketIndex = type.lastIndexOf('[');
int rightBracketIndex = type.lastIndexOf(']');
array = true;
if (rightBracketIndex - leftBracketIndex > 1) {
size = Integer.parseInt(type.substring(leftBracketIndex + 1, rightBracketIndex));
}
type = type.substring(0, leftBracketIndex);
}
if (type.equals("Header")) {
// The header field is treated as though it were a built-in and silently
// expanded to "std_msgs/Header."
Preconditions.checkState(name.equals("header"), "Header field must be named \"header.\"");
type = "std_msgs/Header";
} else if (!PrimitiveFieldType.existsFor(type) && !type.contains("/")) {
// Handle package relative message names.
type = messageType.substring(0, messageType.lastIndexOf('/') + 1) + type;
}
if (value != null) {
if (array) {
// TODO(damonkohler): Handle array constants?
throw new UnsupportedOperationException("Array constants are not supported.");
}
// Comments inline with string constants are treated as data.
if (!type.equals(PrimitiveFieldType.STRING.getName()) && value.contains("#")) {
Preconditions.checkState(!value.startsWith("#"), "Constants must define a value.");
value = value.substring(0, value.indexOf('#'));
value = value.trim();
}
visitor.constantValue(type, name, value);
} else {
if (array) {
visitor.variableList(type, size, name);
} else {
visitor.variableValue(type, name);
}
}
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.definition;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.ros.message.MessageDefinitionProvider;
import org.ros.message.MessageIdentifier;
import java.util.Collection;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class MessageDefinitionProviderChain implements MessageDefinitionProvider {
private final Collection<MessageDefinitionProvider> messageDefinitionProviders;
public MessageDefinitionProviderChain() {
messageDefinitionProviders = Lists.newArrayList();
}
public void addMessageDefinitionProvider(MessageDefinitionProvider messageDefinitionProvider) {
messageDefinitionProviders.add(messageDefinitionProvider);
}
@Override
public String get(String messageType) {
for (MessageDefinitionProvider messageDefinitionProvider : messageDefinitionProviders) {
if (messageDefinitionProvider.has(messageType)) {
return messageDefinitionProvider.get(messageType);
}
}
throw new NoSuchElementException("No message definition available for: " + messageType);
}
@Override
public boolean has(String messageType) {
for (MessageDefinitionProvider messageDefinitionProvider : messageDefinitionProviders) {
if (messageDefinitionProvider.has(messageType)) {
return true;
}
}
return false;
}
@Override
public Collection<String> getPackages() {
Set<String> result = Sets.newHashSet();
for (MessageDefinitionProvider messageDefinitionProvider : messageDefinitionProviders) {
Collection<String> packages = messageDefinitionProvider.getPackages();
result.addAll(packages);
}
return result;
}
@Override
public Collection<MessageIdentifier> getMessageIdentifiersByPackage(String pkg) {
Set<MessageIdentifier> result = Sets.newHashSet();
for (MessageDefinitionProvider messageDefinitionProvider : messageDefinitionProviders) {
Collection<MessageIdentifier> messageIdentifiers =
messageDefinitionProvider.getMessageIdentifiersByPackage(pkg);
if (messageIdentifiers != null) {
result.addAll(messageIdentifiers);
}
}
return result;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.definition;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import org.ros.exception.RosRuntimeException;
import org.ros.message.MessageDefinitionProvider;
import org.ros.message.MessageIdentifier;
import java.util.Collection;
import java.util.Map;
/**
* A {@link MessageDefinitionProvider} that uses reflection to load the message
* definition {@link String} from a generated interface {@link Class}.
* <p>
* Note that this {@link MessageDefinitionProvider} does not support enumerating
* messages by package.
*
* @author damonkohler@google.com (Damon Kohler)
*/
public class MessageDefinitionReflectionProvider implements MessageDefinitionProvider {
private static final String DEFINITION_FIELD = "_DEFINITION";
private final Map<String, String> cache;
public MessageDefinitionReflectionProvider() {
cache = Maps.newConcurrentMap();
}
@Override
public String get(String messageType) {
String messageDefinition = cache.get(messageType);
if (messageDefinition == null) {
String className = messageType.replace("/", ".");
try {
Class<?> loadedClass = getClass().getClassLoader().loadClass(className);
messageDefinition = (String) loadedClass.getDeclaredField(DEFINITION_FIELD).get(null);
cache.put(messageType, messageDefinition);
} catch (Exception e) {
throw new RosRuntimeException(e);
}
}
return messageDefinition;
}
@Override
public boolean has(String messageType) {
try {
get(messageType);
} catch (Exception e) {
return false;
}
return true;
}
@Override
public Collection<String> getPackages() {
throw new UnsupportedOperationException();
}
@Override
public Collection<MessageIdentifier> getMessageIdentifiersByPackage(String pkg) {
throw new UnsupportedOperationException();
}
@VisibleForTesting
public void add(String messageType, String messageDefinition) {
cache.put(messageType, messageDefinition);
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.definition;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.List;
/**
* Splits message definitions tuples (e.g. service definitions) into separate
* message definitions.
*
* @author damonkohler@google.com (Damon Kohler)
*/
public class MessageDefinitionTupleParser {
private static final String SEPARATOR = "---";
/**
* Splits the message definition tuple into a {@link List} of message
* definitions. Split message definitions may be empty (e.g. std_srvs/Empty).
*
* @param definition
* the message definition tuple
* @param size
* the expected tuple size, or -1 to ignore this requirement
* @return a {@link List} of the specified size
*/
public static List<String> parse(String definition, int size) {
Preconditions.checkNotNull(definition);
List<String> definitions = Lists.newArrayList();
StringBuilder current = new StringBuilder();
for (String line : definition.split("\n")) {
if (line.startsWith(SEPARATOR)) {
definitions.add(current.toString());
current = new StringBuilder();
continue;
}
current.append(line);
current.append("\n");
}
if (current.length() > 0) {
current.deleteCharAt(current.length() - 1);
}
definitions.add(current.toString());
Preconditions.checkState(size == -1 || definitions.size() <= size,
String.format("Message tuple exceeds expected size: %d > %d", definitions.size(), size));
while (definitions.size() < size) {
definitions.add("");
}
return definitions;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import com.google.common.base.Preconditions;
import org.jboss.netty.buffer.ChannelBuffer;
import java.util.Arrays;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class BooleanArrayField extends Field {
private final int size;
private boolean[] value;
public static BooleanArrayField newVariable(String name, int size) {
return new BooleanArrayField(PrimitiveFieldType.BOOL, name, size);
}
private BooleanArrayField(FieldType type, String name, int size) {
super(type, name, false);
this.size = size;
setValue(new boolean[Math.max(0, size)]);
}
@SuppressWarnings("unchecked")
@Override
public boolean[] getValue() {
return value;
}
@Override
public void setValue(Object value) {
Preconditions.checkArgument(size < 0 || ((boolean[]) value).length == size);
this.value = (boolean[]) value;
}
@Override
public void serialize(ChannelBuffer buffer) {
if (size < 0) {
buffer.writeInt(value.length);
}
for (boolean v : value) {
type.serialize(v, buffer);
}
}
@Override
public void deserialize(ChannelBuffer buffer) {
int currentSize = size;
if (currentSize < 0) {
currentSize = buffer.readInt();
}
value = new boolean[currentSize];
for (int i = 0; i < currentSize; i++) {
value[i] = buffer.readByte() == 1;
}
}
@Override
public String getMd5String() {
return String.format("%s %s\n", type, name);
}
@Override
public String getJavaTypeName() {
return type.getJavaTypeName() + "[]";
}
@Override
public String toString() {
return "BooleanArrayField<" + type + ", " + name + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
BooleanArrayField other = (BooleanArrayField) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!Arrays.equals(value, other.value))
return false;
return true;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import com.google.common.base.Preconditions;
import org.jboss.netty.buffer.ChannelBuffer;
import java.util.Arrays;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class ByteArrayField extends Field {
private final int size;
private byte[] value;
public static ByteArrayField newVariable(FieldType type, String name, int size) {
return new ByteArrayField(type, name, size);
}
private ByteArrayField(FieldType type, String name, int size) {
super(type, name, false);
this.size = size;
setValue(new byte[Math.max(0, size)]);
}
@SuppressWarnings("unchecked")
@Override
public byte[] getValue() {
return value;
}
@Override
public void setValue(Object value) {
Preconditions.checkArgument(size < 0 || ((byte[]) value).length == size);
this.value = (byte[]) value;
}
@Override
public void serialize(ChannelBuffer buffer) {
if (size < 0) {
buffer.writeInt(value.length);
}
for (byte v : value) {
type.serialize(v, buffer);
}
}
@Override
public void deserialize(ChannelBuffer buffer) {
int currentSize = size;
if (currentSize < 0) {
currentSize = buffer.readInt();
}
value = new byte[currentSize];
for (int i = 0; i < currentSize; i++) {
value[i] = buffer.readByte();
}
}
@Override
public String getMd5String() {
return String.format("%s %s\n", type, name);
}
@Override
public String getJavaTypeName() {
return type.getJavaTypeName() + "[]";
}
@Override
public String toString() {
return "ByteArrayField<" + type + ", " + name + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
ByteArrayField other = (ByteArrayField) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!Arrays.equals(value, other.value))
return false;
return true;
}
}
/*
* Copyright (C) 2012 Google Inc.
*
* 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.ros.internal.message.field;
import com.google.common.base.Preconditions;
import org.jboss.netty.buffer.ChannelBuffer;
import org.ros.internal.message.MessageBuffers;
import java.nio.ByteOrder;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class ChannelBufferField extends Field {
private final int size;
private ChannelBuffer value;
public static ChannelBufferField newVariable(FieldType type, String name, int size) {
return new ChannelBufferField(type, name, size);
}
private ChannelBufferField(FieldType type, String name, int size) {
super(type, name, false);
this.size = size;
value = MessageBuffers.dynamicBuffer();
}
@SuppressWarnings("unchecked")
@Override
public ChannelBuffer getValue() {
// Return a defensive duplicate. Unlike with copy(), duplicated
// ChannelBuffers share the same backing array, so this is relatively cheap.
return value.duplicate();
}
@Override
public void setValue(Object value) {
Preconditions.checkArgument(((ChannelBuffer) value).order() == ByteOrder.LITTLE_ENDIAN);
Preconditions.checkArgument(size < 0 || ((ChannelBuffer) value).readableBytes() == size);
this.value = (ChannelBuffer) value;
}
@Override
public void serialize(ChannelBuffer buffer) {
if (size < 0) {
buffer.writeInt(value.readableBytes());
}
// By specifying the start index and length we avoid modifying value's
// indices and marks.
buffer.writeBytes(value, 0, value.readableBytes());
}
@Override
public void deserialize(ChannelBuffer buffer) {
int currentSize = size;
if (currentSize < 0) {
currentSize = buffer.readInt();
}
value = buffer.readSlice(currentSize);
}
@Override
public String getMd5String() {
return String.format("%s %s\n", type, name);
}
@Override
public String getJavaTypeName() {
return "org.jboss.netty.buffer.ChannelBuffer";
}
@Override
public String toString() {
return "ChannelBufferField<" + type + ", " + name + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
ChannelBufferField other = (ChannelBufferField) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import com.google.common.base.Preconditions;
import org.jboss.netty.buffer.ChannelBuffer;
import java.util.Arrays;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class DoubleArrayField extends Field {
private final int size;
private double[] value;
public static DoubleArrayField newVariable(String name, int size) {
return new DoubleArrayField(PrimitiveFieldType.FLOAT64, name, size);
}
private DoubleArrayField(FieldType type, String name, int size) {
super(type, name, false);
this.size = size;
setValue(new double[Math.max(0, size)]);
}
@SuppressWarnings("unchecked")
@Override
public double[] getValue() {
return value;
}
@Override
public void setValue(Object value) {
Preconditions.checkArgument(size < 0 || ((double[]) value).length == size);
this.value = (double[]) value;
}
@Override
public void serialize(ChannelBuffer buffer) {
if (size < 0) {
buffer.writeInt(value.length);
}
for (double v : value) {
type.serialize(v, buffer);
}
}
@Override
public void deserialize(ChannelBuffer buffer) {
int currentSize = size;
if (currentSize < 0) {
currentSize = buffer.readInt();
}
value = new double[currentSize];
for (int i = 0; i < currentSize; i++) {
value[i] = buffer.readDouble();
}
}
@Override
public String getMd5String() {
return String.format("%s %s\n", type, name);
}
@Override
public String getJavaTypeName() {
return type.getJavaTypeName() + "[]";
}
@Override
public String toString() {
return "DoubleArrayField<" + type + ", " + name + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
DoubleArrayField other = (DoubleArrayField) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!Arrays.equals(value, other.value))
return false;
return true;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import org.jboss.netty.buffer.ChannelBuffer;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public abstract class Field {
protected final FieldType type;
protected final String name;
protected final boolean isConstant;
protected Field(FieldType type, String name, boolean isConstant) {
this.name = name;
this.type = type;
this.isConstant = isConstant;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the type
*/
public FieldType getType() {
return type;
}
/**
* @return <code>true</code> if this {@link ListField} represents a constant
*/
public boolean isConstant() {
return isConstant;
}
/**
* @return the textual representation of this field used for computing the MD5
* of a message definition
*/
public String getMd5String() {
if (isConstant()) {
return String.format("%s %s=%s\n", getType().getMd5String(), getName(), getValue());
}
return String.format("%s %s\n", getType().getMd5String(), getName());
}
public abstract void serialize(ChannelBuffer buffer);
public abstract void deserialize(ChannelBuffer buffer);
public abstract <T> T getValue();
// TODO(damonkohler): Why not make Field generic?
public abstract void setValue(Object value);
public abstract String getJavaTypeName();
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (isConstant ? 1231 : 1237);
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Field other = (Field) obj;
if (isConstant != other.isConstant)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public interface FieldFactory {
Field create();
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import org.jboss.netty.buffer.ChannelBuffer;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public interface FieldType {
public <T> T getDefaultValue();
public String getName();
public <T> T parseFromString(String value);
public String getMd5String();
public String getJavaTypeName();
/**
* @return the serialized size of this {@link FieldType} in bytes
*/
public int getSerializedSize();
public <T> void serialize(T value, ChannelBuffer buffer);
public <T> T deserialize(ChannelBuffer buffer);
public Field newVariableValue(String name);
public Field newVariableList(String name, int size);
public <T> Field newConstantValue(String name, T value);
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import com.google.common.base.Preconditions;
import org.jboss.netty.buffer.ChannelBuffer;
import java.util.Arrays;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class FloatArrayField extends Field {
private final int size;
private float[] value;
public static FloatArrayField newVariable(String name, int size) {
return new FloatArrayField(PrimitiveFieldType.FLOAT32, name, size);
}
private FloatArrayField(FieldType type, String name, int size) {
super(type, name, false);
this.size = size;
setValue(new float[Math.max(0, size)]);
}
@SuppressWarnings("unchecked")
@Override
public float[] getValue() {
return value;
}
@Override
public void setValue(Object value) {
Preconditions.checkArgument(size < 0 || ((float[]) value).length == size);
this.value = (float[]) value;
}
@Override
public void serialize(ChannelBuffer buffer) {
if (size < 0) {
buffer.writeInt(value.length);
}
for (float v : value) {
type.serialize(v, buffer);
}
}
@Override
public void deserialize(ChannelBuffer buffer) {
int currentSize = size;
if (currentSize < 0) {
currentSize = buffer.readInt();
}
value = new float[currentSize];
for (int i = 0; i < currentSize; i++) {
value[i] = buffer.readFloat();
}
}
@Override
public String getMd5String() {
return String.format("%s %s\n", type, name);
}
@Override
public String getJavaTypeName() {
return type.getJavaTypeName() + "[]";
}
@Override
public String toString() {
return "FloatArrayField<" + type + ", " + name + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
FloatArrayField other = (FloatArrayField) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!Arrays.equals(value, other.value))
return false;
return true;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import com.google.common.base.Preconditions;
import org.jboss.netty.buffer.ChannelBuffer;
import java.util.Arrays;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class IntegerArrayField extends Field {
private final int size;
private int[] value;
public static IntegerArrayField newVariable(FieldType type, String name, int size) {
return new IntegerArrayField(type, name, size);
}
private IntegerArrayField(FieldType type, String name, int size) {
super(type, name, false);
this.size = size;
setValue(new int[Math.max(0, size)]);
}
@SuppressWarnings("unchecked")
@Override
public int[] getValue() {
return value;
}
@Override
public void setValue(Object value) {
Preconditions.checkArgument(size < 0 || ((int[]) value).length == size);
this.value = (int[]) value;
}
@Override
public void serialize(ChannelBuffer buffer) {
if (size < 0) {
buffer.writeInt(value.length);
}
for (int v : value) {
type.serialize(v, buffer);
}
}
@Override
public void deserialize(ChannelBuffer buffer) {
int currentSize = size;
if (currentSize < 0) {
currentSize = buffer.readInt();
}
value = new int[currentSize];
for (int i = 0; i < currentSize; i++) {
value[i] = buffer.readInt();
}
}
@Override
public String getMd5String() {
return String.format("%s %s\n", type, name);
}
@Override
public String getJavaTypeName() {
return type.getJavaTypeName() + "[]";
}
@Override
public String toString() {
return "IntegerArrayField<" + type + ", " + name + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
IntegerArrayField other = (IntegerArrayField) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!Arrays.equals(value, other.value))
return false;
return true;
}
}
/*
* Copyright (C) 2011 Google Inc.
*
* 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.ros.internal.message.field;
import com.google.common.base.Preconditions;
import org.jboss.netty.buffer.ChannelBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* @author damonkohler@google.com (Damon Kohler)
*
* @param <T>
* the value type
*/
public class ListField<T> extends Field {
private List<T> value;
public static <T> ListField<T> newVariable(FieldType type, String name) {
return new ListField<T>(type, name);
}
private ListField(FieldType type, String name) {
super(type, name, false);
value = new ArrayList<T>();
}
@SuppressWarnings("unchecked")
@Override
public List<T> getValue() {
return value;
}
@SuppressWarnings("unchecked")
@Override
public void setValue(Object value) {
Preconditions.checkNotNull(value);
this.value = (List<T>) value;
}
@Override
public void serialize(ChannelBuffer buffer) {
buffer.writeInt(value.size());
for (T v : value) {
type.serialize(v, buffer);
}
}
@Override
public void deserialize(ChannelBuffer buffer) {
value.clear();
int size = buffer.readInt();
for (int i = 0; i < size; i++) {
value.add(type.<T>deserialize(buffer));
}
}
@Override
public String getMd5String() {
return String.format("%s %s\n", type, name);
}
@Override
public String getJavaTypeName() {
return String.format("java.util.List<%s>", type.getJavaTypeName());
}
@Override
public String toString() {
return "ListField<" + type + ", " + name + ">";
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@SuppressWarnings("rawtypes")
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
ListField other = (ListField) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment